From 0b02296014ede27120b3cce6b6da9053394b6724 Mon Sep 17 00:00:00 2001 From: TreeHugger Robot Date: Fri, 29 Oct 2021 18:09:45 +0000 Subject: [PATCH] Removing Non-HIDL Widevine DRM Plugin for Android [ Merge of http://go/wvgerrit/138089 ] Non-hidl code is no longer needed in the widevine android plugin. By doing work this cleanup will save the team from having to keep maintaining code that isn't needed anymore. Clean up steps taken as follows: 1. Remove non-hidl code but keep commonly used code 2. Remove legacy test code 3. Remove legacy test build and test entry Bug: 69573078 Bug: 172285246 Test: unit tests, GtsMediaTestCases, CtsMediaDrmTestCases Change-Id: I75938d69413c631ef6be82da3d885ba173efc581 --- libwvdrmengine/Android.bp | 66 +- libwvdrmengine/build_all_unit_tests.sh | 3 - .../include/WVCreatePluginFactories.h | 18 - libwvdrmengine/include/WVCryptoFactory.h | 33 - libwvdrmengine/include/WVDrmFactory.h | 37 - libwvdrmengine/include/mapErrors-inl.h | 630 ------ libwvdrmengine/mediacrypto/Android.bp | 53 +- .../mediacrypto/include/WVCryptoPlugin.h | 57 - .../mediacrypto/src/WVCryptoPlugin.cpp | 261 --- libwvdrmengine/mediacrypto/test/Android.mk | 64 - .../test/legacy_src/WVCryptoPlugin_test.cpp | 430 ---- libwvdrmengine/mediadrm/Android.bp | 50 - libwvdrmengine/mediadrm/include/WVDrmPlugin.h | 306 --- .../include/WVGenericCryptoInterface.h | 98 - libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp | 1154 ---------- .../mediadrm/src/WVGenericCryptoInterface.cpp | 51 - libwvdrmengine/mediadrm/test/Android.mk | 67 - .../test/legacy_src/WVDrmPlugin_test.cpp | 1930 ----------------- libwvdrmengine/run_all_unit_tests.sh | 9 - .../src/WVCreatePluginFactories.cpp | 22 - libwvdrmengine/src/WVCryptoFactory.cpp | 39 - libwvdrmengine/src/WVDrmFactory.cpp | 46 - libwvdrmengine/test/unit/Android.mk | 51 - .../WVCreatePluginFactories_test.cpp | 26 - .../unit/legacy_src/WVCryptoFactory_test.cpp | 44 - .../unit/legacy_src/WVDrmFactory_test.cpp | 88 - tests/Android.mk | 3 - 27 files changed, 2 insertions(+), 5634 deletions(-) delete mode 100644 libwvdrmengine/include/WVCreatePluginFactories.h delete mode 100644 libwvdrmengine/include/WVCryptoFactory.h delete mode 100644 libwvdrmengine/include/WVDrmFactory.h delete mode 100644 libwvdrmengine/include/mapErrors-inl.h delete mode 100644 libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h delete mode 100644 libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp delete mode 100644 libwvdrmengine/mediacrypto/test/legacy_src/WVCryptoPlugin_test.cpp delete mode 100644 libwvdrmengine/mediadrm/include/WVDrmPlugin.h delete mode 100644 libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h delete mode 100644 libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp delete mode 100644 libwvdrmengine/mediadrm/src/WVGenericCryptoInterface.cpp delete mode 100644 libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp delete mode 100644 libwvdrmengine/src/WVCreatePluginFactories.cpp delete mode 100644 libwvdrmengine/src/WVCryptoFactory.cpp delete mode 100644 libwvdrmengine/src/WVDrmFactory.cpp delete mode 100644 libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp delete mode 100644 libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp delete mode 100644 libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp diff --git a/libwvdrmengine/Android.bp b/libwvdrmengine/Android.bp index cb75396d..c3b7b718 100644 --- a/libwvdrmengine/Android.bp +++ b/libwvdrmengine/Android.bp @@ -96,7 +96,7 @@ cc_defaults { relative_install_path: "hw", include_dirs: [ "vendor/widevine/libwvdrmengine/include_hidl", - "vendor/widevine/libwvdrmengine/mediadrm/include", + "vendor/widevine/libwvdrmengine/mediadrm/include_hidl", "vendor/widevine/libwvdrmengine/oemcrypto/include", ], header_libs: ["libstagefright_foundation_headers"], @@ -274,68 +274,6 @@ cc_library_static { } -// ---------------------------------------------------------------------------- -// Builds libwvdrmengine.so -// -cc_library_shared { - name: "libwvdrmengine", - - srcs: [ - "src/WVCDMSingleton.cpp", - "src/WVCreatePluginFactories.cpp", - "src/WVCryptoFactory.cpp", - "src/WVDrmFactory.cpp", - "src/WVUUID.cpp", - ], - - include_dirs: [ - "frameworks/av/include", - "frameworks/native/include", - "vendor/widevine/libwvdrmengine/cdm/core/include", - "vendor/widevine/libwvdrmengine/cdm/metrics/include", - "vendor/widevine/libwvdrmengine/cdm/util/include", - "vendor/widevine/libwvdrmengine/cdm/include", - "vendor/widevine/libwvdrmengine/include", - "vendor/widevine/libwvdrmengine/mediacrypto/include", - "vendor/widevine/libwvdrmengine/mediadrm/include", - "vendor/widevine/libwvdrmengine/oemcrypto/include", - ], - - static_libs: [ - "libcdm", - "libcdm_protos", - "libcdm_utils", - "libjsmn", - "libwvdrmcryptoplugin", - "libwvdrmdrmplugin", - "libwvlevel3", - "libwv_odk", - ], - - shared_libs: [ - "libbase", - "libcrypto", - "libdl", - "libhidlbase", - "liblog", - "libprotobuf-cpp-lite", - "libstagefright_foundation", - "libutils", - ], - - header_libs: [ - "libutils_headers", - "libstagefright_headers", - ], - - relative_install_path: "mediadrm", - - owner: "widevine", - - proprietary: true, - -} - // ---------------------------------------------------------------------------- // Builds libwvhidl.so // @@ -361,9 +299,7 @@ cc_library_shared { "vendor/widevine/libwvdrmengine/include_hidl", "vendor/widevine/libwvdrmengine/include", "vendor/widevine/libwvdrmengine/mediacrypto/include_hidl", - "vendor/widevine/libwvdrmengine/mediacrypto/include", "vendor/widevine/libwvdrmengine/mediadrm/include_hidl", - "vendor/widevine/libwvdrmengine/mediadrm/include", "vendor/widevine/libwvdrmengine/oemcrypto/include", ], diff --git a/libwvdrmengine/build_all_unit_tests.sh b/libwvdrmengine/build_all_unit_tests.sh index 0ff0a34e..b09aa39b 100755 --- a/libwvdrmengine/build_all_unit_tests.sh +++ b/libwvdrmengine/build_all_unit_tests.sh @@ -50,11 +50,8 @@ WV_TEST_TARGETS="base64_test \ initialization_data_unittest \ keybox_ota_test \ libwvdrmdrmplugin_hidl_test \ - libwvdrmdrmplugin_test \ libwvdrmengine_hidl_test \ - libwvdrmengine_test \ libwvdrmmediacrypto_hidl_test \ - libwvdrmmediacrypto_test \ license_keys_unittest \ license_unittest \ metrics_collections_unittest \ diff --git a/libwvdrmengine/include/WVCreatePluginFactories.h b/libwvdrmengine/include/WVCreatePluginFactories.h deleted file mode 100644 index ba3b4ed8..00000000 --- a/libwvdrmengine/include/WVCreatePluginFactories.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#ifndef WV_CREATE_PLUGIN_FACTORIES_H_ -#define WV_CREATE_PLUGIN_FACTORIES_H_ - -#include "media/drm/DrmAPI.h" -#include "media/hardware/CryptoAPI.h" - -extern "C" { - android::DrmFactory* createDrmFactory(); - android::CryptoFactory* createCryptoFactory(); -} - -#endif // WV_CREATE_PLUGIN_FACTORIES_H_ diff --git a/libwvdrmengine/include/WVCryptoFactory.h b/libwvdrmengine/include/WVCryptoFactory.h deleted file mode 100644 index 54c7402a..00000000 --- a/libwvdrmengine/include/WVCryptoFactory.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#ifndef WV_CRYPTO_FACTORY_H_ -#define WV_CRYPTO_FACTORY_H_ - -#include "media/hardware/CryptoAPI.h" -#include "media/stagefright/foundation/ABase.h" -#include "utils/Errors.h" - -namespace wvdrm { - -class WVCryptoFactory : public android::CryptoFactory { - public: - WVCryptoFactory() {} - virtual ~WVCryptoFactory() {} - - virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const; - - virtual android::status_t createPlugin(const uint8_t uuid[16], - const void* data, size_t size, - android::CryptoPlugin** plugin); - - private: - DISALLOW_EVIL_CONSTRUCTORS(WVCryptoFactory); -}; - -} // namespace wvdrm - -#endif // WV_CRYPTO_FACTORY_H_ diff --git a/libwvdrmengine/include/WVDrmFactory.h b/libwvdrmengine/include/WVDrmFactory.h deleted file mode 100644 index 1c6d0cf0..00000000 --- a/libwvdrmengine/include/WVDrmFactory.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#ifndef WV_DRM_FACTORY_H_ -#define WV_DRM_FACTORY_H_ - -#include "media/drm/DrmAPI.h" -#include "media/stagefright/foundation/ABase.h" -#include "utils/Errors.h" -#include "WVGenericCryptoInterface.h" - -namespace wvdrm { - -class WVDrmFactory : public android::DrmFactory { - public: - WVDrmFactory() {} - virtual ~WVDrmFactory() {} - - virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]); - - virtual bool isContentTypeSupported(const android::String8 &initDataType); - - virtual android::status_t createDrmPlugin(const uint8_t uuid[16], - android::DrmPlugin** plugin); - - private: - DISALLOW_EVIL_CONSTRUCTORS(WVDrmFactory); - - static WVGenericCryptoInterface sOemCryptoInterface; -}; - -} // namespace wvdrm - -#endif // WV_DRM_FACTORY_H_ diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h deleted file mode 100644 index f9ea0b98..00000000 --- a/libwvdrmengine/include/mapErrors-inl.h +++ /dev/null @@ -1,630 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#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) { - // Android return codes. - // This first group is for "android::OK". - 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; - // The remaining android::* are alphabetically ordered based on the first - // case condition in the group. - case wvcdm::ANALOG_OUTPUT_ERROR: - case wvcdm::INSUFFICIENT_OUTPUT_PROTECTION: - case wvcdm::KEY_PROHIBITED_FOR_SECURITY_LEVEL: - return android::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION; - case wvcdm::DECRYPT_ERROR: - case wvcdm::SECURE_BUFFER_REQUIRED: - return android::ERROR_DRM_CANNOT_HANDLE; - case wvcdm::DECRYPT_NOT_READY: - case wvcdm::KEY_NOT_FOUND_IN_SESSION: - case wvcdm::NEED_KEY: - case wvcdm::NO_MATCHING_ENTITLEMENT_KEY: - case wvcdm::NO_CONTENT_KEY_3: - return android::ERROR_DRM_NO_LICENSE; - case wvcdm::DEVICE_REVOKED: - return android::ERROR_DRM_DEVICE_REVOKED; - case wvcdm::INSUFFICIENT_CRYPTO_RESOURCES: - return android::ERROR_DRM_RESOURCE_BUSY; - case wvcdm::NEED_PROVISIONING: - return android::ERROR_DRM_NOT_PROVISIONED; - case wvcdm::RELEASE_USAGE_INFO_FAILED: - case wvcdm::RELEASE_USAGE_INFO_ERROR: - return android::ERROR_DRM_TAMPER_DETECTED; - case wvcdm::SESSION_NOT_FOUND_1: - case wvcdm::SESSION_NOT_FOUND_2: - case wvcdm::SESSION_NOT_FOUND_3: - case wvcdm::SESSION_NOT_FOUND_4: - case wvcdm::SESSION_NOT_FOUND_5: - case wvcdm::SESSION_NOT_FOUND_6: - case wvcdm::SESSION_NOT_FOUND_7: - case wvcdm::SESSION_NOT_FOUND_8: - case wvcdm::SESSION_NOT_FOUND_9: - case wvcdm::SESSION_NOT_FOUND_10: - case wvcdm::SESSION_NOT_FOUND_18: - case wvcdm::SESSION_NOT_FOUND_19: - case wvcdm::SESSION_NOT_FOUND_20: - case wvcdm::SESSION_NOT_FOUND_21: - case wvcdm::SESSION_NOT_FOUND_22: - case wvcdm::SESSION_NOT_FOUND_23: - case wvcdm::SESSION_NOT_FOUND_FOR_DECRYPT: - return android::ERROR_DRM_SESSION_NOT_OPENED; - case wvcdm::UNKNOWN_ERROR: - return android::ERROR_DRM_UNKNOWN; - // WV return codes. - // Alphabetically ordered based on the case condition. - case wvcdm::ADD_KEY_ERROR: - return kAddKeyError; - case wvcdm::CANNOT_DECRYPT_ZERO_SAMPLES: - return kCannotDecryptZeroSamples; - case wvcdm::CANNOT_DECRYPT_ZERO_SUBSAMPLES: - return kCannotDecryptZeroSubsamples; - case wvcdm::CENC_INIT_DATA_UNAVAILABLE: - return kCencInitDataUnavailable; - case wvcdm::CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE: - return kCertProvisioningEmptyServiceCertificate; - case wvcdm::CERT_PROVISIONING_GET_KEYBOX_ERROR_1: - return kCertProvisioningGetKeyboxError1; - case wvcdm::CERT_PROVISIONING_INVALID_CERT_TYPE: - return kCertProvisioningInvalidCertType; - case wvcdm::CERT_PROVISIONING_NONCE_GENERATION_ERROR: - return kCertProvisioningRequestNonceGenerationError; - case wvcdm::CERT_PROVISIONING_REQUEST_ERROR_1: - return kCertProvisioningRequestError1; - case wvcdm::CERT_PROVISIONING_REQUEST_ERROR_4: - return kCertProvisioningRequestError4; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_1: - return kCertProvisioningResponseError1; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_2: - return kCertProvisioningResponseError2; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_3: - return kCertProvisioningResponseError3; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_4: - return kCertProvisioningResponseError4; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_7: - return kCertProvisioningResponseError7; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_8: - return kCertProvisioningResponseError8; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_9: - return kCertProvisioningResponseError9; - case wvcdm::CERT_PROVISIONING_RESPONSE_ERROR_10: - return kCertProvisioningResponseError10; - case wvcdm::CLIENT_IDENTIFICATION_TOKEN_ERROR_1: - return kClientIdentificationTokenError1; - case wvcdm::CLIENT_ID_AES_ENCRYPT_ERROR: - return kClientIdAesEncryptError; - case wvcdm::CLIENT_ID_AES_INIT_ERROR: - return kClientIdAesInitError; - case wvcdm::CLIENT_ID_GENERATE_RANDOM_ERROR: - return kClientIdGenerateRandomError; - case wvcdm::CLIENT_ID_RSA_ENCRYPT_ERROR: - return kClientIdRsaEncryptError; - case wvcdm::CLIENT_ID_RSA_INIT_ERROR: - return kClientIdRsaInitError; - case wvcdm::CLIENT_TOKEN_NOT_SET: - return kClientTokenNotSet; - case wvcdm::COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR: - return kCopyOldUsageEntryUnknownError; - case wvcdm::CORE_MESSAGE_NOT_FOUND: - return kCoreMessageNotFound; - case wvcdm::CREATE_USAGE_ENTRY_UNKNOWN_ERROR: - return kCreateUsageEntryUnknownError; - case wvcdm::CREATE_USAGE_TABLE_ERROR: - return kCreateUsageTableError; - case wvcdm::DELETE_USAGE_ERROR_1: - return kDeleteUsageError1; - case wvcdm::DELETE_USAGE_ERROR_2: - return kDeleteUsageError2; - case wvcdm::DELETE_USAGE_ERROR_3: - return kDeleteUsageError3; - case wvcdm::DEVICE_CANNOT_REPROVISION: - return kDeviceCannotReprovision; - case wvcdm::DEVICE_CERTIFICATE_ERROR_1: - return kDeviceCertificateError1; - case wvcdm::DEVICE_CERTIFICATE_ERROR_2: - return kDeviceCertificateError2; - case wvcdm::DEVICE_CERTIFICATE_ERROR_3: - return kDeviceCertificateError3; - case wvcdm::DEVICE_CERTIFICATE_ERROR_4: - return kDeviceCertificateError4; - case wvcdm::DUPLICATE_SESSION_ID_SPECIFIED: - return kDuplicateSessionIdSpecified; - case wvcdm::EMPTY_KEYSET_ID: - return kEmptyKeySetId; - case wvcdm::EMPTY_KEYSET_ID_ENG_1: - return kEmptyKeySetIdEng1; - case wvcdm::EMPTY_KEYSET_ID_ENG_2: - return kEmptyKeySetIdEng2; - case wvcdm::EMPTY_KEYSET_ID_ENG_3: - return kEmptyKeySetIdEng3; - case wvcdm::EMPTY_KEYSET_ID_ENG_4: - return kEmptyKeySetIdEng4; - case wvcdm::EMPTY_KEYSET_ID_ENG_5: - return kEmptyKeySetIdEng5; - case wvcdm::EMPTY_KEY_DATA_1: - return kEmptyKeyData1; - case wvcdm::EMPTY_KEY_DATA_2: - return kEmptyKeyData2; - case wvcdm::EMPTY_LICENSE_RENEWAL: - return kEmptyLicenseRenewal; - case wvcdm::EMPTY_LICENSE_REQUEST: - return kEmptyLicenseRequest; - case wvcdm::EMPTY_LICENSE_REQUEST_2: - return kEmptyLicenseRequest2; - case wvcdm::EMPTY_LICENSE_REQUEST_3: - return kEmptyLicenseRequest3; - case wvcdm::EMPTY_LICENSE_RESPONSE_1: - return kEmptyLicenseResponse1; - case wvcdm::EMPTY_LICENSE_RESPONSE_2: - return kEmptyLicenseResponse2; - case wvcdm::EMPTY_LICENSE_RESPONSE_3: - return kEmptyLicenseResponse3; - case wvcdm::EMPTY_LICENSE_RESPONSE_4: - return kEmptyLicenseResponse4; - case wvcdm::EMPTY_PROVISIONING_CERTIFICATE_1: - return kEmptyProvisioningCertificate1; - case wvcdm::EMPTY_PROVISIONING_CERTIFICATE_2: - return kEmptyProvisioningCertificate2; - case wvcdm::EMPTY_PROVISIONING_RESPONSE: - return kEmptyProvisioningResponse; - case wvcdm::EMPTY_RESPONSE_ERROR_1: - return kEmptyResponseError1; - case wvcdm::EMPTY_SESSION_ID: - return kEmptySessionId; - case wvcdm::GENERATE_DERIVED_KEYS_ERROR: - return kGenerateDerivedKeysError; - case wvcdm::GENERATE_USAGE_REPORT_ERROR: - return kGenerateUsageReportError; - case wvcdm::GET_DECRYPT_HASH_ERROR: - return kGetDecryptHashError; - case wvcdm::GET_LICENSE_ERROR: - case wvcdm::KEYSET_ID_NOT_FOUND_4: - // There is a sub-error code that distinguishes the two. - return kGetLicenseError; - case wvcdm::GET_PROVISIONING_METHOD_ERROR: - return kGetProvisioningError; - case wvcdm::GET_RELEASED_LICENSE_ERROR: - return kGetReleasedLicenseError; - case wvcdm::GET_USAGE_INFO_ERROR_1: - return kGetUsageInfoError1; - case wvcdm::GET_USAGE_INFO_ERROR_2: - return kGetUsageInfoError2; - case wvcdm::GET_USAGE_INFO_ERROR_3: - return kGetUsageInfoError3; - case wvcdm::GET_USAGE_INFO_ERROR_4: - return kGetUsageInfoError4; - case wvcdm::INCORRECT_CRYPTO_MODE: - return kIncorrectCryptoMode; - case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_1: - return kIncorrectUsageSupportType1; - case wvcdm::INCORRECT_USAGE_SUPPORT_TYPE_2: - return kIncorrectUsageSupportType2; - case wvcdm::INIT_DATA_NOT_FOUND: - return kInitDataNotFound; - case wvcdm::INVALID_DECRYPT_HASH_FORMAT: - return kInvalidDecryptHashFormat; - case wvcdm::INVALID_DECRYPT_PARAMETERS_ENG_1: - return kInvalidDecryptParametersEng1; - case wvcdm::INVALID_DECRYPT_PARAMETERS_ENG_2: - return kInvalidDecryptParametersEng2; - case wvcdm::INVALID_DECRYPT_PARAMETERS_ENG_3: - return kInvalidDecryptParametersEng3; - case wvcdm::INVALID_DECRYPT_PARAMETERS_ENG_4: - return kInvalidDecryptParametersEng4; - case wvcdm::INVALID_DEVICE_CERTIFICATE_TYPE: - return kInvalidDeviceCertificateType; - case wvcdm::INVALID_IV_SIZE: - return kInvalidIvSize; - case wvcdm::INVALID_KEY_SYSTEM: - return kInvalidKeySystem; - case wvcdm::INVALID_LICENSE_REQUEST_TYPE_1: - return kInvalidLicenseRequestType1; - case wvcdm::INVALID_LICENSE_REQUEST_TYPE_2: - return kInvalidLicenseRequestType2; - case wvcdm::INVALID_LICENSE_RESPONSE: - return kInvalidLicenseResponse; - case wvcdm::INVALID_LICENSE_TYPE: - return kInvalidLicenseType; - case wvcdm::INVALID_LICENSE_TYPE_2: - return kInvalidLicenseType2; - case wvcdm::INVALID_PARAMETERS_ENG_5: - return kInvalidParametersEng5; - case wvcdm::INVALID_PARAMETERS_ENG_13: - return kInvalidParametersEng13; - case wvcdm::INVALID_PARAMETERS_ENG_14: - return kInvalidParametersEng14; - case wvcdm::INVALID_PARAMETERS_ENG_15: - return kInvalidParametersEng15; - case wvcdm::INVALID_PARAMETERS_ENG_16: - return kInvalidParametersEng16; - case wvcdm::INVALID_PARAMETERS_ENG_22: - return kInvalidParametersEng22; - case wvcdm::INVALID_PARAMETERS_ENG_23: - return kInvalidParametersEng23; - case wvcdm::INVALID_PARAMETERS_ENG_24: - return kInvalidParametersEng24; - case wvcdm::INVALID_PARAMETERS_LIC_1: - return kInvalidParametersLic1; - case wvcdm::INVALID_PARAMETERS_LIC_2: - return kInvalidParametersLic2; - case wvcdm::INVALID_PARAMETERS_LIC_3: - return kInvalidParametersLic3; - case wvcdm::INVALID_PARAMETERS_LIC_4: - return kInvalidParametersLic4; - case wvcdm::INVALID_PARAMETERS_LIC_6: - return kInvalidParametersLic6; - case wvcdm::INVALID_PARAMETERS_LIC_7: - return kInvalidParametersLic7; - case wvcdm::INVALID_PROVISIONING_PARAMETERS_1: - return kInvalidProvisioningParam1; - case wvcdm::INVALID_PROVISIONING_PARAMETERS_2: - return kInvalidProvisioningParam2; - case wvcdm::INVALID_PROVISIONING_REQUEST_PARAM_1: - return kInvalidProvisioningReqParam1; - case wvcdm::INVALID_PROVISIONING_REQUEST_PARAM_2: - return kInvalidProvisioningReqParam2; - case wvcdm::INVALID_QUERY_KEY: - return kInvalidQueryKey; - case wvcdm::INVALID_SESSION_1: - return kInvalidSession1; - case wvcdm::INVALID_SESSION_2: - return kInvalidSession2; - case wvcdm::INVALID_SESSION_ID: - return kInvalidSessionId; - case wvcdm::INVALID_USAGE_ENTRY_NUMBER_MODIFICATION: - return kInvalidUsageEntryNumberModification; - case wvcdm::KEYSET_ID_NOT_FOUND_1: - return kKeySetIdNotFound1; - case wvcdm::KEYSET_ID_NOT_FOUND_2: - return kKeySetIdNotFound2; - case wvcdm::KEYSET_ID_NOT_FOUND_3: - return kKeySetIdNotFound3; - case wvcdm::KEY_CONFLICT_1: - return kKeyConflict1; - 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::KEY_NOT_FOUND_1: - return kKeyNotFound1; - case wvcdm::KEY_NOT_FOUND_2: - return kKeyNotFound2; - case wvcdm::KEY_NOT_FOUND_3: - return kKeyNotFound3; - case wvcdm::KEY_NOT_FOUND_4: - return kKeyNotFound4; - case wvcdm::KEY_NOT_FOUND_5: - return kKeyNotFound5; - case wvcdm::KEY_NOT_FOUND_6: - return kKeyNotFound6; - case wvcdm::KEY_REQUEST_ERROR_1: - return kKeyRequestError1; - case wvcdm::KEY_SIZE_ERROR_1: - return kKeySizeError1; - case wvcdm::KEY_SIZE_ERROR_2: - return kKeySizeError2; - case wvcdm::LICENSE_ID_NOT_FOUND: - return kLicenseIdNotFound; - case wvcdm::LICENSE_PARSER_INIT_ERROR: - return kLicenseParserInitError; - case wvcdm::LICENSE_PARSER_NOT_INITIALIZED_1: - return kLicenseParserNotInitialized1; - case wvcdm::LICENSE_PARSER_NOT_INITIALIZED_2: - return kLicenseParserNotInitialized2; - case wvcdm::LICENSE_PARSER_NOT_INITIALIZED_3: - return kLicenseParserNotInitialized3; - case wvcdm::LICENSE_PARSER_NOT_INITIALIZED_4: - return kLicenseParserNotInitialized4; - case wvcdm::LICENSE_RENEWAL_NONCE_GENERATION_ERROR: - return kLicenseRenewalNonceGenerationError; - case wvcdm::LICENSE_RENEWAL_PROHIBITED: - return kLicenseRenewalProhibited; - case wvcdm::LICENSE_REQUEST_NONCE_GENERATION_ERROR: - return kLicenseRequestNonceGenerationError; - case wvcdm::LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR: - return kLicenseRequestServiceCertificateGenerationError; - case wvcdm::LICENSE_RESPONSE_NOT_SIGNED: - return kLicenseResponseNotSigned; - case wvcdm::LICENSE_RESPONSE_PARSE_ERROR_1: - return kLicenseResponseParseError1; - case wvcdm::LICENSE_RESPONSE_PARSE_ERROR_2: - return kLicenseResponseParseError2; - case wvcdm::LICENSE_RESPONSE_PARSE_ERROR_3: - return kLicenseResponseParseError3; - case wvcdm::LICENSE_RESPONSE_PARSE_ERROR_4: - return kLicenseResponseParseError4; - case wvcdm::LICENSE_RESPONSE_PARSE_ERROR_5: - return kLicenseResponseParseError5; - case wvcdm::LICENSE_USAGE_ENTRY_MISSING: - return kLicenseUsageEntryMissing; - case wvcdm::LIST_LICENSE_ERROR_1: - return kListLicenseError1; - case wvcdm::LIST_LICENSE_ERROR_2: - return kListLicenseError2; - case wvcdm::LIST_USAGE_ERROR_1: - return kListUsageError1; - case wvcdm::LIST_USAGE_ERROR_2: - return kListUsageError2; - case wvcdm::LOAD_ENTITLED_CONTENT_KEYS_ERROR: - return kLoadEntitledContentKeysError; - case wvcdm::LOAD_KEY_ERROR: - return kLoadKeyError; - case wvcdm::LOAD_LICENSE_ERROR: - return kLoadLicenseError; - case wvcdm::LOAD_PROVISIONING_ERROR: - return kLoadProvisioningError; - case wvcdm::LOAD_RENEWAL_ERROR: - return kLoadRenewalError; - case wvcdm::LOAD_SYSTEM_ID_ERROR: - return kLoadSystemIdError; - case wvcdm::LOAD_USAGE_ENTRY_GENERATION_SKEW: - return kLoadUsageEntryGenerationSkew; - case wvcdm::LOAD_USAGE_ENTRY_INVALID_SESSION: - return kLoadUsageEntryInvalidSession; - case wvcdm::LOAD_USAGE_ENTRY_SIGNATURE_FAILURE: - return kLoadUsageEntrySignatureFailure; - case wvcdm::LOAD_USAGE_ENTRY_UNKNOWN_ERROR: - return kLoadUsageEntryUnknownError; - case wvcdm::LOAD_USAGE_HEADER_BAD_MAGIC: - return kLoadUsageHeaderBadMagic; - case wvcdm::LOAD_USAGE_HEADER_GENERATION_SKEW: - return kLoadUsageHeaderGenerationSkew; - case wvcdm::LOAD_USAGE_HEADER_SIGNATURE_FAILURE: - return kLoadUsageHeaderSignatureFailure; - case wvcdm::LOAD_USAGE_HEADER_UNKNOWN_ERROR: - return kLoadUsageHeaderUnknownError; - case wvcdm::LOAD_USAGE_INFO_FILE_ERROR: - return kLoadUsageInfoFileError; - case wvcdm::LOAD_USAGE_INFO_MISSING: - return kLoadUsageInfoMissing; - case wvcdm::MOVE_USAGE_ENTRY_DESTINATION_IN_USE: - return kMoveUsageEntryDestinationInUse; - case wvcdm::MOVE_USAGE_ENTRY_UNKNOWN_ERROR: - return kMoveUsageEntryUnknownError; - case wvcdm::NOT_AN_ENTITLEMENT_SESSION: - return kNotAnEntitlementSession; - case wvcdm::NOT_INITIALIZED_ERROR: - return kNotInitializedError; - case wvcdm::NO_CONTENT_KEY: - return kNoContentKey; - case wvcdm::NO_CONTENT_KEY_2: - return kNoContentKey2; - case wvcdm::NO_DEVICE_KEY_1: - return kNoDeviceKey1; - case wvcdm::NO_SRM_VERSION: - return kNoSrmVersion; - case wvcdm::NO_USAGE_ENTRIES: - return kNoUsageEntries; - case wvcdm::OFFLINE_LICENSE_PROHIBITED: - return kOfflineLicenseProhibited; - case wvcdm::OKP_ALREADY_PROVISIONED: - return kOkpAlreadyProvisioned; - case wvcdm::PARAMETER_NULL: - return kParameterNull; - case wvcdm::PARSE_OKP_RESPONSE_ERROR: - return kParseOkpResponseError; - case wvcdm::PARSE_REQUEST_ERROR_1: - return kParseRequestError1; - case wvcdm::PARSE_REQUEST_ERROR_2: - return kParseRequestError2; - case wvcdm::PARSE_RESPONSE_ERROR_1: - return kParseResponseError1; - case wvcdm::PARSE_RESPONSE_ERROR_2: - return kParseResponseError2; - case wvcdm::PARSE_RESPONSE_ERROR_3: - return kParseResponseError3; - case wvcdm::PARSE_RESPONSE_ERROR_4: - return kParseResponseError4; - case wvcdm::PARSE_SERVICE_CERTIFICATE_ERROR: - return kParseServiceCertificateError; - case wvcdm::PREPARE_CENC_CONTENT_ID_FAILED: - return kPrepareCencContentIdFailed; - case wvcdm::PREPARE_WEBM_CONTENT_ID_FAILED: - return kPrepareWebmContentIdFailed; - case wvcdm::PRIVACY_MODE_ERROR_1: - return kPrivacyModeError1; - case wvcdm::PRIVACY_MODE_ERROR_2: - return kPrivacyModeError2; - case wvcdm::PRIVACY_MODE_ERROR_3: - return kPrivacyModeError3; - case wvcdm::PROVISIONING_NOT_ALLOWED_FOR_ATSC: - return kProvisioningNotAllowedForAtsc; - case wvcdm::REFRESH_KEYS_ERROR: - return kRefreshKeysError; - case wvcdm::REINIT_ERROR: - return kReinitError; - case wvcdm::RELEASE_KEY_ERROR: - return kReleaseKeyError; - case wvcdm::RELEASE_KEY_REQUEST_ERROR: - return kReleaseKeyRequestError; - case wvcdm::RELEASE_LICENSE_ERROR_1: - return kReleaseLicenseError1; - case wvcdm::RELEASE_LICENSE_ERROR_2: - return kReleaseLicenseError2; - case wvcdm::REMOVE_ALL_USAGE_INFO_ERROR_1: - return kRemoveAllUsageInfoError1; - case wvcdm::REMOVE_ALL_USAGE_INFO_ERROR_2: - return kRemoveAllUsageInfoError2; - case wvcdm::REMOVE_ALL_USAGE_INFO_ERROR_5: - return kRemoveAllUsageInfoError5; - case wvcdm::REMOVE_ALL_USAGE_INFO_ERROR_6: - return kRemoveAllUsageInfoError6; - case wvcdm::REMOVE_ALL_USAGE_INFO_ERROR_7: - return kRemoveAllUsageInfoError7; - case wvcdm::REMOVE_USAGE_INFO_ERROR_1: - return kRemoveUsageInfoError1; - case wvcdm::REMOVE_USAGE_INFO_ERROR_2: - return kRemoveUsageInfoError2; - case wvcdm::REMOVE_USAGE_INFO_ERROR_3: - return kRemoveUsageInfoError3; - case wvcdm::RENEW_KEY_ERROR_1: - return kRenewKeyError1; - case wvcdm::RENEW_KEY_ERROR_2: - return kRenewKeyError2; - case wvcdm::RESTORE_OFFLINE_LICENSE_ERROR_2: - return kRestoreOfflineLicenseError2; - case wvcdm::RESTORE_OFFLINE_LICENSE_ERROR_3: - return kRestoreOfflineLicenseError3; - case wvcdm::SAMPLE_AND_SUBSAMPLE_SIZE_MISMATCH: - return kSampleAndSubsampleSizeMismatch; - case wvcdm::SESSION_FILE_HANDLE_INIT_ERROR: - return kSessionFileHandleInitError; - case wvcdm::SESSION_KEYS_NOT_FOUND: - return kSessionKeysNotFound; - case wvcdm::SESSION_KEYS_NOT_FOUND_2: - return kSessionKeysNotFound2; - case wvcdm::SESSION_NOT_FOUND_11: - return kSessionNotFound11; - case wvcdm::SESSION_NOT_FOUND_12: - return kSessionNotFound12; - case wvcdm::SESSION_NOT_FOUND_13: - return kSessionNotFound13; - case wvcdm::SESSION_NOT_FOUND_14: - return kSessionNotFound14; - case wvcdm::SESSION_NOT_FOUND_15: - return kSessionNotFound15; - case wvcdm::SESSION_NOT_FOUND_16: - return kSessionNotFound16; - case wvcdm::SET_DECRYPT_HASH_ERROR: - return kSetDecryptHashError; - case wvcdm::SHRINK_USAGE_TABLE_HEADER_ENTRY_IN_USE: - return kShrinkUsageTableHeaderEntryInUse; - case wvcdm::SHRINK_USAGE_TABLE_HEADER_UNKNOWN_ERROR: - return kShrinkUsageTableHeaderUnknownError; - case wvcdm::SIGNATURE_NOT_FOUND: - return kSignatureNotFound; - case wvcdm::SIGNATURE_NOT_FOUND_2: - return kSignatureNotFound2; - case wvcdm::STORAGE_PROHIBITED: - return kStorageProhibited; - case wvcdm::STORE_LICENSE_ERROR_1: - return kStoreLicenseError1; - case wvcdm::STORE_LICENSE_ERROR_2: - return kStoreLicenseError2; - case wvcdm::STORE_USAGE_INFO_ERROR: - return kStoreUsageInfoError; - case wvcdm::UNEXPECTED_EMPTY_USAGE_ENTRY: - return kUnexpectedEmptyUsageEntry; - case wvcdm::UNKNOWN_SELECT_KEY_ERROR_1: - return kUnknownSelectKeyError1; - case wvcdm::UNKNOWN_SELECT_KEY_ERROR_2: - return kUnknownSelectKeyError2; - case wvcdm::UNPROVISION_ERROR_1: - return kUnprovisioningError1; - case wvcdm::UNPROVISION_ERROR_2: - return kUnprovisioningError2; - case wvcdm::UNPROVISION_ERROR_3: - return kUnprovisioningError3; - case wvcdm::UNPROVISION_ERROR_4: - return kUnprovisioningError4; - case wvcdm::UNSUPPORTED_INIT_DATA: - return kUnsupportedInitData; - case wvcdm::UNSUPPORTED_INIT_DATA_FORMAT: - return kUnsupportedInitDataFormat; - case wvcdm::UPDATE_USAGE_ENTRY_UNKNOWN_ERROR: - return kUpdateUsageEntryUnknownError; - case wvcdm::USAGE_ENTRY_NUMBER_MISMATCH: - return kUsageEntryNumberMismatch; - case wvcdm::USAGE_ENTRY_ALREADY_LOADED: - return kUsageEntryAlreadyLoaded; - case wvcdm::USAGE_GET_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE: - return kUsageGetEntryRetrieveInvalidStorageType; - case wvcdm::USAGE_GET_ENTRY_RETRIEVE_LICENSE_FAILED: - return kUsageGetEntryRetrieveLicenseFailed; - case wvcdm::USAGE_GET_ENTRY_RETRIEVE_USAGE_INFO_FAILED: - return kUsageGetEntryRetrieveUsageInfoFailed; - case wvcdm::USAGE_INFORMATION_SUPPORT_FAILED: - return kUsageInformationSupportFailed; - case wvcdm::USAGE_INFO_NOT_FOUND: - return kUsageInfoNotFound; - case wvcdm::USAGE_INVALID_LOAD_ENTRY: - return kUsageInvalidLoadEntry; - case wvcdm::USAGE_INVALID_NEW_ENTRY: - return kUsageInvalidNewEntry; - case wvcdm::USAGE_INVALID_PARAMETERS_1: - return kUsageInvalidParameters1; - case wvcdm::USAGE_INVALID_PARAMETERS_2: - return kUsageInvalidParameters2; - case wvcdm::USAGE_STORE_ENTRY_RETRIEVE_INVALID_STORAGE_TYPE: - return kUsageStoreEntryRetrieveInvalidStorageType; - case wvcdm::USAGE_STORE_ENTRY_RETRIEVE_LICENSE_FAILED: - return kUsageStoreEntryRetrieveLicenseFailed; - case wvcdm::USAGE_STORE_ENTRY_RETRIEVE_USAGE_INFO_FAILED: - return kUsageStoreEntryRetrieveUsageInfoFailed; - case wvcdm::USAGE_STORE_LICENSE_FAILED: - return kUsageStoreLicenseFailed; - case wvcdm::USAGE_STORE_USAGE_INFO_FAILED: - return kUsageStoreUsageInfoFailed; - case wvcdm::USAGE_SUPPORT_GET_API_FAILED: - return kUsageSupportGetApiFailed; - case wvcdm::WEBM_INIT_DATA_UNAVAILABLE: - return kWebmInitDataUnavailable; - - // This error is only returned in API 29 by the hidl service. - // It should never be used in the legacy plugin. - // It is mapped here to clear the compiler warning. - case wvcdm::GET_OFFLINE_LICENSE_STATE_ERROR_1: - case wvcdm::GET_OFFLINE_LICENSE_STATE_ERROR_2: - case wvcdm::REMOVE_OFFLINE_LICENSE_ERROR_1: - case wvcdm::REMOVE_OFFLINE_LICENSE_ERROR_2: - case wvcdm::OUTPUT_TOO_LARGE_ERROR: - case wvcdm::SESSION_LOST_STATE_ERROR: - case wvcdm::GENERATE_DERIVED_KEYS_ERROR_2: - case wvcdm::LOAD_DEVICE_RSA_KEY_ERROR: - case wvcdm::NONCE_GENERATION_ERROR: - case wvcdm::GENERATE_SIGNATURE_ERROR: - case wvcdm::UNKNOWN_CLIENT_TOKEN_TYPE: - case wvcdm::DEACTIVATE_USAGE_ENTRY_ERROR: - case wvcdm::SYSTEM_INVALIDATED_ERROR: - case wvcdm::OPEN_CRYPTO_SESSION_ERROR: - case wvcdm::LOAD_SRM_ERROR: - case wvcdm::RANDOM_GENERATION_ERROR: - case wvcdm::CRYPTO_SESSION_NOT_INITIALIZED: - case wvcdm::GET_DEVICE_ID_ERROR: - case wvcdm::GET_TOKEN_FROM_OEM_CERT_ERROR: - case wvcdm::CRYPTO_SESSION_NOT_OPEN: - case wvcdm::GET_TOKEN_FROM_KEYBOX_ERROR: - case wvcdm::KEYBOX_TOKEN_TOO_SHORT: - case wvcdm::EXTRACT_SYSTEM_ID_FROM_OEM_CERT_ERROR: - case wvcdm::RSA_SIGNATURE_GENERATION_ERROR: - case wvcdm::GET_HDCP_CAPABILITY_FAILED: - case wvcdm::GET_NUMBER_OF_OPEN_SESSIONS_ERROR: - case wvcdm::GET_MAX_NUMBER_OF_OPEN_SESSIONS_ERROR: - case wvcdm::NOT_IMPLEMENTED_ERROR: - case wvcdm::GET_SRM_VERSION_ERROR: - case wvcdm::REWRAP_DEVICE_RSA_KEY_ERROR: - case wvcdm::SERVICE_CERTIFICATE_PROVIDER_ID_EMPTY: - case wvcdm::INVALID_SRM_LIST: - 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.bp b/libwvdrmengine/mediacrypto/Android.bp index 02821504..d5744495 100644 --- a/libwvdrmengine/mediacrypto/Android.bp +++ b/libwvdrmengine/mediacrypto/Android.bp @@ -11,56 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - -// ---------------------------------------------------------------------------- -// Builds libwvdrmcryptoplugin -// -// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE -// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE -// DEPENDING ON IT IN YOUR PROJECT. *** -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "vendor_widevine_license" - // to get the below license kinds: - // legacy_by_exception_only (by exception only) - default_applicable_licenses: ["vendor_widevine_license"], -} - -cc_library_static { - name: "libwvdrmcryptoplugin", - - srcs: ["src/WVCryptoPlugin.cpp"], - - include_dirs: [ - "frameworks/av/include", - "frameworks/native/include", - "vendor/widevine/libwvdrmengine/cdm/core/include", - "vendor/widevine/libwvdrmengine/cdm/include", - "vendor/widevine/libwvdrmengine/cdm/metrics/include", - "vendor/widevine/libwvdrmengine/cdm/util/include", - "vendor/widevine/libwvdrmengine/include", - "vendor/widevine/libwvdrmengine/mediacrypto/include", - "vendor/widevine/libwvdrmengine/oemcrypto/include", - ], - - header_libs: [ - "libstagefright_headers", - "libstagefright_foundation_headers", - "libutils_headers", - ], - - static_libs: ["libcdm_protos"], - - shared_libs: [ - "libcrypto", - "liblog", - ], - - proprietary: true, - -} - // ----------------------------------------------------------------------------- // Builds libwvdrmcryptoplugin_hidl // @@ -76,10 +26,9 @@ cc_library_static { "vendor/widevine/libwvdrmengine/cdm/include", "vendor/widevine/libwvdrmengine/cdm/metrics/include", "vendor/widevine/libwvdrmengine/cdm/util/include", - "vendor/widevine/libwvdrmengine/include_hidl", + "vendor/widevine/libwvdrmengine/include_hidl", "vendor/widevine/libwvdrmengine/include", "vendor/widevine/libwvdrmengine/mediacrypto/include_hidl", - "vendor/widevine/libwvdrmengine/mediacrypto/include", "vendor/widevine/libwvdrmengine/oemcrypto/include", ], diff --git a/libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h b/libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h deleted file mode 100644 index faf4cd5a..00000000 --- a/libwvdrmengine/mediacrypto/include/WVCryptoPlugin.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#ifndef WV_CRYPTO_PLUGIN_H_ -#define WV_CRYPTO_PLUGIN_H_ - -#include - -#include "utils/StrongPointer.h" -#include "utils/Vector.h" - -#include "media/hardware/CryptoAPI.h" -#include "media/stagefright/foundation/ABase.h" -#include "media/stagefright/foundation/AString.h" -#include "wv_content_decryption_module.h" - -namespace wvdrm { - -class WVCryptoPlugin : public android::CryptoPlugin { - public: - WVCryptoPlugin(const void* data, size_t size, - const android::sp& cdm); - virtual ~WVCryptoPlugin() {} - - virtual bool requiresSecureDecoderComponent(const char* mime) const; - - virtual void notifyResolution(uint32_t width, uint32_t height); - - virtual android::status_t setMediaDrmSession( - const android::Vector& sessionId); - - virtual ssize_t decrypt(bool secure, const uint8_t key[16], - const uint8_t iv[16], Mode mode, const Pattern &pattern, - const void* srcPtr, - const SubSample* subSamples, size_t numSubSamples, - void* dstPtr, android::AString* errorDetailMsg); - - private: - DISALLOW_EVIL_CONSTRUCTORS(WVCryptoPlugin); - - android::sp const mCDM; - - bool mTestMode; - wvcdm::CdmSessionId mSessionId; - - wvcdm::CdmSessionId configureTestMode(const void* data, size_t size); - android::status_t attemptDecrypt( - const wvcdm::CdmDecryptionParametersV16& params, - bool haveEncryptedSubsamples, android::AString* errorDetailMsg); -}; - -} // namespace wvdrm - -#endif // WV_CRYPTO_PLUGIN_H_ diff --git a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp b/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp deleted file mode 100644 index add3e5be..00000000 --- a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp +++ /dev/null @@ -1,261 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WVCdm" -#include - -#include "WVCryptoPlugin.h" - -#include -#include -#include -#include -#include -#include - -#include "mapErrors-inl.h" -#include "media/stagefright/MediaErrors.h" -#include "OEMCryptoCENC.h" -#include "openssl/sha.h" -#include "utils/Errors.h" -#include "utils/String8.h" -#include "wv_cdm_constants.h" -#include "WVErrors.h" - -namespace wvdrm { - -using namespace android; -using namespace std; -using namespace wvcdm; - -WVCryptoPlugin::WVCryptoPlugin(const void* data, size_t size, - const sp& cdm) - : mCDM(cdm), - mTestMode(false), - mSessionId(configureTestMode(data, size)) {} - -CdmSessionId WVCryptoPlugin::configureTestMode(const void* data, size_t size) { - CdmSessionId sessionId; - if (data != NULL) { - sessionId.assign(static_cast(data), size); - size_t index = sessionId.find("test_mode"); - if (index != string::npos) { - sessionId = sessionId.substr(0, index); - mTestMode = true; - } - } - if (!mCDM->IsOpenSession(sessionId)) { - sessionId.clear(); - } - 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. - CdmQueryMap status; - - CdmResponseType res = mCDM->QuerySessionStatus(mSessionId, &status); - - if (!isCdmResponseTypeSuccess(res)) { - ALOGE("Error querying CDM status: %u", res); - return false; - } - - return status[QUERY_KEY_SECURITY_LEVEL] == QUERY_VALUE_SECURITY_LEVEL_L1; - } else { - // Type is not video, so never require a secure decoder. - return false; - } -} - -void WVCryptoPlugin::notifyResolution(uint32_t width, uint32_t height) { - mCDM->NotifyResolution(mSessionId, width, height); -} - -status_t WVCryptoPlugin::setMediaDrmSession(const Vector& sessionId) { - CdmSessionId cdmSessionId(reinterpret_cast(sessionId.array()), - sessionId.size()); - if (sessionId.size() == 0) { - return android::BAD_VALUE; - } - if (!mCDM->IsOpenSession(cdmSessionId)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } else { - mSessionId = cdmSessionId; - return android::NO_ERROR; - } -} - -// Returns negative values for error code and positive values for the size of -// decrypted data. In theory, the output size can be larger than the input -// size, but in practice this should never happen for AES-CTR. -ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], - const uint8_t iv[KEY_IV_SIZE], Mode mode, - const Pattern& pattern, const void* srcPtr, - const SubSample* subSamples, - size_t numSubSamples, void* dstPtr, - AString* errorDetailMsg) { - if (mode != kMode_Unencrypted && - mode != kMode_AES_CTR && - mode != kMode_AES_CBC) { - errorDetailMsg->setTo( - "The requested encryption mode is not supported by Widevine CDM."); - return kErrorUnsupportedCrypto; - } else if (mode == kMode_AES_CTR && - (pattern.mEncryptBlocks != 0 || pattern.mSkipBlocks != 0)) { - errorDetailMsg->setTo( - "The 'cens' schema is not supported by Widevine CDM."); - return kErrorUnsupportedCrypto; - } - - // Convert parameters to the form the CDM wishes to consume them in. - const KeyId keyId(reinterpret_cast(key), KEY_ID_SIZE); - vector ivVector(iv, iv + KEY_IV_SIZE); - const uint8_t* const source = static_cast(srcPtr); - uint8_t* const dest = static_cast(dstPtr); - - // Set up the decrypt params - CdmDecryptionParametersV16 params; - params.key_id = keyId; - params.is_secure = secure; - if (mode == kMode_AES_CTR) { - params.cipher_mode = kCipherModeCtr; - } else if (mode == kMode_AES_CBC) { - params.cipher_mode = kCipherModeCbc; - } - params.pattern.encrypt_blocks = pattern.mEncryptBlocks; - params.pattern.skip_blocks = pattern.mSkipBlocks; - - // Set up the sample - // Android's API only supports one at a time - params.samples.emplace_back(); - CdmDecryptionSample& sample = params.samples.back(); - sample.encrypt_buffer = source; - sample.decrypt_buffer = dest; - sample.decrypt_buffer_offset = 0; - sample.iv = ivVector; - - // Set up the subsamples - // We abuse std::transform() here to also do some side-effects: Tallying the - // total size of the sample and checking if any of the data is protected. - size_t totalSize = 0; - bool hasProtectedData = false; - sample.subsamples.reserve(numSubSamples); - std::transform(subSamples, subSamples + numSubSamples, - std::back_inserter(sample.subsamples), - [&](const SubSample& subSample) -> CdmDecryptionSubsample { - totalSize += - subSample.mNumBytesOfClearData + subSample.mNumBytesOfEncryptedData; - hasProtectedData |= subSample.mNumBytesOfEncryptedData > 0; - return CdmDecryptionSubsample(subSample.mNumBytesOfClearData, - subSample.mNumBytesOfEncryptedData); - }); - - sample.encrypt_buffer_length = totalSize; - sample.decrypt_buffer_size = totalSize; - - if (mode == kMode_Unencrypted && hasProtectedData) { - errorDetailMsg->setTo("Protected ranges found in allegedly clear data."); - return kErrorExpectedUnencrypted; - } - - // Decrypt - status_t res = attemptDecrypt(params, hasProtectedData, errorDetailMsg); - if (res != android::OK) { - return res; - } - - // In test mode, we return an error that causes a detailed error - // message string containing a SHA256 hash of the decrypted data - // to get passed to the java app via CryptoException. The test app - // can then use the hash to verify that decryption was successful. - - if (mTestMode) { - if (secure) { - // can't access data in secure mode - errorDetailMsg->setTo("secure"); - } else { - SHA256_CTX ctx; - uint8_t digest[SHA256_DIGEST_LENGTH]; - SHA256_Init(&ctx); - SHA256_Update(&ctx, dstPtr, totalSize); - SHA256_Final(digest, &ctx); - String8 buf; - for (size_t i = 0; i < sizeof(digest); i++) { - buf.appendFormat("%02x", digest[i]); - } - errorDetailMsg->setTo(buf.string()); - } - - return kErrorTestMode; - } - - return static_cast(totalSize); -} - -status_t WVCryptoPlugin::attemptDecrypt( - const CdmDecryptionParametersV16& params, bool hasProtectedData, - AString* errorDetailMsg) { - CdmResponseType res = mCDM->DecryptV16(mSessionId, hasProtectedData, - params); - - if (isCdmResponseTypeSuccess(res)) { - return android::OK; - } else { - ALOGE("Decrypt error in session %s during a sample %s protected data: %d", - mSessionId.c_str(), - hasProtectedData ? "with" : "without", - res); - bool actionableError = true; - switch (res) { - case wvcdm::INSUFFICIENT_CRYPTO_RESOURCES: - errorDetailMsg->setTo( - "Error decrypting data: insufficient crypto resources"); - break; - case wvcdm::NEED_KEY: - case wvcdm::KEY_NOT_FOUND_IN_SESSION: - errorDetailMsg->setTo( - "Error decrypting data: requested key has not been loaded"); - break; - case wvcdm::DECRYPT_NOT_READY: - errorDetailMsg->setTo( - "Error decrypting data: license validity period is in the future"); - break; - case wvcdm::SESSION_NOT_FOUND_FOR_DECRYPT: - errorDetailMsg->setTo( - "Error decrypting data: session not found, possibly reclaimed"); - break; - case wvcdm::DECRYPT_ERROR: - errorDetailMsg->setTo( - "Error decrypting data: unspecified error"); - break; - case wvcdm::INSUFFICIENT_OUTPUT_PROTECTION: - case wvcdm::ANALOG_OUTPUT_ERROR: - errorDetailMsg->setTo( - "Error decrypting data: insufficient output protection"); - break; - case wvcdm::KEY_PROHIBITED_FOR_SECURITY_LEVEL: - errorDetailMsg->setTo( - "Error decrypting data: key prohibited for security level"); - break; - default: - actionableError = false; - break; - } - - if (actionableError) { - // This error is actionable by the app and should be passed up. - return mapCdmResponseType(res); - } else { - // Swallow the specifics of other errors to obscure decrypt internals. - return kErrorCDMGeneric; - } - } -} - -} // namespace wvdrm diff --git a/libwvdrmengine/mediacrypto/test/Android.mk b/libwvdrmengine/mediacrypto/test/Android.mk index 91169e8a..979fe75b 100644 --- a/libwvdrmengine/mediacrypto/test/Android.mk +++ b/libwvdrmengine/mediacrypto/test/Android.mk @@ -1,67 +1,4 @@ LOCAL_PATH := $(call my-dir) - -# ----------------------------------------------------------------------------- -# Builds libwvdrmmediacrypto_test -# -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - legacy_src/WVCryptoPlugin_test.cpp \ - -LOCAL_C_INCLUDES := \ - frameworks/av/include \ - frameworks/native/include \ - vendor/widevine/libwvdrmengine/cdm/core/include \ - vendor/widevine/libwvdrmengine/cdm/include \ - vendor/widevine/libwvdrmengine/cdm/metrics/include \ - vendor/widevine/libwvdrmengine/cdm/util/include \ - vendor/widevine/libwvdrmengine/mediacrypto/include \ - vendor/widevine/libwvdrmengine/oemcrypto/include \ - -LOCAL_STATIC_LIBRARIES := \ - libcdm \ - libcdm_protos \ - libcdm_utils \ - libjsmn \ - libgmock \ - libgmock_main \ - libgtest \ - libwvlevel3 \ - libwvdrmcryptoplugin \ - libwv_odk \ - -LOCAL_SHARED_LIBRARIES := \ - libbase \ - libcrypto \ - libcutils \ - libdl \ - libhidlbase \ - liblog \ - libprotobuf-cpp-lite \ - libstagefright_foundation \ - libutils \ - -LOCAL_C_INCLUDES += \ - external/protobuf/src \ - -LOCAL_MODULE := libwvdrmmediacrypto_test -LOCAL_LICENSE_KINDS := legacy_by_exception_only -LOCAL_LICENSE_CONDITIONS := by_exception_only - -LOCAL_MODULE_TAGS := tests - -LOCAL_MODULE_OWNER := widevine -LOCAL_PROPRIETARY_MODULE := true - -# When built, explicitly put it in the DATA/nativetest directory. -LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest - -ifneq ($(TARGET_ENABLE_MEDIADRM_64), true) -LOCAL_MODULE_TARGET_ARCH := arm x86 mips -endif - -include $(BUILD_EXECUTABLE) - # ----------------------------------------------------------------------------- # Builds libwvdrmmediacrypto_hidl_test # @@ -79,7 +16,6 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/cdm/util/include \ vendor/widevine/libwvdrmengine/include_hidl \ vendor/widevine/libwvdrmengine/mediacrypto/include_hidl \ - vendor/widevine/libwvdrmengine/mediacrypto/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ LOCAL_STATIC_LIBRARIES := \ diff --git a/libwvdrmengine/mediacrypto/test/legacy_src/WVCryptoPlugin_test.cpp b/libwvdrmengine/mediacrypto/test/legacy_src/WVCryptoPlugin_test.cpp deleted file mode 100644 index 91ba5034..00000000 --- a/libwvdrmengine/mediacrypto/test/legacy_src/WVCryptoPlugin_test.cpp +++ /dev/null @@ -1,430 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#include -#include -#include - -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include "media/stagefright/foundation/ABase.h" -#include "media/stagefright/foundation/AString.h" -#include "media/stagefright/MediaErrors.h" - -#include "OEMCryptoCENC.h" -#include "wv_cdm_constants.h" -#include "wv_cdm_types.h" -#include "wv_content_decryption_module.h" -#include "WVCryptoPlugin.h" - -using namespace android; -using namespace std; -using namespace testing; -using namespace wvcdm; -using namespace wvdrm; - -namespace { -constexpr ssize_t kErrorUnsupportedCrypto = ERROR_DRM_VENDOR_MIN + 2; -} - -class MockCDM : public WvContentDecryptionModule { - public: - MOCK_METHOD1(IsOpenSession, bool(const CdmSessionId&)); - - MOCK_METHOD3(DecryptV16, CdmResponseType(const CdmSessionId&, bool, - const CdmDecryptionParametersV16&)); - - MOCK_METHOD2(QuerySessionStatus, CdmResponseType(const CdmSessionId&, - CdmQueryMap*)); -}; - -class WVCryptoPluginTest : public Test { - protected: - static const uint32_t kSessionIdSize = 16; - uint8_t sessionId[kSessionIdSize]; - - virtual void SetUp() { - FILE* fp = fopen("/dev/urandom", "r"); - fread(sessionId, sizeof(uint8_t), kSessionIdSize, fp); - fclose(fp); - - // Set default CdmResponseType value for gMock - DefaultValue::Set(wvcdm::NO_ERROR); - } -}; - -TEST_F(WVCryptoPluginTest, CorrectlyReportsSecureBuffers) { - android::sp> cdm = new StrictMock(); - - CdmQueryMap l1Map; - l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1; - CdmQueryMap l3Map; - l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3; - - // Provide the expected behavior for IsOpenSession - EXPECT_CALL(*cdm, IsOpenSession(_)) - .WillRepeatedly(Return(true)); - - // Specify the expected calls to QuerySessionStatus - EXPECT_CALL(*cdm, QuerySessionStatus(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(l1Map), - Return(wvcdm::NO_ERROR))) - .WillOnce(DoAll(SetArgPointee<1>(l3Map), - Return(wvcdm::NO_ERROR))); - - WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get()); - - EXPECT_TRUE(plugin.requiresSecureDecoderComponent("video/mp4")) << - "WVCryptoPlugin incorrectly allows an insecure video decoder on L1"; - EXPECT_FALSE(plugin.requiresSecureDecoderComponent("video/mp4")) << - "WVCryptoPlugin incorrectly expects a secure video decoder on L3"; - EXPECT_FALSE(plugin.requiresSecureDecoderComponent("audio/aac")) << - "WVCryptoPlugin incorrectly expects a secure audio decoder"; -} - -// TODO(b/28295739): -// Add New MediaCrypto Unit Tests for CBC & Pattern Mode in cdmPatternDesc. - -// Predicate that validates that the fields of a passed-in -// CdmDecryptionParametersV16 match the values it was given at construction -// time. -// -// This could be done with a huge pile of gMock matchers, but it is ugly and -// unmaintainable, particularly once you get into validating the subsamples. The -// logic here is complex enough to warrant a custom matcher for this one test. -class CDPMatcher { - public: - CDPMatcher(const uint8_t* keyId, bool isSecure, CryptoPlugin::Mode cipherMode, - const CryptoPlugin::Pattern& pattern, - const uint8_t* input, size_t inputLength, - const uint8_t* output, size_t outputLength, const uint8_t* iv, - const CryptoPlugin::SubSample* subsamples, - size_t subsamplesLength) - : mKeyId(keyId, keyId + KEY_ID_SIZE), mIsSecure(isSecure), - mCipherMode(cipherMode), mPattern(pattern), mInput(input), - mInputLength(inputLength), mOutput(output), mOutputLength(outputLength), - mIv(iv, iv + KEY_IV_SIZE), - mSubsamples(subsamples, subsamples + subsamplesLength) {} - - bool operator()(const CdmDecryptionParametersV16& params) const { - if (mCipherMode == CryptoPlugin::kMode_AES_CTR && - params.cipher_mode != kCipherModeCtr) { - return false; - } else if (mCipherMode == CryptoPlugin::kMode_AES_CBC && - params.cipher_mode != kCipherModeCbc) { - return false; - } - - if (params.key_id != mKeyId || - params.is_secure != mIsSecure || - params.pattern.encrypt_blocks != mPattern.mEncryptBlocks || - params.pattern.skip_blocks != mPattern.mSkipBlocks || - params.samples.size() != 1) { - return false; - } - - const CdmDecryptionSample& sample = params.samples[0]; - if (sample.encrypt_buffer != mInput || - sample.encrypt_buffer_length != mInputLength || - sample.decrypt_buffer != mOutput || - sample.decrypt_buffer_size != mOutputLength || - sample.decrypt_buffer_offset != 0 || - sample.iv != mIv || - sample.subsamples.size() != mSubsamples.size()) { - return false; - } - - for (size_t i = 0; i < mSubsamples.size(); ++i) { - const CryptoPlugin::SubSample& androidSubsample = mSubsamples[i]; - const CdmDecryptionSubsample& cdmSubsample = sample.subsamples[i]; - - if (cdmSubsample.clear_bytes != androidSubsample.mNumBytesOfClearData|| - cdmSubsample.protected_bytes != androidSubsample.mNumBytesOfEncryptedData) { - return false; - } - } - - return true; - } - - private: - const KeyId mKeyId; - const bool mIsSecure; - const CryptoPlugin::Mode mCipherMode; - const CryptoPlugin::Pattern mPattern; - const uint8_t* const mInput; - const size_t mInputLength; - const uint8_t* const mOutput; - const size_t mOutputLength; - const std::vector mIv; - const std::vector mSubsamples; -}; - -TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) { - android::sp> cdm = new StrictMock(); - - constexpr size_t kSubSampleCount = 6; - CryptoPlugin::SubSample subSamples[kSubSampleCount]; - memset(subSamples, 0, sizeof(subSamples)); - subSamples[0].mNumBytesOfEncryptedData = 16; - subSamples[1].mNumBytesOfClearData = 16; - subSamples[1].mNumBytesOfEncryptedData = 16; - subSamples[2].mNumBytesOfEncryptedData = 8; - subSamples[3].mNumBytesOfClearData = 29; - subSamples[3].mNumBytesOfEncryptedData = 24; - subSamples[4].mNumBytesOfEncryptedData = 60; - subSamples[5].mNumBytesOfEncryptedData = 16; - - uint8_t keyId[KEY_ID_SIZE]; - uint8_t iv[KEY_IV_SIZE]; - - constexpr size_t kDataSize = 185; - uint8_t inputData[kDataSize]; - uint8_t outputData[kDataSize]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp); - fread(inputData, sizeof(uint8_t), kDataSize, fp); - fclose(fp); - - android::CryptoPlugin::Pattern noPattern = { 0, 0 }; - - // Provide the expected behavior for IsOpenSession - EXPECT_CALL(*cdm, IsOpenSession(_)) - .WillRepeatedly(Return(true)); - - // Specify the expected calls to Decrypt - CDPMatcher paramsMatcher(keyId, false, CryptoPlugin::kMode_AES_CTR, noPattern, - inputData, kDataSize, outputData, kDataSize, iv, - subSamples, kSubSampleCount); - - EXPECT_CALL(*cdm, DecryptV16(ElementsAreArray(sessionId, kSessionIdSize), - true, - Truly(paramsMatcher))) - .Times(1); - - WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get()); - AString errorDetailMessage; - - ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, - noPattern, inputData, subSamples, - kSubSampleCount, outputData, - &errorDetailMessage); - - EXPECT_EQ(static_cast(kDataSize), res) << - "WVCryptoPlugin decrypted the wrong number of bytes"; - EXPECT_EQ(0u, errorDetailMessage.size()) << - "WVCryptoPlugin reported a detailed error message."; -} - -TEST_F(WVCryptoPluginTest, RejectsCens) { - android::sp> cdm = new StrictMock(); - - constexpr size_t kSubSampleCount = 2; - CryptoPlugin::SubSample subSamples[kSubSampleCount]; - memset(subSamples, 0, sizeof(subSamples)); - subSamples[0].mNumBytesOfEncryptedData = 16; - subSamples[1].mNumBytesOfClearData = 16; - subSamples[1].mNumBytesOfEncryptedData = 16; - - uint8_t keyId[KEY_ID_SIZE]; - uint8_t iv[KEY_IV_SIZE]; - - constexpr size_t kDataSize = 48; - uint8_t inputData[kDataSize]; - uint8_t outputData[kDataSize]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp); - fread(inputData, sizeof(uint8_t), kDataSize, fp); - fclose(fp); - - android::CryptoPlugin::Pattern recommendedPattern = { 1, 9 }; - - // Provide the expected behavior for IsOpenSession - EXPECT_CALL(*cdm, IsOpenSession(_)) - .WillRepeatedly(Return(true)); - - // Refuse calls to Decrypt - EXPECT_CALL(*cdm, DecryptV16(_, _, _)) - .Times(0); - - WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get()); - AString errorDetailMessage; - - ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, - recommendedPattern, inputData, subSamples, - kSubSampleCount, outputData, - &errorDetailMessage); - - EXPECT_EQ(res, kErrorUnsupportedCrypto) << - "WVCryptoPlugin did not return an error for 'cens'."; - EXPECT_NE(errorDetailMessage.size(), 0u) << - "WVCryptoPlugin did not report a detailed error message for 'cens'."; -} - -TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) { - android::sp> cdm = new StrictMock(); - - uint8_t keyId[KEY_ID_SIZE]; - uint8_t iv[KEY_IV_SIZE]; - - static const size_t kDataSize = 32; - uint8_t in[kDataSize]; - uint8_t out[kDataSize]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp); - fread(in, sizeof(uint8_t), kDataSize, fp); - fclose(fp); - - static const uint32_t kSubSampleCount = 1; - CryptoPlugin::SubSample subSamples[kSubSampleCount]; - memset(subSamples, 0, sizeof(subSamples)); - subSamples[0].mNumBytesOfClearData = 16; - subSamples[0].mNumBytesOfEncryptedData = 16; - - // Provide the expected behavior for IsOpenSession - EXPECT_CALL(*cdm, IsOpenSession(_)) - .WillRepeatedly(Return(true)); - - // Specify the expected calls to Decrypt - { - InSequence calls; - - typedef CdmDecryptionParametersV16 CDP; - - EXPECT_CALL(*cdm, DecryptV16(_, _, Field(&CDP::is_secure, false))) - .Times(1); - - EXPECT_CALL(*cdm, DecryptV16(_, _, Field(&CDP::is_secure, true))) - .Times(1); - } - - WVCryptoPlugin plugin(sessionId, kSessionIdSize, cdm.get()); - android::CryptoPlugin::Pattern noPattern = { 0, 0 }; - AString errorDetailMessage; - - ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, - noPattern, in, subSamples, kSubSampleCount, - out, &errorDetailMessage); - ASSERT_GE(res, 0) << - "WVCryptoPlugin returned an error"; - EXPECT_EQ(0u, errorDetailMessage.size()) << - "WVCryptoPlugin reported a detailed error message."; - - res = plugin.decrypt(true, keyId, iv, CryptoPlugin::kMode_AES_CTR, - noPattern, in, subSamples, kSubSampleCount, out, - &errorDetailMessage); - ASSERT_GE(res, 0) << - "WVCryptoPlugin returned an error"; - EXPECT_EQ(0u, errorDetailMessage.size()) << - "WVCryptoPlugin reported a detailed error message."; -} - -TEST_F(WVCryptoPluginTest, AllowsSessionIdChanges) { - android::sp> cdm = new StrictMock(); - - uint8_t keyId[KEY_ID_SIZE]; - uint8_t iv[KEY_IV_SIZE]; - uint8_t sessionId2[kSessionIdSize]; - - static const size_t kDataSize = 32; - uint8_t in[kDataSize]; - uint8_t out[kDataSize]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp); - fread(sessionId2, sizeof(uint8_t), kSessionIdSize, fp); - fread(in, sizeof(uint8_t), kDataSize, fp); - fclose(fp); - - static const uint32_t kSubSampleCount = 1; - CryptoPlugin::SubSample subSamples[kSubSampleCount]; - memset(subSamples, 0, sizeof(subSamples)); - subSamples[0].mNumBytesOfClearData = 16; - subSamples[0].mNumBytesOfEncryptedData = 16; - - Vector sessionIdVector; - sessionIdVector.appendArray(sessionId, kSessionIdSize); - Vector sessionId2Vector; - sessionId2Vector.appendArray(sessionId2, kSessionIdSize); - - // Provide the expected behavior for IsOpenSession - EXPECT_CALL(*cdm, IsOpenSession(_)) - .WillRepeatedly(Return(true)); - - // Specify the expected calls to Decrypt - { - InSequence calls; - - EXPECT_CALL(*cdm, - DecryptV16(ElementsAreArray(sessionId, kSessionIdSize), _, _)) - .Times(1); - - EXPECT_CALL(*cdm, - DecryptV16(ElementsAreArray(sessionId2, kSessionIdSize), _, _)) - .Times(1); - } - - uint8_t blank[1]; // Some compilers will not accept 0. - WVCryptoPlugin plugin(blank, 0, cdm.get()); - android::CryptoPlugin::Pattern noPattern = { 0, 0 }; - AString errorDetailMessage; - ssize_t res; - - res = plugin.setMediaDrmSession(sessionIdVector); - EXPECT_EQ(android::NO_ERROR, res); - res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, - noPattern, in, subSamples, kSubSampleCount, out, - &errorDetailMessage); - EXPECT_GE(res, 0) << - "WVCryptoPlugin returned an error"; - EXPECT_EQ(0u, errorDetailMessage.size()) << - "WVCryptoPlugin reported a detailed error message."; - - res = plugin.setMediaDrmSession(sessionId2Vector); - EXPECT_EQ(android::NO_ERROR, res); - res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, - noPattern, in, subSamples, kSubSampleCount, out, - &errorDetailMessage); - EXPECT_GE(res, 0) << - "WVCryptoPlugin returned an error"; - EXPECT_EQ(0u, errorDetailMessage.size()) << - "WVCryptoPlugin reported a detailed error message."; -} - -TEST_F(WVCryptoPluginTest, DisallowsUnopenedSessionIdChanges) { - android::sp> cdm = new StrictMock(); - - uint8_t blank[1]; // Some compilers will not accept 0. - Vector sessionIdVector; - sessionIdVector.appendArray(sessionId, kSessionIdSize); - - // Specify the expected calls to IsOpenSession - { - InSequence calls; - - EXPECT_CALL(*cdm, IsOpenSession(ElementsAreArray(blank, 0))) - .WillOnce(Return(false)); - - EXPECT_CALL(*cdm, IsOpenSession(ElementsAreArray(sessionId, kSessionIdSize))) - .WillOnce(Return(false)) - .WillOnce(Return(true)); - } - - WVCryptoPlugin plugin(blank, 0, cdm.get()); - - ssize_t res; - res = plugin.setMediaDrmSession(sessionIdVector); - EXPECT_EQ(android::ERROR_DRM_SESSION_NOT_OPENED, res); - res = plugin.setMediaDrmSession(sessionIdVector); - EXPECT_EQ(android::NO_ERROR, res); -} diff --git a/libwvdrmengine/mediadrm/Android.bp b/libwvdrmengine/mediadrm/Android.bp index 4ad257d1..b45258da 100644 --- a/libwvdrmengine/mediadrm/Android.bp +++ b/libwvdrmengine/mediadrm/Android.bp @@ -12,55 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// ---------------------------------------------------------------------------- -// Builds libwvdrmdrmplugin -// -// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE -// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE -// DEPENDING ON IT IN YOUR PROJECT. *** -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "vendor_widevine_license" - // to get the below license kinds: - // legacy_by_exception_only (by exception only) - default_applicable_licenses: ["vendor_widevine_license"], -} - -cc_library_static { - name: "libwvdrmdrmplugin", - - srcs: [ - "src/WVDrmPlugin.cpp", - "src/WVGenericCryptoInterface.cpp", - ], - - include_dirs: [ - "frameworks/av/include", - "frameworks/native/include", - "vendor/widevine/libwvdrmengine/cdm/core/include", - "vendor/widevine/libwvdrmengine/cdm/include", - "vendor/widevine/libwvdrmengine/cdm/metrics/include", - "vendor/widevine/libwvdrmengine/cdm/util/include", - "vendor/widevine/libwvdrmengine/include", - "vendor/widevine/libwvdrmengine/mediadrm/include", - "vendor/widevine/libwvdrmengine/oemcrypto/include", - ], - - header_libs: [ - "libstagefright_headers", - "libstagefright_foundation_headers", - "libutils_headers", - ], - - shared_libs: ["liblog"], - - static_libs: ["libcdm_protos"], - - proprietary: true, - -} - // ---------------------------------------------------------------------------- // Builds libwvdrmdrmplugin_hidl // @@ -83,7 +34,6 @@ cc_library_static { "vendor/widevine/libwvdrmengine/include_hidl", "vendor/widevine/libwvdrmengine/include", "vendor/widevine/libwvdrmengine/mediadrm/include_hidl", - "vendor/widevine/libwvdrmengine/mediadrm/include", "vendor/widevine/libwvdrmengine/oemcrypto/include", ], diff --git a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include/WVDrmPlugin.h deleted file mode 100644 index f61d5e37..00000000 --- a/libwvdrmengine/mediadrm/include/WVDrmPlugin.h +++ /dev/null @@ -1,306 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#ifndef WV_DRM_PLUGIN_H_ -#define WV_DRM_PLUGIN_H_ - -#include -#include - -#include "cdm_client_property_set.h" -#include "cdm_identifier.h" -#include "media/drm/DrmAPI.h" -#include "media/stagefright/foundation/ABase.h" -#include "media/stagefright/foundation/AString.h" -#include "OEMCryptoCENC.h" -#include "utils/Errors.h" -#include "utils/KeyedVector.h" -#include "utils/List.h" -#include "utils/String8.h" -#include "utils/StrongPointer.h" -#include "utils/Vector.h" -#include "wv_cdm_event_listener.h" -#include "wv_content_decryption_module.h" -#include "WVGenericCryptoInterface.h" - -namespace wvdrm { - -using android::KeyedVector; -using android::List; -using android::status_t; -using android::String8; -using android::Vector; -using std::map; -using wvcdm::CdmIdentifier; -using wvcdm::CdmKeyStatusMap; -using wvcdm::CdmSessionId; -using wvcdm::CdmResponseType; -using wvcdm::WvContentDecryptionModule; - -const OEMCrypto_Algorithm kInvalidCryptoAlgorithm = - static_cast(-1); - -class WVDrmPlugin : public android::DrmPlugin, - public wvcdm::WvCdmEventListener { - public: - WVDrmPlugin(const android::sp& cdm, - WVGenericCryptoInterface* crypto); - - virtual ~WVDrmPlugin(); - - virtual status_t openSession(Vector& sessionId); - - virtual status_t closeSession(const Vector& sessionId); - - virtual status_t getKeyRequest( - const Vector& scope, - const Vector& initData, - const String8& initDataType, - KeyType keyType, - const KeyedVector& optionalParameters, - Vector& request, - String8& defaultUrl, - KeyRequestType *keyRequestType); - - virtual status_t provideKeyResponse(const Vector& scope, - const Vector& response, - Vector& keySetId); - - virtual status_t removeKeys(const Vector& sessionId); - - virtual status_t restoreKeys(const Vector& sessionId, - const Vector& keySetId); - - virtual status_t queryKeyStatus( - const Vector& sessionId, - KeyedVector& infoMap) const; - - virtual status_t getProvisionRequest(const String8& cert_type, - const String8& cert_authority, - Vector& request, - String8& defaultUrl); - - virtual status_t provideProvisionResponse(const Vector& response, - Vector& certificate, - Vector& wrapped_key); - - virtual status_t unprovisionDevice(); - - virtual status_t getSecureStop(const Vector& ssid, - Vector& secureStop); - - virtual status_t getSecureStops(List >& secureStops); - - virtual status_t releaseAllSecureStops(); - - virtual status_t releaseSecureStops(const Vector& ssRelease); - - virtual status_t getPropertyString(const String8& name, String8& value) const; - - virtual status_t getPropertyByteArray(const String8& name, - Vector& value) const; - - virtual status_t setPropertyString(const String8& name, const String8& value); - - virtual status_t setPropertyByteArray(const String8& name, - const Vector& value); - - virtual status_t setCipherAlgorithm(const Vector& sessionId, - const String8& algorithm); - - virtual status_t setMacAlgorithm(const Vector& sessionId, - const String8& algorithm); - - virtual status_t encrypt(const Vector& sessionId, - const Vector& keyId, - const Vector& input, - const Vector& iv, - Vector& output); - - virtual status_t decrypt(const Vector& sessionId, - const Vector& keyId, - const Vector& input, - const Vector& iv, - Vector& output); - - virtual status_t sign(const Vector& sessionId, - const Vector& keyId, - const Vector& message, - Vector& signature); - - virtual status_t verify(const Vector& sessionId, - const Vector& keyId, - const Vector& message, - const Vector& signature, - bool& match); - - virtual status_t signRSA(const Vector& sessionId, - const String8& algorithm, - const Vector& message, - const Vector& wrappedKey, - Vector& signature); - - virtual void OnSessionRenewalNeeded(const CdmSessionId& cdmSessionId); - - virtual void OnSessionKeysChange(const CdmSessionId& cdmSessionId, - const CdmKeyStatusMap& cdmKeysStatus, - bool hasNewUsableKey); - - virtual void OnExpirationUpdate(const CdmSessionId& cdmSessionId, - int64_t newExpiryTimeSeconds); - - private: - DISALLOW_EVIL_CONSTRUCTORS(WVDrmPlugin); - - struct CryptoSession { - public: - CryptoSession() - : mOecSessionId(-1), - mCipherAlgorithm(kInvalidCryptoAlgorithm), - mMacAlgorithm(kInvalidCryptoAlgorithm) {} - - CryptoSession(OEMCrypto_SESSION sessionId) - : mOecSessionId(sessionId), - mCipherAlgorithm(kInvalidCryptoAlgorithm), - mMacAlgorithm(kInvalidCryptoAlgorithm) {} - - OEMCrypto_SESSION oecSessionId() const { return mOecSessionId; } - - OEMCrypto_Algorithm cipherAlgorithm() const { return mCipherAlgorithm; } - - void setCipherAlgorithm(OEMCrypto_Algorithm newAlgorithm) { - mCipherAlgorithm = newAlgorithm; - } - - OEMCrypto_Algorithm macAlgorithm() const { return mMacAlgorithm; } - - void setMacAlgorithm(OEMCrypto_Algorithm newAlgorithm) { - mMacAlgorithm = newAlgorithm; - } - - private: - OEMCrypto_SESSION mOecSessionId; - OEMCrypto_Algorithm mCipherAlgorithm; - OEMCrypto_Algorithm mMacAlgorithm; - }; - - class WVClientPropertySet : public wvcdm::CdmClientPropertySet { - public: - WVClientPropertySet() - : mUsePrivacyMode(false), mShareKeys(false), mSessionSharingId(0), - mUseAtscMode(false) {} - - virtual ~WVClientPropertySet() {} - - virtual const std::string& security_level() const { - return mSecurityLevel; - } - - void set_security_level(const std::string& securityLevel) { - mSecurityLevel = securityLevel; - } - - virtual bool use_privacy_mode() const { - return mUsePrivacyMode; - } - - void set_use_privacy_mode(bool usePrivacyMode) { - mUsePrivacyMode = usePrivacyMode; - } - - virtual const std::string& service_certificate() const { - return mServiceCertificate; - } - - virtual void set_service_certificate( - const std::string& serviceCertificate) { - mServiceCertificate = serviceCertificate; - } - - virtual bool is_session_sharing_enabled() const { - return mShareKeys; - } - - void set_is_session_sharing_enabled(bool shareKeys) { - mShareKeys = shareKeys; - } - - virtual uint32_t session_sharing_id() const { - return mSessionSharingId; - } - - virtual void set_session_sharing_id(uint32_t id) { - mSessionSharingId = id; - } - - virtual const std::string& app_id() const { - return mAppId; - } - - void set_app_id(const std::string& appId) { - mAppId = appId; - } - - virtual bool use_atsc_mode() const { - return mUseAtscMode; - } - - void set_use_atsc_mode(bool useAtscMode) { - mUseAtscMode = useAtscMode; - } - - private: - DISALLOW_EVIL_CONSTRUCTORS(WVClientPropertySet); - - std::string mSecurityLevel; - bool mUsePrivacyMode; - std::string mServiceCertificate; - bool mShareKeys; - uint32_t mSessionSharingId; - std::string mAppId; - bool mUseAtscMode; - const std::string mEmptyString; - } mPropertySet; - - android::sp const mCDM; - WVGenericCryptoInterface* mCrypto; - map mCryptoSessions; - - CdmIdentifier mCdmIdentifier; - - std::string mProvisioningServiceCertificate; - - CdmSessionId mDecryptHashSessionId; - - status_t queryProperty(const std::string& property, - std::string& stringValue) const; - - status_t queryProperty(wvcdm::SecurityLevel securityLevel, - const std::string& property, - std::string& stringValue) const; - - status_t queryProperty(const std::string& property, - String8& string8_value) const; - - status_t queryProperty(const std::string& property, - Vector& vector_value) const; - - status_t mapAndNotifyOfCdmResponseType(const Vector& sessionId, - CdmResponseType res); - - status_t mapAndNotifyOfOEMCryptoResult(const Vector& sessionId, - OEMCryptoResult res); - - status_t mapOEMCryptoResult(OEMCryptoResult res); - - bool initDataResemblesPSSH(const Vector& initData); - - status_t unprovision(const CdmIdentifier& identifier); -}; - -} // namespace wvdrm - -#endif // WV_DRM_PLUGIN_H_ diff --git a/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h b/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h deleted file mode 100644 index 0fc43587..00000000 --- a/libwvdrmengine/mediadrm/include/WVGenericCryptoInterface.h +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#ifndef WV_GENERIC_CRYPTO_INTERFACE_H_ -#define WV_GENERIC_CRYPTO_INTERFACE_H_ - -#include - -#include "OEMCryptoCENC.h" -#include "media/stagefright/foundation/ABase.h" -#include "utils/Vector.h" - -namespace wvdrm { - -class WVGenericCryptoInterface { - public: - WVGenericCryptoInterface() {} - virtual ~WVGenericCryptoInterface() {} - - virtual OEMCryptoResult selectKey(const OEMCrypto_SESSION session, - const uint8_t* key_id, - size_t key_id_length) { - return OEMCrypto_SelectKey(session, key_id, key_id_length, - OEMCrypto_CipherMode_CBC); - } - - virtual OEMCryptoResult encrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - return OEMCrypto_Generic_Encrypt(session, in_buffer, buffer_length, iv, - algorithm, out_buffer); - } - - virtual OEMCryptoResult decrypt(OEMCrypto_SESSION session, - const uint8_t* in_buffer, - size_t buffer_length, const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - return OEMCrypto_Generic_Decrypt(session, in_buffer, buffer_length, iv, - algorithm, out_buffer); - } - - virtual OEMCryptoResult sign(OEMCrypto_SESSION session, - const uint8_t* in_buffer, size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, size_t* signature_length) { - return OEMCrypto_Generic_Sign(session, in_buffer, buffer_length, algorithm, - signature, signature_length); - } - - virtual OEMCryptoResult verify(OEMCrypto_SESSION session, - const uint8_t* in_buffer, size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length) { - return OEMCrypto_Generic_Verify(session, in_buffer, buffer_length, - algorithm, signature, signature_length); - } - - virtual OEMCryptoResult signRSA(const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length, - const uint8_t* message, - size_t message_length, - android::Vector& signature, - RSA_Padding_Scheme padding_scheme); - - - virtual OEMCryptoResult loadDeviceRSAKey(OEMCrypto_SESSION session, - const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length) { - return OEMCrypto_LoadDRMPrivateKey(session, OEMCrypto_RSA_Private_Key, - wrapped_rsa_key, wrapped_rsa_key_length); - } - - virtual OEMCryptoResult generateRSASignature( - OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length, - RSA_Padding_Scheme padding_scheme) { - return OEMCrypto_GenerateRSASignature(session, message, message_length, - signature, signature_length, - padding_scheme); -} - - private: - DISALLOW_EVIL_CONSTRUCTORS(WVGenericCryptoInterface); -}; - -} // namespace wvdrm - -#endif // WV_GENERIC_CRYPTO_INTERFACE_H_ diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp deleted file mode 100644 index 76f09a49..00000000 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ /dev/null @@ -1,1154 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WVCdm" -#include - -#include "WVDrmPlugin.h" - -#include -#include -#include -#include -#include -#include - -#include "mapErrors-inl.h" -#include "media/stagefright/MediaErrors.h" -#include "utils/Errors.h" -#include "wv_cdm_constants.h" - -namespace { - static const char* const kResetSecurityLevel = ""; - static const char* const kEnable = "enable"; - static const char* const kDisable = "disable"; - static const std::string kPsshTag = "pssh"; - static const char* const kSpecialUnprovisionResponse = "unprovision"; -} - -namespace wvdrm { - -using namespace android; -using namespace std; -using namespace wvcdm; - -namespace { - -Vector ToVector(const std::string& str) { - Vector vector; - vector.appendArray(reinterpret_cast(str.data()), str.size()); - return vector; -} - -DrmPlugin::KeyRequestType ConvertFromCdmKeyRequestType( - CdmKeyRequestType keyRequestType) { - switch (keyRequestType) { - case kKeyRequestTypeInitial: - return DrmPlugin::kKeyRequestType_Initial; - case kKeyRequestTypeRenewal: - return DrmPlugin::kKeyRequestType_Renewal; - case kKeyRequestTypeRelease: - return DrmPlugin::kKeyRequestType_Release; - default: - return DrmPlugin::kKeyRequestType_Unknown; - } -} - -DrmPlugin::KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) { - switch (keyStatus) { - case kKeyStatusUsable: - return DrmPlugin::kKeyStatusType_Usable; - case kKeyStatusExpired: - return DrmPlugin::kKeyStatusType_Expired; - case kKeyStatusOutputNotAllowed: - return DrmPlugin::kKeyStatusType_OutputNotAllowed; - case kKeyStatusPending: - return DrmPlugin::kKeyStatusType_StatusPending; - case kKeyStatusUsableInFuture: - return DrmPlugin::kKeyStatusType_UsableInFuture; - case kKeyStatusInternalError: - default: - return DrmPlugin::kKeyStatusType_InternalError; - } -} - -} // namespace - -WVDrmPlugin::WVDrmPlugin(const sp& cdm, - WVGenericCryptoInterface* crypto) - : mCDM(cdm), - mCrypto(crypto), - mCryptoSessions(), - mCdmIdentifier(kDefaultCdmIdentifier) {} - -WVDrmPlugin::~WVDrmPlugin() { - typedef map::iterator mapIterator; - for (mapIterator iter = mCryptoSessions.begin(); - iter != mCryptoSessions.end(); - ++iter) { - CdmResponseType res = mCDM->CloseSession(iter->first); - if (!isCdmResponseTypeSuccess(res)) { - ALOGE("Failed to close session while destroying WVDrmPlugin"); - } - } - mCryptoSessions.clear(); -} - -status_t WVDrmPlugin::openSession(Vector& sessionId) { - CdmSessionId cdmSessionId; - CdmResponseType res = - mCDM->OpenSession("com.widevine", &mPropertySet, mCdmIdentifier, this, - &cdmSessionId); - - if (!isCdmResponseTypeSuccess(res)) { - return mapAndNotifyOfCdmResponseType(sessionId, res); - } - - bool success = false; - - // Construct a CryptoSession - CdmQueryMap info; - res = mCDM->QueryOemCryptoSessionId(cdmSessionId, &info); - - if (isCdmResponseTypeSuccess(res) && - info.count(QUERY_KEY_OEMCRYPTO_SESSION_ID)) { - OEMCrypto_SESSION oecSessionId = - std::stoul(info[QUERY_KEY_OEMCRYPTO_SESSION_ID]); - mCryptoSessions[cdmSessionId] = CryptoSession(oecSessionId); - success = true; - } else { - ALOGE("Unable to query key control info."); - } - - if (success) { - // Marshal Session ID - sessionId = ToVector(cdmSessionId); - - return android::OK; - } else { - mCDM->CloseSession(cdmSessionId); - - if (!isCdmResponseTypeSuccess(res)) { - // We got an error code we can return. - return mapAndNotifyOfCdmResponseType(sessionId, 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; - } - } -} - -status_t WVDrmPlugin::closeSession(const Vector& sessionId) { - if (!sessionId.size()) { - return android::BAD_VALUE; - } - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - CdmResponseType res = mCDM->CloseSession(cdmSessionId); - mCryptoSessions.erase(cdmSessionId); - if (!isCdmResponseTypeSuccess(res)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } - return android::OK; -} - -status_t WVDrmPlugin::getKeyRequest( - const Vector& scope, - const Vector& initData, - const String8& initDataType, - KeyType keyType, - const KeyedVector& optionalParameters, - Vector& request, - String8& defaultUrl, - KeyRequestType *keyRequestType) { - CdmLicenseType cdmLicenseType; - CdmSessionId cdmSessionId; - CdmKeySetId cdmKeySetId; - if (!scope.size()) { - return android::BAD_VALUE; - } - if (keyType == kKeyType_Offline) { - cdmLicenseType = kLicenseTypeOffline; - cdmSessionId.assign(scope.begin(), scope.end()); - } else if (keyType == kKeyType_Streaming) { - cdmLicenseType = kLicenseTypeStreaming; - cdmSessionId.assign(scope.begin(), scope.end()); - } else if (keyType == kKeyType_Release) { - cdmLicenseType = kLicenseTypeRelease; - cdmKeySetId.assign(scope.begin(), scope.end()); - } else { - return android::ERROR_DRM_CANNOT_HANDLE; - } - - string cdmInitDataType = initDataType.string(); - // Provide backwards-compatibility for apps that pass non-EME-compatible MIME - // types. - if (!WvContentDecryptionModule::IsSupported(cdmInitDataType)) { - cdmInitDataType = wvcdm::ISO_BMFF_VIDEO_MIME_TYPE; - } - - CdmInitData processedInitData; - if (initData.size() > 0 && - WvContentDecryptionModule::IsCenc(cdmInitDataType) && - !initDataResemblesPSSH(initData)) { - // This data was passed in the old format, pre-unwrapped. We need to wrap - // the init data in a new PSSH header. - static const uint8_t psshPrefix[] = { - 0, 0, 0, 0, // Total size - 'p', 's', 's', 'h', // "PSSH" - 0, 0, 0, 0, // Flags - must be zero - 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, // Widevine UUID - 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED, - 0, 0, 0, 0 // Size of initData - }; - processedInitData.assign(reinterpret_cast(psshPrefix), - sizeof(psshPrefix) / sizeof(uint8_t)); - processedInitData.append(reinterpret_cast(initData.array()), - initData.size()); - const size_t kPsshBoxSizeLocation = 0; - const size_t kInitDataSizeLocation = - sizeof(psshPrefix) - sizeof(uint32_t); - uint32_t psshBoxSize = htonl(processedInitData.size()); - uint32_t initDataSize = htonl(initData.size()); - memcpy(&processedInitData[kPsshBoxSizeLocation], &psshBoxSize, - sizeof(uint32_t)); - memcpy(&processedInitData[kInitDataSizeLocation], &initDataSize, - sizeof(uint32_t)); - } else { - // For other formats, we can pass the init data through unmodified. - processedInitData.assign(reinterpret_cast(initData.array()), - initData.size()); - } - - CdmAppParameterMap cdmParameters; - for (size_t i = 0; i < optionalParameters.size(); ++i) { - const String8& key = optionalParameters.keyAt(i); - const String8& value = optionalParameters.valueAt(i); - - string cdmKey(key.string(), key.size()); - string cdmValue(value.string(), value.size()); - - cdmParameters[cdmKey] = cdmValue; - } - - CdmKeyRequest keyRequest; - CdmResponseType res = mCDM->GenerateKeyRequest( - cdmSessionId, cdmKeySetId, cdmInitDataType, processedInitData, - cdmLicenseType, cdmParameters, &mPropertySet, mCdmIdentifier, - &keyRequest); - - *keyRequestType = ConvertFromCdmKeyRequestType(keyRequest.type); - - if (isCdmResponseTypeSuccess(res)) { - defaultUrl.clear(); - defaultUrl.setTo(keyRequest.url.data(), keyRequest.url.size()); - - request = ToVector(keyRequest.message); - } - - if (keyType == kKeyType_Release) { - // When releasing keys, we do not have a session ID. - return mapCdmResponseType(res); - } else { - // For all other requests, we have a session ID. - return mapAndNotifyOfCdmResponseType(scope, res); - } -} - -status_t WVDrmPlugin::provideKeyResponse( - const Vector& scope, - const Vector& response, - Vector& keySetId) { - if (scope.size() == 0 || response.size() == 0) { - return android::BAD_VALUE; - } - CdmSessionId cdmSessionId; - CdmKeyResponse cdmResponse(response.begin(), response.end()); - CdmKeySetId cdmKeySetId; - - bool isRequest = (memcmp(scope.array(), SESSION_ID_PREFIX, - sizeof(SESSION_ID_PREFIX) - 1) == 0); - bool isRelease = (memcmp(scope.array(), KEY_SET_ID_PREFIX, - sizeof(KEY_SET_ID_PREFIX) - 1) == 0); - - if (isRequest) { - cdmSessionId.assign(scope.begin(), scope.end()); - } else if (isRelease) { - cdmKeySetId.assign(scope.begin(), scope.end()); - } else { - return android::ERROR_DRM_CANNOT_HANDLE; - } - - CdmResponseType res = mCDM->AddKey(cdmSessionId, cdmResponse, &cdmKeySetId); - - if (isRequest && isCdmResponseTypeSuccess(res)) { - keySetId = ToVector(cdmKeySetId); - } - - if (isRelease) { - // When releasing keys, we do not have a session ID. - return mapCdmResponseType(res); - } else { - // For all other requests, we have a session ID. - status_t status = mapAndNotifyOfCdmResponseType(scope, res); - // For "NEED_KEY," we still want to send the notifcation, but then we don't - // return the error. This is because "NEED_KEY" from AddKey() is an - // expected behavior when sending a privacy certificate. - if (res == wvcdm::NEED_KEY && mPropertySet.use_privacy_mode()) { - status = android::OK; - } - return status; - } -} - -status_t WVDrmPlugin::removeKeys(const Vector& sessionId) { - if (!sessionId.size()) { - return android::BAD_VALUE; - } - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - - CdmResponseType res = mCDM->RemoveKeys(cdmSessionId); - - return mapAndNotifyOfCdmResponseType(sessionId, res); -} - -status_t WVDrmPlugin::restoreKeys(const Vector& sessionId, - const Vector& keySetId) { - if (sessionId.size() == 0 || keySetId.size() == 0) { - return android::BAD_VALUE; - } - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - CdmKeySetId cdmKeySetId(keySetId.begin(), keySetId.end()); - - CdmResponseType res = mCDM->RestoreKey(cdmSessionId, cdmKeySetId); - - return mapAndNotifyOfCdmResponseType(sessionId, res); -} - -status_t WVDrmPlugin::queryKeyStatus( - const Vector& sessionId, - KeyedVector& infoMap) const { - if (sessionId.size() == 0) { - return android::BAD_VALUE; - } - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - CdmQueryMap cdmLicenseInfo; - - CdmResponseType res = mCDM->QueryKeyStatus(cdmSessionId, &cdmLicenseInfo); - - 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); - } - } - - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::getProvisionRequest(const String8& cert_type, - const String8& cert_authority, - Vector& request, - String8& defaultUrl) { - CdmProvisioningRequest cdmProvisionRequest; - string cdmDefaultUrl; - - if (mPropertySet.use_atsc_mode()) { - return mapCdmResponseType(wvcdm::PROVISIONING_NOT_ALLOWED_FOR_ATSC); - } - - CdmCertificateType cdmCertType = kCertificateWidevine; - if (cert_type == "X.509") { - cdmCertType = kCertificateX509; - } - - string cdmCertAuthority = cert_authority.string(); - - wvcdm::SecurityLevel requested_security_level = - mPropertySet.security_level().compare(QUERY_VALUE_SECURITY_LEVEL_L3) == 0 - ? kLevel3 - : kLevelDefault; - - CdmResponseType res = mCDM->GetProvisioningRequest( - cdmCertType, cdmCertAuthority, mCdmIdentifier, - mProvisioningServiceCertificate, requested_security_level, - &cdmProvisionRequest, &cdmDefaultUrl); - - if (isCdmResponseTypeSuccess(res)) { - request = ToVector(cdmProvisionRequest); - defaultUrl.clear(); - defaultUrl.setTo(cdmDefaultUrl.data(), cdmDefaultUrl.size()); - } - - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::provideProvisionResponse( - const Vector& response, - Vector& certificate, - Vector& wrapped_key) { - if (!response.size()) { - return android::BAD_VALUE; - } - CdmProvisioningResponse cdmResponse(response.begin(), response.end()); - if (cdmResponse == kSpecialUnprovisionResponse) { - if (mCdmIdentifier.IsEquivalentToDefault()) { - return kErrorNoOriginSpecified; - } - return unprovision(mCdmIdentifier); - } else { - string cdmCertificate; - string cdmWrappedKey; - wvcdm::SecurityLevel requested_security_level = - mPropertySet.security_level() - .compare(QUERY_VALUE_SECURITY_LEVEL_L3) == 0 - ? kLevel3 - : kLevelDefault; - CdmResponseType res = - mCDM->HandleProvisioningResponse(mCdmIdentifier, cdmResponse, - requested_security_level, - &cdmCertificate, &cdmWrappedKey); - if (isCdmResponseTypeSuccess(res)) { - certificate = ToVector(cdmCertificate); - wrapped_key = ToVector(cdmWrappedKey); - } - - return mapCdmResponseType(res); - } -} - -status_t WVDrmPlugin::unprovisionDevice() { - return unprovision(kDefaultCdmIdentifier); -} - -status_t WVDrmPlugin::getSecureStop(const Vector& ssid, - Vector& secureStop) { - if (!ssid.size()) { - return android::BAD_VALUE; - } - CdmUsageInfo cdmUsageInfo; - CdmSecureStopId cdmSsid(ssid.begin(), ssid.end()); - CdmResponseType res = mCDM->GetUsageInfo( - mPropertySet.app_id(), cdmSsid, mCdmIdentifier, &cdmUsageInfo); - if (isCdmResponseTypeSuccess(res)) { - secureStop.clear(); - for (CdmUsageInfo::const_iterator iter = cdmUsageInfo.begin(); - iter != cdmUsageInfo.end(); - ++iter) { - const string& cdmStop = *iter; - - secureStop.appendArray(reinterpret_cast(cdmStop.data()), - cdmStop.size()); - } - } - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::getSecureStops(List >& secureStops) { - CdmUsageInfo cdmUsageInfo; - CdmResponseType res = - mCDM->GetUsageInfo(mPropertySet.app_id(), mCdmIdentifier, &cdmUsageInfo); - if (isCdmResponseTypeSuccess(res)) { - secureStops.clear(); - for (CdmUsageInfo::const_iterator iter = cdmUsageInfo.begin(); - iter != cdmUsageInfo.end(); - ++iter) { - const string& cdmStop = *iter; - - secureStops.push_back(ToVector(cdmStop)); - } - } - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::releaseAllSecureStops() { - CdmResponseType res = mCDM->RemoveAllUsageInfo(mPropertySet.app_id(), - mCdmIdentifier); - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::releaseSecureStops(const Vector& ssRelease) { - if (!ssRelease.size()) { - return android::BAD_VALUE; - } - CdmUsageInfoReleaseMessage cdmMessage(ssRelease.begin(), ssRelease.end()); - CdmResponseType res = mCDM->ReleaseUsageInfo(cdmMessage, mCdmIdentifier); - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::getPropertyString(const String8& name, - String8& value) const { - if (name == "vendor") { - value = "Google"; - } else if (name == "version") { - return queryProperty(QUERY_KEY_WVCDM_VERSION, value); - } else if (name == "description") { - value = "Widevine CDM"; - } else if (name == "algorithms") { - value = "AES/CBC/NoPadding,HmacSHA256"; - } else if (name == "securityLevel") { - string requestedLevel = mPropertySet.security_level(); - - if (requestedLevel.length() > 0) { - value = requestedLevel.c_str(); - } else { - return queryProperty(QUERY_KEY_SECURITY_LEVEL, value); - } - } else if (name == "systemId") { - return queryProperty(QUERY_KEY_SYSTEM_ID, value); - } else if (name == "privacyMode") { - if (mPropertySet.use_privacy_mode()) { - value = kEnable; - } else { - value = kDisable; - } - } else if (name == "sessionSharing") { - if (mPropertySet.is_session_sharing_enabled()) { - value = kEnable; - } else { - value = kDisable; - } - } else if (name == "hdcpLevel") { - return queryProperty(QUERY_KEY_CURRENT_HDCP_LEVEL, value); - } else if (name == "maxHdcpLevel") { - return queryProperty(QUERY_KEY_MAX_HDCP_LEVEL, value); - } else if (name == "usageReportingSupport") { - return queryProperty(QUERY_KEY_USAGE_SUPPORT, value); - } else if (name == "numberOfOpenSessions") { - return queryProperty(QUERY_KEY_NUMBER_OF_OPEN_SESSIONS, value); - } else if (name == "maxNumberOfSessions") { - return queryProperty(QUERY_KEY_MAX_NUMBER_OF_SESSIONS, value); - } else if (name == "oemCryptoApiVersion") { - return queryProperty(QUERY_KEY_OEMCRYPTO_API_VERSION, value); - } else if (name == "appId") { - value = mPropertySet.app_id().c_str(); - } else if (name == "origin") { - value = mCdmIdentifier.origin.c_str(); - } else if (name == "CurrentSRMVersion") { - return queryProperty(QUERY_KEY_CURRENT_SRM_VERSION, value); - } else if (name == "SRMUpdateSupport") { - return queryProperty(QUERY_KEY_SRM_UPDATE_SUPPORT, value); - } else if (name == "resourceRatingTier") { - return queryProperty(QUERY_KEY_RESOURCE_RATING_TIER, value); - } else if (name == "oemCryptoBuildInformation") { - return queryProperty(QUERY_KEY_OEMCRYPTO_BUILD_INFORMATION, value); - } else if (name == "decryptHashSupport") { - return queryProperty(QUERY_KEY_DECRYPT_HASH_SUPPORT, value); - } else if (name == "decryptHashError") { - std::string hash_error_string; - CdmResponseType res = - mCDM->GetDecryptHashError(mDecryptHashSessionId, &hash_error_string); - value = hash_error_string.c_str(); - return mapCdmResponseType(res); - } else if (name == "maxUsageEntriesSupported") { - return queryProperty(QUERY_KEY_MAX_USAGE_TABLE_ENTRIES, value); - } else if (name == "oemCryptoApiMinorVersion") { - return queryProperty(QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION, value); - } else if (name == "analogOutputCapabilities") { - return queryProperty(QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES, value); - } else if (name == "canDisableAnalogOutput") { - return queryProperty(QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT, value); - } else if (name == "atscMode") { - if (mPropertySet.use_atsc_mode()) { - value = kEnable; - } else { - value = kDisable; - } - } else { - ALOGE("App requested unknown string property %s", name.string()); - return android::ERROR_DRM_CANNOT_HANDLE; - } - - return android::OK; -} - -status_t WVDrmPlugin::getPropertyByteArray(const String8& name, - Vector& value) const { - if (name == "deviceUniqueId") { - return queryProperty(QUERY_KEY_DEVICE_ID, value); - } else if (name == "provisioningUniqueId") { - return queryProperty(QUERY_KEY_PROVISIONING_ID, value); - } else if (name == "serviceCertificate") { - value = ToVector(mPropertySet.service_certificate()); - } else if (name == "provisioningServiceCertificate") { - value = ToVector(mProvisioningServiceCertificate); - } else if (name == "metrics") { - std::string serialized_metrics; - drm_metrics::WvCdmMetrics metrics; - mCDM->GetMetrics(mCdmIdentifier, &metrics); - if (!metrics.SerializeToString(&serialized_metrics)) { - return android::ERROR_DRM_UNKNOWN; - } else { - value = ToVector(serialized_metrics); - } - } else { - ALOGE("App requested unknown byte array property %s", name.string()); - return android::ERROR_DRM_CANNOT_HANDLE; - } - - return android::OK; -} - -status_t WVDrmPlugin::setPropertyString(const String8& name, - const String8& value) { - if (name == "securityLevel") { - if (mCryptoSessions.size() == 0) { - if (value == QUERY_VALUE_SECURITY_LEVEL_L3.c_str()) { - mPropertySet.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); - } else if (value == QUERY_VALUE_SECURITY_LEVEL_L1.c_str()) { - // We must be sure we CAN set the security level to L1. - std::string current_security_level; - status_t status = - queryProperty(kLevelDefault, QUERY_KEY_SECURITY_LEVEL, - current_security_level); - if (status != android::OK) return status; - - if (current_security_level != QUERY_VALUE_SECURITY_LEVEL_L1) { - ALOGE("App requested L1 security on a non-L1 device."); - return android::BAD_VALUE; - } else { - mPropertySet.set_security_level(kResetSecurityLevel); - } - } else if (value == kResetSecurityLevel) { - mPropertySet.set_security_level(kResetSecurityLevel); - } else { - ALOGE("App requested invalid security level %s", value.string()); - return android::BAD_VALUE; - } - } else { - ALOGE("App tried to change security level while sessions are open."); - return kErrorSessionIsOpen; - } - } else if (name == "privacyMode") { - if (value == kEnable) { - mPropertySet.set_use_privacy_mode(true); - } else if (value == kDisable) { - mPropertySet.set_use_privacy_mode(false); - } else { - ALOGE("App requested unknown privacy mode %s", value.string()); - return android::BAD_VALUE; - } - } else if (name == "sessionSharing") { - if (mCryptoSessions.size() == 0) { - if (value == kEnable) { - mPropertySet.set_is_session_sharing_enabled(true); - } else if (value == kDisable) { - mPropertySet.set_is_session_sharing_enabled(false); - } else { - ALOGE("App requested unknown sharing type %s", value.string()); - return android::BAD_VALUE; - } - } else { - ALOGE("App tried to change key sharing while sessions are open."); - return kErrorSessionIsOpen; - } - } else if (name == "appId") { - if (mCryptoSessions.size() == 0) { - mPropertySet.set_app_id(value.string()); - } else { - ALOGE("App tried to set the application id while sessions are opened."); - return kErrorSessionIsOpen; - } - } else if (name == "origin") { - if (mCryptoSessions.size() != 0) { - ALOGE("App tried to set the origin while sessions are opened."); - return kErrorSessionIsOpen; - } else { - mCdmIdentifier.origin = value.string(); - } - } else if (name == "debugIgnoreKeyboxCount") { - std::istringstream ss(value.string()); - uint32_t count = 0; - ss >> count; - if (ss.fail()) { - ALOGE("Could not parse an integer from '%s'", value.string()); - count = 0; - return android::BAD_VALUE; - } - CdmResponseType res = mCDM->SetDebugIgnoreKeyboxCount(count); - return mapCdmResponseType(res); - } else if (name == "decryptHash") { - CdmSessionId sessionId; - CdmResponseType res = - mCDM->SetDecryptHash(value.string(), &sessionId); - - if (wvcdm::NO_ERROR == res) mDecryptHashSessionId = sessionId; - - return mapCdmResponseType(res); - } else if (name == "decryptHashSessionId") { - mDecryptHashSessionId = value.string(); - } else if (name == "debugOtaKeyboxFallbackDuration") { - bool success = false; - if (value == "default") { - success = mCDM->SetDefaultOtaKeyboxFallbackDurationRules(); - } else if (value == "fast") { - success = mCDM->SetFastOtaKeyboxFallbackDurationRules(); - } else { - ALOGE("Unknown OTA fallback duration value %s", value.string()); - return android::BAD_VALUE; - } - if (!success) { - return android::UNKNOWN_ERROR; - } - } else if (name == "atscMode") { - if (value == kEnable) { - mPropertySet.set_use_atsc_mode(true); - } else if (value == kDisable) { - mPropertySet.set_use_atsc_mode(false); - } else { - ALOGE("App requested unknown atsc mode %s", value.string()); - return android::BAD_VALUE; - } - } else { - ALOGE("App set unknown string property %s", name.string()); - return android::ERROR_DRM_CANNOT_HANDLE; - } - - return android::OK; -} - -status_t WVDrmPlugin::setPropertyByteArray(const String8& name, - const Vector& value) { - if (name == "serviceCertificate") { - std::string cert(value.begin(), value.end()); - if (value.isEmpty() || mCDM->IsValidServiceCertificate(cert)) { - mPropertySet.set_service_certificate(cert); - } else { - return android::BAD_VALUE; - } - } else if (name == "provisioningServiceCertificate") { - std::string cert(value.begin(), value.end()); - if (value.isEmpty() || mCDM->IsValidServiceCertificate(cert)) { - mProvisioningServiceCertificate = cert; - } else { - return android::BAD_VALUE; - } - } else { - ALOGE("App set unknown byte array property %s", name.string()); - return android::ERROR_DRM_CANNOT_HANDLE; - } - - return android::OK; -} - -status_t WVDrmPlugin::setCipherAlgorithm(const Vector& sessionId, - const String8& algorithm) { - if (sessionId.size() == 0 || algorithm.size() == 0) { - return android::BAD_VALUE; - } - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } - - CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (algorithm == "AES/CBC/NoPadding") { - cryptoSession.setCipherAlgorithm(OEMCrypto_AES_CBC_128_NO_PADDING); - } else { - return android::ERROR_DRM_CANNOT_HANDLE; - } - - return android::OK; -} - -status_t WVDrmPlugin::setMacAlgorithm(const Vector& sessionId, - const String8& algorithm) { - if (sessionId.size() == 0 || algorithm.size() == 0) { - return android::BAD_VALUE; - } - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } - - CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (algorithm == "HmacSHA256") { - cryptoSession.setMacAlgorithm(OEMCrypto_HMAC_SHA256); - } else { - return android::ERROR_DRM_CANNOT_HANDLE; - } - - return android::OK; -} - -status_t WVDrmPlugin::encrypt(const Vector& sessionId, - const Vector& keyId, - const Vector& input, - const Vector& iv, - Vector& output) { - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } - - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.cipherAlgorithm() == kInvalidCryptoAlgorithm) { - return android::NO_INIT; - } - - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), - keyId.array(), keyId.size()); - - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } - - output.resize(input.size()); - - res = mCrypto->encrypt(cryptoSession.oecSessionId(), input.array(), - input.size(), iv.array(), - cryptoSession.cipherAlgorithm(), output.editArray()); - - if (res == OEMCrypto_SUCCESS) { - return android::OK; - } else { - ALOGE("OEMCrypto_Generic_Encrypt failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } -} - -status_t WVDrmPlugin::decrypt(const Vector& sessionId, - const Vector& keyId, - const Vector& input, - const Vector& iv, - Vector& output) { - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } - - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.cipherAlgorithm() == kInvalidCryptoAlgorithm) { - return android::NO_INIT; - } - - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), - keyId.array(), keyId.size()); - - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } - - output.resize(input.size()); - - res = mCrypto->decrypt(cryptoSession.oecSessionId(), input.array(), - input.size(), iv.array(), - cryptoSession.cipherAlgorithm(), output.editArray()); - - if (res == OEMCrypto_SUCCESS) { - return android::OK; - } else { - ALOGE("OEMCrypto_Generic_Decrypt failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } -} - -status_t WVDrmPlugin::sign(const Vector& sessionId, - const Vector& keyId, - const Vector& message, - Vector& signature) { - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } - - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.macAlgorithm() == kInvalidCryptoAlgorithm) { - return android::NO_INIT; - } - - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), - keyId.array(), keyId.size()); - - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } - - size_t signatureSize = 0; - - res = mCrypto->sign(cryptoSession.oecSessionId(), message.array(), - message.size(), cryptoSession.macAlgorithm(), - NULL, &signatureSize); - - if (res != OEMCrypto_ERROR_SHORT_BUFFER) { - ALOGE("OEMCrypto_Generic_Sign failed with %u when requesting signature " - "size", res); - if (res != OEMCrypto_SUCCESS) { - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } else { - return android::ERROR_DRM_UNKNOWN; - } - } - - signature.resize(signatureSize); - - res = mCrypto->sign(cryptoSession.oecSessionId(), message.array(), - message.size(), cryptoSession.macAlgorithm(), - signature.editArray(), &signatureSize); - - if (res == OEMCrypto_SUCCESS) { - return android::OK; - } else { - ALOGE("OEMCrypto_Generic_Sign failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } -} - -status_t WVDrmPlugin::verify(const Vector& sessionId, - const Vector& keyId, - const Vector& message, - const Vector& signature, - bool& match) { - CdmSessionId cdmSessionId(sessionId.begin(), sessionId.end()); - if (!mCryptoSessions.count(cdmSessionId)) { - return android::ERROR_DRM_SESSION_NOT_OPENED; - } - - const CryptoSession& cryptoSession = mCryptoSessions[cdmSessionId]; - - if (cryptoSession.macAlgorithm() == kInvalidCryptoAlgorithm) { - return android::NO_INIT; - } - - OEMCryptoResult res = mCrypto->selectKey(cryptoSession.oecSessionId(), - keyId.array(), keyId.size()); - - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_SelectKey failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } - - res = mCrypto->verify(cryptoSession.oecSessionId(), message.array(), - message.size(), cryptoSession.macAlgorithm(), - signature.array(), signature.size()); - - if (res == OEMCrypto_SUCCESS) { - match = true; - return android::OK; - } else if (res == OEMCrypto_ERROR_SIGNATURE_FAILURE) { - match = false; - return android::OK; - } else { - ALOGE("OEMCrypto_Generic_Verify failed with %u", res); - return mapAndNotifyOfOEMCryptoResult(sessionId, res); - } -} - -status_t WVDrmPlugin::signRSA(const Vector& sessionId, - const String8& algorithm, - const Vector& message, - const Vector& wrappedKey, - Vector& signature) { - if (sessionId.size() == 0 || algorithm.size() == 0 || - message.size() == 0 || wrappedKey.size() == 0) { - return android::BAD_VALUE; - } - RSA_Padding_Scheme padding_scheme; - if (algorithm == "RSASSA-PSS-SHA1") { - padding_scheme = kSign_RSASSA_PSS; - } else if (algorithm == "PKCS1-BlockType1") { - padding_scheme = kSign_PKCS1_Block1; - } else { - ALOGE("Unknown RSA Algorithm %s", algorithm.string()); - return android::ERROR_DRM_CANNOT_HANDLE; - } - OEMCryptoResult res = mCrypto->signRSA(wrappedKey.array(), - wrappedKey.size(), - message.array(), message.size(), - signature, - padding_scheme); - - if (res != OEMCrypto_SUCCESS) { - ALOGE("OEMCrypto_GenerateRSASignature failed with %u", res); - return mapOEMCryptoResult(res); - } - - return android::OK; -} - -void WVDrmPlugin::OnSessionRenewalNeeded(const CdmSessionId& cdmSessionId) { - Vector sessionId = ToVector(cdmSessionId); - sendEvent(kDrmPluginEventKeyNeeded, 0, &sessionId, NULL); -} - -void WVDrmPlugin::OnSessionKeysChange(const CdmSessionId& cdmSessionId, - const CdmKeyStatusMap& cdmKeysStatus, - bool hasNewUsableKey) { - bool expired = false; - Vector keyStatusList; - for (CdmKeyStatusMap::const_iterator it = cdmKeysStatus.begin(); - it != cdmKeysStatus.end(); ++it) { - const KeyId& keyId = it->first; - const CdmKeyStatus cdmKeyStatus = it->second; - if (cdmKeyStatus == kKeyStatusExpired) expired = true; - - keyStatusList.push( - {ToVector(keyId), ConvertFromCdmKeyStatus(cdmKeyStatus)}); - } - - Vector sessionId = ToVector(cdmSessionId); - sendKeysChange(&sessionId, &keyStatusList, hasNewUsableKey); - // For backward compatibility. - if (expired) sendEvent(kDrmPluginEventKeyExpired, 0, &sessionId, NULL); -} - -void WVDrmPlugin::OnExpirationUpdate(const CdmSessionId& cdmSessionId, - int64_t newExpiryTimeSeconds) { - Vector sessionId = ToVector(cdmSessionId); - int64_t newExpiryTimeMilliseconds = newExpiryTimeSeconds == NEVER_EXPIRES - ? newExpiryTimeSeconds - : newExpiryTimeSeconds * 1000; - sendExpirationUpdate(&sessionId, newExpiryTimeMilliseconds); -} - -status_t WVDrmPlugin::queryProperty(const std::string& property, - std::string& stringValue) const { - wvcdm::SecurityLevel securityLevel = - mPropertySet.security_level().compare(QUERY_VALUE_SECURITY_LEVEL_L3) == 0 - ? kLevel3 - : kLevelDefault; - return queryProperty(securityLevel, property, stringValue); -} - -status_t WVDrmPlugin::queryProperty(wvcdm::SecurityLevel securityLevel, - const std::string& property, - std::string& stringValue) const { - CdmResponseType res = - mCDM->QueryStatus(securityLevel, property, &stringValue); - - if (res != wvcdm::NO_ERROR) { - ALOGE("Error querying CDM status: %u", res); - } - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::queryProperty(const std::string& property, - String8& string8_value) const { - std::string string_value; - status_t status = queryProperty(property, string_value); - if (status != android::OK) return status; - string8_value = string_value.c_str(); - return android::OK; -} - -status_t WVDrmPlugin::queryProperty(const std::string& property, - Vector& vector_value) const { - std::string string_value; - status_t status = queryProperty(property, string_value); - if (status != android::OK) return status; - vector_value = ToVector(string_value); - return android::OK; -} - -status_t WVDrmPlugin::mapAndNotifyOfCdmResponseType( - const Vector& sessionId, - CdmResponseType res) { - if (res == wvcdm::NEED_PROVISIONING) { - sendEvent(kDrmPluginEventProvisionRequired, 0, &sessionId, NULL); - } else if (res == wvcdm::NEED_KEY) { - sendEvent(kDrmPluginEventKeyNeeded, 0, &sessionId, NULL); - } - - return mapCdmResponseType(res); -} - -status_t WVDrmPlugin::mapAndNotifyOfOEMCryptoResult( - const Vector& sessionId, - OEMCryptoResult res) { - if (res == OEMCrypto_ERROR_NO_DEVICE_KEY) { - sendEvent(kDrmPluginEventProvisionRequired, 0, &sessionId, NULL); - } - return mapOEMCryptoResult(res); -} - -status_t WVDrmPlugin::mapOEMCryptoResult(OEMCryptoResult res) { - 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 android::ERROR_DRM_NOT_PROVISIONED; - case OEMCrypto_ERROR_INVALID_SESSION: - return android::ERROR_DRM_SESSION_NOT_OPENED; - case OEMCrypto_ERROR_TOO_MANY_SESSIONS: - return android::ERROR_DRM_RESOURCE_BUSY; - case OEMCrypto_ERROR_INVALID_RSA_KEY: - return kErrorInvalidKey; - case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES: - return android::ERROR_DRM_RESOURCE_BUSY; - case OEMCrypto_ERROR_NOT_IMPLEMENTED: - return android::ERROR_DRM_CANNOT_HANDLE; - case OEMCrypto_ERROR_UNKNOWN_FAILURE: - case OEMCrypto_ERROR_OPEN_SESSION_FAILED: - return android::ERROR_DRM_UNKNOWN; - default: - return android::UNKNOWN_ERROR; - } -} - -bool WVDrmPlugin::initDataResemblesPSSH(const Vector& initData) { - const uint8_t* const initDataArray = initData.array(); - - if (sizeof(uint32_t) + kPsshTag.size() > initData.size()) { - // The init data is so small that it couldn't contain a size and PSSH tag. - return false; - } - - // Extract the size field - const uint8_t* const sizeField = &initDataArray[0]; - uint32_t nboSize; - memcpy(&nboSize, sizeField, sizeof(nboSize)); - uint32_t size = ntohl(nboSize); - - if (size > initData.size()) { - return false; - } - - // Extract the ID field - const char* const idField = - reinterpret_cast(&initDataArray[sizeof(nboSize)]); - string id(idField, kPsshTag.size()); - return id == kPsshTag; -} - -status_t WVDrmPlugin::unprovision(const CdmIdentifier& identifier) { - if (mPropertySet.use_atsc_mode()) { - return mapCdmResponseType(wvcdm::PROVISIONING_NOT_ALLOWED_FOR_ATSC); - } - - CdmResponseType res1 = mCDM->Unprovision(kSecurityLevelL1, identifier); - CdmResponseType res3 = mCDM->Unprovision(kSecurityLevelL3, identifier); - if (!isCdmResponseTypeSuccess(res1)) - { - return mapCdmResponseType(res1); - } - else - { - return mapCdmResponseType(res3); - } -} - -} // namespace wvdrm diff --git a/libwvdrmengine/mediadrm/src/WVGenericCryptoInterface.cpp b/libwvdrmengine/mediadrm/src/WVGenericCryptoInterface.cpp deleted file mode 100644 index f32d51fb..00000000 --- a/libwvdrmengine/mediadrm/src/WVGenericCryptoInterface.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WVCdm" -#include - -#include "WVGenericCryptoInterface.h" - -#include "wv_cdm_constants.h" - -namespace wvdrm { - -using namespace android; -using namespace std; -using namespace wvcdm; - -OEMCryptoResult WVGenericCryptoInterface::signRSA(const uint8_t* wrapped_rsa_key, - size_t wrapped_rsa_key_length, - const uint8_t* message, - size_t message_length, - Vector& signature, - RSA_Padding_Scheme padding_scheme) { - OEMCrypto_SESSION session; - OEMCryptoResult sts = OEMCrypto_OpenSession(&session); - if (sts != OEMCrypto_SUCCESS) return sts; - sts = OEMCrypto_LoadDRMPrivateKey(session, OEMCrypto_RSA_Private_Key, - wrapped_rsa_key, wrapped_rsa_key_length); - if (sts == OEMCrypto_SUCCESS) { - size_t signatureSize = 0; - sts = OEMCrypto_GenerateRSASignature(session, message, message_length, - NULL, &signatureSize, - padding_scheme); - if (sts == OEMCrypto_SUCCESS) { - // Should be short buffer. - sts = OEMCrypto_ERROR_UNKNOWN_FAILURE; - } else if (sts == OEMCrypto_ERROR_SHORT_BUFFER) { - signature.resize(signatureSize); - sts = OEMCrypto_GenerateRSASignature(session, message, message_length, - signature.editArray(), &signatureSize, - padding_scheme); - } - } - OEMCrypto_CloseSession(session); - return sts; -} - -} // namespace wvdrm diff --git a/libwvdrmengine/mediadrm/test/Android.mk b/libwvdrmengine/mediadrm/test/Android.mk index b6792a33..146fa7fe 100644 --- a/libwvdrmengine/mediadrm/test/Android.mk +++ b/libwvdrmengine/mediadrm/test/Android.mk @@ -1,70 +1,5 @@ LOCAL_PATH := $(call my-dir) -# ----------------------------------------------------------------------------- -# Builds libwvdrmdrmplugin_test -# -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - legacy_src/WVDrmPlugin_test.cpp \ - -LOCAL_C_INCLUDES := \ - frameworks/av/include \ - frameworks/native/include \ - vendor/widevine/libwvdrmengine/cdm/core/include \ - vendor/widevine/libwvdrmengine/cdm/include \ - vendor/widevine/libwvdrmengine/cdm/metrics/include \ - vendor/widevine/libwvdrmengine/cdm/util/include \ - vendor/widevine/libwvdrmengine/include \ - vendor/widevine/libwvdrmengine/mediadrm/include \ - vendor/widevine/libwvdrmengine/oemcrypto/include \ - -LOCAL_STATIC_LIBRARIES := \ - libcdm \ - libcdm_protos \ - libcdm_utils \ - libjsmn \ - libgmock \ - libgmock_main \ - libgtest \ - libwvlevel3 \ - libwvdrmdrmplugin \ - libwv_odk \ - -LOCAL_SHARED_LIBRARIES := \ - libbase \ - libcrypto \ - libdl \ - libhidlbase \ - liblog \ - libprotobuf-cpp-lite \ - libutils \ - -LOCAL_HEADER_LIBRARIES := \ - libstagefright_headers \ - libstagefright_foundation_headers \ - -LOCAL_C_INCLUDES += \ - external/protobuf/src \ - -LOCAL_MODULE := libwvdrmdrmplugin_test -LOCAL_LICENSE_KINDS := legacy_by_exception_only -LOCAL_LICENSE_CONDITIONS := by_exception_only - -LOCAL_MODULE_TAGS := tests - -LOCAL_MODULE_OWNER := widevine -LOCAL_PROPRIETARY_MODULE := true - -# When built, explicitly put it in the DATA/nativetest directory. -LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest - -ifneq ($(TARGET_ENABLE_MEDIADRM_64), true) -LOCAL_MODULE_TARGET_ARCH := arm x86 mips -endif - -include $(BUILD_EXECUTABLE) - # ----------------------------------------------------------------------------- # Builds libwvdrmdrmplugin_hidl_test # @@ -83,7 +18,6 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/include_hidl \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediadrm/include_hidl \ - vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ LOCAL_STATIC_LIBRARIES := \ @@ -156,7 +90,6 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/include_hidl \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediadrm/include_hidl \ - vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ LOCAL_STATIC_LIBRARIES := \ diff --git a/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp deleted file mode 100644 index 7a8e8d14..00000000 --- a/libwvdrmengine/mediadrm/test/legacy_src/WVDrmPlugin_test.cpp +++ /dev/null @@ -1,1930 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#include -#include -#include -#include - -#include "WVDrmPlugin.h" -#include "WVErrors.h" -#include "cdm_client_property_set.h" -#include "media/stagefright/MediaErrors.h" -#include "media/stagefright/foundation/ABase.h" -#include "media/stagefright/foundation/AString.h" -#include "string_conversions.h" -#include "wv_cdm_constants.h" -#include "wv_cdm_types.h" -#include "wv_content_decryption_module.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -using namespace android; -using namespace std; -using namespace testing; -using namespace wvcdm; -using namespace wvdrm; - -namespace { -const String8 kEmptyString; -const String8 kOrigin("widevine.com"); -const String8 kAppId("com.unittest.mock.app.id"); -const uint8_t* const kUnprovisionResponse = - reinterpret_cast("unprovision"); -const size_t kUnprovisionResponseSize = 11; - -// This is a serialized WvCdmMetrics message containing a small amount of -// sample data. This ensures we're able to extract it via a property. -const char kSerializedMetricsHex[] = - "0a580a001a0210072202100d2a02100832182216636f6d2e676f6f676c652e616e64726f69" - "642e676d734208220631342e302e304a06080112020800520610d5f3fad5056a0b1d00fd4c" - "47280132020804a2010608011202080012cb010a0622047369643412b5010a021001520919" - "1d5a643bdfff50405a0b1d00d01945280132021001620d1d00f8e84528013204080020006a" - "0310b739820102100d8a01060801120248009a010310ff01da0106080112024800e2010e1d" - "005243472801320528800248009a020d1d00b016452801320428404800a202060801120248" - "19aa0206080212024800b2020b1d8098f047280132024800ba02021001ca020b1d00101945" - "280132024800e202021004fa02021002a203021000b2030210021a09196891ed7c3f355040"; - -} // anonymous namespace - -class MockCDM : public WvContentDecryptionModule { - public: - MOCK_METHOD5(OpenSession, CdmResponseType(const CdmKeySystem&, - CdmClientPropertySet*, - const CdmIdentifier&, - WvCdmEventListener*, - CdmSessionId*)); - - MOCK_METHOD1(CloseSession, CdmResponseType(const CdmSessionId&)); - - MOCK_METHOD9(GenerateKeyRequest, - CdmResponseType(const CdmSessionId&, const CdmKeySetId&, - const std::string&, const CdmInitData&, - const CdmLicenseType, CdmAppParameterMap&, - CdmClientPropertySet*, const CdmIdentifier&, - CdmKeyRequest*)); - - MOCK_METHOD3(AddKey, CdmResponseType(const CdmSessionId&, - const CdmKeyResponse&, - CdmKeySetId*)); - - MOCK_METHOD1(RemoveKeys, CdmResponseType(const CdmSessionId&)); - - MOCK_METHOD2(RestoreKey, CdmResponseType(const CdmSessionId&, - const CdmKeySetId&)); - - MOCK_METHOD3(QueryStatus, CdmResponseType(SecurityLevel, const std::string&, - std::string*)); - - MOCK_METHOD2(QueryKeyStatus, CdmResponseType(const CdmSessionId&, - CdmQueryMap*)); - - MOCK_METHOD2(QueryOemCryptoSessionId, CdmResponseType(const CdmSessionId&, - CdmQueryMap*)); - - MOCK_METHOD7(GetProvisioningRequest, CdmResponseType(CdmCertificateType, - const std::string&, - const CdmIdentifier&, - const std::string&, - SecurityLevel, - CdmProvisioningRequest*, - std::string*)); - - MOCK_METHOD5(HandleProvisioningResponse, - CdmResponseType(const CdmIdentifier&, CdmProvisioningResponse&, - SecurityLevel, std::string*, std::string*)); - - MOCK_METHOD2(Unprovision, CdmResponseType(CdmSecurityLevel, - const CdmIdentifier&)); - - MOCK_METHOD3(GetUsageInfo, CdmResponseType(const std::string&, - const CdmIdentifier&, - CdmUsageInfo*)); - - MOCK_METHOD4(GetUsageInfo, CdmResponseType(const std::string&, - const CdmSecureStopId&, - const CdmIdentifier&, - CdmUsageInfo*)); - - MOCK_METHOD2(RemoveAllUsageInfo, CdmResponseType(const std::string&, - const CdmIdentifier&)); - - MOCK_METHOD2(ReleaseUsageInfo, - CdmResponseType(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&)); - - MOCK_METHOD1(IsValidServiceCertificate, bool(const std::string&)); - - MOCK_METHOD2(GetMetrics, CdmResponseType(const CdmIdentifier&, - drm_metrics::WvCdmMetrics*)); -}; - -class MockCrypto : public WVGenericCryptoInterface { - public: - MOCK_METHOD3(selectKey, OEMCryptoResult(const OEMCrypto_SESSION, - const uint8_t*, size_t)); - - MOCK_METHOD6(encrypt, OEMCryptoResult(OEMCrypto_SESSION, const uint8_t*, - size_t, const uint8_t*, - OEMCrypto_Algorithm, uint8_t*)); - - MOCK_METHOD6(decrypt, OEMCryptoResult(OEMCrypto_SESSION, const uint8_t*, - size_t, const uint8_t*, - OEMCrypto_Algorithm, uint8_t*)); - - MOCK_METHOD6(sign, OEMCryptoResult(OEMCrypto_SESSION, const uint8_t*, size_t, - OEMCrypto_Algorithm, uint8_t*, size_t*)); - - MOCK_METHOD6(verify, OEMCryptoResult(OEMCrypto_SESSION, const uint8_t*, - size_t, OEMCrypto_Algorithm, - const uint8_t*, size_t)); - - MOCK_METHOD3(loadDeviceRSAKey, OEMCryptoResult(OEMCrypto_SESSION, - const uint8_t*, size_t)); - - MOCK_METHOD6(generateRSASignature, OEMCryptoResult(OEMCrypto_SESSION, - const uint8_t*, size_t, - uint8_t*, size_t*, - RSA_Padding_Scheme)); -}; - -class MockDrmPluginListener : public DrmPluginListener { - public: - MOCK_METHOD4(sendEvent, void(DrmPlugin::EventType, int, - const Vector*, const Vector*)); - MOCK_METHOD2(sendExpirationUpdate, void(const Vector*, int64_t)); - MOCK_METHOD3(sendKeysChange, void(const Vector*, - const Vector*, bool)); -}; - -template -CdmResponseType setSessionIdOnMap(Unused, CdmQueryMap* map) { - static const char oecId[] = {DIGIT + '0', '\0'}; - (*map)[QUERY_KEY_OEMCRYPTO_SESSION_ID] = oecId; - return wvcdm::NO_ERROR; -} - -MATCHER_P(HasOrigin, origin, "") { - return arg.origin == origin; -} - -class WVDrmPluginTest : public Test { - protected: - static const uint32_t kSessionIdSize = 16; - uint8_t sessionIdRaw[kSessionIdSize]; - Vector sessionId; - CdmSessionId cdmSessionId; - - virtual void SetUp() { - // Fill the session ID - FILE* fp = fopen("/dev/urandom", "r"); - fread(sessionIdRaw, sizeof(uint8_t), kSessionIdSize, fp); - fclose(fp); - - memcpy(sessionIdRaw, SESSION_ID_PREFIX, sizeof(SESSION_ID_PREFIX) - 1); - sessionId.appendArray(sessionIdRaw, kSessionIdSize); - cdmSessionId.assign(sessionId.begin(), sessionId.end()); - - // Set default return values for gMock - DefaultValue::Set(wvcdm::NO_ERROR); - DefaultValue::Set(OEMCrypto_SUCCESS); - DefaultValue::Set(true); - } -}; - -struct OriginTestVariant { - // For a test that does not expect any follow-up queries - OriginTestVariant(const std::string& nameValue, const String8& originValue, - const std::string& expectedOriginValue) - : name(nameValue), origin(originValue), - expectedOrigin(expectedOriginValue) {} - - const std::string name; - const String8 origin; - const std::string expectedOrigin; -}; - -void PrintTo(const OriginTestVariant& param, ::std::ostream* os) { - *os << param.name << " Variant"; - -} - -class WVDrmPluginOriginTest : public WVDrmPluginTest, - public WithParamInterface {}; - -TEST_F(WVDrmPluginTest, OpensSessions) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - EXPECT_CALL(*cdm, - OpenSession(StrEq("com.widevine"), _, HasOrigin(EMPTY_ORIGIN), _, _)) - .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .Times(AtLeast(1)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - - ASSERT_EQ(OK, res); - EXPECT_THAT(sessionId, ElementsAreArray(sessionIdRaw, kSessionIdSize)); -} - -TEST_F(WVDrmPluginTest, ClosesSessions) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - EXPECT_CALL(*cdm, CloseSession(cdmSessionId)) - .Times(1); - - status_t res = plugin.closeSession(sessionId); - - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, ClosesSessionWithError) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - EXPECT_CALL(*cdm, CloseSession(cdmSessionId)) - .WillOnce(Return(SESSION_NOT_FOUND_1)); - - status_t res = plugin.closeSession(sessionId); - - ASSERT_EQ(ERROR_DRM_SESSION_NOT_OPENED, res); -} - -TEST_F(WVDrmPluginTest, GeneratesKeyRequests) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const size_t kInitDataSize = 128; - uint8_t initDataRaw[kInitDataSize]; - static const size_t kRequestSize = 256; - uint8_t requestRaw[kRequestSize]; - static const uint32_t kKeySetIdSize = 32; - uint8_t keySetIdRaw[kKeySetIdSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(initDataRaw, sizeof(uint8_t), kInitDataSize, fp); - fread(requestRaw, sizeof(uint8_t), kRequestSize, fp); - fread(keySetIdRaw, sizeof(uint8_t), kKeySetIdSize, fp); - fclose(fp); - - memcpy(keySetIdRaw, KEY_SET_ID_PREFIX, sizeof(KEY_SET_ID_PREFIX) - 1); - CdmKeySetId cdmKeySetId(reinterpret_cast(keySetIdRaw), kKeySetIdSize); - Vector keySetId; - keySetId.appendArray(keySetIdRaw, kKeySetIdSize); - - CdmInitData cdmInitData(reinterpret_cast(initDataRaw), kInitDataSize); - Vector initData; - initData.appendArray(initDataRaw, kInitDataSize); - - static const uint8_t psshPrefix[] = { - 0, 0, 0, 32 + kInitDataSize, // Total size - 'p', 's', 's', 'h', // "PSSH" - 0, 0, 0, 0, // Flags - must be zero - 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, // Widevine UUID - 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED, - 0, 0, 0, kInitDataSize // Size of initData - }; - static const size_t kPsshPrefixSize = sizeof(psshPrefix); - static const size_t kPsshBoxSize = kPsshPrefixSize + kInitDataSize; - uint8_t psshBoxRaw[kPsshBoxSize]; - memcpy(psshBoxRaw, psshPrefix, kPsshPrefixSize); - memcpy(psshBoxRaw + kPsshPrefixSize, initDataRaw, kInitDataSize); - CdmInitData cdmPsshBox(reinterpret_cast(psshBoxRaw), kPsshBoxSize); - Vector psshBox; - psshBox.appendArray(psshBoxRaw, kPsshBoxSize); - - CdmKeyMessage cdmRequest(requestRaw, requestRaw + kRequestSize); - - KeyedVector parameters; - CdmAppParameterMap cdmParameters; - parameters.add(String8("paddingScheme"), String8("BUBBLE WRAP")); - cdmParameters["paddingScheme"] = "BUBBLE WRAP"; - parameters.add(String8("favorite-particle"), String8("tetraquark")); - cdmParameters["favorite-particle"] = "tetraquark"; - parameters.add(String8("answer"), String8("6 * 9")); - cdmParameters["answer"] = "6 * 9"; - - static const char* kDefaultUrl = "http://google.com/"; - static const char* kIsoBmffMimeType = "cenc"; - static const char* kWebmMimeType = "webm"; - - struct TestSet { - const char* mimeType; - const Vector& initDataIn; - const CdmInitData& initDataOut; - }; - - // We run the same set of operations on several sets of data, simulating - // different valid calling patterns. - TestSet testSets[] = { - {kIsoBmffMimeType, psshBox, cdmPsshBox}, // ISO-BMFF, EME passing style - {kIsoBmffMimeType, initData, cdmPsshBox}, // ISO-BMFF, old passing style - {kWebmMimeType, initData, cdmInitData} // WebM - }; - size_t testSetCount = sizeof(testSets) / sizeof(TestSet); - - // Set up the expected calls. Per gMock rules, this must be done for all test - // sets prior to testing any of them. - { - InSequence calls; - - for (size_t i = 0; i < testSetCount; ++i) - { - const char* mimeType = testSets[i].mimeType; - const CdmInitData& initData = testSets[i].initDataOut; - - CdmKeyRequest initialRequest = { - cdmRequest, - kKeyRequestTypeInitial, - kDefaultUrl - }; - - CdmKeyRequest renewalRequest = { - cdmRequest, - kKeyRequestTypeRenewal, - kDefaultUrl - }; - - CdmKeyRequest releaseRequest = { - cdmRequest, - kKeyRequestTypeRelease, - kDefaultUrl - }; - - EXPECT_CALL(*cdm, GenerateKeyRequest(cdmSessionId, "", mimeType, initData, - kLicenseTypeOffline, cdmParameters, - NotNull(), HasOrigin(EMPTY_ORIGIN), - _)) - .WillOnce(DoAll(SetArgPointee<8>(initialRequest), - Return(wvcdm::KEY_MESSAGE))); - - EXPECT_CALL(*cdm, GenerateKeyRequest(cdmSessionId, "", mimeType, initData, - kLicenseTypeStreaming, cdmParameters, - NotNull(), HasOrigin(EMPTY_ORIGIN), - _)) - .WillOnce(DoAll(SetArgPointee<8>(renewalRequest), - Return(wvcdm::KEY_MESSAGE))); - - EXPECT_CALL(*cdm, GenerateKeyRequest("", cdmKeySetId, mimeType, initData, - kLicenseTypeRelease, cdmParameters, - NotNull(), HasOrigin(EMPTY_ORIGIN), - _)) - - .WillOnce(DoAll(SetArgPointee<8>(releaseRequest), - Return(wvcdm::KEY_MESSAGE))); - } - } - - // Performs the actual tests - for (size_t i = 0; i < testSetCount; ++i) - { - const String8 mimeType(testSets[i].mimeType); - const Vector& initData = testSets[i].initDataIn; - - Vector request; - String8 defaultUrl; - DrmPlugin::KeyRequestType keyRequestType; - - status_t res = plugin.getKeyRequest(sessionId, initData, mimeType, - DrmPlugin::kKeyType_Offline, - parameters, request, defaultUrl, - &keyRequestType); - ASSERT_EQ(OK, res); - EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize)); - EXPECT_EQ(DrmPlugin::kKeyRequestType_Initial, keyRequestType); - EXPECT_STREQ(kDefaultUrl, defaultUrl.string()); - - res = plugin.getKeyRequest(sessionId, initData, mimeType, - DrmPlugin::kKeyType_Streaming, parameters, - request, defaultUrl, &keyRequestType); - ASSERT_EQ(OK, res); - EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize)); - EXPECT_EQ(DrmPlugin::kKeyRequestType_Renewal, keyRequestType); - EXPECT_STREQ(kDefaultUrl, defaultUrl.string()); - - res = plugin.getKeyRequest(keySetId, initData, mimeType, - DrmPlugin::kKeyType_Release, parameters, - request, defaultUrl, &keyRequestType); - ASSERT_EQ(OK, res); - EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize)); - EXPECT_EQ(DrmPlugin::kKeyRequestType_Release, keyRequestType); - EXPECT_STREQ(kDefaultUrl, defaultUrl.string()); - } -} - -TEST_F(WVDrmPluginTest, AddsKeys) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const uint32_t kResponseSize = 256; - uint8_t responseRaw[kResponseSize]; - static const uint32_t kKeySetIdSize = 32; - uint8_t keySetIdRaw[kKeySetIdSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(responseRaw, sizeof(uint8_t), kResponseSize, fp); - fread(keySetIdRaw, sizeof(uint8_t), kKeySetIdSize, fp); - fclose(fp); - - Vector response; - response.appendArray(responseRaw, kResponseSize); - - memcpy(keySetIdRaw, KEY_SET_ID_PREFIX, sizeof(KEY_SET_ID_PREFIX) - 1); - CdmKeySetId cdmKeySetId(reinterpret_cast(keySetIdRaw), kKeySetIdSize); - Vector keySetId; - - Vector emptyKeySetId; - - EXPECT_CALL(*cdm, AddKey(cdmSessionId, - ElementsAreArray(responseRaw, kResponseSize), _)) - .WillOnce(DoAll(SetArgPointee<2>(cdmKeySetId), - Return(wvcdm::KEY_ADDED))); - - EXPECT_CALL(*cdm, AddKey("", ElementsAreArray(responseRaw, kResponseSize), - Pointee(cdmKeySetId))) - .Times(1); - - status_t res = plugin.provideKeyResponse(sessionId, response, keySetId); - ASSERT_EQ(OK, res); - ASSERT_THAT(keySetId, ElementsAreArray(keySetIdRaw, kKeySetIdSize)); - - res = plugin.provideKeyResponse(keySetId, response, emptyKeySetId); - ASSERT_EQ(OK, res); - EXPECT_EQ(0u, emptyKeySetId.size()); -} - -TEST_F(WVDrmPluginTest, HandlesPrivacyCertCaseOfAddKey) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - sp > listener = - new StrictMock(); - - const CdmClientPropertySet* propertySet = NULL; - - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - static const uint32_t kResponseSize = 256; - uint8_t responseRaw[kResponseSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(responseRaw, sizeof(uint8_t), kResponseSize, fp); - fclose(fp); - - Vector response; - response.appendArray(responseRaw, kResponseSize); - Vector keySetId; - - EXPECT_CALL(*listener, sendEvent(DrmPlugin::kDrmPluginEventKeyNeeded, 0, - Pointee(ElementsAreArray(sessionIdRaw, - kSessionIdSize)), - NULL)) - .Times(1); - - EXPECT_CALL(*cdm, AddKey(_, _, _)) - .WillRepeatedly(Return(wvcdm::NEED_KEY)); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - - status_t res = plugin.setListener(listener); - ASSERT_EQ(OK, res); - - res = plugin.setPropertyString(String8("privacyMode"), String8("enable")); - ASSERT_EQ(OK, res); - EXPECT_TRUE(propertySet->use_privacy_mode()); - - res = plugin.provideKeyResponse(sessionId, response, keySetId); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, RemovesKeys) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - EXPECT_CALL(*cdm, RemoveKeys(cdmSessionId)) - .Times(1); - - status_t res = plugin.removeKeys(sessionId); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, RestoresKeys) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const size_t kKeySetIdSize = 32; - uint8_t keySetIdRaw[kKeySetIdSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(keySetIdRaw, sizeof(uint8_t), kKeySetIdSize, fp); - fclose(fp); - - Vector keySetId; - keySetId.appendArray(keySetIdRaw, kKeySetIdSize); - - EXPECT_CALL(*cdm, RestoreKey(cdmSessionId, - ElementsAreArray(keySetIdRaw, kKeySetIdSize))) - .Times(1); - - status_t res = plugin.restoreKeys(sessionId, keySetId); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, QueriesKeyStatus) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - KeyedVector expectedLicenseStatus; - CdmQueryMap cdmLicenseStatus; - - expectedLicenseStatus.add(String8("areTheKeysAllRight"), String8("yes")); - cdmLicenseStatus["areTheKeysAllRight"] = "yes"; - expectedLicenseStatus.add(String8("isGMockAwesome"), String8("ohhhhhhYeah")); - cdmLicenseStatus["isGMockAwesome"] = "ohhhhhhYeah"; - expectedLicenseStatus.add(String8("answer"), String8("42")); - cdmLicenseStatus["answer"] = "42"; - - EXPECT_CALL(*cdm, QueryKeyStatus(cdmSessionId, _)) - .WillOnce(DoAll(SetArgPointee<1>(cdmLicenseStatus), - Return(wvcdm::NO_ERROR))); - - KeyedVector licenseStatus; - - status_t res = plugin.queryKeyStatus(sessionId, licenseStatus); - - ASSERT_EQ(OK, res); - - ASSERT_EQ(expectedLicenseStatus.size(), licenseStatus.size()); - for (size_t i = 0; i < expectedLicenseStatus.size(); ++i) { - const String8& key = expectedLicenseStatus.keyAt(i); - EXPECT_NE(android::NAME_NOT_FOUND, licenseStatus.indexOfKey(key)); - EXPECT_EQ(expectedLicenseStatus.valueFor(key), licenseStatus.valueFor(key)); - } -} - -TEST_F(WVDrmPluginTest, GetsProvisioningRequests) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const uint32_t kRequestSize = 256; - uint8_t requestRaw[kRequestSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(requestRaw, sizeof(uint8_t), kRequestSize, fp); - fclose(fp); - - CdmProvisioningRequest cdmRequest(requestRaw, requestRaw + kRequestSize); - - static const char* kDefaultUrl = "http://google.com/"; - - EXPECT_CALL(*cdm, GetProvisioningRequest(kCertificateWidevine, IsEmpty(), - HasOrigin(EMPTY_ORIGIN), IsEmpty(), - wvcdm::kLevelDefault, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(cdmRequest), - SetArgPointee<6>(kDefaultUrl), - Return(wvcdm::NO_ERROR))); - - Vector request; - String8 defaultUrl; - - status_t res = plugin.getProvisionRequest(String8(""), String8(""), request, - defaultUrl); - - ASSERT_EQ(OK, res); - EXPECT_THAT(request, ElementsAreArray(requestRaw, kRequestSize)); - EXPECT_STREQ(kDefaultUrl, defaultUrl.string()); -} - -TEST_F(WVDrmPluginTest, HandlesProvisioningResponses) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const uint32_t kResponseSize = 512; - uint8_t responseRaw[kResponseSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(responseRaw, sizeof(uint8_t), kResponseSize, fp); - fclose(fp); - - Vector response; - response.appendArray(responseRaw, kResponseSize); - - EXPECT_CALL(*cdm, HandleProvisioningResponse(HasOrigin(EMPTY_ORIGIN), - ElementsAreArray(responseRaw, - kResponseSize), - wvcdm::kLevelDefault, _, _)) - .Times(1); - - Vector cert; - Vector key; - - status_t res = plugin.provideProvisionResponse(response, cert, key); - - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, UnprovisionsDevice) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL1, HasOrigin(EMPTY_ORIGIN))) - .Times(1); - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL3, HasOrigin(EMPTY_ORIGIN))) - .Times(1); - - status_t res = plugin.unprovisionDevice(); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, MuxesUnprovisioningErrors) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - // Tests that both Unprovisions are called even if one fails. Also tests that - // no matter which fails, the function always propagates the error. - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL1, HasOrigin(EMPTY_ORIGIN))) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)) - .WillOnce(Return(wvcdm::NO_ERROR)) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)); - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL3, HasOrigin(EMPTY_ORIGIN))) - .WillOnce(Return(wvcdm::NO_ERROR)) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)); - - status_t res = plugin.unprovisionDevice(); - ASSERT_NE(OK, res); - res = plugin.unprovisionDevice(); - ASSERT_NE(OK, res); - res = plugin.unprovisionDevice(); - ASSERT_NE(OK, res); -} - -TEST_F(WVDrmPluginTest, UnprovisionsOrigin) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - Vector cert; - Vector key; - Vector specialResponse; - specialResponse.appendArray(kUnprovisionResponse, kUnprovisionResponseSize); - - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL1, HasOrigin(kOrigin.string()))) - .Times(1); - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL3, HasOrigin(kOrigin.string()))) - .Times(1); - - status_t res = plugin.setPropertyString(String8("origin"), kOrigin); - ASSERT_EQ(OK, res); - res = plugin.provideProvisionResponse(specialResponse, cert, key); - EXPECT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, WillNotUnprovisionWithoutOrigin) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - Vector cert; - Vector key; - Vector specialResponse; - specialResponse.appendArray(kUnprovisionResponse, kUnprovisionResponseSize); - - EXPECT_CALL(*cdm, Unprovision(_, _)) - .Times(0); - - status_t res = plugin.provideProvisionResponse(specialResponse, cert, key); - EXPECT_NE(OK, res); -} - -TEST_F(WVDrmPluginTest, MuxesOriginUnprovisioningErrors) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - Vector cert; - Vector key; - Vector specialResponse; - specialResponse.appendArray(kUnprovisionResponse, kUnprovisionResponseSize); - - // Tests that both Unprovisions are called even if one fails. Also tests that - // no matter which fails, the function always propagates the error. - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL1, HasOrigin(kOrigin.string()))) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)) - .WillOnce(Return(wvcdm::NO_ERROR)) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)); - EXPECT_CALL(*cdm, Unprovision(kSecurityLevelL3, HasOrigin(kOrigin.string()))) - .WillOnce(Return(wvcdm::NO_ERROR)) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)) - .WillOnce(Return(wvcdm::UNKNOWN_ERROR)); - - status_t res = plugin.setPropertyString(String8("origin"), kOrigin); - ASSERT_EQ(OK, res); - res = plugin.provideProvisionResponse(specialResponse, cert, key); - EXPECT_NE(OK, res); - res = plugin.provideProvisionResponse(specialResponse, cert, key); - EXPECT_NE(OK, res); - res = plugin.provideProvisionResponse(specialResponse, cert, key); - EXPECT_NE(OK, res); -} - -TEST_F(WVDrmPluginTest, GetsSecureStops) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - const char* app_id = "my_app_id"; - plugin.setPropertyString(String8("appId"), String8(app_id)); - - static const uint32_t kStopSize = 53; - static const uint32_t kStopCount = 7; - uint8_t stopsRaw[kStopCount][kStopSize]; - FILE* fp = fopen("/dev/urandom", "r"); - for (uint32_t i = 0; i < kStopCount; ++i) { - fread(stopsRaw[i], sizeof(uint8_t), kStopSize, fp); - } - fclose(fp); - - CdmUsageInfo cdmStops; - for (uint32_t i = 0; i < kStopCount; ++i) { - cdmStops.push_back(string(stopsRaw[i], stopsRaw[i] + kStopSize)); - } - - EXPECT_CALL(*cdm, GetUsageInfo(StrEq(app_id), _, _)) - .WillOnce(DoAll(SetArgPointee<2>(cdmStops), - Return(wvcdm::NO_ERROR))); - - List > stops; - - status_t res = plugin.getSecureStops(stops); - - ASSERT_EQ(OK, res); - - List >::iterator iter = stops.begin(); - uint32_t rawIter = 0; - while (rawIter < kStopCount && iter != stops.end()) { - EXPECT_THAT(*iter, ElementsAreArray(stopsRaw[rawIter], kStopSize)); - - ++iter; - ++rawIter; - } - // Assert that both lists are the same length - EXPECT_EQ(kStopCount, rawIter); - EXPECT_EQ(stops.end(), iter); -} - -TEST_F(WVDrmPluginTest, ReleasesAllSecureStops) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - status_t res = plugin.setPropertyString(String8("appId"), String8("")); - ASSERT_EQ(OK, res); - - EXPECT_CALL(*cdm, RemoveAllUsageInfo(StrEq(""), _)) - .Times(1); - - res = plugin.releaseAllSecureStops(); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, ReleasesSecureStops) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const uint32_t kMessageSize = 128; - uint8_t messageRaw[kMessageSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(messageRaw, sizeof(uint8_t), kMessageSize, fp); - fclose(fp); - - Vector message; - message.appendArray(messageRaw, kMessageSize); - - EXPECT_CALL(*cdm, ReleaseUsageInfo(ElementsAreArray(messageRaw, - kMessageSize), - _)) - .Times(1); - - status_t res = plugin.releaseSecureStops(message); - - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - CdmQueryMap l1Map; - l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1; - - CdmQueryMap l3Map; - l3Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3; - - static const string uniqueId = "The Universe"; - static const string systemId = "42"; - static const string provisioningId("Life\0&Everything", 16); - static const string openSessions = "15"; - static const string maxSessions = "18"; - static const string oemCryptoApiVersion = "10"; - static const string currentSRMVersion = "1"; - static const string cdmVersion = "Infinity Minus 1"; - - drm_metrics::WvCdmMetrics expected_metrics; - std::string serialized_metrics = wvcdm::a2bs_hex(kSerializedMetricsHex); - ASSERT_TRUE(expected_metrics.ParseFromString(serialized_metrics)); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _)) - .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1), - Return(wvcdm::NO_ERROR))) - .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L3), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_DEVICE_ID, _)) - .WillOnce(DoAll(SetArgPointee<2>(uniqueId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SYSTEM_ID, _)) - .WillOnce(DoAll(SetArgPointee<2>(systemId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_PROVISIONING_ID, _)) - .WillOnce(DoAll(SetArgPointee<2>(provisioningId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_NUMBER_OF_OPEN_SESSIONS, _)) - .WillOnce(DoAll(SetArgPointee<2>(openSessions), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_MAX_NUMBER_OF_SESSIONS, _)) - .WillOnce(DoAll(SetArgPointee<2>(maxSessions), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_OEMCRYPTO_API_VERSION, _)) - .WillOnce(DoAll(SetArgPointee<2>(oemCryptoApiVersion), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SRM_UPDATE_SUPPORT, _)) - .WillOnce(DoAll(SetArgPointee<2>("True"), - testing::Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_CURRENT_SRM_VERSION, _)) - .WillOnce(DoAll(SetArgPointee<2>(currentSRMVersion), - testing::Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_WVCDM_VERSION, _)) - .WillOnce(DoAll(SetArgPointee<2>(cdmVersion), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, GetMetrics(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(expected_metrics), - testing::Return(wvcdm::NO_ERROR))); - - String8 stringResult; - Vector vectorResult; - - status_t res = plugin.getPropertyString(String8("vendor"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ("Google", stringResult.string()); - - res = plugin.getPropertyString(String8("version"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ(cdmVersion.c_str(), stringResult.string()); - - res = plugin.getPropertyString(String8("description"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ("Widevine CDM", stringResult.string()); - - res = plugin.getPropertyString(String8("algorithms"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ("AES/CBC/NoPadding,HmacSHA256", stringResult.string()); - - res = plugin.getPropertyString(String8("securityLevel"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ(QUERY_VALUE_SECURITY_LEVEL_L1.c_str(), stringResult.string()); - - res = plugin.getPropertyString(String8("securityLevel"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ(QUERY_VALUE_SECURITY_LEVEL_L3.c_str(), stringResult.string()); - - res = plugin.getPropertyByteArray(String8("deviceUniqueId"), vectorResult); - ASSERT_EQ(OK, res); - EXPECT_THAT(vectorResult, ElementsAreArray(uniqueId.data(), uniqueId.size())); - - res = plugin.getPropertyString(String8("systemId"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ(systemId.c_str(), stringResult.string()); - - res = plugin.getPropertyByteArray(String8("provisioningUniqueId"), vectorResult); - ASSERT_EQ(OK, res); - EXPECT_THAT(vectorResult, ElementsAreArray(provisioningId.data(), - provisioningId.size())); - - res = plugin.getPropertyString(String8("numberOfOpenSessions"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_EQ(openSessions, stringResult.string()); - - res = plugin.getPropertyString(String8("maxNumberOfSessions"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_EQ(maxSessions, stringResult.string()); - - res = plugin.getPropertyString(String8("oemCryptoApiVersion"), stringResult); - ASSERT_EQ(OK, res); - - EXPECT_STREQ(oemCryptoApiVersion.c_str(), stringResult.string()); - - res = plugin.getPropertyString(String8("SRMUpdateSupport"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ("True", stringResult.string()); - - res = plugin.getPropertyString(String8("CurrentSRMVersion"), stringResult); - ASSERT_EQ(OK, res); - EXPECT_STREQ(currentSRMVersion.c_str(), stringResult.string()); - - vectorResult.clear(); - res = plugin.getPropertyByteArray(String8("metrics"), vectorResult); - ASSERT_EQ(OK, res); - EXPECT_THAT(vectorResult, ElementsAreArray(serialized_metrics.data(), - serialized_metrics.size())); -} - -TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - String8 stringResult; - Vector vectorResult; - - status_t res = plugin.getPropertyString(String8("unknownProperty"), - stringResult); - ASSERT_NE(OK, res); - EXPECT_TRUE(stringResult.isEmpty()); - - res = plugin.getPropertyByteArray(String8("unknownProperty"), - vectorResult); - ASSERT_NE(OK, res); - EXPECT_TRUE(vectorResult.isEmpty()); -} - -TEST_F(WVDrmPluginTest, DoesNotSetUnknownProperties) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const uint32_t kValueSize = 32; - uint8_t valueRaw[kValueSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(valueRaw, sizeof(uint8_t), kValueSize, fp); - fclose(fp); - - Vector value; - value.appendArray(valueRaw, kValueSize); - - status_t res = plugin.setPropertyString(String8("unknownProperty"), - String8("ignored")); - ASSERT_NE(OK, res); - - res = plugin.setPropertyByteArray(String8("unknownProperty"), value); - ASSERT_NE(OK, res); -} - -TEST_F(WVDrmPluginTest, FailsGenericMethodsWithoutAnAlgorithmSet) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - Vector keyId; - Vector input; - Vector iv; - Vector output; - bool match; - - // Provide expected behavior to support session creation - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .Times(AtLeast(1)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .Times(AtLeast(1)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); - - // Note that we do not set the algorithms. This should cause these methods - // to fail. - - res = plugin.encrypt(sessionId, keyId, input, iv, output); - EXPECT_EQ(NO_INIT, res); - - res = plugin.decrypt(sessionId, keyId, input, iv, output); - EXPECT_EQ(NO_INIT, res); - - res = plugin.sign(sessionId, keyId, input, output); - EXPECT_EQ(NO_INIT, res); - - res = plugin.verify(sessionId, keyId, input, output, match); - EXPECT_EQ(NO_INIT, res); -} - -MATCHER_P(IsIV, iv, "") { - for (size_t i = 0; i < KEY_IV_SIZE; ++i) { - if (iv[i] != arg[i]) { - return false; - } - } - - return true; -} - -TEST_F(WVDrmPluginTest, CallsGenericEncrypt) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const size_t kDataSize = 256; - uint8_t keyIdRaw[KEY_ID_SIZE]; - uint8_t inputRaw[kDataSize]; - uint8_t ivRaw[KEY_IV_SIZE]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyIdRaw, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(inputRaw, sizeof(uint8_t), kDataSize, fp); - fread(ivRaw, sizeof(uint8_t), KEY_IV_SIZE, fp); - fclose(fp); - - Vector keyId; - keyId.appendArray(keyIdRaw, KEY_ID_SIZE); - Vector input; - input.appendArray(inputRaw, kDataSize); - Vector iv; - iv.appendArray(ivRaw, KEY_IV_SIZE); - Vector output; - - { - InSequence calls; - - EXPECT_CALL(crypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(crypto, encrypt(4, _, kDataSize, IsIV(ivRaw), - OEMCrypto_AES_CBC_128_NO_PADDING, _)) - .With(Args<1, 2>(ElementsAreArray(inputRaw, kDataSize))) - .Times(1); - } - - // Provide expected behavior to support session creation - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .Times(AtLeast(1)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .Times(AtLeast(1)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); - - res = plugin.setCipherAlgorithm(sessionId, String8("AES/CBC/NoPadding")); - ASSERT_EQ(OK, res); - - res = plugin.encrypt(sessionId, keyId, input, iv, output); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, CallsGenericDecrypt) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const size_t kDataSize = 256; - uint8_t keyIdRaw[KEY_ID_SIZE]; - uint8_t inputRaw[kDataSize]; - uint8_t ivRaw[KEY_IV_SIZE]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyIdRaw, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(inputRaw, sizeof(uint8_t), kDataSize, fp); - fread(ivRaw, sizeof(uint8_t), KEY_IV_SIZE, fp); - fclose(fp); - - Vector keyId; - keyId.appendArray(keyIdRaw, KEY_ID_SIZE); - Vector input; - input.appendArray(inputRaw, kDataSize); - Vector iv; - iv.appendArray(ivRaw, KEY_IV_SIZE); - Vector output; - - { - InSequence calls; - - EXPECT_CALL(crypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(crypto, decrypt(4, _, kDataSize, IsIV(ivRaw), - OEMCrypto_AES_CBC_128_NO_PADDING, _)) - .With(Args<1, 2>(ElementsAreArray(inputRaw, kDataSize))) - .Times(1); - } - - // Provide expected behavior to support session creation - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .Times(AtLeast(1)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .Times(AtLeast(1)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); - - res = plugin.setCipherAlgorithm(sessionId, String8("AES/CBC/NoPadding")); - ASSERT_EQ(OK, res); - - res = plugin.decrypt(sessionId, keyId, input, iv, output); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, CallsGenericSign) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const size_t kDataSize = 256; - uint8_t keyIdRaw[KEY_ID_SIZE]; - uint8_t messageRaw[kDataSize]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyIdRaw, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(messageRaw, sizeof(uint8_t), kDataSize, fp); - fclose(fp); - - Vector keyId; - keyId.appendArray(keyIdRaw, KEY_ID_SIZE); - Vector message; - message.appendArray(messageRaw, kDataSize); - Vector signature; - - { - InSequence calls; - - EXPECT_CALL(crypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(crypto, sign(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, - Pointee(0))) - .With(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize))) - .WillOnce(DoAll(SetArgPointee<5>(64), - Return(OEMCrypto_ERROR_SHORT_BUFFER))); - - EXPECT_CALL(crypto, sign(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, - Pointee(64))) - .With(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize))) - .Times(1); - } - - // Provide expected behavior to support session creation - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .Times(AtLeast(1)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .Times(AtLeast(1)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); - - res = plugin.setMacAlgorithm(sessionId, String8("HmacSHA256")); - ASSERT_EQ(OK, res); - - res = plugin.sign(sessionId, keyId, message, signature); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, CallsGenericVerify) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - static const size_t kDataSize = 256; - static const size_t kSignatureSize = 16; - uint8_t keyIdRaw[KEY_ID_SIZE]; - uint8_t messageRaw[kDataSize]; - uint8_t signatureRaw[kSignatureSize]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(keyIdRaw, sizeof(uint8_t), KEY_ID_SIZE, fp); - fread(messageRaw, sizeof(uint8_t), kDataSize, fp); - fread(signatureRaw, sizeof(uint8_t), kSignatureSize, fp); - fclose(fp); - - Vector keyId; - keyId.appendArray(keyIdRaw, KEY_ID_SIZE); - Vector message; - message.appendArray(messageRaw, kDataSize); - Vector signature; - signature.appendArray(signatureRaw, kSignatureSize); - bool match; - - { - InSequence calls; - - EXPECT_CALL(crypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(crypto, verify(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, - kSignatureSize)) - .With(AllOf(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize)), - Args<4, 5>(ElementsAreArray(signatureRaw, kSignatureSize)))) - .WillOnce(Return(OEMCrypto_SUCCESS)); - - EXPECT_CALL(crypto, selectKey(4, _, KEY_ID_SIZE)) - .With(Args<1, 2>(ElementsAreArray(keyIdRaw, KEY_ID_SIZE))) - .Times(1); - - EXPECT_CALL(crypto, verify(4, _, kDataSize, OEMCrypto_HMAC_SHA256, _, - kSignatureSize)) - .With(AllOf(Args<1, 2>(ElementsAreArray(messageRaw, kDataSize)), - Args<4, 5>(ElementsAreArray(signatureRaw, kSignatureSize)))) - .WillOnce(Return(OEMCrypto_ERROR_SIGNATURE_FAILURE)); - } - - // Provide expected behavior to support session creation - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .Times(AtLeast(1)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .Times(AtLeast(1)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); - - res = plugin.setMacAlgorithm(sessionId, String8("HmacSHA256")); - ASSERT_EQ(OK, res); - - res = plugin.verify(sessionId, keyId, message, signature, match); - ASSERT_EQ(OK, res); - EXPECT_TRUE(match); - - res = plugin.verify(sessionId, keyId, message, signature, match); - ASSERT_EQ(OK, res); - EXPECT_FALSE(match); -} - -TEST_F(WVDrmPluginTest, RegistersForEvents) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - // Provide expected behavior to support session creation - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, &plugin, _)) - .Times(AtLeast(1)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .Times(AtLeast(1)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); -} - -TEST_F(WVDrmPluginTest, UnregistersForAllEventsOnDestruction) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - - { - WVDrmPlugin plugin(cdm.get(), &crypto); - - uint8_t sessionIdRaw1[kSessionIdSize]; - uint8_t sessionIdRaw2[kSessionIdSize]; - FILE* fp = fopen("/dev/urandom", "r"); - fread(sessionIdRaw1, sizeof(uint8_t), kSessionIdSize, fp); - fread(sessionIdRaw2, sizeof(uint8_t), kSessionIdSize, fp); - fclose(fp); - - CdmSessionId cdmSessionId1(sessionIdRaw1, sessionIdRaw1 + kSessionIdSize); - CdmSessionId cdmSessionId2(sessionIdRaw2, sessionIdRaw2 + kSessionIdSize); - - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId1), - Return(wvcdm::NO_ERROR))) - .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId2), - Return(wvcdm::NO_ERROR))); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId1, _)) - .WillOnce(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId2, _)) - .WillOnce(Invoke(setSessionIdOnMap<5>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); - - res = plugin.openSession(sessionId); - ASSERT_EQ(OK, res); - } -} - -TEST_F(WVDrmPluginTest, MarshalsEvents) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - sp > listener = - new StrictMock(); - - const int64_t kExpiryTimeInSeconds = 123456789012LL; - const char kKeyId1[] = "Testing Key1 Id "; - const char kKeyId2[] = "Testing Key2 Id "; - const char kKeyId3[] = "Testing Key3 Id "; - const char kKeyId4[] = "Testing Key4 Id "; - const char kKeyId5[] = "Testing Key5 Id "; - - { - InSequence calls; - - EXPECT_CALL(*listener, - sendKeysChange( - Pointee(ElementsAreArray(sessionIdRaw, kSessionIdSize)), - Pointee(UnorderedElementsAre(AllOf( - Field(&DrmPlugin::KeyStatus::mKeyId, - ElementsAreArray(kKeyId1, sizeof(kKeyId1) - 1)), - Field(&DrmPlugin::KeyStatus::mType, - DrmPlugin::kKeyStatusType_Expired)))), - false)); - EXPECT_CALL( - *listener, - sendEvent(DrmPlugin::kDrmPluginEventKeyExpired, 0, - Pointee(ElementsAreArray(sessionIdRaw, kSessionIdSize)), - NULL)); - EXPECT_CALL( - *listener, - sendEvent(DrmPlugin::kDrmPluginEventKeyNeeded, 0, - Pointee(ElementsAreArray(sessionIdRaw, kSessionIdSize)), - NULL)); - // Expiry Time in Java API is in milliseconds. - EXPECT_CALL(*listener, - sendExpirationUpdate( - Pointee(ElementsAreArray(sessionIdRaw, kSessionIdSize)), - NEVER_EXPIRES)); - EXPECT_CALL(*listener, - sendExpirationUpdate( - Pointee(ElementsAreArray(sessionIdRaw, kSessionIdSize)), - kExpiryTimeInSeconds * 1000)); - EXPECT_CALL( - *listener, - sendKeysChange( - Pointee(ElementsAreArray(sessionIdRaw, kSessionIdSize)), - Pointee(UnorderedElementsAre( - AllOf(Field(&DrmPlugin::KeyStatus::mKeyId, - ElementsAreArray(kKeyId1, sizeof(kKeyId1) - 1)), - Field(&DrmPlugin::KeyStatus::mType, - DrmPlugin::kKeyStatusType_Usable)), - AllOf(Field(&DrmPlugin::KeyStatus::mKeyId, - ElementsAreArray(kKeyId2, sizeof(kKeyId2) - 1)), - Field(&DrmPlugin::KeyStatus::mType, - DrmPlugin::kKeyStatusType_OutputNotAllowed)), - AllOf(Field(&DrmPlugin::KeyStatus::mKeyId, - ElementsAreArray(kKeyId3, sizeof(kKeyId3) - 1)), - Field(&DrmPlugin::KeyStatus::mType, - DrmPlugin::kKeyStatusType_InternalError)), - AllOf(Field(&DrmPlugin::KeyStatus::mKeyId, - ElementsAreArray(kKeyId4, sizeof(kKeyId4) - 1)), - Field(&DrmPlugin::KeyStatus::mType, - DrmPlugin::kKeyStatusType_StatusPending)), - AllOf(Field(&DrmPlugin::KeyStatus::mKeyId, - ElementsAreArray(kKeyId5, sizeof(kKeyId5) - 1)), - Field(&DrmPlugin::KeyStatus::mType, - DrmPlugin::kKeyStatusType_UsableInFuture)))), - true)); - } - - status_t res = plugin.setListener(listener); - ASSERT_EQ(OK, res); - - CdmKeyStatusMap cdmKeysStatus; - cdmKeysStatus[kKeyId1] = kKeyStatusExpired; - plugin.OnSessionKeysChange(cdmSessionId, cdmKeysStatus, false); - - plugin.OnSessionRenewalNeeded(cdmSessionId); - plugin.OnExpirationUpdate(cdmSessionId, NEVER_EXPIRES); - plugin.OnExpirationUpdate(cdmSessionId, kExpiryTimeInSeconds); - - cdmKeysStatus[kKeyId1] = kKeyStatusUsable; - cdmKeysStatus[kKeyId2] = kKeyStatusOutputNotAllowed; - cdmKeysStatus[kKeyId3] = kKeyStatusInternalError; - cdmKeysStatus[kKeyId4] = kKeyStatusPending; - cdmKeysStatus[kKeyId5] = kKeyStatusUsableInFuture; - plugin.OnSessionKeysChange(cdmSessionId, cdmKeysStatus, true); -} - -TEST_F(WVDrmPluginTest, GeneratesProvisioningNeededEvent) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - sp > listener = - new StrictMock(); - - EXPECT_CALL(*listener, sendEvent(DrmPlugin::kDrmPluginEventProvisionRequired, 0, - Pointee(ElementsAreArray(sessionIdRaw, - kSessionIdSize)), - NULL)) - .Times(1); - - EXPECT_CALL(*cdm, OpenSession(StrEq("com.widevine"), _, _, _, _)) - .Times(AtLeast(1)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NEED_PROVISIONING))); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - - status_t res = plugin.setListener(listener); - ASSERT_EQ(OK, res); - - res = plugin.openSession(sessionId); - ASSERT_EQ(ERROR_DRM_NOT_PROVISIONED, res); -} - -TEST_F(WVDrmPluginTest, ProvidesExpectedDefaultPropertiesToCdm) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - const CdmClientPropertySet* propertySet = NULL; - - // Provide expected mock behavior - { - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - plugin.openSession(sessionId); - - ASSERT_THAT(propertySet, NotNull()); - EXPECT_STREQ("", propertySet->security_level().c_str()); - EXPECT_FALSE(propertySet->use_privacy_mode()); - EXPECT_EQ(0u, propertySet->service_certificate().size()); - EXPECT_FALSE(propertySet->is_session_sharing_enabled()); - EXPECT_EQ(0u, propertySet->session_sharing_id()); - EXPECT_STREQ("", propertySet->app_id().c_str()); -} - -TEST_F(WVDrmPluginTest, CanSetAppId) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - const CdmClientPropertySet* propertySet = NULL; - - // Provide expected mock behavior - { - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin queries for the security level - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _)) - .WillRepeatedly(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L3), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - status_t res; - - // Test setting an empty string - res = plugin.setPropertyString(String8("appId"), String8("")); - ASSERT_EQ(OK, res); - - // Test setting an application id before a session is opened. - res = plugin.setPropertyString(String8("appId"), kAppId); - ASSERT_EQ(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - - // Verify application id is set correctly. - EXPECT_STREQ(kAppId, propertySet->app_id().c_str()); - - // Test setting application id while session is opened, this should fail. - res = plugin.setPropertyString(String8("appId"), kAppId); - ASSERT_EQ(kErrorSessionIsOpen, res); -} - -TEST_P(WVDrmPluginOriginTest, CanSetOrigin) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - OriginTestVariant params = GetParam(); - - // Provide expected mock behavior - { - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - // Provide expected behavior when plugin closes a session - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - // Note which mock calls we expect - EXPECT_CALL(*cdm, OpenSession(_, _, HasOrigin(params.expectedOrigin), _, _)) - .WillOnce(DoAll(SetArgPointee<4>(cdmSessionId), - Return(wvcdm::NO_ERROR))); - - // Set the properties & run the test - if (!params.origin.isEmpty()) { - ASSERT_EQ(OK, plugin.setPropertyString(String8("origin"), params.origin)); - } - EXPECT_EQ(OK, plugin.openSession(sessionId)); - // Test setting an origin while sessions are opened. This should fail. - EXPECT_NE(OK, plugin.setPropertyString(String8("origin"), kOrigin)); - EXPECT_EQ(OK, plugin.closeSession(sessionId)); -} - -INSTANTIATE_TEST_CASE_P(OriginTests, WVDrmPluginOriginTest, Values( - OriginTestVariant("No Origin", kEmptyString, EMPTY_ORIGIN), - OriginTestVariant("With an Origin", kOrigin, kOrigin.string()))); - -TEST_F(WVDrmPluginTest, CanSetSecurityLevel) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - const CdmClientPropertySet* propertySet = NULL; - - EXPECT_CALL(*cdm, QueryStatus(_, QUERY_KEY_SECURITY_LEVEL, _)) - .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L3), - Return(wvcdm::NO_ERROR))) - .WillOnce(DoAll(SetArgPointee<2>(QUERY_VALUE_SECURITY_LEVEL_L1), - Return(wvcdm::NO_ERROR))); - - // Provide expected mock behavior - { - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - status_t res; - - // Test forcing L3 - res = plugin.setPropertyString(String8("securityLevel"), String8("L3")); - ASSERT_EQ(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_STREQ("L3", propertySet->security_level().c_str()); - plugin.closeSession(sessionId); - - // Test returning to L1 on an L3 device (Should Fail) - res = plugin.setPropertyString(String8("securityLevel"), String8("L1")); - ASSERT_NE(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_STREQ("L3", propertySet->security_level().c_str()); - plugin.closeSession(sessionId); - - // Test returning to L1 on an L1 device - res = plugin.setPropertyString(String8("securityLevel"), String8("L1")); - ASSERT_EQ(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_STREQ("", propertySet->security_level().c_str()); - plugin.closeSession(sessionId); - - // Test un-forcing a level (first forcing to L3 so we have something to reset) - res = plugin.setPropertyString(String8("securityLevel"), String8("L3")); - ASSERT_EQ(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_STREQ("L3", propertySet->security_level().c_str()); - plugin.closeSession(sessionId); - - res = plugin.setPropertyString(String8("securityLevel"), String8("")); - ASSERT_EQ(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_STREQ("", propertySet->security_level().c_str()); - plugin.closeSession(sessionId); - - // Test nonsense (Should Fail) - res = plugin.setPropertyString(String8("securityLevel"), String8("nonsense")); - ASSERT_NE(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_STREQ("", propertySet->security_level().c_str()); - plugin.closeSession(sessionId); - - // Test attempting to force a level with a session open (Should Fail) - plugin.openSession(sessionId); - res = plugin.setPropertyString(String8("securityLevel"), String8("L3")); - ASSERT_NE(OK, res); -} - -TEST_F(WVDrmPluginTest, CanSetPrivacyMode) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - const CdmClientPropertySet* propertySet = NULL; - - // Provide expected mock behavior - { - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - - status_t res; - - // Test turning on privacy mode - res = plugin.setPropertyString(String8("privacyMode"), String8("enable")); - ASSERT_EQ(OK, res); - EXPECT_TRUE(propertySet->use_privacy_mode()); - - // Test turning off privacy mode - res = plugin.setPropertyString(String8("privacyMode"), String8("disable")); - ASSERT_EQ(OK, res); - EXPECT_FALSE(propertySet->use_privacy_mode()); - - // Test nonsense (Should Fail) - res = plugin.setPropertyString(String8("privacyMode"), String8("nonsense")); - ASSERT_NE(OK, res); -} - -TEST_F(WVDrmPluginTest, CanSetServiceCertificate) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - const CdmClientPropertySet* propertySet = NULL; - - static const size_t kPrivacyCertSize = 256; - uint8_t privacyCertRaw[kPrivacyCertSize]; - - FILE* fp = fopen("/dev/urandom", "r"); - fread(privacyCertRaw, sizeof(uint8_t), kPrivacyCertSize, fp); - fclose(fp); - - Vector privacyCert; - privacyCert.appendArray(privacyCertRaw, kPrivacyCertSize); - std::string strPrivacyCert(reinterpret_cast(privacyCertRaw), - kPrivacyCertSize); - Vector emptyVector; - - // Provide expected mock behavior - { - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - // Validate that the certificate is validated. Accept it once and reject it - // once. Note that there is no expected call for when the certificate is - // cleared. - EXPECT_CALL(*cdm, IsValidServiceCertificate(strPrivacyCert)) - .WillOnce(Return(true)) - .WillOnce(Return(false)); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - - status_t res; - - // Test setting a certificate - res = plugin.setPropertyByteArray(String8("serviceCertificate"), privacyCert); - ASSERT_EQ(OK, res); - EXPECT_THAT(propertySet->service_certificate(), - ElementsAreArray(privacyCertRaw, kPrivacyCertSize)); - - // Test clearing a certificate - res = plugin.setPropertyByteArray(String8("serviceCertificate"), emptyVector); - ASSERT_EQ(OK, res); - EXPECT_EQ(0u, propertySet->service_certificate().size()); - - // Test setting a certificate and having it fail - res = plugin.setPropertyByteArray(String8("serviceCertificate"), privacyCert); - ASSERT_NE(OK, res); - EXPECT_EQ(0u, propertySet->service_certificate().size()); -} - -TEST_F(WVDrmPluginTest, CanSetSessionSharing) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - const CdmClientPropertySet* propertySet = NULL; - - // Provide expected mock behavior - { - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - status_t res; - - // Test turning on session sharing - res = plugin.setPropertyString(String8("sessionSharing"), String8("enable")); - ASSERT_EQ(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_TRUE(propertySet->is_session_sharing_enabled()); - plugin.closeSession(sessionId); - - // Test turning off session sharing - res = plugin.setPropertyString(String8("sessionSharing"), String8("disable")); - ASSERT_EQ(OK, res); - - plugin.openSession(sessionId); - ASSERT_THAT(propertySet, NotNull()); - EXPECT_FALSE(propertySet->is_session_sharing_enabled()); - plugin.closeSession(sessionId); - - // Test nonsense (Should Fail) - res = plugin.setPropertyString(String8("sessionSharing"), String8("nonsense")); - ASSERT_NE(OK, res); - - // Test changing sharing with a session open (Should Fail) - plugin.openSession(sessionId); - res = plugin.setPropertyString(String8("sessionSharing"), String8("enable")); - ASSERT_NE(OK, res); -} - -TEST_F(WVDrmPluginTest, AllowsStoringOfSessionSharingId) { - android::sp> cdm = new StrictMock(); - StrictMock crypto; - WVDrmPlugin plugin(cdm.get(), &crypto); - - CdmClientPropertySet* propertySet = NULL; - - uint32_t sharingId; - FILE* fp = fopen("/dev/urandom", "r"); - fread(&sharingId, sizeof(uint32_t), 1, fp); - fclose(fp); - - // Provide expected mock behavior - { - // Provide expected behavior in response to OpenSession and store the - // property set - EXPECT_CALL(*cdm, OpenSession(_, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<4>(cdmSessionId), - SaveArg<1>(&propertySet), - Return(wvcdm::NO_ERROR))); - - // Provide expected behavior when plugin requests session control info - EXPECT_CALL(*cdm, QueryOemCryptoSessionId(cdmSessionId, _)) - .WillRepeatedly(Invoke(setSessionIdOnMap<4>)); - - EXPECT_CALL(*cdm, CloseSession(_)) - .Times(AtLeast(0)); - } - - plugin.openSession(sessionId); - - ASSERT_THAT(propertySet, NotNull()); - propertySet->set_session_sharing_id(sharingId); - EXPECT_EQ(sharingId, propertySet->session_sharing_id()); -} diff --git a/libwvdrmengine/run_all_unit_tests.sh b/libwvdrmengine/run_all_unit_tests.sh index 3ac58a99..6cb4cd9c 100755 --- a/libwvdrmengine/run_all_unit_tests.sh +++ b/libwvdrmengine/run_all_unit_tests.sh @@ -112,9 +112,7 @@ adb_shell_run hidl_metrics_adapter_unittest adb_shell_run http_socket_test adb_shell_run initialization_data_unittest adb_shell_run libwvdrmdrmplugin_hidl_test -adb_shell_run libwvdrmdrmplugin_test adb_shell_run libwvdrmmediacrypto_hidl_test -adb_shell_run libwvdrmmediacrypto_test adb_shell_run license_keys_unittest adb_shell_run license_unittest adb_shell_run odk_test @@ -130,13 +128,6 @@ adb_shell_run usage_table_header_unittest adb_shell_run value_metric_unittest adb_shell_run wv_cdm_metrics_test -# Run the non-Treble test on non-Treble devices -if adb $SERIAL_NUM shell ls /vendor/lib/mediadrm/libwvdrmengine.so &> /dev/null || - adb $SERIAL_NUM shell ls /vendor/lib64/mediadrm/libwvdrmengine.so &> /dev/null; then - library_path="/vendor/lib/mediadrm/:/vendor/lib64/mediadrm/" - adb_shell_run libwvdrmengine_test LD_LIBRARY_PATH=$library_path -fi - # Run the Treble test on Treble devices if adb $SERIAL_NUM shell ls /vendor/lib/libwvhidl.so &> /dev/null || adb $SERIAL_NUM shell ls /vendor/lib64/libwvhidl.so &> /dev/null; then diff --git a/libwvdrmengine/src/WVCreatePluginFactories.cpp b/libwvdrmengine/src/WVCreatePluginFactories.cpp deleted file mode 100644 index 6c1d2c05..00000000 --- a/libwvdrmengine/src/WVCreatePluginFactories.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#include "WVCreatePluginFactories.h" - -#include "WVCryptoFactory.h" -#include "WVDrmFactory.h" - -extern "C" { - -android::DrmFactory* createDrmFactory() { - return new wvdrm::WVDrmFactory(); -} - -android::CryptoFactory* createCryptoFactory() { - return new wvdrm::WVCryptoFactory(); -} - -} // extern "C" diff --git a/libwvdrmengine/src/WVCryptoFactory.cpp b/libwvdrmengine/src/WVCryptoFactory.cpp deleted file mode 100644 index c1e3fad4..00000000 --- a/libwvdrmengine/src/WVCryptoFactory.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WVCdm" -#include - -#include "WVCryptoFactory.h" - -#include - -#include "utils/Errors.h" -#include "WVCDMSingleton.h" -#include "WVCryptoPlugin.h" -#include "WVUUID.h" - -namespace wvdrm { - -using namespace android; - -bool WVCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const { - return isWidevineUUID(uuid); -} - -status_t WVCryptoFactory::createPlugin(const uint8_t uuid[16], const void* data, - size_t size, CryptoPlugin** plugin) { - if (!isCryptoSchemeSupported(uuid)) { - *plugin = NULL; - return BAD_VALUE; - } - - *plugin = new WVCryptoPlugin(data, size, getCDM()); - return OK; -} - -} // namespace wvdrm diff --git a/libwvdrmengine/src/WVDrmFactory.cpp b/libwvdrmengine/src/WVDrmFactory.cpp deleted file mode 100644 index 1571f8f4..00000000 --- a/libwvdrmengine/src/WVDrmFactory.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WVCdm" -#include - -#include "WVDrmFactory.h" - -#include "utils/Errors.h" -#include "wv_cdm_constants.h" -#include "WVCDMSingleton.h" -#include "wv_content_decryption_module.h" -#include "WVDrmPlugin.h" -#include "WVUUID.h" - -namespace wvdrm { - -using namespace android; - -WVGenericCryptoInterface WVDrmFactory::sOemCryptoInterface; - -bool WVDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) { - return isWidevineUUID(uuid); -} - -bool WVDrmFactory::isContentTypeSupported(const String8 &initDataType) { - return wvcdm::WvContentDecryptionModule::IsSupported(initDataType.string()); -} - -status_t WVDrmFactory::createDrmPlugin(const uint8_t uuid[16], - DrmPlugin** plugin) { - if (!isCryptoSchemeSupported(uuid)) { - *plugin = NULL; - return BAD_VALUE; - } - - *plugin = new WVDrmPlugin(getCDM(), &sOemCryptoInterface); - - return OK; -} - -} // namespace wvdrm diff --git a/libwvdrmengine/test/unit/Android.mk b/libwvdrmengine/test/unit/Android.mk index a9cd618e..e7b613a5 100644 --- a/libwvdrmengine/test/unit/Android.mk +++ b/libwvdrmengine/test/unit/Android.mk @@ -1,55 +1,5 @@ LOCAL_PATH:= $(call my-dir) -# ----------------------------------------------------------------------------- -# Builds libwvdrmengine_test -# -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - legacy_src/WVCreatePluginFactories_test.cpp \ - legacy_src/WVCryptoFactory_test.cpp \ - legacy_src/WVDrmFactory_test.cpp \ - -LOCAL_C_INCLUDES := \ - frameworks/av/include \ - frameworks/native/include \ - vendor/widevine/libwvdrmengine/include \ - vendor/widevine/libwvdrmengine/mediadrm/include \ - vendor/widevine/libwvdrmengine/oemcrypto/include \ - -LOCAL_STATIC_LIBRARIES := \ - libgtest \ - libgtest_main \ - -LOCAL_SHARED_LIBRARIES := \ - libcrypto \ - libdl \ - liblog \ - libutils \ - libwvdrmengine \ - -LOCAL_HEADER_LIBRARIES := \ - libstagefright_headers \ - libstagefright_foundation_headers \ - -LOCAL_MODULE := libwvdrmengine_test -LOCAL_LICENSE_KINDS := legacy_by_exception_only -LOCAL_LICENSE_CONDITIONS := by_exception_only - -LOCAL_MODULE_TAGS := tests - -LOCAL_MODULE_OWNER := widevine -LOCAL_PROPRIETARY_MODULE := true - -# When built, explicitly put it in the DATA/nativetest directory. -LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest - -ifneq ($(TARGET_ENABLE_MEDIADRM_64), true) -LOCAL_MODULE_TARGET_ARCH := arm x86 mips -endif - -include $(BUILD_EXECUTABLE) - # ----------------------------------------------------------------------------- # Builds libwvdrmengine_hidl_test # @@ -66,7 +16,6 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/include_hidl \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediadrm/include_hidl \ - vendor/widevine/libwvdrmengine/mediadrm/include \ vendor/widevine/libwvdrmengine/oemcrypto/include \ LOCAL_STATIC_LIBRARIES := \ diff --git a/libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp b/libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp deleted file mode 100644 index 8e3f34e9..00000000 --- a/libwvdrmengine/test/unit/legacy_src/WVCreatePluginFactories_test.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// - -#include "gtest/gtest.h" -#include "WVCreatePluginFactories.h" - -#include - -using namespace android; - -TEST(CreatePluginFactoriesTest, CreatesDrmFactory) { - std::unique_ptr factory(createDrmFactory()); - - EXPECT_NE((DrmFactory*)NULL, factory.get()) << - "createDrmFactory() returned null"; -} - -TEST(CreatePluginFactoriesTest, CreatesCryptoFactory) { - std::unique_ptr factory(createCryptoFactory()); - - EXPECT_NE((CryptoFactory*)NULL, factory.get()) << - "createCryptoFactory() returned null"; -} diff --git a/libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp b/libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp deleted file mode 100644 index 5dbfa8e8..00000000 --- a/libwvdrmengine/test/unit/legacy_src/WVCryptoFactory_test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary - * source code may only be used and distributed under the Widevine License - * Agreement. - */ - -#include "gtest/gtest.h" -#include "WVCryptoFactory.h" - -#include - -using namespace wvdrm; - -const uint8_t kWidevineUUID[16] = { - 0xED,0xEF,0x8B,0xA9,0x79,0xD6,0x4A,0xCE, - 0xA3,0xC8,0x27,0xDC,0xD5,0x1D,0x21,0xED -}; - -const uint8_t kOldNetflixWidevineUUID[16] = { - 0x29,0x70,0x1F,0xE4,0x3C,0xC7,0x4A,0x34, - 0x8C,0x5B,0xAE,0x90,0xC7,0x43,0x9A,0x47 -}; - -const uint8_t kUnknownUUID[16] = { - 0x6A,0x7F,0xAA,0xB0,0x83,0xC7,0x9E,0x20, - 0x08,0xBC,0xEF,0x32,0x34,0x1A,0x9A,0x26 -}; - -TEST(WVCryptoFactoryTest, SupportsSupportedCryptoSchemes) { - std::unique_ptr factory(new WVCryptoFactory()); - - EXPECT_TRUE(factory->isCryptoSchemeSupported(kWidevineUUID)) << - "WVPluginFactory does not support Widevine's UUID"; - - EXPECT_TRUE(factory->isCryptoSchemeSupported(kOldNetflixWidevineUUID)) << - "WVPluginFactory does not support the old Netflix Widevine UUID"; -} - -TEST(WVCryptoFactoryTest, DoesNotSupportUnsupportedCryptoSchemes) { - std::unique_ptr factory(new WVCryptoFactory()); - - EXPECT_FALSE(factory->isCryptoSchemeSupported(kUnknownUUID)) << - "WVPluginFactory incorrectly claims to support an unknown UUID"; -} diff --git a/libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp b/libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp deleted file mode 100644 index 841d0493..00000000 --- a/libwvdrmengine/test/unit/legacy_src/WVDrmFactory_test.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary - * source code may only be used and distributed under the Widevine License - * Agreement. - */ - -#include "gtest/gtest.h" -#include "WVDrmFactory.h" - -using namespace wvdrm; -using namespace android; - -const uint8_t kWidevineUUID[16] = { - 0xED,0xEF,0x8B,0xA9,0x79,0xD6,0x4A,0xCE, - 0xA3,0xC8,0x27,0xDC,0xD5,0x1D,0x21,0xED -}; - -const uint8_t kOldNetflixWidevineUUID[16] = { - 0x29,0x70,0x1F,0xE4,0x3C,0xC7,0x4A,0x34, - 0x8C,0x5B,0xAE,0x90,0xC7,0x43,0x9A,0x47 -}; - -const uint8_t kUnknownUUID[16] = { - 0x6A,0x7F,0xAA,0xB0,0x83,0xC7,0x9E,0x20, - 0x08,0xBC,0xEF,0x32,0x34,0x1A,0x9A,0x26 -}; - -TEST(WVDrmFactoryTest, SupportsSupportedCryptoSchemes) { - WVDrmFactory factory; - - EXPECT_TRUE(factory.isCryptoSchemeSupported(kWidevineUUID)) << - "WVPluginFactory does not support Widevine's UUID"; - - EXPECT_TRUE(factory.isCryptoSchemeSupported(kOldNetflixWidevineUUID)) << - "WVPluginFactory does not support the old Netflix Widevine UUID"; -} - -TEST(WVDrmFactoryTest, DoesNotSupportUnsupportedCryptoSchemes) { - WVDrmFactory factory; - - EXPECT_FALSE(factory.isCryptoSchemeSupported(kUnknownUUID)) << - "WVPluginFactory incorrectly claims to support an unknown UUID"; -} - -TEST(WVDrmFactoryTest, SupportsSupportedContainerFormats) { - WVDrmFactory factory; - - EXPECT_TRUE(factory.isContentTypeSupported(String8("video/mp4"))) << - "WVPluginFactory does not support ISO-BMFF video"; - - EXPECT_TRUE(factory.isContentTypeSupported(String8("audio/mp4"))) << - "WVPluginFactory does not support ISO-BMFF audio"; - - EXPECT_TRUE(factory.isContentTypeSupported(String8("video/webm"))) << - "WVPluginFactory does not support WebM video"; - - EXPECT_TRUE(factory.isContentTypeSupported(String8("audio/webm"))) << - "WVPluginFactory does not support WebM audio"; -} - -TEST(WVDrmFactoryTest, DoesNotSupportUnsupportedContainerFormats) { - WVDrmFactory factory; - - // Taken from Encoding.com's list of the most common internet video MIME-types - EXPECT_FALSE(factory.isContentTypeSupported(String8("video/x-matroska"))) << - "WVPluginFactory incorrectly claims to support Matroska"; - - EXPECT_FALSE(factory.isContentTypeSupported(String8("video/x-flv"))) << - "WVPluginFactory incorrectly claims to support Flash Video"; - - EXPECT_FALSE(factory.isContentTypeSupported(String8("application/x-mpegURL"))) << - "WVPluginFactory incorrectly claims to support m3u8 Indexes"; - - EXPECT_FALSE(factory.isContentTypeSupported(String8("video/MP2T"))) << - "WVPluginFactory incorrectly claims to support MPEG-2 TS"; - - EXPECT_FALSE(factory.isContentTypeSupported(String8("video/3gpp"))) << - "WVPluginFactory incorrectly claims to support 3GP Mobile"; - - EXPECT_FALSE(factory.isContentTypeSupported(String8("video/quicktime"))) << - "WVPluginFactory incorrectly claims to support Quicktime"; - - EXPECT_FALSE(factory.isContentTypeSupported(String8("video/x-msvideo"))) << - "WVPluginFactory incorrectly claims to support AVI"; - - EXPECT_FALSE(factory.isContentTypeSupported(String8("video/x-ms-wmv"))) << - "WVPluginFactory incorrectly claims to support WMV"; -} diff --git a/tests/Android.mk b/tests/Android.mk index 0bc2668a..0bec3f8d 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -27,11 +27,8 @@ WIDEVINE_TEST_MAKE_TARGETS += \ http_socket_test \ initialization_data_unittest \ libwvdrmdrmplugin_hidl_test \ - libwvdrmdrmplugin_test \ libwvdrmengine_hidl_test \ - libwvdrmengine_test \ libwvdrmmediacrypto_hidl_test \ - libwvdrmmediacrypto_test \ license_keys_unittest \ license_unittest \ odk_test \