diff --git a/libwvdrmengine/cdm/core/include/crypto_engine.h b/libwvdrmengine/cdm/core/include/crypto_engine.h index 4efa40bc..f6f99b34 100644 --- a/libwvdrmengine/cdm/core/include/crypto_engine.h +++ b/libwvdrmengine/cdm/core/include/crypto_engine.h @@ -6,6 +6,7 @@ #define CDM_BASE_CRYPTO_ENGINE_H_ #include +#include #include #include "crypto_session.h" @@ -51,6 +52,7 @@ class CryptoEngine { SecurityLevel GetSecurityLevel(); bool GetDeviceUniqueId(std::string* deviceId); bool GetSystemId(uint32_t* systemId); + bool GetProvisioningId(std::string* provisioningId); private: diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index 6253a845..06cfafed 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -17,6 +17,7 @@ static const size_t KEY_IV_SIZE = 16; static const size_t KEY_PAD_SIZE = 16; static const size_t KEY_SIZE = 16; static const size_t MAC_KEY_SIZE = 32; +static const size_t KEYBOX_KEY_DATA_SIZE = 72; static const std::string SESSION_ID_PREFIX = "sid"; static const std::string KEY_SET_ID_PREFIX = "ksid"; @@ -46,6 +47,8 @@ static const std::string QUERY_KEY_DEVICE_ID = "DeviceID"; // device unique id static const std::string QUERY_KEY_SYSTEM_ID = "SystemID"; // system id +static const std::string QUERY_KEY_PROVISIONING_ID = "ProvisioningID"; + // provisioning unique id static const std::string QUERY_VALUE_TRUE = "True"; static const std::string QUERY_VALUE_FALSE = "False"; diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index e5709e33..fcaed864 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -403,6 +403,12 @@ CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) { (*key_info)[QUERY_KEY_SYSTEM_ID] = system_id_stream.str(); } + std::string provisioning_id; + success = crypto_engine->GetProvisioningId(&provisioning_id); + if (success) { + (*key_info)[QUERY_KEY_PROVISIONING_ID] = provisioning_id; + } + return NO_ERROR; } diff --git a/libwvdrmengine/cdm/core/src/crypto_engine.cpp b/libwvdrmengine/cdm/core/src/crypto_engine.cpp index 67dcb196..76425d94 100644 --- a/libwvdrmengine/cdm/core/src/crypto_engine.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_engine.cpp @@ -168,13 +168,13 @@ bool CryptoEngine::GetToken(std::string* token) { LOGE("CryptoEngine::GetToken : No token passed to method."); return false; } - uint8_t buf[72]; - size_t buflen = 72; - OEMCryptoResult sts = OEMCrypto_GetKeyData(buf, &buflen); + uint8_t buf[KEYBOX_KEY_DATA_SIZE]; + size_t bufSize = sizeof(buf); + OEMCryptoResult sts = OEMCrypto_GetKeyData(buf, &bufSize); if (OEMCrypto_SUCCESS != sts) { return false; } - token->assign((const char*)buf, (size_t)buflen); + token->assign((const char*)buf, bufSize); return true; } @@ -182,6 +182,9 @@ CryptoEngine::SecurityLevel CryptoEngine::GetSecurityLevel() { if (!Init()) return kSecurityLevelUnknown; + LOGV("CryptoEngine::GetSecurityLevel: Lock"); + AutoLock auto_lock(crypto_lock_); + std::string security_level = OEMCrypto_SecurityLevel(); if ((security_level.size() != 2) || @@ -203,6 +206,14 @@ bool CryptoEngine::GetDeviceUniqueId(std::string* deviceId) { if (!Init()) return false; + if (!deviceId) { + LOGE("CryptoEngine::GetDeviceUniqueId : No buffer passed to method."); + return false; + } + + LOGV("CryptoEngine::GetDeviceUniqueId: Lock"); + AutoLock auto_lock(crypto_lock_); + std::vector id; size_t idLength = 32; @@ -222,10 +233,18 @@ bool CryptoEngine::GetSystemId(uint32_t* systemId) { if (!Init()) return false; - uint8_t buf[72]; - size_t buflen = 72; + if (!systemId) { + LOGE("CryptoEngine::GetSystemId : No buffer passed to method."); + return false; + } - OEMCryptoResult sts = OEMCrypto_GetKeyData(buf, &buflen); + LOGV("CryptoEngine::GetSystemId: Lock"); + AutoLock auto_lock(crypto_lock_); + + uint8_t buf[KEYBOX_KEY_DATA_SIZE]; + size_t bufSize = sizeof(buf); + + OEMCryptoResult sts = OEMCrypto_GetKeyData(buf, &bufSize); if (OEMCrypto_SUCCESS != sts) { return false; @@ -239,4 +258,29 @@ bool CryptoEngine::GetSystemId(uint32_t* systemId) { return true; } +bool CryptoEngine::GetProvisioningId(std::string* provisioningId) { + if (!Init()) + return false; + + if (!provisioningId) { + LOGE("CryptoEngine::GetProvisioningId : No buffer passed to method."); + return false; + } + + LOGV("CryptoEngine::GetProvisioningId: Lock"); + AutoLock auto_lock(crypto_lock_); + + uint8_t buf[KEYBOX_KEY_DATA_SIZE]; + size_t bufSize = sizeof(buf); + + OEMCryptoResult sts = OEMCrypto_GetKeyData(buf, &bufSize); + + if (OEMCrypto_SUCCESS != sts) { + return false; + } + + provisioningId->assign(reinterpret_cast(&buf[8]), 16); + return true; +} + }; // namespace wvcdm diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index ee64410b..7aa6e93b 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -534,6 +534,10 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) { EXPECT_TRUE(ss >> system_id); EXPECT_TRUE(ss.eof()); + itr = query_info.find(wvcdm::QUERY_KEY_PROVISIONING_ID); + ASSERT_TRUE(itr != query_info.end()); + EXPECT_EQ(16, (int)itr->second.size()); + decryptor_.CloseSession(session_id_); } diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index a7fc09a7..543eddbb 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -382,12 +382,30 @@ status_t WVDrmPlugin::getPropertyByteArray(const String8& name, ALOGE("Error querying CDM status: %u", res); return mapCdmResponseType(res); } else if (!status.count(QUERY_KEY_DEVICE_ID)) { - ALOGE("CDM did not report a unique ID"); + ALOGE("CDM did not report a device unique ID"); return kErrorCDMGeneric; } const string& uniqueId = status[QUERY_KEY_DEVICE_ID]; + value.clear(); + value.appendArray(reinterpret_cast(uniqueId.data()), + uniqueId.size()); + } else if (name == "provisioningUniqueId") { + CdmQueryMap status; + + CdmResponseType res = mCDM->QueryStatus(&status); + + if (!isCdmResponseTypeSuccess(res)) { + ALOGE("Error querying CDM status: %u", res); + return mapCdmResponseType(res); + } else if (!status.count(QUERY_KEY_PROVISIONING_ID)) { + ALOGE("CDM did not report a provisioning unique ID"); + return kErrorCDMGeneric; + } + + const string& uniqueId = status[QUERY_KEY_PROVISIONING_ID]; + value.clear(); value.appendArray(reinterpret_cast(uniqueId.data()), uniqueId.size()); diff --git a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp index 8bd09c5a..bb00c18f 100644 --- a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp +++ b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp @@ -520,6 +520,10 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { CdmQueryMap systemIDMap; systemIDMap[QUERY_KEY_SYSTEM_ID] = systemId; + static const string provisioningId("Life\0&Everything", 16); + CdmQueryMap provisioningIDMap; + provisioningIDMap[QUERY_KEY_PROVISIONING_ID] = provisioningId; + EXPECT_CALL(cdm, QueryStatus(_)) .WillOnce(DoAll(SetArgPointee<0>(l1Map), Return(wvcdm::NO_ERROR))) @@ -528,6 +532,8 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { .WillOnce(DoAll(SetArgPointee<0>(deviceIDMap), Return(wvcdm::NO_ERROR))) .WillOnce(DoAll(SetArgPointee<0>(systemIDMap), + Return(wvcdm::NO_ERROR))) + .WillOnce(DoAll(SetArgPointee<0>(provisioningIDMap), Return(wvcdm::NO_ERROR))); String8 stringResult; @@ -564,6 +570,11 @@ TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) { 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())); } TEST_F(WVDrmPluginTest, DoesNotGetUnknownProperties) {