From ce6bd416275d5a91aded9b2330b5547d4f5ae0b3 Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Tue, 11 Apr 2017 11:58:33 -0700 Subject: [PATCH 1/2] Define Provisioning-Unique ID for New Device IDs (This is a merge of wvgerrit/25583) Devices that use Provisioning 3.0 did not have a Provisioning-Unique ID defined. Attempting to retrieve it would result in an error. Devices that use SPOIDs with keyboxes would expose the keybox's real Provisioning-Unique ID when asked. This is a security flaw. To solve both cases, an alternative Provisioning-Unique ID is used, consisting of the Device-Unique ID bitwise-inverted. Bug: 36065223 Test: run_all_unit_tests.sh Change-Id: I32512a3e11403e679939187e156904a57a9e24ef --- .../cdm/core/src/crypto_session.cpp | 47 ++++++++++++------- .../mediadrm/include_hidl/WVDrmPlugin.h | 1 + .../mediadrm/src_hidl/WVDrmPlugin.cpp | 24 +++++++++- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 4962d870..f62cd347 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -374,23 +374,38 @@ bool CryptoSession::GetProvisioningId(std::string* provisioning_id) { if (!initialized_) { return false; } - OEMCryptoResult sts; - M_TIME( - sts = OEMCrypto_GetKeyData( - buf, - &buf_size, - requested_security_level_), - metrics_, - oemcrypto_get_key_data_, - sts, - metrics::Pow2Bucket(buf_size), - requested_security_level_); - if (OEMCrypto_SUCCESS != sts) { - return false; - } - provisioning_id->assign(reinterpret_cast(&buf[8]), 16); - return true; + if (pre_provision_token_type_ == kClientTokenOemCert) { + // OEM Cert devices have no provisioning-unique ID embedded in them, so we + // synthesize one by using the External Device-Unique ID and inverting all + // the bits. + if (!GetExternalDeviceUniqueId(provisioning_id)) return false; + + for (size_t i = 0; i < provisioning_id->size(); ++i) { + char value = (*provisioning_id)[i]; + (*provisioning_id)[i] = ~value; + } + + return true; + } else { + OEMCryptoResult sts; + M_TIME( + sts = OEMCrypto_GetKeyData( + buf, + &buf_size, + requested_security_level_), + metrics_, + oemcrypto_get_key_data_, + sts, + metrics::Pow2Bucket(buf_size), + requested_security_level_); + if (OEMCrypto_SUCCESS != sts) { + return false; + } + + provisioning_id->assign(reinterpret_cast(&buf[8]), 16); + return true; + } } uint8_t CryptoSession::GetSecurityPatchLevel() { diff --git a/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h index 4e283b2c..1aa89a46 100644 --- a/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h +++ b/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h @@ -323,6 +323,7 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, // On SPOID devices, calling this will seal the CDM Identifier Builder, thus // making it an error to change the origin. status_t getDeviceUniqueId(std::string* id); + status_t getProvisioningUniqueId(std::string* id); const std::string& origin() const { return mCdmIdentifier.origin; } bool set_origin(const std::string& id); diff --git a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp index ab668fa4..bcbe9903 100644 --- a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp @@ -678,7 +678,11 @@ Return WVDrmPlugin::getPropertyByteArray( value = StrToVector(id); } } else if (name == "provisioningUniqueId") { - status = queryProperty(wvcdm::QUERY_KEY_PROVISIONING_ID, value); + std::string id; + status = mCdmIdentifierBuilder.getProvisioningUniqueId(&id); + if (status == android::OK) { + value = StrToVector(id); + } } else if (name == "serviceCertificate") { value = StrToVector(mPropertySet.service_certificate()); } else { @@ -1343,6 +1347,24 @@ status_t WVDrmPlugin::CdmIdentifierBuilder::getDeviceUniqueId(std::string* id) { } } +status_t WVDrmPlugin::CdmIdentifierBuilder::getProvisioningUniqueId(std::string* id) { + if (mUseSpoid) { + // To fake a provisioning-unique ID on SPOID devices where we can't expose + // the real provisioning-unique ID, we just use the SPOID and invert all the + // bits. + status_t res = getDeviceUniqueId(id); + if (res != android::OK) return res; + + for (char& c : *id) { + c = ~c; + } + + return android::OK; + } else { + return mParent.queryProperty(wvcdm::QUERY_KEY_PROVISIONING_ID, *id); + } +} + bool WVDrmPlugin::CdmIdentifierBuilder::set_origin(const std::string& id) { if (mIsIdentifierSealed) return false; mCdmIdentifier.origin = id; From 68d26ef98b42c2fb84d4a63b2b6cd5ad7b7d987a Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Wed, 19 Apr 2017 16:48:14 -0700 Subject: [PATCH 2/2] Remove API Version TODO Comments (This is a merge of http://go/wvgerrit/26221) We have agreed on API 26 for O, so these comments can be removed without making any further changes. Bug: 34548395 Test: This is a comment-only change. But I verified it builds. Change-Id: I490befba4f47902a84b60e562a7a5eb162a9f3be --- libwvdrmengine/src_hidl/WVDrmFactory.cpp | 1 - libwvdrmengine/test/unit/WVDrmFactory_test.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/libwvdrmengine/src_hidl/WVDrmFactory.cpp b/libwvdrmengine/src_hidl/WVDrmFactory.cpp index be688053..533e0d90 100644 --- a/libwvdrmengine/src_hidl/WVDrmFactory.cpp +++ b/libwvdrmengine/src_hidl/WVDrmFactory.cpp @@ -63,7 +63,6 @@ bool WVDrmFactory::areSpoidsEnabled() { // version is the first if it's a factory ROM. firstApiLevel = property_get_int32("ro.build.version.sdk", 0); } - // TODO(juce): b/34548395 Make sure this API version is correct. return firstApiLevel >= 26; // Android O } diff --git a/libwvdrmengine/test/unit/WVDrmFactory_test.cpp b/libwvdrmengine/test/unit/WVDrmFactory_test.cpp index 4336d979..52fa2bad 100644 --- a/libwvdrmengine/test/unit/WVDrmFactory_test.cpp +++ b/libwvdrmengine/test/unit/WVDrmFactory_test.cpp @@ -104,7 +104,6 @@ TEST(WVDrmFactoryTest, CalculatesSpoidUseCorrectly) { // version is the first if it's a factory ROM. firstApiLevel = property_get_int32("ro.build.version.sdk", 0); } - // TODO(juce): b/34548395 Make sure this API version is correct. bool shouldUseSpoids = (firstApiLevel >= 26); // Android O EXPECT_EQ(shouldUseSpoids, factory.areSpoidsEnabled()) <<