Implement license protocol 2.2 for OEMCrypto v19
This updates the code and tests to allow for using license protocol 2.2 when using OEMCrypto v19. Issue: 80428549 Issue: 121031064 Issue: 232464183 Change-Id: Ib6bb61f86dd310b566227462658530bca5940b88
This commit is contained in:
committed by
Robert Shih
parent
5f3bc77c52
commit
4b32cb4b10
@@ -140,6 +140,7 @@ class CdmLicense {
|
|||||||
bool initialized_;
|
bool initialized_;
|
||||||
std::set<KeyId> loaded_keys_;
|
std::set<KeyId> loaded_keys_;
|
||||||
std::string provider_session_token_;
|
std::string provider_session_token_;
|
||||||
|
video_widevine::ProtocolVersion protocol_version_;
|
||||||
bool renew_with_client_id_;
|
bool renew_with_client_id_;
|
||||||
bool is_offline_;
|
bool is_offline_;
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ bool ExtractExtensionValueFromCertificate(const std::string& cert,
|
|||||||
|
|
||||||
std::string Md5Hash(const std::string& data);
|
std::string Md5Hash(const std::string& data);
|
||||||
std::string Sha256Hash(const std::string& data);
|
std::string Sha256Hash(const std::string& data);
|
||||||
|
std::string Sha512Hash(const std::string& data);
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ std::vector<CryptoKey> ExtractEntitlementKeys(const License& license) {
|
|||||||
return key_array;
|
return key_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
std::vector<CryptoKey> ExtractContentKeys(
|
||||||
|
const License& license, video_widevine::ProtocolVersion version) {
|
||||||
std::vector<CryptoKey> key_array;
|
std::vector<CryptoKey> key_array;
|
||||||
|
|
||||||
// Extract content key(s)
|
// Extract content key(s)
|
||||||
@@ -130,21 +131,20 @@ std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
|||||||
// TODO(b/232464183): When we switch to License Protocol 2.2, there will
|
// TODO(b/232464183): When we switch to License Protocol 2.2, there will
|
||||||
// no longer be padding on these keys, so this
|
// no longer be padding on these keys, so this
|
||||||
// removal code must be removed at the same time.
|
// removal code must be removed at the same time.
|
||||||
if (license.key(i).key().size() !=
|
const auto padding = version <= video_widevine::VERSION_2_1
|
||||||
CONTENT_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING &&
|
? LICENSE_PROTOCOL_2_1_PADDING
|
||||||
license.key(i).key().size() !=
|
: 0;
|
||||||
MAC_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING) {
|
if (license.key(i).key().size() != CONTENT_KEY_SIZE + padding &&
|
||||||
|
license.key(i).key().size() != MAC_KEY_SIZE + padding) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"Skipping key %s because it is an unexpected size. Expected: %zu "
|
"Skipping key %s because it is an unexpected size. Expected: %zu "
|
||||||
"or %zu, Actual: %zu",
|
"or %zu, Actual: %zu",
|
||||||
license.key(i).id().c_str(),
|
license.key(i).id().c_str(), CONTENT_KEY_SIZE + padding,
|
||||||
CONTENT_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING,
|
MAC_KEY_SIZE + padding, license.key(i).key().size());
|
||||||
MAC_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING,
|
|
||||||
license.key(i).key().size());
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const size_t length =
|
const size_t length =
|
||||||
license.key(i).key().size() - LICENSE_PROTOCOL_2_1_PADDING;
|
license.key(i).key().size() - padding;
|
||||||
key.set_key_data(license.key(i).key().substr(0, length));
|
key.set_key_data(license.key(i).key().substr(0, length));
|
||||||
key.set_key_data_iv(license.key(i).iv());
|
key.set_key_data_iv(license.key(i).iv());
|
||||||
if (license.key(i).has_key_control()) {
|
if (license.key(i).has_key_control()) {
|
||||||
@@ -199,6 +199,7 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id)
|
|||||||
policy_engine_(nullptr),
|
policy_engine_(nullptr),
|
||||||
session_id_(session_id),
|
session_id_(session_id),
|
||||||
initialized_(false),
|
initialized_(false),
|
||||||
|
protocol_version_(video_widevine::VERSION_2_2),
|
||||||
renew_with_client_id_(false),
|
renew_with_client_id_(false),
|
||||||
is_offline_(false),
|
is_offline_(false),
|
||||||
use_privacy_mode_(false),
|
use_privacy_mode_(false),
|
||||||
@@ -210,6 +211,7 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id, wvutil::Clock* clock)
|
|||||||
policy_engine_(nullptr),
|
policy_engine_(nullptr),
|
||||||
session_id_(session_id),
|
session_id_(session_id),
|
||||||
initialized_(false),
|
initialized_(false),
|
||||||
|
protocol_version_(video_widevine::VERSION_2_2),
|
||||||
renew_with_client_id_(false),
|
renew_with_client_id_(false),
|
||||||
is_offline_(false),
|
is_offline_(false),
|
||||||
use_privacy_mode_(false),
|
use_privacy_mode_(false),
|
||||||
@@ -244,6 +246,13 @@ bool CdmLicense::Init(bool use_privacy_mode,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t api_version;
|
||||||
|
if (!session->GetApiVersion(&api_version)) {
|
||||||
|
api_version = 16;
|
||||||
|
}
|
||||||
|
protocol_version_ = api_version >= 19 ? video_widevine::VERSION_2_2
|
||||||
|
: video_widevine::VERSION_2_1;
|
||||||
|
|
||||||
crypto_session_ = session;
|
crypto_session_ = session;
|
||||||
policy_engine_ = policy_engine;
|
policy_engine_ = policy_engine;
|
||||||
use_privacy_mode_ = use_privacy_mode;
|
use_privacy_mode_ = use_privacy_mode;
|
||||||
@@ -338,7 +347,7 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
|
|||||||
return CdmResponseType(LICENSE_REQUEST_NONCE_GENERATION_ERROR);
|
return CdmResponseType(LICENSE_REQUEST_NONCE_GENERATION_ERROR);
|
||||||
}
|
}
|
||||||
license_request.set_key_control_nonce(license_nonce_);
|
license_request.set_key_control_nonce(license_nonce_);
|
||||||
license_request.set_protocol_version(video_widevine::VERSION_2_1);
|
license_request.set_protocol_version(protocol_version_);
|
||||||
|
|
||||||
// License request is complete. Serialize it.
|
// License request is complete. Serialize it.
|
||||||
std::string serialized_license_req;
|
std::string serialized_license_req;
|
||||||
@@ -494,7 +503,7 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
|
|||||||
current_license->set_seconds_since_last_played(seconds_since_last_played);
|
current_license->set_seconds_since_last_played(seconds_since_last_played);
|
||||||
}
|
}
|
||||||
|
|
||||||
license_request.set_protocol_version(video_widevine::VERSION_2_1);
|
license_request.set_protocol_version(protocol_version_);
|
||||||
|
|
||||||
// License request is complete. Serialize it.
|
// License request is complete. Serialize it.
|
||||||
std::string serialized_license_req;
|
std::string serialized_license_req;
|
||||||
@@ -619,7 +628,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
|||||||
CdmLicenseKeyType key_type = kLicenseKeyTypeEntitlement;
|
CdmLicenseKeyType key_type = kLicenseKeyTypeEntitlement;
|
||||||
std::vector<CryptoKey> key_array = ExtractEntitlementKeys(license);
|
std::vector<CryptoKey> key_array = ExtractEntitlementKeys(license);
|
||||||
if (key_array.empty()) {
|
if (key_array.empty()) {
|
||||||
key_array = ExtractContentKeys(license);
|
key_array = ExtractContentKeys(license, protocol_version_);
|
||||||
key_type = kLicenseKeyTypeContent;
|
key_type = kLicenseKeyTypeContent;
|
||||||
}
|
}
|
||||||
if (key_array.empty()) {
|
if (key_array.empty()) {
|
||||||
@@ -794,6 +803,7 @@ CdmResponseType CdmLicense::RestoreOfflineLicense(
|
|||||||
LOGW("Could not parse original request.");
|
LOGW("Could not parse original request.");
|
||||||
} else {
|
} else {
|
||||||
license_nonce_ = original_license_request.key_control_nonce();
|
license_nonce_ = original_license_request.key_control_nonce();
|
||||||
|
protocol_version_ = original_license_request.protocol_version();
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType sts = HandleKeyResponse(true, license_response);
|
CdmResponseType sts = HandleKeyResponse(true, license_response);
|
||||||
@@ -1091,9 +1101,11 @@ CdmResponseType CdmLicense::HandleContentKeyResponse(
|
|||||||
LOGE("No content keys provided");
|
LOGE("No content keys provided");
|
||||||
return CdmResponseType(NO_CONTENT_KEY);
|
return CdmResponseType(NO_CONTENT_KEY);
|
||||||
}
|
}
|
||||||
const CdmResponseType resp =
|
const CdmResponseType resp = crypto_session_->LoadLicense(
|
||||||
crypto_session_->LoadLicense(key_request_, session_key, msg, core_message,
|
protocol_version_ <= video_widevine::VERSION_2_1
|
||||||
signature, kLicenseKeyTypeContent);
|
? key_request_
|
||||||
|
: Sha512Hash(key_request_),
|
||||||
|
session_key, msg, core_message, signature, kLicenseKeyTypeContent);
|
||||||
if (KEY_ADDED == resp) {
|
if (KEY_ADDED == resp) {
|
||||||
loaded_keys_.clear();
|
loaded_keys_.clear();
|
||||||
for (const CryptoKey& key : key_array) {
|
for (const CryptoKey& key : key_array) {
|
||||||
@@ -1113,9 +1125,11 @@ CdmResponseType CdmLicense::HandleEntitlementKeyResponse(
|
|||||||
LOGE("No entitlement keys provided");
|
LOGE("No entitlement keys provided");
|
||||||
return CdmResponseType(NO_CONTENT_KEY);
|
return CdmResponseType(NO_CONTENT_KEY);
|
||||||
}
|
}
|
||||||
const CdmResponseType resp =
|
const CdmResponseType resp = crypto_session_->LoadLicense(
|
||||||
crypto_session_->LoadLicense(key_request_, session_key, msg, core_message,
|
protocol_version_ <= video_widevine::VERSION_2_1
|
||||||
signature, kLicenseKeyTypeEntitlement);
|
? key_request_
|
||||||
|
: Sha512Hash(key_request_),
|
||||||
|
session_key, msg, core_message, signature, kLicenseKeyTypeEntitlement);
|
||||||
|
|
||||||
if (KEY_ADDED != resp) {
|
if (KEY_ADDED != resp) {
|
||||||
return resp;
|
return resp;
|
||||||
|
|||||||
@@ -417,4 +417,11 @@ std::string Sha256Hash(const std::string& data) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Sha512Hash(const std::string& data) {
|
||||||
|
std::string hash(SHA512_DIGEST_LENGTH, '\0');
|
||||||
|
SHA512(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||||
|
reinterpret_cast<uint8_t*>(&hash[0]));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
# include <CommonCrypto/CommonDigest.h>
|
# include <CommonCrypto/CommonDigest.h>
|
||||||
# define SHA256 CC_SHA256
|
# define SHA256 CC_SHA256
|
||||||
# define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
|
# define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
|
||||||
|
# define SHA512 CC_SHA512
|
||||||
|
# define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
|
||||||
# define MD5 CC_MD5
|
# define MD5 CC_MD5
|
||||||
# define MD5_DIGEST_LENGTH CC_MD5_DIGEST_LENGTH
|
# define MD5_DIGEST_LENGTH CC_MD5_DIGEST_LENGTH
|
||||||
#else
|
#else
|
||||||
@@ -69,4 +71,10 @@ std::string Sha256Hash(const std::string& data) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Sha512Hash(const std::string& data) {
|
||||||
|
std::string hash(SHA512_DIGEST_LENGTH, '\0');
|
||||||
|
SHA512(data.data(), data.size(), reinterpret_cast<uint8_t*>(&hash[0]));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
|||||||
// Supported certificates set by SetUp().
|
// Supported certificates set by SetUp().
|
||||||
EXPECT_CALL(*crypto_session_, GetSupportedCertificateTypes(NotNull()));
|
EXPECT_CALL(*crypto_session_, GetSupportedCertificateTypes(NotNull()));
|
||||||
EXPECT_CALL(*crypto_session_, GetApiVersion(NotNull()))
|
EXPECT_CALL(*crypto_session_, GetApiVersion(NotNull()))
|
||||||
.WillOnce(
|
.WillRepeatedly(
|
||||||
DoAll(SetArgPointee<0>(crypto_session_api_version), Return(true)));
|
DoAll(SetArgPointee<0>(crypto_session_api_version), Return(true)));
|
||||||
EXPECT_CALL(*crypto_session_, GetResourceRatingTier(NotNull()))
|
EXPECT_CALL(*crypto_session_, GetResourceRatingTier(NotNull()))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(resource_rating_tier), Return(true)));
|
.WillOnce(DoAll(SetArgPointee<0>(resource_rating_tier), Return(true)));
|
||||||
@@ -450,7 +450,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
|||||||
Return(CdmResponseType(NO_ERROR))));
|
Return(CdmResponseType(NO_ERROR))));
|
||||||
EXPECT_CALL(*crypto_session_, GetSupportedCertificateTypes(NotNull()));
|
EXPECT_CALL(*crypto_session_, GetSupportedCertificateTypes(NotNull()));
|
||||||
EXPECT_CALL(*crypto_session_, GetApiVersion(NotNull()))
|
EXPECT_CALL(*crypto_session_, GetApiVersion(NotNull()))
|
||||||
.WillOnce(
|
.WillRepeatedly(
|
||||||
DoAll(SetArgPointee<0>(crypto_session_api_version), Return(true)));
|
DoAll(SetArgPointee<0>(crypto_session_api_version), Return(true)));
|
||||||
EXPECT_CALL(*crypto_session_, GetResourceRatingTier(NotNull()))
|
EXPECT_CALL(*crypto_session_, GetResourceRatingTier(NotNull()))
|
||||||
.WillOnce(DoAll(SetArgPointee<0>(resource_rating_tier), Return(true)));
|
.WillOnce(DoAll(SetArgPointee<0>(resource_rating_tier), Return(true)));
|
||||||
@@ -617,7 +617,7 @@ TEST_P(CdmLicenseEntitledKeyTest, LoadsEntitledKeys) {
|
|||||||
|
|
||||||
// Set up the CdmLicense with the mocks and fake entitlement key
|
// Set up the CdmLicense with the mocks and fake entitlement key
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
ASSERT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||||
crypto_session_, policy_engine_));
|
crypto_session_, policy_engine_));
|
||||||
cdm_license_->set_entitlement_keys(entitlement_license);
|
cdm_license_->set_entitlement_keys(entitlement_license);
|
||||||
|
|
||||||
|
|||||||
@@ -1025,6 +1025,9 @@ OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
|||||||
* Refer to the Signing Messages Sent to a Server section above for more
|
* Refer to the Signing Messages Sent to a Server section above for more
|
||||||
* details about the signature algorithm.
|
* details about the signature algorithm.
|
||||||
*
|
*
|
||||||
|
* Starting in OEMCrypto v19, the |message| buffer must be hashed using SHA512
|
||||||
|
* before signing.
|
||||||
|
*
|
||||||
* NOTE: if signature pointer is null and/or input signature_length is zero,
|
* NOTE: if signature pointer is null and/or input signature_length is zero,
|
||||||
* this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
* this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
||||||
* signature_length to the size needed to receive the output signature.
|
* signature_length to the size needed to receive the output signature.
|
||||||
|
|||||||
@@ -782,17 +782,18 @@ void LicenseRoundTrip::VerifyRequestSignature(
|
|||||||
if (api_version_ > global_features.api_version)
|
if (api_version_ > global_features.api_version)
|
||||||
api_version_ = global_features.api_version;
|
api_version_ = global_features.api_version;
|
||||||
|
|
||||||
|
vector<uint8_t> sign_source;
|
||||||
if (global_features.api_version < 17) {
|
if (global_features.api_version < 17) {
|
||||||
const std::vector<uint8_t> subdata(data.begin() + core_message_length,
|
sign_source.assign(data.begin() + core_message_length, data.end());
|
||||||
data.end());
|
} else if (global_features.api_version < 19) {
|
||||||
session()->VerifyRsaSignature(subdata, generated_signature.data(),
|
sign_source = data;
|
||||||
generated_signature.size(), kSign_RSASSA_PSS);
|
|
||||||
SHA256(data.data(), core_message_length, request_hash_);
|
|
||||||
} else {
|
} else {
|
||||||
session()->VerifySignature(data, generated_signature.data(),
|
sign_source.resize(SHA512_DIGEST_LENGTH);
|
||||||
generated_signature.size(), kSign_RSASSA_PSS);
|
SHA512(data.data(), data.size(), sign_source.data());
|
||||||
SHA256(data.data(), core_message_length, request_hash_);
|
|
||||||
}
|
}
|
||||||
|
session()->VerifySignature(sign_source, generated_signature.data(),
|
||||||
|
generated_signature.size(), kSign_RSASSA_PSS);
|
||||||
|
SHA256(data.data(), core_message_length, request_hash_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicenseRoundTrip::FillAndVerifyCoreRequest(
|
void LicenseRoundTrip::FillAndVerifyCoreRequest(
|
||||||
@@ -998,7 +999,8 @@ void LicenseRoundTrip::FillCoreResponseSubstrings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LicenseRoundTrip::EncryptResponse(bool force_clear_kcb) {
|
void LicenseRoundTrip::EncryptResponse(bool force_clear_kcb) {
|
||||||
ASSERT_NO_FATAL_FAILURE(session_->GenerateDerivedKeysFromSessionKey());
|
const auto context = session_->GetDefaultContext(!skip_request_hash_);
|
||||||
|
ASSERT_NO_FATAL_FAILURE(session_->GenerateDerivedKeysFromSessionKey(context));
|
||||||
encrypted_response_data_ = response_data_;
|
encrypted_response_data_ = response_data_;
|
||||||
uint8_t iv_buffer[KEY_IV_SIZE];
|
uint8_t iv_buffer[KEY_IV_SIZE];
|
||||||
memcpy(iv_buffer, &response_data_.mac_key_iv[0], KEY_IV_SIZE);
|
memcpy(iv_buffer, &response_data_.mac_key_iv[0], KEY_IV_SIZE);
|
||||||
@@ -1129,7 +1131,8 @@ OEMCryptoResult LicenseRoundTrip::LoadResponse(Session* session,
|
|||||||
core_response_.key_array_length * sizeof(*core_response_.key_array));
|
core_response_.key_array_length * sizeof(*core_response_.key_array));
|
||||||
}
|
}
|
||||||
|
|
||||||
const vector<uint8_t> context = session->GetDefaultContext();
|
const vector<uint8_t> context =
|
||||||
|
session->GetDefaultContext(!skip_request_hash_);
|
||||||
|
|
||||||
// Some tests adjust the offset to be beyond the length of the message. Here,
|
// Some tests adjust the offset to be beyond the length of the message. Here,
|
||||||
// we create a duplicate of the main message buffer so that these offsets do
|
// we create a duplicate of the main message buffer so that these offsets do
|
||||||
@@ -1674,18 +1677,24 @@ void Session::GenerateNonce(int* error_counter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<uint8_t> Session::GetDefaultContext() {
|
vector<uint8_t> Session::GetDefaultContext(bool do_hash) {
|
||||||
/* Context string
|
/* Context string
|
||||||
* This context string is normally created by the CDM layer
|
* This context string is normally created by the CDM layer
|
||||||
* from a license request message.
|
* from a license request message.
|
||||||
* They are used to test MAC and ENC key generation.
|
* They are used to test MAC and ENC key generation.
|
||||||
*/
|
*/
|
||||||
return wvutil::a2b_hex(
|
auto ret = wvutil::a2b_hex(
|
||||||
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
|
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
|
||||||
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
|
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
|
||||||
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
|
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
|
||||||
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
|
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
|
||||||
"38373430350000");
|
"38373430350000");
|
||||||
|
if (do_hash) {
|
||||||
|
uint8_t hash[SHA512_DIGEST_LENGTH];
|
||||||
|
SHA512(ret.data(), ret.size(), hash);
|
||||||
|
ret.assign(hash, hash + sizeof(hash));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should only be called if the device uses Provisioning 2.0. A failure in
|
// This should only be called if the device uses Provisioning 2.0. A failure in
|
||||||
|
|||||||
@@ -444,6 +444,7 @@ class LicenseRoundTrip
|
|||||||
update_mac_keys_(true),
|
update_mac_keys_(true),
|
||||||
api_version_(kCurrentAPI),
|
api_version_(kCurrentAPI),
|
||||||
expect_request_has_correct_nonce_(true),
|
expect_request_has_correct_nonce_(true),
|
||||||
|
skip_request_hash_(global_features.api_version < 19),
|
||||||
license_type_(OEMCrypto_ContentLicense),
|
license_type_(OEMCrypto_ContentLicense),
|
||||||
request_hash_() {}
|
request_hash_() {}
|
||||||
void CreateDefaultResponse() override;
|
void CreateDefaultResponse() override;
|
||||||
@@ -518,6 +519,8 @@ class LicenseRoundTrip
|
|||||||
}
|
}
|
||||||
// Skip the nonce check when verifying the license request.
|
// Skip the nonce check when verifying the license request.
|
||||||
void skip_nonce_check() { expect_request_has_correct_nonce_ = false; }
|
void skip_nonce_check() { expect_request_has_correct_nonce_ = false; }
|
||||||
|
// Skip hashing license request before signing/KDF.
|
||||||
|
void skip_request_hash() { skip_request_hash_ = true; }
|
||||||
// This sets the key id of the specified key to the specified string.
|
// This sets the key id of the specified key to the specified string.
|
||||||
// This is used to test with different key id lengths.
|
// This is used to test with different key id lengths.
|
||||||
void SetKeyId(size_t index, const string& key_id);
|
void SetKeyId(size_t index, const string& key_id);
|
||||||
@@ -549,6 +552,9 @@ class LicenseRoundTrip
|
|||||||
// session. This is usually true, but when we are testing how OEMCrypto
|
// session. This is usually true, but when we are testing how OEMCrypto
|
||||||
// handles a bad nonce, we don't want to.
|
// handles a bad nonce, we don't want to.
|
||||||
bool expect_request_has_correct_nonce_;
|
bool expect_request_has_correct_nonce_;
|
||||||
|
// Whether to skip hashing the request before signing and KDF; this is used
|
||||||
|
// for license protocol 2.2.
|
||||||
|
bool skip_request_hash_;
|
||||||
// Whether this is a content license or an entitlement license. Used in
|
// Whether this is a content license or an entitlement license. Used in
|
||||||
// CreateDefaultResponse.
|
// CreateDefaultResponse.
|
||||||
OEMCrypto_LicenseType license_type_;
|
OEMCrypto_LicenseType license_type_;
|
||||||
@@ -674,7 +680,7 @@ class Session {
|
|||||||
// not null, it will be incremented when a nonce flood is detected.
|
// not null, it will be incremented when a nonce flood is detected.
|
||||||
void GenerateNonce(int* error_counter = nullptr);
|
void GenerateNonce(int* error_counter = nullptr);
|
||||||
// Fill the vector with test context which generate known mac and enc keys.
|
// Fill the vector with test context which generate known mac and enc keys.
|
||||||
std::vector<uint8_t> GetDefaultContext();
|
std::vector<uint8_t> GetDefaultContext(bool do_hash = false);
|
||||||
// Generate known mac and enc keys using OEMCrypto_GenerateDerivedKeys and
|
// Generate known mac and enc keys using OEMCrypto_GenerateDerivedKeys and
|
||||||
// also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
// also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||||
void GenerateDerivedKeysFromKeybox(const wvoec::WidevineKeybox& keybox);
|
void GenerateDerivedKeysFromKeybox(const wvoec::WidevineKeybox& keybox);
|
||||||
|
|||||||
@@ -457,6 +457,8 @@ TEST_P(OEMCryptoLicenseTest, LoadKeyWithBadVerification) {
|
|||||||
// This test verifies that LoadKeys still works when the message is not aligned
|
// This test verifies that LoadKeys still works when the message is not aligned
|
||||||
// in memory on a word (2 or 4 byte) boundary.
|
// in memory on a word (2 or 4 byte) boundary.
|
||||||
TEST_P(OEMCryptoLicenseTest, LoadKeyUnalignedMessageAPI16) {
|
TEST_P(OEMCryptoLicenseTest, LoadKeyUnalignedMessageAPI16) {
|
||||||
|
license_messages_.skip_request_hash();
|
||||||
|
|
||||||
ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest());
|
ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest());
|
||||||
ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse());
|
ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse());
|
||||||
ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse());
|
ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse());
|
||||||
|
|||||||
Reference in New Issue
Block a user