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
@@ -1025,6 +1025,9 @@ OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
||||
* Refer to the Signing Messages Sent to a Server section above for more
|
||||
* 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,
|
||||
* this function returns OEMCrypto_ERROR_SHORT_BUFFER and sets output
|
||||
* 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)
|
||||
api_version_ = global_features.api_version;
|
||||
|
||||
vector<uint8_t> sign_source;
|
||||
if (global_features.api_version < 17) {
|
||||
const std::vector<uint8_t> subdata(data.begin() + core_message_length,
|
||||
data.end());
|
||||
session()->VerifyRsaSignature(subdata, generated_signature.data(),
|
||||
generated_signature.size(), kSign_RSASSA_PSS);
|
||||
SHA256(data.data(), core_message_length, request_hash_);
|
||||
sign_source.assign(data.begin() + core_message_length, data.end());
|
||||
} else if (global_features.api_version < 19) {
|
||||
sign_source = data;
|
||||
} else {
|
||||
session()->VerifySignature(data, generated_signature.data(),
|
||||
generated_signature.size(), kSign_RSASSA_PSS);
|
||||
SHA256(data.data(), core_message_length, request_hash_);
|
||||
sign_source.resize(SHA512_DIGEST_LENGTH);
|
||||
SHA512(data.data(), data.size(), sign_source.data());
|
||||
}
|
||||
session()->VerifySignature(sign_source, generated_signature.data(),
|
||||
generated_signature.size(), kSign_RSASSA_PSS);
|
||||
SHA256(data.data(), core_message_length, request_hash_);
|
||||
}
|
||||
|
||||
void LicenseRoundTrip::FillAndVerifyCoreRequest(
|
||||
@@ -998,7 +999,8 @@ void LicenseRoundTrip::FillCoreResponseSubstrings() {
|
||||
}
|
||||
|
||||
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_;
|
||||
uint8_t iv_buffer[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));
|
||||
}
|
||||
|
||||
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,
|
||||
// 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
|
||||
* This context string is normally created by the CDM layer
|
||||
* from a license request message.
|
||||
* They are used to test MAC and ENC key generation.
|
||||
*/
|
||||
return wvutil::a2b_hex(
|
||||
auto ret = wvutil::a2b_hex(
|
||||
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
|
||||
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
|
||||
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
|
||||
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
|
||||
"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
|
||||
|
||||
@@ -444,6 +444,7 @@ class LicenseRoundTrip
|
||||
update_mac_keys_(true),
|
||||
api_version_(kCurrentAPI),
|
||||
expect_request_has_correct_nonce_(true),
|
||||
skip_request_hash_(global_features.api_version < 19),
|
||||
license_type_(OEMCrypto_ContentLicense),
|
||||
request_hash_() {}
|
||||
void CreateDefaultResponse() override;
|
||||
@@ -518,6 +519,8 @@ class LicenseRoundTrip
|
||||
}
|
||||
// Skip the nonce check when verifying the license request.
|
||||
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 is used to test with different key id lengths.
|
||||
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
|
||||
// handles a bad nonce, we don't want to.
|
||||
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
|
||||
// CreateDefaultResponse.
|
||||
OEMCrypto_LicenseType license_type_;
|
||||
@@ -674,7 +680,7 @@ class Session {
|
||||
// not null, it will be incremented when a nonce flood is detected.
|
||||
void GenerateNonce(int* error_counter = nullptr);
|
||||
// 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
|
||||
// also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||
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
|
||||
// in memory on a word (2 or 4 byte) boundary.
|
||||
TEST_P(OEMCryptoLicenseTest, LoadKeyUnalignedMessageAPI16) {
|
||||
license_messages_.skip_request_hash();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest());
|
||||
ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse());
|
||||
ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse());
|
||||
|
||||
Reference in New Issue
Block a user