Revise a few metrics and add unit tests.
This is a merge of Widevine cl 39040. A few of the metrics were not implemented, or implemented incorrectly in O MR1. This cleans them up Bug: 64001676 Test: Re-ran unit tests and added some additional tests. GPlay Movies check. Change-Id: I1e8bcc36fecd76e72d853306075bc46d82f45161
This commit is contained in:
@@ -75,7 +75,6 @@ class CryptoSession {
|
||||
explicit CryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
||||
virtual ~CryptoSession();
|
||||
|
||||
virtual bool GetClientToken(std::string* client_token);
|
||||
virtual bool GetProvisioningToken(std::string* client_token);
|
||||
virtual CdmClientTokenType GetPreProvisionTokenType() {
|
||||
return pre_provision_token_type_;
|
||||
@@ -227,6 +226,7 @@ class CryptoSession {
|
||||
bool GetTokenFromOemCert(std::string* token);
|
||||
static bool ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
uint32_t* system_id);
|
||||
bool GetSystemIdInternal(uint32_t* system_id);
|
||||
bool GenerateSignature(const std::string& message, std::string* signature);
|
||||
bool GenerateRsaSignature(const std::string& message, std::string* signature);
|
||||
|
||||
@@ -273,6 +273,7 @@ class CryptoSession {
|
||||
|
||||
metrics::CryptoMetrics* metrics_;
|
||||
metrics::TimerMetric life_span_;
|
||||
uint32_t system_id_;
|
||||
|
||||
bool open_;
|
||||
CdmClientTokenType pre_provision_token_type_;
|
||||
|
||||
@@ -318,6 +318,7 @@ enum CdmResponseType {
|
||||
RELEASE_ALL_USAGE_INFO_ERROR_7 = 276,
|
||||
LICENSE_REQUEST_INVALID_SUBLICENSE = 277,
|
||||
CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE = 278,
|
||||
LOAD_SYSTEM_ID_ERROR = 279,
|
||||
};
|
||||
|
||||
enum CdmKeyStatus {
|
||||
|
||||
@@ -480,17 +480,16 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
std::string* query_response) {
|
||||
LOGI("CdmEngine::QueryStatus");
|
||||
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
|
||||
if (security_level == kLevel3) {
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = crypto_session.Open(
|
||||
kLevel3),
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_open_,
|
||||
status,
|
||||
kLevel3);
|
||||
if (NO_ERROR != status) return INVALID_QUERY_STATUS;
|
||||
}
|
||||
CdmResponseType status;
|
||||
M_TIME(
|
||||
status = crypto_session.Open(
|
||||
security_level),
|
||||
metrics_.GetCryptoMetrics(),
|
||||
crypto_session_open_,
|
||||
status,
|
||||
security_level);
|
||||
if (status != NO_ERROR)
|
||||
return INVALID_QUERY_STATUS;
|
||||
|
||||
if (!query_response) {
|
||||
LOGE("CdmEngine::QueryStatus: no query response destination");
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Encode unsigned integer into a big endian formatted string
|
||||
std::string EncodeUint32(unsigned int u) {
|
||||
std::string s;
|
||||
@@ -32,6 +33,7 @@ std::string EncodeUint32(unsigned int u) {
|
||||
s.append(1, (u >> 0) & 0xFF);
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t GetOffset(std::string message, std::string field) {
|
||||
size_t pos = message.find(field);
|
||||
if (pos == std::string::npos) {
|
||||
@@ -40,6 +42,7 @@ size_t GetOffset(std::string message, std::string field) {
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
void GenerateMacContext(const std::string& input_context,
|
||||
std::string* deriv_context) {
|
||||
if (!deriv_context) {
|
||||
@@ -677,6 +680,7 @@ class SubLicenseKeySession : public KeySession {
|
||||
|
||||
CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
|
||||
: metrics_(metrics),
|
||||
system_id_(-1),
|
||||
open_(false),
|
||||
update_usage_table_after_close_session_(false),
|
||||
is_destination_buffer_type_valid_(false),
|
||||
@@ -700,9 +704,11 @@ CryptoSession::~CryptoSession() {
|
||||
}
|
||||
|
||||
bool CryptoSession::GetProvisioningMethod(CdmClientTokenType* token_type) {
|
||||
OEMCrypto_ProvisioningMethod method;
|
||||
OEMCrypto_ProvisioningMethod method =
|
||||
OEMCrypto_GetProvisioningMethod(requested_security_level_);
|
||||
metrics_->oemcrypto_provisioning_method_.Record(method);
|
||||
CdmClientTokenType type;
|
||||
switch (method = OEMCrypto_GetProvisioningMethod(requested_security_level_)) {
|
||||
switch (method) {
|
||||
case OEMCrypto_OEMCertificate:
|
||||
type = kClientTokenOemCert;
|
||||
break;
|
||||
@@ -714,7 +720,8 @@ bool CryptoSession::GetProvisioningMethod(CdmClientTokenType* token_type) {
|
||||
break;
|
||||
case OEMCrypto_ProvisioningError:
|
||||
default:
|
||||
LOGE("OEMCrypto_GetProvisioningMethod failed", method);
|
||||
LOGE("OEMCrypto_GetProvisioningMethod failed. %d", method);
|
||||
metrics_->oemcrypto_provisioning_method_.SetError(method);
|
||||
return false;
|
||||
}
|
||||
*token_type = type;
|
||||
@@ -805,13 +812,14 @@ bool CryptoSession::GetTokenFromOemCert(std::string* token) {
|
||||
size_t buf_size = temp_buffer.size();
|
||||
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
|
||||
status = OEMCrypto_GetOEMPublicCertificate(oec_session_id_, buf, &buf_size);
|
||||
metrics_->oemcrypto_get_oem_public_certificate_.Increment(status);
|
||||
if (OEMCrypto_SUCCESS == status) {
|
||||
temp_buffer.resize(buf_size);
|
||||
oem_token_.assign(temp_buffer);
|
||||
token->assign(temp_buffer);
|
||||
return true;
|
||||
}
|
||||
if (OEMCrypto_ERROR_SHORT_BUFFER && !retrying) {
|
||||
if (status == OEMCrypto_ERROR_SHORT_BUFFER && !retrying) {
|
||||
temp_buffer.resize(buf_size);
|
||||
retrying = true;
|
||||
continue;
|
||||
@@ -821,42 +829,28 @@ bool CryptoSession::GetTokenFromOemCert(std::string* token) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CryptoSession::GetClientToken(std::string* token) {
|
||||
if (!token) {
|
||||
LOGE("CryptoSession::GetClientToken : No token passed to method.");
|
||||
return false;
|
||||
}
|
||||
LOGV("CryptoSession::GetClientToken: Lock");
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!initialized_) {
|
||||
return false;
|
||||
}
|
||||
// Only keybox is used for client token. All other cases use DRM Cert.
|
||||
if (pre_provision_token_type_ != kClientTokenKeybox) {
|
||||
return false;
|
||||
}
|
||||
return GetTokenFromKeybox(token);
|
||||
}
|
||||
|
||||
bool CryptoSession::GetProvisioningToken(std::string* token) {
|
||||
if (!token) {
|
||||
LOGE("CryptoSession::GetProvisioningToken : No token passed to method.");
|
||||
metrics_->crypto_session_get_token_.Increment(false);
|
||||
return false;
|
||||
}
|
||||
LOGV("CryptoSession::GetProvisioningToken: Lock");
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
|
||||
if (!initialized_) {
|
||||
metrics_->crypto_session_get_token_.Increment(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
if (pre_provision_token_type_ == kClientTokenKeybox) {
|
||||
return GetTokenFromKeybox(token);
|
||||
result = GetTokenFromKeybox(token);
|
||||
} else if (pre_provision_token_type_ == kClientTokenOemCert) {
|
||||
return GetTokenFromOemCert(token);
|
||||
} else {
|
||||
return false;
|
||||
result = GetTokenFromOemCert(token);
|
||||
}
|
||||
metrics_->crypto_session_get_token_.Increment(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
CdmSecurityLevel CryptoSession::GetSecurityLevel() {
|
||||
@@ -977,7 +971,19 @@ bool CryptoSession::GetSystemId(uint32_t* system_id) {
|
||||
|
||||
LOGV("CryptoSession::GetSystemId: Lock");
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!initialized_) {
|
||||
if (!initialized_ || !open_) {
|
||||
return false;
|
||||
}
|
||||
*system_id = system_id_;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This method gets the system id from the keybox key data.
|
||||
// This method assumes that OEMCrypto has been initialized and that
|
||||
// the caller has acquired the crypto_lock_ before making this call.
|
||||
bool CryptoSession::GetSystemIdInternal(uint32_t* system_id) {
|
||||
if (!system_id) {
|
||||
LOGE("CryptoSession::GetSystemIdInternal: No system_id passed to method.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -991,8 +997,8 @@ bool CryptoSession::GetSystemId(uint32_t* system_id) {
|
||||
metrics_, oemcrypto_get_key_data_, sts, metrics::Pow2Bucket(buf_size));
|
||||
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
LOGE("CryptoSession::GetSystemId: OEMCrypto_GetKeyData failed with %d",
|
||||
sts);
|
||||
LOGE("CryptoSession::GetSystemIdInternal: "
|
||||
"OEMCrypto_GetKeyData failed with %d", sts);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1010,9 +1016,13 @@ bool CryptoSession::GetSystemId(uint32_t* system_id) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (pre_provision_token_type_ == kClientTokenDrmCert) {
|
||||
// TODO(blueeyes): Support loading the system id from a pre-provisioned
|
||||
// Drm certificate.
|
||||
return true;
|
||||
} else {
|
||||
LOGE("CryptoSession::GetSystemId: Unsupported pre-provision token type %d",
|
||||
pre_provision_token_type_);
|
||||
LOGE("CryptoSession::GetSystemIdInternal: "
|
||||
"Unsupported pre-provision token type %d", pre_provision_token_type_);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1023,7 +1033,8 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||
sk_X509_new_null());
|
||||
if (x509_stack.get() == NULL) {
|
||||
LOGE("CryptoSession::GetSystemId: Unable to allocate X509 Stack.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Unable to allocate X509 Stack.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1031,7 +1042,8 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
CBS_init(&pkcs7, reinterpret_cast<const uint8_t*>(oem_cert.data()),
|
||||
oem_cert.size());
|
||||
if (!PKCS7_get_certificates(x509_stack.get(), &pkcs7)) {
|
||||
LOGE("CryptoSession::GetSystemId: Error getting certificate chain.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Error getting certificate chain.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1039,14 +1051,16 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
|
||||
// Get the Widevine intermediate cert from the stack
|
||||
if (sk_X509_num(certs) != 2) {
|
||||
LOGE("CryptoSession::GetSystemId: Expected 2 certificates in chain, got %d",
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Expected 2 certificates in chain, got %d",
|
||||
sk_X509_num(certs));
|
||||
return false;
|
||||
}
|
||||
|
||||
X509* const intermediate_cert = sk_X509_value(certs, 1);
|
||||
if (!intermediate_cert) {
|
||||
LOGE("CryptoSession::GetSystemId: Unable to get intermediate cert.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Unable to get intermediate cert.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1055,16 +1069,15 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
for (int i = 0; i < extension_count; ++i) {
|
||||
X509_EXTENSION* const extension = X509_get_ext(intermediate_cert, i);
|
||||
if (!extension) {
|
||||
LOGE("CryptoSession::GetSystemId: Unable to get cert extension %d", i);
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Unable to get cert extension %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
ASN1_OBJECT* const extension_object = X509_EXTENSION_get_object(extension);
|
||||
if (!extension_object) {
|
||||
LOGE(
|
||||
"CryptoSession::GetSystemId: Unable to get object of cert "
|
||||
"extension %d",
|
||||
i);
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Unable to get object of cert extension %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1078,35 +1091,31 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
|
||||
ASN1_OCTET_STRING* const octet_str = X509_EXTENSION_get_data(extension);
|
||||
if (!octet_str) {
|
||||
LOGE(
|
||||
"CryptoSession::GetSystemId: Unable to get data of Widevine System "
|
||||
"ID extension.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Unable to get data of Widevine System ID extension.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned char* data = octet_str->data;
|
||||
if (!data) {
|
||||
LOGE(
|
||||
"CryptoSession::GetSystemId: Null data in Widevine System ID "
|
||||
"extension.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Null data in Widevine System ID extension.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ASN1_INTEGER* const asn1_integer =
|
||||
d2i_ASN1_INTEGER(NULL, &data, octet_str->length);
|
||||
if (!asn1_integer) {
|
||||
LOGE(
|
||||
"CryptoSession::GetSystemId: Unable to decode data in Widevine "
|
||||
"System ID extension.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Unable to decode data in Widevine System ID extension.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const long system_id_long = ASN1_INTEGER_get(asn1_integer);
|
||||
ASN1_INTEGER_free(asn1_integer);
|
||||
if (system_id_long == -1) {
|
||||
LOGE(
|
||||
"CryptoSession::GetSystemId: Unable to decode ASN integer in "
|
||||
"Widevine System ID extension.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Unable to decode ASN integer in Widevine System ID extension.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1114,7 +1123,8 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGE("CryptoSession::GetSystemId: Widevine System ID extension not found.");
|
||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
||||
"Widevine System ID extension not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1191,13 +1201,25 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
||||
session_count_, (int)initialized_);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
// Get System ID and save it.
|
||||
if (GetSystemIdInternal(&system_id_)) {
|
||||
metrics_->crypto_session_system_id_.Record(system_id_);
|
||||
} else {
|
||||
LOGE("CryptoSession::Open: Failed to fetch system id.");
|
||||
metrics_->crypto_session_system_id_.SetError(LOAD_SYSTEM_ID_ERROR);
|
||||
return LOAD_SYSTEM_ID_ERROR;
|
||||
}
|
||||
|
||||
OEMCryptoResult random_sts = OEMCrypto_GetRandom(
|
||||
reinterpret_cast<uint8_t*>(&request_id_base_), sizeof(request_id_base_));
|
||||
metrics_->oemcrypto_get_random_.Increment(random_sts);
|
||||
++request_id_index_;
|
||||
|
||||
CdmUsageSupportType usage_support_type;
|
||||
if (GetUsageSupportType(&usage_support_type) == NO_ERROR) {
|
||||
CdmResponseType result = GetUsageSupportType(&usage_support_type);
|
||||
if (result == NO_ERROR) {
|
||||
metrics_->oemcrypto_usage_table_support_.Record(usage_support_type);
|
||||
if (usage_support_type == kUsageEntrySupport) {
|
||||
CdmSecurityLevel security_level = GetSecurityLevel();
|
||||
if (security_level == kSecurityLevelL1 ||
|
||||
@@ -1224,6 +1246,8 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
||||
usage_table_header_ = *header;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
metrics_->oemcrypto_usage_table_support_.SetError(result);
|
||||
}
|
||||
|
||||
// TODO(gmorgan, jfore): resolve handling of usage records in sublicenses
|
||||
@@ -1361,6 +1385,7 @@ bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) {
|
||||
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
|
||||
OEMCryptoResult sts =
|
||||
OEMCrypto_GetOEMPublicCertificate(oec_session_id_, buf, &buf_size);
|
||||
metrics_->oemcrypto_get_oem_public_certificate_.Increment(sts);
|
||||
|
||||
LOGV("LoadDeviceRSAKey: id=%ld", (uint32_t)oec_session_id_);
|
||||
M_TIME(
|
||||
@@ -2032,10 +2057,15 @@ bool CryptoSession::RewrapDeviceRSAKey30(const std::string& message,
|
||||
// Gets wrapped_rsa_key_length by passing NULL as uint8_t* wrapped_rsa_key
|
||||
// and 0 as wrapped_rsa_key_length.
|
||||
size_t wrapped_private_key_length = 0;
|
||||
OEMCryptoResult status = OEMCrypto_RewrapDeviceRSAKey30(
|
||||
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
|
||||
msg_private_key, private_key.size(), msg_iv, NULL,
|
||||
&wrapped_private_key_length);
|
||||
OEMCryptoResult status;
|
||||
M_TIME(
|
||||
status = OEMCrypto_RewrapDeviceRSAKey30(
|
||||
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
|
||||
msg_private_key, private_key.size(), msg_iv, NULL,
|
||||
&wrapped_private_key_length),
|
||||
metrics_,
|
||||
oemcrypto_rewrap_device_rsa_key_30_,
|
||||
status);
|
||||
|
||||
if (status != OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||
LOGE("OEMCrypto_RewrapDeviceRSAKey30 failed getting wrapped key length");
|
||||
@@ -2043,11 +2073,15 @@ bool CryptoSession::RewrapDeviceRSAKey30(const std::string& message,
|
||||
}
|
||||
|
||||
wrapped_private_key->resize(wrapped_private_key_length);
|
||||
status = OEMCrypto_RewrapDeviceRSAKey30(
|
||||
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
|
||||
msg_private_key, private_key.size(), msg_iv,
|
||||
reinterpret_cast<uint8_t*>(&(*wrapped_private_key)[0]),
|
||||
&wrapped_private_key_length);
|
||||
M_TIME(
|
||||
status = OEMCrypto_RewrapDeviceRSAKey30(
|
||||
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
|
||||
msg_private_key, private_key.size(), msg_iv,
|
||||
reinterpret_cast<uint8_t*>(&(*wrapped_private_key)[0]),
|
||||
&wrapped_private_key_length),
|
||||
metrics_,
|
||||
oemcrypto_rewrap_device_rsa_key_30_,
|
||||
status);
|
||||
|
||||
wrapped_private_key->resize(wrapped_private_key_length);
|
||||
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "crypto_session.h"
|
||||
#include "log.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "metrics.pb.h"
|
||||
#include "scoped_ptr.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -245,4 +249,188 @@ TEST(CryptoSessionTest, CanExtractSystemIdFromOemCertificate) {
|
||||
ASSERT_EQ(kOemCertSystemId, system_id);
|
||||
}
|
||||
|
||||
class CryptoSessionMetricsTest : public testing::Test {
|
||||
protected:
|
||||
void MakeMetricMap(
|
||||
const drm_metrics::MetricsGroup& metric_group,
|
||||
std::map<std::string, drm_metrics::MetricsGroup::Metric>* metric_map) {
|
||||
std::transform(metric_group.metric().begin(),
|
||||
metric_group.metric().end(),
|
||||
std::inserter(*metric_map, metric_map->end()),
|
||||
CryptoSessionMetricsTest::MakeMetricPair);
|
||||
|
||||
}
|
||||
|
||||
bool FindMetric(
|
||||
const std::map<std::string,
|
||||
drm_metrics::MetricsGroup::Metric>& metric_map,
|
||||
const std::string& metric_name,
|
||||
drm_metrics::MetricsGroup::Metric* metric) {
|
||||
std::map<std::string,
|
||||
drm_metrics::MetricsGroup::Metric>::const_iterator it =
|
||||
metric_map.find(metric_name);
|
||||
if (it == metric_map.end()) {
|
||||
return false;
|
||||
}
|
||||
*metric = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::pair<std::string, drm_metrics::MetricsGroup::Metric>
|
||||
MakeMetricPair(const drm_metrics::MetricsGroup::Metric& metric) {
|
||||
LOGV("Metric: %s", metric.name().c_str());
|
||||
return std::make_pair(metric.name(), metric);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CryptoSessionMetricsTest, OpenSessionValidMetrics) {
|
||||
metrics::CryptoMetrics crypto_metrics;
|
||||
CryptoSession session(&crypto_metrics);
|
||||
session.Open(wvcdm::kLevelDefault);
|
||||
|
||||
drm_metrics::MetricsGroup actual_metrics;
|
||||
crypto_metrics.Serialize(&actual_metrics);
|
||||
|
||||
// TODO(blueeyes): If we an convert to use full proto rather than proto lite,
|
||||
// convert these tests to use Message-based convenience functions.
|
||||
std::map<std::string, drm_metrics::MetricsGroup::Metric> metric_map;
|
||||
MakeMetricMap(actual_metrics, &metric_map);
|
||||
|
||||
// Validate common metrics regardless of provisioning type.
|
||||
drm_metrics::MetricsGroup::Metric metric;
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/initialize/time/count{oemcrypto_error:0}",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 1);
|
||||
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/initialize/time/mean{oemcrypto_error:0}",
|
||||
&metric));
|
||||
EXPECT_TRUE(metric.value().has_double_value());
|
||||
|
||||
CdmUsageSupportType usage_type;
|
||||
ASSERT_EQ(NO_ERROR, session.GetUsageSupportType(&usage_type));
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/usage_table_support",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), usage_type);
|
||||
|
||||
// Validate metrics that differ based on provisioning type.
|
||||
CdmClientTokenType token_type = session.GetPreProvisionTokenType();
|
||||
|
||||
if (token_type == kClientTokenKeybox) {
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map, "/drm/widevine/crypto_session/system_id", &metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 4121);
|
||||
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/provisioning_method",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), OEMCrypto_Keybox);
|
||||
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/get_key_data/time/count"
|
||||
"{oemcrypto_error:0&length:64}",
|
||||
&metric));
|
||||
EXPECT_GE(metric.value().int_value(), 1);
|
||||
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/get_key_data/time/mean"
|
||||
"{oemcrypto_error:0&length:64}",
|
||||
&metric));
|
||||
EXPECT_TRUE(metric.value().has_double_value());
|
||||
} else if (token_type == kClientTokenOemCert) {
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map, "/drm/widevine/crypto_session/system_id", &metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 7346);
|
||||
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/provisioning_method",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), OEMCrypto_OEMCertificate);
|
||||
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/get_oem_public_certificate/count"
|
||||
"{oemcrypto_error:0}",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 1);
|
||||
} else if (token_type == kClientTokenDrmCert) {
|
||||
// TODO(blueeyes): Add support for getting the system id from a
|
||||
// pre-installed DRM certificate..
|
||||
} else {
|
||||
FAIL() << "Unexpected token type: " << token_type;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CryptoSessionMetricsTest, GetProvisioningTokenValidMetrics) {
|
||||
metrics::CryptoMetrics crypto_metrics;
|
||||
CryptoSession session(&crypto_metrics);
|
||||
|
||||
ASSERT_EQ(NO_ERROR, session.Open(wvcdm::kLevelDefault));
|
||||
|
||||
CdmClientTokenType token_type = session.GetPreProvisionTokenType();
|
||||
LOGI("token_type: %d", token_type);
|
||||
|
||||
// DRM Certificate provisioning method does not support a provisioning
|
||||
// token. Otherwise, we should be able to fetch the token.
|
||||
std::string token;
|
||||
if (token_type != kClientTokenDrmCert) {
|
||||
ASSERT_TRUE(session.GetProvisioningToken(&token));
|
||||
}
|
||||
|
||||
drm_metrics::MetricsGroup actual_metrics;
|
||||
crypto_metrics.Serialize(&actual_metrics);
|
||||
|
||||
std::map<std::string, drm_metrics::MetricsGroup::Metric> metric_map;
|
||||
MakeMetricMap(actual_metrics, &metric_map);
|
||||
|
||||
drm_metrics::MetricsGroup::Metric metric;
|
||||
if (token_type == kClientTokenKeybox) {
|
||||
// TODO(blueeyes): Add more metrics verifications.
|
||||
ASSERT_TRUE(FindMetric(
|
||||
metric_map, "/drm/widevine/crypto_session/get_token/count{success:1}",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 1);
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map, "/drm/widevine/crypto_session/system_id",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 4121);
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/get_key_data/time/count"
|
||||
"{oemcrypto_error:0&length:64}",
|
||||
&metric));
|
||||
EXPECT_GE(metric.value().int_value(), 1);
|
||||
} else if (token_type == kClientTokenOemCert) {
|
||||
// TODO(blueeyes): Add more metrics verifications.
|
||||
ASSERT_TRUE(FindMetric(
|
||||
metric_map, "/drm/widevine/crypto_session/get_token/count{success:1}",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 1);
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map, "/drm/widevine/crypto_session/system_id",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 7346);
|
||||
EXPECT_TRUE(FindMetric(
|
||||
metric_map,
|
||||
"/drm/widevine/oemcrypto/get_oem_public_certificate/count"
|
||||
"{oemcrypto_error:0}",
|
||||
&metric));
|
||||
EXPECT_EQ(metric.value().int_value(), 1);
|
||||
} else {
|
||||
ASSERT_FALSE(FindMetric(
|
||||
metric_map, "/drm/widevine/crypto_session/get_token/count{success:1}",
|
||||
&metric));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -568,6 +568,12 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case LICENSE_REQUEST_INVALID_SUBLICENSE:
|
||||
*os << "LICENSE_REQUEST_INVALID_SUBLICENSE";
|
||||
break;
|
||||
case CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE:
|
||||
*os << "CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE";
|
||||
break;
|
||||
case LOAD_SYSTEM_ID_ERROR:
|
||||
*os << "LOAD_SYSTEM_ID_ERROR";
|
||||
break;
|
||||
default:
|
||||
*os << "Unknown CdmResponseType";
|
||||
break;
|
||||
|
||||
@@ -128,7 +128,6 @@ class CryptoMetrics {
|
||||
CounterMetric<OEMCryptoResult> oemcrypto_get_oem_public_certificate_;
|
||||
CounterMetric<OEMCryptoResult> oemcrypto_get_random_;
|
||||
EventMetric<OEMCryptoResult> oemcrypto_initialize_;
|
||||
EventMetric<OEMCryptoResult> oemcrypto_install_keybox_;
|
||||
ValueMetric<bool> oemcrypto_is_anti_rollback_hw_present_;
|
||||
ValueMetric<bool> oemcrypto_is_keybox_valid_;
|
||||
EventMetric<OEMCryptoResult> oemcrypto_load_device_rsa_key_;
|
||||
@@ -143,9 +142,8 @@ class CryptoMetrics {
|
||||
EventMetric<OEMCryptoResult> oemcrypto_rewrap_device_rsa_key_30_;
|
||||
ValueMetric<uint16_t> oemcrypto_security_patch_level_;
|
||||
EventMetric<OEMCryptoResult> oemcrypto_select_key_;
|
||||
ValueMetric<bool> oemcrypto_supports_usage_table_;
|
||||
ValueMetric<CdmUsageSupportType> oemcrypto_usage_table_support_;
|
||||
CounterMetric<OEMCryptoResult> oemcrypto_update_usage_table_;
|
||||
EventMetric<OEMCryptoResult> oemcrypto_wrap_keybox_;
|
||||
};
|
||||
|
||||
// This class contains session-scoped metrics. All properties and
|
||||
|
||||
@@ -189,9 +189,6 @@ CryptoMetrics::CryptoMetrics() :
|
||||
oemcrypto_initialize_(
|
||||
"/drm/widevine/oemcrypto/initialize/time",
|
||||
"oemcrypto_error"),
|
||||
oemcrypto_install_keybox_(
|
||||
"/drm/widevine/oemcrypto/install_keybox/time",
|
||||
"oemcrypto_error"),
|
||||
oemcrypto_is_anti_rollback_hw_present_(
|
||||
"/drm/widevine/oemcrypto/is_anti_rollback_hw_present"),
|
||||
oemcrypto_is_keybox_valid_(
|
||||
@@ -227,13 +224,10 @@ CryptoMetrics::CryptoMetrics() :
|
||||
oemcrypto_select_key_(
|
||||
"/drm/widevine/oemcrypto/select_key/time",
|
||||
"oemcrypto_error"),
|
||||
oemcrypto_supports_usage_table_(
|
||||
"/drm/widevine/oemcrypto/supports_usage_table"),
|
||||
oemcrypto_usage_table_support_(
|
||||
"/drm/widevine/oemcrypto/usage_table_support"),
|
||||
oemcrypto_update_usage_table_(
|
||||
"/drm/widevine/oemcrypto/update_usage_table",
|
||||
"oemcrypto_error"),
|
||||
oemcrypto_wrap_keybox_(
|
||||
"/drm/widevine/oemcrypto/wrap_keybox/time",
|
||||
"oemcrypto_error") {
|
||||
}
|
||||
|
||||
@@ -280,7 +274,6 @@ void CryptoMetrics::Serialize(MetricsGroup* metrics) {
|
||||
oemcrypto_get_oem_public_certificate_.Serialize(&serializer);
|
||||
oemcrypto_get_random_.Serialize(&serializer);
|
||||
oemcrypto_initialize_.Serialize(&serializer);
|
||||
oemcrypto_install_keybox_.Serialize(&serializer);
|
||||
oemcrypto_is_anti_rollback_hw_present_.Serialize(&serializer);
|
||||
oemcrypto_is_keybox_valid_.Serialize(&serializer);
|
||||
oemcrypto_load_device_rsa_key_.Serialize(&serializer);
|
||||
@@ -295,9 +288,8 @@ void CryptoMetrics::Serialize(MetricsGroup* metrics) {
|
||||
oemcrypto_rewrap_device_rsa_key_30_.Serialize(&serializer);
|
||||
oemcrypto_security_patch_level_.Serialize(&serializer);
|
||||
oemcrypto_select_key_.Serialize(&serializer);
|
||||
oemcrypto_supports_usage_table_.Serialize(&serializer);
|
||||
oemcrypto_usage_table_support_.Serialize(&serializer);
|
||||
oemcrypto_update_usage_table_.Serialize(&serializer);
|
||||
oemcrypto_wrap_keybox_.Serialize(&serializer);
|
||||
}
|
||||
|
||||
SessionMetrics::SessionMetrics() :
|
||||
|
||||
@@ -110,6 +110,14 @@ void Serialize<OEMCryptoInitializationMode>(
|
||||
serializer->SetInt32(metric_name, value);
|
||||
}
|
||||
|
||||
template<>
|
||||
void Serialize<CdmUsageSupportType>(
|
||||
MetricSerializer* serializer,
|
||||
const std::string& metric_name,
|
||||
const CdmUsageSupportType& value) {
|
||||
serializer->SetInt32(metric_name, value);
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
} // namespace metrics
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -259,10 +259,11 @@ enum {
|
||||
kReleaseAllUsageInfoError7 = ERROR_DRM_VENDOR_MIN + 268,
|
||||
kLicenseRequestInvalidSublicense = ERROR_DRM_VENDOR_MIN + 269,
|
||||
kCertProvisioningEmptyServiceCertificate = ERROR_DRM_VENDOR_MIN + 270,
|
||||
kLoadSystemIdError = ERROR_DRM_VENDOR_MIN + 271,
|
||||
|
||||
// This should always follow the last error code.
|
||||
// The offset value should be updated each time a new error code is added.
|
||||
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 270,
|
||||
kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 271,
|
||||
|
||||
// Used by crypto test mode
|
||||
kErrorTestMode = ERROR_DRM_VENDOR_MAX,
|
||||
|
||||
@@ -499,6 +499,8 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) {
|
||||
return kLicenseRequestInvalidSublicense;
|
||||
case wvcdm::CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE:
|
||||
return kCertProvisioningEmptyServiceCertificate;
|
||||
case wvcdm::LOAD_SYSTEM_ID_ERROR:
|
||||
return kLoadSystemIdError;
|
||||
}
|
||||
|
||||
// Return here instead of as a default case so that the compiler will warn
|
||||
|
||||
@@ -286,6 +286,7 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) {
|
||||
case wvcdm::PARSE_RESPONSE_ERROR_2:
|
||||
case wvcdm::PARSE_RESPONSE_ERROR_3:
|
||||
case wvcdm::PARSE_RESPONSE_ERROR_4:
|
||||
case wvcdm::LOAD_SYSTEM_ID_ERROR:
|
||||
ALOGW("Returns UNKNOWN error for legacy status: %d", res);
|
||||
return Status::ERROR_DRM_UNKNOWN;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user