Merge "WVDrmPlugin changes to query device CSR payload for prov 4" into udc-widevine-dev

This commit is contained in:
Cong Lin
2023-07-21 06:23:26 +00:00
committed by Android (Google) Code Review
4 changed files with 110 additions and 23 deletions

View File

@@ -11,7 +11,7 @@
#include <memory>
#include <mutex>
#include <utils/RefBase.h>
#include "utils/RefBase.h"
#include "cdm_identifier.h"
#include "disallow_copy_and_assign.h"
@@ -135,6 +135,11 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
virtual CdmResponseType QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
// Query device CSR information for Provisioning 4.0
virtual CdmResponseType QueryDeviceSignedCsrPayload(
const std::string& challenge, const std::string& device_info,
std::string* value);
// Query OEMCrypto session ID
virtual CdmResponseType QueryOemCryptoSessionId(
const CdmSessionId& session_id, CdmQueryMap* response);

View File

@@ -305,6 +305,13 @@ CdmResponseType WvContentDecryptionModule::QueryOemCryptoSessionId(
return cdm_engine->QueryOemCryptoSessionId(session_id, response);
}
CdmResponseType WvContentDecryptionModule::QueryDeviceSignedCsrPayload(
const std::string& challenge, const std::string& device_info,
std::string* value) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
return cdm_engine->QueryDeviceSignedCsrPayload(challenge, device_info, value);
}
bool WvContentDecryptionModule::IsSecurityLevelSupported(
CdmSecurityLevel level) {
return CdmEngine::IsSecurityLevelSupported(level);

View File

@@ -42,7 +42,7 @@ const OEMCrypto_Algorithm kInvalidCryptoAlgorithm =
static_cast<OEMCrypto_Algorithm>(-1);
class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin,
wvcdm::WvCdmEventListener {
wvcdm::WvCdmEventListener {
public:
WVDrmPlugin(const android::sp<WvContentDecryptionModule>& cdm,
const std::string& appPackageName,
@@ -462,6 +462,9 @@ class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin,
std::string mAppPackageName;
std::string mCertificateSigningRequestChallenge;
std::string mDeviceInfo;
::ndk::SpAIBinder createBinder() override;
WvStatus queryProperty(const std::string& property,

View File

@@ -4,7 +4,7 @@
// Agreement.
//
//#define LOG_NDEBUG 0
// #define LOG_NDEBUG 0
#define LOG_TAG "WVCdm"
#include "WVDrmPlugin.h"
@@ -154,6 +154,12 @@ HdcpLevel mapHdcpLevel(const std::string& level) {
}
}
bool isRootOrShell() {
const uid_t AID_ROOT = 0, AID_SHELL = 2000;
const uid_t uid = AIBinder_getCallingUid();
return (uid == AID_ROOT || uid == AID_SHELL);
}
} // namespace
WVDrmPlugin::WVDrmPlugin(const android::sp<WvContentDecryptionModule>& cdm,
@@ -759,7 +765,8 @@ Status WVDrmPlugin::unprovisionDevice() {
}
drm_metrics::WvCdmMetrics proto_metrics;
const CdmResponseType result = mCDM->GetCurrentMetrics(identifier, &proto_metrics);
const CdmResponseType result =
mCDM->GetCurrentMetrics(identifier, &proto_metrics);
if (result != wvcdm::NO_ERROR) {
return toNdkScopedAStatus(mapCdmResponseType(result));
}
@@ -1066,7 +1073,8 @@ Status WVDrmPlugin::unprovisionDevice() {
value = info->name;
} else {
auto err = info.error();
ALOGW("apex info error %d: %s", err.code().value(), err.message().c_str());
ALOGW("apex info error %d: %s", err.code().value(),
err.message().c_str());
value = "Google";
}
#else
@@ -1165,6 +1173,26 @@ Status WVDrmPlugin::unprovisionDevice() {
return toNdkScopedAStatus(status);
}
static WvStatus getDeviceSignedCsrPayload(
android::sp<wvcdm::WvContentDecryptionModule> const cdm,
std::string& certificate_signing_request_challenge,
std::string& device_info, std::string* csr) {
if (certificate_signing_request_challenge.empty() || device_info.empty()) {
ALOGW("CSR challenge or device info is empty.");
return WvStatus(Status::BAD_VALUE);
}
std::string signed_csr_payload;
CdmResponseType res = cdm->QueryDeviceSignedCsrPayload(
certificate_signing_request_challenge, device_info, &signed_csr_payload);
if (res != wvcdm::NO_ERROR) {
ALOGE("Error querying CDM device_signed_csr_payload: %d",
static_cast<int>(res));
return mapCdmResponseType(res);
}
*csr = signed_csr_payload;
return WvStatus(Status::OK);
}
::ndk::ScopedAStatus WVDrmPlugin::getPropertyByteArray(
const std::string& in_propertyName, vector<uint8_t>* _aidl_return) {
WvStatus status(Status::OK);
@@ -1210,6 +1238,42 @@ Status WVDrmPlugin::unprovisionDevice() {
value = StrToVector(serialized_metrics);
}
}
} else if (name == "bootCertificateChain" && isRootOrShell()) {
std::string boot_certificate_chain;
CdmResponseType res = mCDM->QueryStatus(
wvcdm::kLevelDefault, wvcdm::QUERY_KEY_DEBUG_BOOT_CERTIFICATE_CHAIN,
&boot_certificate_chain);
if (res != wvcdm::NO_ERROR) {
ALOGE("Error querying CDM boot certificate chain: %d",
static_cast<int>(res));
status = mapCdmResponseType(res);
} else {
value = StrToVector(boot_certificate_chain);
}
} else if (name == "verifiedDeviceInfo" && isRootOrShell()) {
std::string verified_device_info;
CdmResponseType res = mCDM->QueryStatus(wvcdm::kLevelDefault,
wvcdm::QUERY_KEY_DEVICE_INFORMATION,
&verified_device_info);
if (res != wvcdm::NO_ERROR) {
ALOGE("Error querying CDM verified device info: %d",
static_cast<int>(res));
status = mapCdmResponseType(res);
} else {
value = StrToVector(verified_device_info);
}
} else if (name == "deviceSignedCsrPayload" && isRootOrShell()) {
std::string signed_csr_payload;
status =
getDeviceSignedCsrPayload(mCDM, mCertificateSigningRequestChallenge,
mDeviceInfo, &signed_csr_payload);
if (status != Status::OK) {
ALOGE("Error querying CDM signed CSR payload: %d", status.get());
} else {
value = StrToVector(signed_csr_payload);
}
mCertificateSigningRequestChallenge.clear();
mDeviceInfo.clear();
} else {
ALOGE("App requested unknown byte array property %s", name.c_str());
status = WvStatus(Status::ERROR_DRM_CANNOT_HANDLE);
@@ -1349,8 +1413,9 @@ Status WVDrmPlugin::unprovisionDevice() {
}
} else if (name == "storeAtscLicense") {
if (!mCdmIdentifierBuilder.is_sealed()) {
ALOGE("Cdm identifier builder is not sealed. Storing ATSC license "
"prohibited");
ALOGE(
"Cdm identifier builder is not sealed. Storing ATSC license "
"prohibited");
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
}
if (!mPropertySet.use_atsc_mode()) {
@@ -1366,8 +1431,7 @@ Status WVDrmPlugin::unprovisionDevice() {
}
std::string key_set_id, license_data;
status = parseAtscLicenseData(_value, &key_set_id, &license_data);
if (status != Status::OK)
return toNdkScopedAStatus(status);
if (status != Status::OK) return toNdkScopedAStatus(status);
const CdmResponseType res = mCDM->StoreAtscLicense(
identifier, getRequestedSecurityLevel(), key_set_id, license_data);
@@ -1400,6 +1464,11 @@ Status WVDrmPlugin::unprovisionDevice() {
} else {
return toNdkScopedAStatus(Status::BAD_VALUE);
}
} else if (name == "certificateSigningRequestChallenge" && isRootOrShell()) {
mCertificateSigningRequestChallenge =
std::string(_value.begin(), _value.end());
} else if (name == "deviceInfo" && isRootOrShell()) {
mDeviceInfo = std::string(_value.begin(), _value.end());
} else {
ALOGE("App set unknown byte array property %s", name.c_str());
return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE);
@@ -1830,8 +1899,7 @@ bool WVDrmPlugin::isProvisioned(wvcdm::CdmSecurityLevel securityLevel,
}
WvStatus WVDrmPlugin::parseAtscLicenseData(
const std::string& in_value,
std::string* key_set_id,
const std::string& in_value, std::string* key_set_id,
std::string* serialized_license_data) {
if (key_set_id == nullptr) {
ALOGE("key_set_id null");
@@ -1843,34 +1911,39 @@ WvStatus WVDrmPlugin::parseAtscLicenseData(
return WvStatus(Status::ERROR_DRM_CANNOT_HANDLE);
}
if (in_value.compare(0,
strlen(wvcdm::ATSC_KEY_SET_ID_PREFIX),
if (in_value.compare(0, strlen(wvcdm::ATSC_KEY_SET_ID_PREFIX),
&wvcdm::ATSC_KEY_SET_ID_PREFIX[0]) != 0) {
ALOGE("ATSC license input does not conform to expectations. Key set does "
"not have a valid ATSC Key set prefix %s", in_value.c_str());
ALOGE(
"ATSC license input does not conform to expectations. Key set does "
"not have a valid ATSC Key set prefix %s",
in_value.c_str());
return WvStatus(Status::BAD_VALUE);
}
const char kColon = ':';
const size_t pos = in_value.find(kColon);
if (pos == std::string::npos) {
ALOGE("ATSC license input does not conform to expectations. Missing colon "
"= %s", in_value.c_str());
ALOGE(
"ATSC license input does not conform to expectations. Missing colon "
"= %s",
in_value.c_str());
return WvStatus(Status::BAD_VALUE);
}
if (pos == in_value.length()) {
ALOGE("ATSC license input does not conform to expectations. No data after "
"colon");
ALOGE(
"ATSC license input does not conform to expectations. No data after "
"colon");
return WvStatus(Status::BAD_VALUE);
}
*key_set_id = in_value.substr(0, pos);
const std::vector<uint8_t> license_data_binary =
wvutil::Base64Decode(in_value.substr(pos+1));
wvutil::Base64Decode(in_value.substr(pos + 1));
if (license_data_binary.empty()) {
ALOGE("ATSC license input does not conform to expectations. License data "
"failed to decode from Base64");
ALOGE(
"ATSC license input does not conform to expectations. License data "
"failed to decode from Base64");
return WvStatus(Status::BAD_VALUE);
}
serialized_license_data->assign(license_data_binary.begin(),
@@ -1879,7 +1952,6 @@ WvStatus WVDrmPlugin::parseAtscLicenseData(
return WvStatus(Status::OK);
}
WvStatus WVDrmPlugin::mapAndNotifyOfCdmResponseType(
const vector<uint8_t>& sessionId, CdmResponseType res) {
notifyOfCdmResponseType(sessionId, res);