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
This commit is contained in:
John W. Bruce
2017-04-11 11:58:33 -07:00
parent 8513b71499
commit ce6bd41627
3 changed files with 55 additions and 17 deletions

View File

@@ -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<char*>(&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<char*>(&buf[8]), 16);
return true;
}
}
uint8_t CryptoSession::GetSecurityPatchLevel() {

View File

@@ -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);

View File

@@ -678,7 +678,11 @@ Return<void> 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;