diff --git a/libwvdrmengine/include/WVErrors.h b/libwvdrmengine/include/WVErrors.h new file mode 100644 index 00000000..93193c1a --- /dev/null +++ b/libwvdrmengine/include/WVErrors.h @@ -0,0 +1,23 @@ +// +// Copyright 2013 Google Inc. All Rights Reserved. +// + +#ifndef WV_ERRORS_H_ +#define WV_ERRORS_H_ + +#include "media/stagefright/MediaErrors.h" + +namespace wvdrm { + +using android::ERROR_DRM_VENDOR_MIN; + +enum { + kErrorNeedProvisioning = ERROR_DRM_VENDOR_MIN, + kErrorDeviceRevoked = ERROR_DRM_VENDOR_MIN + 1, + kErrorIncorrectBufferSize = ERROR_DRM_VENDOR_MIN + 2, + kErrorCDMGeneric = ERROR_DRM_VENDOR_MIN + 3, +}; + +} // namespace wvdrm + +#endif // WV_ERRORS_H_ diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h new file mode 100644 index 00000000..826a80f9 --- /dev/null +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -0,0 +1,49 @@ +// +// Copyright 2013 Google Inc. All Rights Reserved. +// + +#ifndef WV_MAP_ERRORS_H_ +#define WV_MAP_ERRORS_H_ + +#include "media/stagefright/MediaErrors.h" +#include "utils/Errors.h" +#include "wv_cdm_types.h" +#include "WVErrors.h" + +namespace wvdrm { + +static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { + switch (res) { + case wvcdm::NO_ERROR: + case wvcdm::KEY_ADDED: + case wvcdm::KEY_MESSAGE: + case wvcdm::KEY_CANCELED: + // KEY_ADDED, KEY_MESSAGE, and KEY_CANCELLED are all alternative + // success messages for certain CDM methods instead of NO_ERROR. + return android::OK; + case wvcdm::NEED_KEY: + return android::ERROR_DRM_NO_LICENSE; + case wvcdm::NEED_PROVISIONING: + return kErrorNeedProvisioning; + case wvcdm::DEVICE_REVOKED: + return kErrorDeviceRevoked; + case wvcdm::KEY_ERROR: + // KEY_ERROR is used by the CDM to mean just about any kind of error, not + // just license errors, so it is mapped to the generic response. + return kErrorCDMGeneric; + case wvcdm::UNKNOWN_ERROR: + return android::ERROR_DRM_UNKNOWN; + } + + // Return here instead of as a default case so that the compiler will warn + // us if we forget to include an enum member in the switch statement. + return android::UNKNOWN_ERROR; +} + +static inline bool isCdmResponseTypeSuccess(wvcdm::CdmResponseType res) { + return mapCdmResponseType(res) == android::OK; +} + +} // namespace wvdrm + +#endif // WV_MAP_ERRORS_H_ diff --git a/libwvdrmengine/mediacrypto/Android.mk b/libwvdrmengine/mediacrypto/Android.mk index 70563fda..76544000 100644 --- a/libwvdrmengine/mediacrypto/Android.mk +++ b/libwvdrmengine/mediacrypto/Android.mk @@ -12,6 +12,7 @@ LOCAL_C_INCLUDES := \ frameworks/native/include \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/include \ + vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediacrypto/include \ LOCAL_MODULE := libwvdrmcryptoplugin diff --git a/libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h b/libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h index b24e6c0c..411e4001 100644 --- a/libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h +++ b/libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h @@ -5,6 +5,8 @@ #ifndef WV_CRYPTO_PLUGIN_H_ #define WV_CRYPTO_PLUGIN_H_ +#include + #include "media/hardware/CryptoAPI.h" #include "media/stagefright/foundation/ABase.h" #include "media/stagefright/foundation/AString.h" @@ -26,13 +28,14 @@ class WVCryptoPlugin : public android::CryptoPlugin { void* dstPtr, android::AString* errorDetailMsg); private: - wvcdm::CdmSessionId configureTestMode(const void* data, size_t size); DISALLOW_EVIL_CONSTRUCTORS(WVCryptoPlugin); wvcdm::WvContentDecryptionModule* const mCDM; bool mTestMode; const wvcdm::CdmSessionId mSessionId; + + wvcdm::CdmSessionId configureTestMode(const void* data, size_t size); }; } // namespace wvdrm diff --git a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp b/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp index d76fa3d2..30ad844b 100644 --- a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp +++ b/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp @@ -11,12 +11,13 @@ #include #include #include -#include +#include "mapErrors-inl.h" +#include "media/stagefright/MediaErrors.h" +#include "openssl/sha.h" #include "utils/Errors.h" #include "utils/String8.h" #include "wv_cdm_constants.h" -#include "media/stagefright/MediaErrors.h" namespace wvdrm { @@ -26,11 +27,12 @@ using namespace wvcdm; WVCryptoPlugin::WVCryptoPlugin(const void* data, size_t size, WvContentDecryptionModule* cdm) - : mCDM(cdm), + : mCDM(cdm), mTestMode(false), mSessionId(configureTestMode(data, size)) {} -wvcdm::CdmSessionId WVCryptoPlugin::configureTestMode(const void* data, size_t size) { +wvcdm::CdmSessionId WVCryptoPlugin::configureTestMode(const void* data, + size_t size) { wvcdm::CdmSessionId sessionId(static_cast(data), size); size_t index = sessionId.find("test_mode"); if (index != string::npos) { @@ -40,7 +42,6 @@ wvcdm::CdmSessionId WVCryptoPlugin::configureTestMode(const void* data, size_t s return sessionId; } - bool WVCryptoPlugin::requiresSecureDecoderComponent(const char* mime) const { if (!strncasecmp(mime, "video/", 6)) { // Type is video, so query CDM to see if we require a secure decoder. @@ -48,7 +49,7 @@ bool WVCryptoPlugin::requiresSecureDecoderComponent(const char* mime) const { CdmResponseType res = mCDM->QueryStatus(&status); - if (res != wvcdm::NO_ERROR) { + if (!isCdmResponseTypeSuccess(res)) { ALOGE("Error querying CDM status: %u", res); return false; } @@ -70,7 +71,7 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], size_t numSubSamples, void* dstPtr, AString* errorDetailMsg) { if (mode != kMode_Unencrypted && mode != kMode_AES_CTR) { - return BAD_TYPE; + return ERROR_DRM_CANNOT_HANDLE; } // If the caller requested secure decrypt, verify that we can comply. @@ -79,12 +80,12 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], CdmResponseType res = mCDM->QueryStatus(&status); - if (res != wvcdm::NO_ERROR) { + if (!isCdmResponseTypeSuccess(res)) { ALOGE("Error querying CDM status: %u", res); - return PERMISSION_DENIED; + return ERROR_DRM_CANNOT_HANDLE; } else if (status[QUERY_KEY_SECURITY_LEVEL] != QUERY_VALUE_SECURITY_LEVEL_L1) { - return PERMISSION_DENIED; + return ERROR_DRM_CANNOT_HANDLE; } } @@ -102,7 +103,7 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], const SubSample &subSample = subSamples[i]; if (mode == kMode_Unencrypted && subSample.mNumBytesOfEncryptedData != 0) { - return -EINVAL; + return ERROR_DRM_DECRYPT; } // "Decrypt" any unencrypted data. Per the ISO-CENC standard, clear data @@ -113,10 +114,10 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], subSample.mNumBytesOfClearData, ivVector, 0, dest + offset); - if (res != wvcdm::NO_ERROR) { + if (!isCdmResponseTypeSuccess(res)) { ALOGE("Decrypt error result in session %s during unencrypted block: %d", mSessionId.c_str(), res); - return -EINVAL; + return mapCdmResponseType(res); } offset += subSample.mNumBytesOfClearData; @@ -130,10 +131,10 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], subSample.mNumBytesOfEncryptedData, ivVector, encrypted_offset % 16, dest + offset); - if (res != wvcdm::NO_ERROR) { + if (!isCdmResponseTypeSuccess(res)) { ALOGE("Decrypt error result in session %s during encrypted block: %d", mSessionId.c_str(), res); - return -EINVAL; + return mapCdmResponseType(res); } offset += subSample.mNumBytesOfEncryptedData; diff --git a/libwvdrmengine/mediadrm/Android.mk b/libwvdrmengine/mediadrm/Android.mk index c58f2e10..074f1e76 100644 --- a/libwvdrmengine/mediadrm/Android.mk +++ b/libwvdrmengine/mediadrm/Android.mk @@ -11,6 +11,7 @@ LOCAL_C_INCLUDES := \ frameworks/native/include \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/include \ + vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ diff --git a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h index 2ad773b6..93e98ebe 100644 --- a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h +++ b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h @@ -5,6 +5,7 @@ #ifndef WV_DRM_PLUGIN_H_ #define WV_DRM_PLUGIN_H_ +#include #include #include "media/drm/DrmAPI.h" @@ -159,6 +160,8 @@ class WVDrmPlugin : public android::DrmPlugin, WvContentDecryptionModule* mCDM; WVGenericCryptoInterface* mCrypto; map mCryptoSessions; + + static status_t mapOEMCryptoResult(OEMCryptoResult res); }; } // namespace wvdrm diff --git a/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h b/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h index 146d647a..cb6ebb8a 100644 --- a/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h +++ b/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h @@ -5,6 +5,8 @@ #ifndef WV_GENERIC_CRYPTO_INTERFACE_H_ #define WV_GENERIC_CRYPTO_INTERFACE_H_ +#include + #include "OEMCryptoCENC.h" namespace wvdrm { diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index 0297dfca..45fca515 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -12,6 +12,7 @@ #include #include +#include "mapErrors-inl.h" #include "media/stagefright/MediaErrors.h" #include "utils/Errors.h" #include "wv_cdm_constants.h" @@ -45,8 +46,8 @@ status_t WVDrmPlugin::openSession(Vector& sessionId) { CdmSessionId cdmSessionId; CdmResponseType res = mCDM->OpenSession("com.widevine", &cdmSessionId); - if (res != wvcdm::NO_ERROR) { - return android::UNKNOWN_ERROR; + if (!isCdmResponseTypeSuccess(res)) { + return mapCdmResponseType(res); } bool success = false; @@ -58,15 +59,18 @@ status_t WVDrmPlugin::openSession(Vector& sessionId) { // Construct a CryptoSession CdmQueryMap info; - CdmResponseType res = mCDM->QueryKeyControlInfo(cdmSessionId, &info); + res = mCDM->QueryKeyControlInfo(cdmSessionId, &info); - if (res == wvcdm::NO_ERROR && info.count(QUERY_KEY_OEMCRYPTO_SESSION_ID)) { + if (isCdmResponseTypeSuccess(res) && + info.count(QUERY_KEY_OEMCRYPTO_SESSION_ID)) { OEMCrypto_SESSION oecSessionId; istringstream(info[QUERY_KEY_OEMCRYPTO_SESSION_ID]) >> oecSessionId; mCryptoSessions[cdmSessionId] = CryptoSession(oecSessionId); success = true; + } else { + ALOGE("Unable to query key control info."); } } else { ALOGE("Received failure when trying to attach WVDrmPlugin as an event" @@ -87,7 +91,14 @@ status_t WVDrmPlugin::openSession(Vector& sessionId) { mCDM->CloseSession(cdmSessionId); - return android::UNKNOWN_ERROR; + if (!isCdmResponseTypeSuccess(res)) { + // We got an error code we can return. + return mapCdmResponseType(res); + } else { + // We got a failure that did not give us an error code, such as a failure + // of AttachEventListener() or the key being missing from the map. + return kErrorCDMGeneric; + } } } @@ -95,12 +106,11 @@ status_t WVDrmPlugin::closeSession(const Vector& sessionId) { CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); CdmResponseType res = mCDM->CloseSession(cdmSessionId); - if (res == wvcdm::NO_ERROR) { + if (isCdmResponseTypeSuccess(res)) { mCryptoSessions.erase(cdmSessionId); - return android::OK; - } else { - return android::UNKNOWN_ERROR; } + + return mapCdmResponseType(res); } status_t WVDrmPlugin::getKeyRequest( @@ -117,7 +127,7 @@ status_t WVDrmPlugin::getKeyRequest( } else if (keyType == kKeyType_Streaming) { cdmLicenseType = kLicenseTypeStreaming; } else { - return BAD_TYPE; + return android::ERROR_DRM_CANNOT_HANDLE; } CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); @@ -140,17 +150,15 @@ status_t WVDrmPlugin::getKeyRequest( cdmLicenseType, cdmParameters, &keyRequest); - if (res != wvcdm::KEY_MESSAGE) { - return android::UNKNOWN_ERROR; + if (isCdmResponseTypeSuccess(res)) { + defaultUrl.clear(); + + request.clear(); + request.appendArray(reinterpret_cast(keyRequest.data()), + keyRequest.size()); } - defaultUrl.clear(); - - request.clear(); - request.appendArray(reinterpret_cast(keyRequest.data()), - keyRequest.size()); - - return android::OK; + return mapCdmResponseType(res); } status_t WVDrmPlugin::provideKeyResponse( @@ -163,11 +171,7 @@ status_t WVDrmPlugin::provideKeyResponse( CdmResponseType res = mCDM->AddKey(cdmSessionId, cdmResponse); - if (res == wvcdm::KEY_ADDED || res == wvcdm::NO_ERROR) { - return android::OK; - } else { - return android::UNKNOWN_ERROR; - } + return mapCdmResponseType(res); } status_t WVDrmPlugin::removeKeys(const Vector& keySetId) { @@ -189,24 +193,22 @@ status_t WVDrmPlugin::queryKeyStatus( CdmResponseType res = mCDM->QueryKeyStatus(cdmSessionId, &cdmLicenseInfo); - if (res != wvcdm::NO_ERROR) { - return android::UNKNOWN_ERROR; + if (isCdmResponseTypeSuccess(res)) { + infoMap.clear(); + for (CdmQueryMap::const_iterator iter = cdmLicenseInfo.begin(); + iter != cdmLicenseInfo.end(); + ++iter) { + const string& cdmKey = iter->first; + const string& cdmValue = iter->second; + + String8 key(cdmKey.data(), cdmKey.size()); + String8 value(cdmValue.data(), cdmValue.size()); + + infoMap.add(key, value); + } } - infoMap.clear(); - for (CdmQueryMap::const_iterator iter = cdmLicenseInfo.begin(); - iter != cdmLicenseInfo.end(); - ++iter) { - const string& cdmKey = iter->first; - const string& cdmValue = iter->second; - - String8 key(cdmKey.data(), cdmKey.size()); - String8 value(cdmValue.data(), cdmValue.size()); - - infoMap.add(key, value); - } - - return android::OK; + return mapCdmResponseType(res); } status_t WVDrmPlugin::getProvisionRequest(Vector& request, @@ -217,19 +219,17 @@ status_t WVDrmPlugin::getProvisionRequest(Vector& request, CdmResponseType res = mCDM->GetProvisioningRequest(&cdmProvisionRequest, &cdmDefaultUrl); - if (res != wvcdm::NO_ERROR) { - return android::UNKNOWN_ERROR; + if (isCdmResponseTypeSuccess(res)) { + request.clear(); + request.appendArray(reinterpret_cast( + cdmProvisionRequest.data()), + cdmProvisionRequest.size()); + + defaultUrl.clear(); + defaultUrl.setTo(cdmDefaultUrl.data(), cdmDefaultUrl.size()); } - request.clear(); - request.appendArray(reinterpret_cast( - cdmProvisionRequest.data()), - cdmProvisionRequest.size()); - - defaultUrl.clear(); - defaultUrl.setTo(cdmDefaultUrl.data(), cdmDefaultUrl.size()); - - return android::OK; + return mapCdmResponseType(res); } status_t WVDrmPlugin::provideProvisionResponse( @@ -239,11 +239,7 @@ status_t WVDrmPlugin::provideProvisionResponse( CdmResponseType res = mCDM->HandleProvisioningResponse(cdmResponse); - if (res == wvcdm::NO_ERROR) { - return android::OK; - } else { - return android::UNKNOWN_ERROR; - } + return mapCdmResponseType(res); } status_t WVDrmPlugin::getSecureStops(List >& secureStops) { @@ -251,24 +247,22 @@ status_t WVDrmPlugin::getSecureStops(List >& secureStops) { CdmResponseType res = mCDM->GetSecureStops(&cdmSecureStops); - if (res != wvcdm::NO_ERROR) { - return android::UNKNOWN_ERROR; + if (isCdmResponseTypeSuccess(res)) { + secureStops.clear(); + for (CdmSecureStops::const_iterator iter = cdmSecureStops.begin(); + iter != cdmSecureStops.end(); + ++iter) { + const string& cdmStop = *iter; + + Vector stop; + stop.appendArray(reinterpret_cast(cdmStop.data()), + cdmStop.size()); + + secureStops.push_back(stop); + } } - secureStops.clear(); - for (CdmSecureStops::const_iterator iter = cdmSecureStops.begin(); - iter != cdmSecureStops.end(); - ++iter) { - const string& cdmStop = *iter; - - Vector stop; - stop.appendArray(reinterpret_cast(cdmStop.data()), - cdmStop.size()); - - secureStops.push_back(stop); - } - - return android::OK; + return mapCdmResponseType(res); } status_t WVDrmPlugin::releaseSecureStops(const Vector& ssRelease) { @@ -276,11 +270,7 @@ status_t WVDrmPlugin::releaseSecureStops(const Vector& ssRelease) { CdmResponseType res = mCDM->ReleaseSecureStops(cdmMessage); - if (res == wvcdm::NO_ERROR) { - return android::OK; - } else { - return android::UNKNOWN_ERROR; - } + return mapCdmResponseType(res); } status_t WVDrmPlugin::getPropertyString(const String8& name, @@ -298,12 +288,12 @@ status_t WVDrmPlugin::getPropertyString(const String8& name, CdmResponseType res = mCDM->QueryStatus(&status); - if (res != wvcdm::NO_ERROR) { + if (!isCdmResponseTypeSuccess(res)) { ALOGE("Error querying CDM status: %u", res); - return android::UNKNOWN_ERROR; + return mapCdmResponseType(res); } else if (!status.count(QUERY_KEY_SECURITY_LEVEL)) { ALOGE("CDM did not report a security level"); - return android::UNKNOWN_ERROR; + return kErrorCDMGeneric; } const string& securityLevel = status[QUERY_KEY_SECURITY_LEVEL]; @@ -312,7 +302,7 @@ status_t WVDrmPlugin::getPropertyString(const String8& name, value.append(securityLevel.data(), securityLevel.size()); } else { ALOGE("App requested unknown property %s", name.string()); - return android::ERROR_UNSUPPORTED; + return android::ERROR_DRM_CANNOT_HANDLE; } return android::OK; @@ -325,12 +315,12 @@ status_t WVDrmPlugin::getPropertyByteArray(const String8& name, CdmResponseType res = mCDM->QueryStatus(&status); - if (res != wvcdm::NO_ERROR) { + if (!isCdmResponseTypeSuccess(res)) { ALOGE("Error querying CDM status: %u", res); - return android::UNKNOWN_ERROR; + return mapCdmResponseType(res); } else if (!status.count(QUERY_KEY_DEVICE_ID)) { ALOGE("CDM did not report a unique ID"); - return android::UNKNOWN_ERROR; + return kErrorCDMGeneric; } const string& uniqueId = status[QUERY_KEY_DEVICE_ID]; @@ -340,7 +330,7 @@ status_t WVDrmPlugin::getPropertyByteArray(const String8& name, uniqueId.size()); } else { ALOGE("App requested unknown property %s", name.string()); - return android::ERROR_UNSUPPORTED; + return android::ERROR_DRM_CANNOT_HANDLE; } return android::OK; @@ -348,12 +338,12 @@ status_t WVDrmPlugin::getPropertyByteArray(const String8& name, status_t WVDrmPlugin::setPropertyString(const String8& name, const String8& value) { - return android::ERROR_UNSUPPORTED; + return android::ERROR_DRM_CANNOT_HANDLE; } status_t WVDrmPlugin::setPropertyByteArray(const String8& name, const Vector& value) { - return android::ERROR_UNSUPPORTED; + return android::ERROR_DRM_CANNOT_HANDLE; } status_t WVDrmPlugin::setCipherAlgorithm(const Vector& sessionId, @@ -361,7 +351,7 @@ status_t WVDrmPlugin::setCipherAlgorithm(const Vector& sessionId, CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); if (!mCryptoSessions.count(cdmSessionId)) { - return android::NO_INIT; + return android::ERROR_DRM_SESSION_NOT_OPENED; } CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; @@ -369,7 +359,7 @@ status_t WVDrmPlugin::setCipherAlgorithm(const Vector& sessionId, if (algorithm == "AES/CBC/NoPadding") { cryptoSession.setCipherAlgorithm(OEMCrypto_AES_CBC_128_NO_PADDING); } else { - return android::BAD_VALUE; + return android::ERROR_DRM_CANNOT_HANDLE; } return android::OK; @@ -380,7 +370,7 @@ status_t WVDrmPlugin::setMacAlgorithm(const Vector& sessionId, CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); if (!mCryptoSessions.count(cdmSessionId)) { - return android::NO_INIT; + return android::ERROR_DRM_SESSION_NOT_OPENED; } CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; @@ -388,7 +378,7 @@ status_t WVDrmPlugin::setMacAlgorithm(const Vector& sessionId, if (algorithm == "HmacSHA256") { cryptoSession.setMacAlgorithm(OEMCrypto_HMAC_SHA256); } else { - return android::BAD_VALUE; + return android::ERROR_DRM_CANNOT_HANDLE; } return android::OK; @@ -402,7 +392,7 @@ status_t WVDrmPlugin::encrypt(const Vector& sessionId, CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); if (!mCryptoSessions.count(cdmSessionId)) { - return android::NO_INIT; + return android::ERROR_DRM_SESSION_NOT_OPENED; } const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; @@ -416,7 +406,7 @@ status_t WVDrmPlugin::encrypt(const Vector& sessionId, if (res != OEMCrypto_SUCCESS) { ALOGE("OEMCrypto_SelectKey failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } output.resize(input.size()); @@ -429,7 +419,7 @@ status_t WVDrmPlugin::encrypt(const Vector& sessionId, return android::OK; } else { ALOGE("OEMCrypto_Generic_Encrypt failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } } @@ -441,7 +431,7 @@ status_t WVDrmPlugin::decrypt(const Vector& sessionId, CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); if (!mCryptoSessions.count(cdmSessionId)) { - return android::NO_INIT; + return android::ERROR_DRM_SESSION_NOT_OPENED; } const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; @@ -455,7 +445,7 @@ status_t WVDrmPlugin::decrypt(const Vector& sessionId, if (res != OEMCrypto_SUCCESS) { ALOGE("OEMCrypto_SelectKey failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } output.resize(input.size()); @@ -468,7 +458,7 @@ status_t WVDrmPlugin::decrypt(const Vector& sessionId, return android::OK; } else { ALOGE("OEMCrypto_Generic_Decrypt failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } } @@ -479,7 +469,7 @@ status_t WVDrmPlugin::sign(const Vector& sessionId, CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); if (!mCryptoSessions.count(cdmSessionId)) { - return android::NO_INIT; + return android::ERROR_DRM_SESSION_NOT_OPENED; } const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; @@ -493,7 +483,7 @@ status_t WVDrmPlugin::sign(const Vector& sessionId, if (res != OEMCrypto_SUCCESS) { ALOGE("OEMCrypto_SelectKey failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } size_t signatureSize = 0; @@ -505,7 +495,11 @@ status_t WVDrmPlugin::sign(const Vector& sessionId, if (res != OEMCrypto_ERROR_SHORT_BUFFER) { ALOGE("OEMCrypto_Generic_Sign failed with %u when requesting signature " "size", res); - return android::UNKNOWN_ERROR; + if (res != OEMCrypto_SUCCESS) { + return mapOEMCryptoResult(res); + } else { + return android::ERROR_DRM_UNKNOWN; + } } signature.resize(signatureSize); @@ -518,7 +512,7 @@ status_t WVDrmPlugin::sign(const Vector& sessionId, return android::OK; } else { ALOGE("OEMCrypto_Generic_Sign failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } } @@ -530,7 +524,7 @@ status_t WVDrmPlugin::verify(const Vector& sessionId, CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); if (!mCryptoSessions.count(cdmSessionId)) { - return android::NO_INIT; + return android::ERROR_DRM_SESSION_NOT_OPENED; } const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; @@ -544,7 +538,7 @@ status_t WVDrmPlugin::verify(const Vector& sessionId, if (res != OEMCrypto_SUCCESS) { ALOGE("OEMCrypto_SelectKey failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } res = mCrypto->verify(cryptoSession.oecSessionId(), message.array(), @@ -559,7 +553,7 @@ status_t WVDrmPlugin::verify(const Vector& sessionId, return android::OK; } else { ALOGE("OEMCrypto_Generic_Verify failed with %u", res); - return android::UNKNOWN_ERROR; + return mapOEMCryptoResult(res); } } @@ -587,4 +581,25 @@ void WVDrmPlugin::onEvent(const CdmSessionId& cdmSessionId, sendEvent(eventType, 0, &sessionId, NULL); } +status_t WVDrmPlugin::mapOEMCryptoResult(OEMCryptoResult res) { + // Note that we only cover those errors that OEMCryptoCENC.h states may be + // returned by the generic crypto methods. + switch (res) { + case OEMCrypto_SUCCESS: + return android::OK; + case OEMCrypto_ERROR_SIGNATURE_FAILURE: + return android::ERROR_DRM_TAMPER_DETECTED; + case OEMCrypto_ERROR_SHORT_BUFFER: + return kErrorIncorrectBufferSize; + case OEMCrypto_ERROR_NO_DEVICE_KEY: + return kErrorNeedProvisioning; + case OEMCrypto_ERROR_INVALID_SESSION: + return android::ERROR_DRM_SESSION_NOT_OPENED; + case OEMCrypto_ERROR_UNKNOWN_FAILURE: + return android::ERROR_DRM_UNKNOWN; + default: + return android::UNKNOWN_ERROR; + } +} + } // namespace wvdrm