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 ++- include/media/IDrm.h | 62 +++- media/libmedia/IDrm.cpp | 408 +++++++++++++++------- media/libmediaplayerservice/Drm.cpp | 148 +++++++- media/libmediaplayerservice/Drm.h | 53 ++- 6 files changed, 817 insertions(+), 190 deletions(-) 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; diff --git a/include/media/IDrm.h b/include/media/IDrm.h index 38e2378..15d0a75 100644 --- a/include/media/IDrm.h +++ b/include/media/IDrm.h @@ -42,19 +42,23 @@ struct IDrm : public IInterface { virtual status_t closeSession(Vector const &sessionId) = 0; virtual status_t - getLicenseRequest(Vector const &sessionId, - Vector const &initData, - String8 const &mimeType, DrmPlugin::LicenseType licenseType, - KeyedVector const &optionalParameters, - Vector &request, String8 &defaultUrl) = 0; + getKeyRequest(Vector const &sessionId, + Vector const &initData, + String8 const &mimeType, DrmPlugin::KeyType keyType, + KeyedVector const &optionalParameters, + Vector &request, String8 &defaultUrl) = 0; - virtual status_t provideLicenseResponse(Vector const &sessionId, - Vector const &response) = 0; + virtual status_t provideKeyResponse(Vector const &sessionId, + Vector const &response, + Vector &keySetId) = 0; - virtual status_t removeLicense(Vector const &sessionId) = 0; + virtual status_t removeKeys(Vector const &keySetId) = 0; - virtual status_t queryLicenseStatus(Vector const &sessionId, - KeyedVector &infoMap) const = 0; + virtual status_t restoreKeys(Vector const &sessionId, + Vector const &keySetId) = 0; + + virtual status_t queryKeyStatus(Vector const &sessionId, + KeyedVector &infoMap) const = 0; virtual status_t getProvisionRequest(Vector &request, String8 &defaulUrl) = 0; @@ -65,13 +69,42 @@ struct IDrm : public IInterface { virtual status_t releaseSecureStops(Vector const &ssRelease) = 0; - virtual status_t getPropertyString(String8 const &name, String8 &value ) const = 0; + virtual status_t getPropertyString(String8 const &name, String8 &value) const = 0; virtual status_t getPropertyByteArray(String8 const &name, - Vector &value ) const = 0; + Vector &value) const = 0; virtual status_t setPropertyString(String8 const &name, String8 const &value ) const = 0; virtual status_t setPropertyByteArray(String8 const &name, - Vector const &value ) const = 0; + Vector const &value) const = 0; + + virtual status_t setCipherAlgorithm(Vector const &sessionId, + String8 const &algorithm) = 0; + + virtual status_t setMacAlgorithm(Vector const &sessionId, + String8 const &algorithm) = 0; + + virtual status_t encrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) = 0; + + virtual status_t decrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) = 0; + + virtual status_t sign(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector &signature) = 0; + + virtual status_t verify(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector const &signature, + bool &match) = 0; private: DISALLOW_EVIL_CONSTRUCTORS(IDrm); @@ -81,6 +114,9 @@ struct BnDrm : public BnInterface { virtual status_t onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags = 0); +private: + void readVector(const Parcel &data, Vector &vector) const; + void writeVector(Parcel *reply, Vector const &vector) const; }; } // namespace android diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp index 3b13ec6..1641b56 100644 --- a/media/libmedia/IDrm.cpp +++ b/media/libmedia/IDrm.cpp @@ -33,10 +33,11 @@ enum { DESTROY_PLUGIN, OPEN_SESSION, CLOSE_SESSION, - GET_LICENSE_REQUEST, - PROVIDE_LICENSE_RESPONSE, - REMOVE_LICENSE, - QUERY_LICENSE_STATUS, + GET_KEY_REQUEST, + PROVIDE_KEY_RESPONSE, + REMOVE_KEYS, + RESTORE_KEYS, + QUERY_KEY_STATUS, GET_PROVISION_REQUEST, PROVIDE_PROVISION_RESPONSE, GET_SECURE_STOPS, @@ -44,7 +45,13 @@ enum { GET_PROPERTY_STRING, GET_PROPERTY_BYTE_ARRAY, SET_PROPERTY_STRING, - SET_PROPERTY_BYTE_ARRAY + SET_PROPERTY_BYTE_ARRAY, + SET_CIPHER_ALGORITHM, + SET_MAC_ALGORITHM, + ENCRYPT, + DECRYPT, + SIGN, + VERIFY }; struct BpDrm : public BpInterface { @@ -92,9 +99,7 @@ struct BpDrm : public BpInterface { data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); remote()->transact(OPEN_SESSION, data, &reply); - uint32_t size = reply.readInt32(); - sessionId.insertAt((size_t)0, size); - reply.read(sessionId.editArray(), size); + readVector(reply, sessionId); return reply.readInt32(); } @@ -103,80 +108,81 @@ struct BpDrm : public BpInterface { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(sessionId.size()); - data.write(sessionId.array(), sessionId.size()); + writeVector(data, sessionId); remote()->transact(CLOSE_SESSION, data, &reply); return reply.readInt32(); } virtual status_t - getLicenseRequest(Vector const &sessionId, - Vector const &initData, - String8 const &mimeType, DrmPlugin::LicenseType licenseType, - KeyedVector const &optionalParameters, - Vector &request, String8 &defaultUrl) { + getKeyRequest(Vector const &sessionId, + Vector const &initData, + String8 const &mimeType, DrmPlugin::KeyType keyType, + KeyedVector const &optionalParameters, + Vector &request, String8 &defaultUrl) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(sessionId.size()); - data.write(sessionId.array(), sessionId.size()); - - data.writeInt32(initData.size()); - data.write(initData.array(), initData.size()); - + writeVector(data, sessionId); + writeVector(data, initData); data.writeString8(mimeType); - data.writeInt32((uint32_t)licenseType); + data.writeInt32((uint32_t)keyType); data.writeInt32(optionalParameters.size()); for (size_t i = 0; i < optionalParameters.size(); ++i) { data.writeString8(optionalParameters.keyAt(i)); data.writeString8(optionalParameters.valueAt(i)); } - remote()->transact(GET_LICENSE_REQUEST, data, &reply); + remote()->transact(GET_KEY_REQUEST, data, &reply); - uint32_t len = reply.readInt32(); - request.insertAt((size_t)0, len); - reply.read(request.editArray(), len); + readVector(reply, request); defaultUrl = reply.readString8(); return reply.readInt32(); } - virtual status_t provideLicenseResponse(Vector const &sessionId, - Vector const &response) { + virtual status_t provideKeyResponse(Vector const &sessionId, + Vector const &response, + Vector &keySetId) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + writeVector(data, sessionId); + writeVector(data, response); + remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply); + readVector(reply, keySetId); + + return reply.readInt32(); + } + + virtual status_t removeKeys(Vector const &keySetId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(sessionId.size()); - data.write(sessionId.array(), sessionId.size()); - data.writeInt32(response.size()); - data.write(response.array(), response.size()); - remote()->transact(PROVIDE_LICENSE_RESPONSE, data, &reply); + writeVector(data, keySetId); + remote()->transact(REMOVE_KEYS, data, &reply); return reply.readInt32(); } - virtual status_t removeLicense(Vector const &sessionId) { + virtual status_t restoreKeys(Vector const &sessionId, + Vector const &keySetId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(sessionId.size()); - data.write(sessionId.array(), sessionId.size()); - remote()->transact(REMOVE_LICENSE, data, &reply); + writeVector(data, sessionId); + writeVector(data, keySetId); + remote()->transact(RESTORE_KEYS, data, &reply); return reply.readInt32(); } - virtual status_t queryLicenseStatus(Vector const &sessionId, + virtual status_t queryKeyStatus(Vector const &sessionId, KeyedVector &infoMap) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(sessionId.size()); - data.write(sessionId.array(), sessionId.size()); - - remote()->transact(QUERY_LICENSE_STATUS, data, &reply); + writeVector(data, sessionId); + remote()->transact(QUERY_KEY_STATUS, data, &reply); infoMap.clear(); size_t count = reply.readInt32(); @@ -195,9 +201,7 @@ struct BpDrm : public BpInterface { remote()->transact(GET_PROVISION_REQUEST, data, &reply); - uint32_t len = reply.readInt32(); - request.insertAt((size_t)0, len); - reply.read(request.editArray(), len); + readVector(reply, request); defaultUrl = reply.readString8(); return reply.readInt32(); @@ -207,8 +211,7 @@ struct BpDrm : public BpInterface { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(response.size()); - data.write(response.array(), response.size()); + writeVector(data, response); remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply); return reply.readInt32(); @@ -224,9 +227,7 @@ struct BpDrm : public BpInterface { uint32_t count = reply.readInt32(); for (size_t i = 0; i < count; i++) { Vector secureStop; - uint32_t len = reply.readInt32(); - secureStop.insertAt((size_t)0, len); - reply.read(secureStop.editArray(), len); + readVector(reply, secureStop); secureStops.push_back(secureStop); } return reply.readInt32(); @@ -236,8 +237,7 @@ struct BpDrm : public BpInterface { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(ssRelease.size()); - data.write(ssRelease.array(), ssRelease.size()); + writeVector(data, ssRelease); remote()->transact(RELEASE_SECURE_STOPS, data, &reply); return reply.readInt32(); @@ -261,10 +261,7 @@ struct BpDrm : public BpInterface { data.writeString8(name); remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply); - uint32_t len = reply.readInt32(); - value.insertAt((size_t)0, len); - reply.read(value.editArray(), len); - + readVector(reply, value); return reply.readInt32(); } @@ -285,15 +282,120 @@ struct BpDrm : public BpInterface { data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.writeString8(name); - data.writeInt32(value.size()); - data.write(value.array(), value.size()); + writeVector(data, value); remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply); return reply.readInt32(); } + virtual status_t setCipherAlgorithm(Vector const &sessionId, + String8 const &algorithm) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, sessionId); + data.writeString8(algorithm); + remote()->transact(SET_CIPHER_ALGORITHM, data, &reply); + return reply.readInt32(); + } + + virtual status_t setMacAlgorithm(Vector const &sessionId, + String8 const &algorithm) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, sessionId); + data.writeString8(algorithm); + remote()->transact(SET_MAC_ALGORITHM, data, &reply); + return reply.readInt32(); + } + + virtual status_t encrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, sessionId); + writeVector(data, keyId); + writeVector(data, input); + writeVector(data, iv); + + remote()->transact(ENCRYPT, data, &reply); + readVector(reply, output); + + return reply.readInt32(); + } + + virtual status_t decrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, sessionId); + writeVector(data, keyId); + writeVector(data, input); + writeVector(data, iv); + + remote()->transact(DECRYPT, data, &reply); + readVector(reply, output); + + return reply.readInt32(); + } + + virtual status_t sign(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector &signature) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, sessionId); + writeVector(data, keyId); + writeVector(data, message); + + remote()->transact(SIGN, data, &reply); + readVector(reply, signature); + + return reply.readInt32(); + } + + virtual status_t verify(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector const &signature, + bool &match) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, sessionId); + writeVector(data, keyId); + writeVector(data, message); + writeVector(data, signature); + + remote()->transact(VERIFY, data, &reply); + match = (bool)reply.readInt32(); + return reply.readInt32(); + } + private: + void readVector(Parcel &reply, Vector &vector) const { + uint32_t size = reply.readInt32(); + vector.insertAt((size_t)0, size); + reply.read(vector.editArray(), size); + } + + void writeVector(Parcel &data, Vector const &vector) const { + data.writeInt32(vector.size()); + data.write(vector.array(), vector.size()); + } + DISALLOW_EVIL_CONSTRUCTORS(BpDrm); }; @@ -301,6 +403,17 @@ IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm"); //////////////////////////////////////////////////////////////////////////////// +void BnDrm::readVector(const Parcel &data, Vector &vector) const { + uint32_t size = data.readInt32(); + vector.insertAt((size_t)0, size); + data.read(vector.editArray(), size); +} + +void BnDrm::writeVector(Parcel *reply, Vector const &vector) const { + reply->writeInt32(vector.size()); + reply->write(vector.array(), vector.size()); +} + status_t BnDrm::onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { switch (code) { @@ -341,8 +454,7 @@ status_t BnDrm::onTransact( CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; status_t result = openSession(sessionId); - reply->writeInt32(sessionId.size()); - reply->write(sessionId.array(), sessionId.size()); + writeVector(reply, sessionId); reply->writeInt32(result); return OK; } @@ -351,28 +463,20 @@ status_t BnDrm::onTransact( { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; - uint32_t size = data.readInt32(); - sessionId.insertAt((size_t)0, size); - data.read(sessionId.editArray(), size); + readVector(data, sessionId); reply->writeInt32(closeSession(sessionId)); return OK; } - case GET_LICENSE_REQUEST: + case GET_KEY_REQUEST: { CHECK_INTERFACE(IDrm, data, reply); - Vector sessionId; - uint32_t size = data.readInt32(); - sessionId.insertAt((size_t)0, size); - data.read(sessionId.editArray(), size); - - Vector initData; - size = data.readInt32(); - initData.insertAt((size_t)0, size); - data.read(initData.editArray(), size); + Vector sessionId, initData; + readVector(data, sessionId); + readVector(data, initData); String8 mimeType = data.readString8(); - DrmPlugin::LicenseType licenseType = (DrmPlugin::LicenseType)data.readInt32(); + DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32(); KeyedVector optionalParameters; uint32_t count = data.readInt32(); @@ -386,55 +490,54 @@ status_t BnDrm::onTransact( Vector request; String8 defaultUrl; - status_t result = getLicenseRequest(sessionId, initData, - mimeType, licenseType, - optionalParameters, - request, defaultUrl); - reply->writeInt32(request.size()); - reply->write(request.array(), request.size()); + status_t result = getKeyRequest(sessionId, initData, + mimeType, keyType, + optionalParameters, + request, defaultUrl); + writeVector(reply, request); reply->writeString8(defaultUrl); reply->writeInt32(result); return OK; } - case PROVIDE_LICENSE_RESPONSE: + case PROVIDE_KEY_RESPONSE: { CHECK_INTERFACE(IDrm, data, reply); - Vector sessionId; - uint32_t size = data.readInt32(); - sessionId.insertAt((size_t)0, size); - data.read(sessionId.editArray(), size); - Vector response; - size = data.readInt32(); - response.insertAt((size_t)0, size); - data.read(response.editArray(), size); + Vector sessionId, response, keySetId; + readVector(data, sessionId); + readVector(data, response); + uint32_t result = provideKeyResponse(sessionId, response, keySetId); + writeVector(reply, keySetId); + reply->writeInt32(result); + return OK; + } - reply->writeInt32(provideLicenseResponse(sessionId, response)); + case REMOVE_KEYS: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector keySetId; + readVector(data, keySetId); + reply->writeInt32(removeKeys(keySetId)); return OK; } - case REMOVE_LICENSE: + case RESTORE_KEYS: { CHECK_INTERFACE(IDrm, data, reply); - Vector sessionId; - uint32_t size = data.readInt32(); - sessionId.insertAt((size_t)0, size); - data.read(sessionId.editArray(), size); - reply->writeInt32(removeLicense(sessionId)); + Vector sessionId, keySetId; + readVector(data, sessionId); + readVector(data, keySetId); + reply->writeInt32(restoreKeys(sessionId, keySetId)); return OK; } - case QUERY_LICENSE_STATUS: + case QUERY_KEY_STATUS: { CHECK_INTERFACE(IDrm, data, reply); Vector sessionId; - uint32_t size = data.readInt32(); - sessionId.insertAt((size_t)0, size); - data.read(sessionId.editArray(), size); + readVector(data, sessionId); KeyedVector infoMap; - - status_t result = queryLicenseStatus(sessionId, infoMap); - + status_t result = queryKeyStatus(sessionId, infoMap); size_t count = infoMap.size(); reply->writeInt32(count); for (size_t i = 0; i < count; ++i) { @@ -451,8 +554,7 @@ status_t BnDrm::onTransact( Vector request; String8 defaultUrl; status_t result = getProvisionRequest(request, defaultUrl); - reply->writeInt32(request.size()); - reply->write(request.array(), request.size()); + writeVector(reply, request); reply->writeString8(defaultUrl); reply->writeInt32(result); return OK; @@ -462,11 +564,8 @@ status_t BnDrm::onTransact( { CHECK_INTERFACE(IDrm, data, reply); Vector response; - uint32_t size = data.readInt32(); - response.insertAt((size_t)0, size); - data.read(response.editArray(), size); + readVector(data, response); reply->writeInt32(provideProvisionResponse(response)); - return OK; } @@ -491,9 +590,7 @@ status_t BnDrm::onTransact( { CHECK_INTERFACE(IDrm, data, reply); Vector ssRelease; - uint32_t size = data.readInt32(); - ssRelease.insertAt((size_t)0, size); - data.read(ssRelease.editArray(), size); + readVector(data, ssRelease); reply->writeInt32(releaseSecureStops(ssRelease)); return OK; } @@ -515,8 +612,7 @@ status_t BnDrm::onTransact( String8 name = data.readString8(); Vector value; status_t result = getPropertyByteArray(name, value); - reply->writeInt32(value.size()); - reply->write(value.array(), value.size()); + writeVector(reply, value); reply->writeInt32(result); return OK; } @@ -535,15 +631,89 @@ status_t BnDrm::onTransact( CHECK_INTERFACE(IDrm, data, reply); String8 name = data.readString8(); Vector value; - size_t count = data.readInt32(); - value.insertAt((size_t)0, count); - data.read(value.editArray(), count); + readVector(data, value); reply->writeInt32(setPropertyByteArray(name, value)); return OK; } - default: - return BBinder::onTransact(code, data, reply, flags); + case SET_CIPHER_ALGORITHM: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector sessionId; + readVector(data, sessionId); + String8 algorithm = data.readString8(); + reply->writeInt32(setCipherAlgorithm(sessionId, algorithm)); + return OK; + } + + case SET_MAC_ALGORITHM: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector sessionId; + readVector(data, sessionId); + String8 algorithm = data.readString8(); + reply->writeInt32(setMacAlgorithm(sessionId, algorithm)); + return OK; + } + + case ENCRYPT: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector sessionId, keyId, input, iv, output; + readVector(data, sessionId); + readVector(data, keyId); + readVector(data, input); + readVector(data, iv); + uint32_t result = encrypt(sessionId, keyId, input, iv, output); + writeVector(reply, output); + reply->writeInt32(result); + return OK; + } + + case DECRYPT: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector sessionId, keyId, input, iv, output; + readVector(data, sessionId); + readVector(data, keyId); + readVector(data, input); + readVector(data, iv); + uint32_t result = decrypt(sessionId, keyId, input, iv, output); + writeVector(reply, output); + reply->writeInt32(result); + return OK; + } + + case SIGN: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector sessionId, keyId, message, signature; + readVector(data, sessionId); + readVector(data, keyId); + readVector(data, message); + uint32_t result = sign(sessionId, keyId, message, signature); + writeVector(reply, signature); + reply->writeInt32(result); + return OK; + } + + case VERIFY: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector sessionId, keyId, message, signature; + readVector(data, sessionId); + readVector(data, keyId); + readVector(data, message); + readVector(data, signature); + bool match; + uint32_t result = verify(sessionId, keyId, message, signature, match); + reply->writeInt32(match); + reply->writeInt32(result); + return OK; + } + + default: + return BBinder::onTransact(code, data, reply, flags); } } diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp index 6ac7530..5fdb9f4 100644 --- a/media/libmediaplayerservice/Drm.cpp +++ b/media/libmediaplayerservice/Drm.cpp @@ -243,11 +243,11 @@ status_t Drm::closeSession(Vector const &sessionId) { return mPlugin->closeSession(sessionId); } -status_t Drm::getLicenseRequest(Vector const &sessionId, - Vector const &initData, - String8 const &mimeType, DrmPlugin::LicenseType licenseType, - KeyedVector const &optionalParameters, - Vector &request, String8 &defaultUrl) { +status_t Drm::getKeyRequest(Vector const &sessionId, + Vector const &initData, + String8 const &mimeType, DrmPlugin::KeyType keyType, + KeyedVector const &optionalParameters, + Vector &request, String8 &defaultUrl) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { @@ -258,12 +258,13 @@ status_t Drm::getLicenseRequest(Vector const &sessionId, return -EINVAL; } - return mPlugin->getLicenseRequest(sessionId, initData, mimeType, licenseType, - optionalParameters, request, defaultUrl); + return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType, + optionalParameters, request, defaultUrl); } -status_t Drm::provideLicenseResponse(Vector const &sessionId, - Vector const &response) { +status_t Drm::provideKeyResponse(Vector const &sessionId, + Vector const &response, + Vector &keySetId) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { @@ -274,10 +275,10 @@ status_t Drm::provideLicenseResponse(Vector const &sessionId, return -EINVAL; } - return mPlugin->provideLicenseResponse(sessionId, response); + return mPlugin->provideKeyResponse(sessionId, response, keySetId); } -status_t Drm::removeLicense(Vector const &sessionId) { +status_t Drm::removeKeys(Vector const &keySetId) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { @@ -288,11 +289,11 @@ status_t Drm::removeLicense(Vector const &sessionId) { return -EINVAL; } - return mPlugin->removeLicense(sessionId); + return mPlugin->removeKeys(keySetId); } -status_t Drm::queryLicenseStatus(Vector const &sessionId, - KeyedVector &infoMap) const { +status_t Drm::restoreKeys(Vector const &sessionId, + Vector const &keySetId) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { @@ -303,7 +304,22 @@ status_t Drm::queryLicenseStatus(Vector const &sessionId, return -EINVAL; } - return mPlugin->queryLicenseStatus(sessionId, infoMap); + return mPlugin->restoreKeys(sessionId, keySetId); +} + +status_t Drm::queryKeyStatus(Vector const &sessionId, + KeyedVector &infoMap) const { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPlugin == NULL) { + return -EINVAL; + } + + return mPlugin->queryKeyStatus(sessionId, infoMap); } status_t Drm::getProvisionRequest(Vector &request, String8 &defaultUrl) { @@ -420,4 +436,106 @@ status_t Drm::setPropertyByteArray(String8 const &name, return mPlugin->setPropertyByteArray(name, value); } + +status_t Drm::setCipherAlgorithm(Vector const &sessionId, + String8 const &algorithm) { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPlugin == NULL) { + return -EINVAL; + } + + return mPlugin->setCipherAlgorithm(sessionId, algorithm); +} + +status_t Drm::setMacAlgorithm(Vector const &sessionId, + String8 const &algorithm) { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPlugin == NULL) { + return -EINVAL; + } + + return mPlugin->setMacAlgorithm(sessionId, algorithm); +} + +status_t Drm::encrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPlugin == NULL) { + return -EINVAL; + } + + return mPlugin->encrypt(sessionId, keyId, input, iv, output); +} + +status_t Drm::decrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output) { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPlugin == NULL) { + return -EINVAL; + } + + return mPlugin->decrypt(sessionId, keyId, input, iv, output); +} + +status_t Drm::sign(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector &signature) { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPlugin == NULL) { + return -EINVAL; + } + + return mPlugin->sign(sessionId, keyId, message, signature); +} + +status_t Drm::verify(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector const &signature, + bool &match) { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPlugin == NULL) { + return -EINVAL; + } + + return mPlugin->verify(sessionId, keyId, message, signature, match); +} + } // namespace android diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h index 1b10958..f24921e 100644 --- a/media/libmediaplayerservice/Drm.h +++ b/media/libmediaplayerservice/Drm.h @@ -45,19 +45,23 @@ struct Drm : public BnDrm { virtual status_t closeSession(Vector const &sessionId); virtual status_t - getLicenseRequest(Vector const &sessionId, - Vector const &initData, - String8 const &mimeType, DrmPlugin::LicenseType licenseType, - KeyedVector const &optionalParameters, - Vector &request, String8 &defaultUrl); + getKeyRequest(Vector const &sessionId, + Vector const &initData, + String8 const &mimeType, DrmPlugin::KeyType keyType, + KeyedVector const &optionalParameters, + Vector &request, String8 &defaultUrl); - virtual status_t provideLicenseResponse(Vector const &sessionId, - Vector const &response); + virtual status_t provideKeyResponse(Vector const &sessionId, + Vector const &response, + Vector &keySetId); - virtual status_t removeLicense(Vector const &sessionId); + virtual status_t removeKeys(Vector const &keySetId); - virtual status_t queryLicenseStatus(Vector const &sessionId, - KeyedVector &infoMap) const; + virtual status_t restoreKeys(Vector const &sessionId, + Vector const &keySetId); + + virtual status_t queryKeyStatus(Vector const &sessionId, + KeyedVector &infoMap) const; virtual status_t getProvisionRequest(Vector &request, String8 &defaulUrl); @@ -75,6 +79,35 @@ struct Drm : public BnDrm { virtual status_t setPropertyByteArray(String8 const &name, Vector const &value ) const; + virtual status_t setCipherAlgorithm(Vector const &sessionId, + String8 const &algorithm); + + virtual status_t setMacAlgorithm(Vector const &sessionId, + String8 const &algorithm); + + virtual status_t encrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output); + + virtual status_t decrypt(Vector const &sessionId, + Vector const &keyId, + Vector const &input, + Vector const &iv, + Vector &output); + + virtual status_t sign(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector &signature); + + virtual status_t verify(Vector const &sessionId, + Vector const &keyId, + Vector const &message, + Vector const &signature, + bool &match); + private: mutable Mutex mLock; -- cgit v1.1