Cherry pick cdm udc-widevine-release changes to udc-widevine-dev to be in sync with 18.3 release

Merged from go/wvgerrit/178231

Bug: 290252845
Test: WVTS tests seem to be running and passing
Change-Id: Ifff9123a73e173e835a6e89ba7c2760e1cd500fd
(cherry picked from commit 6889845d2e7e24f22c00b333335c34259b3fc96e)
This commit is contained in:
Vicky Min
2023-07-12 18:59:13 +00:00
parent 42a5f26c5a
commit bc20b9dac9
460 changed files with 16767 additions and 3215 deletions

View File

@@ -603,6 +603,161 @@ OEMCryptoResult Provisioning40RoundTrip::LoadDRMCertResponse() {
wrapped_drm_key_.size());
}
void Provisioning40CastRoundTrip::PrepareSession() {
const size_t buffer_size = 5000; // Make sure it is large enough.
std::vector<uint8_t> public_key(buffer_size);
size_t public_key_size = buffer_size;
std::vector<uint8_t> public_key_signature(buffer_size);
size_t public_key_signature_size = buffer_size;
std::vector<uint8_t> wrapped_private_key(buffer_size);
size_t wrapped_private_key_size = buffer_size;
OEMCrypto_PrivateKeyType key_type;
ASSERT_EQ(
OEMCrypto_SUCCESS,
OEMCrypto_GenerateCertificateKeyPair(
session()->session_id(), public_key.data(), &public_key_size,
public_key_signature.data(), &public_key_signature_size,
wrapped_private_key.data(), &wrapped_private_key_size, &key_type));
wrapped_private_key.resize(wrapped_private_key_size);
public_key.resize(public_key_size);
wrapped_drm_key_ = wrapped_private_key;
drm_public_key_ = public_key;
drm_key_type_ = key_type;
}
void Provisioning40CastRoundTrip::LoadDRMPrivateKey() {
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_LoadDRMPrivateKey(session()->session_id(), drm_key_type_,
wrapped_drm_key_.data(),
wrapped_drm_key_.size()));
}
void Provisioning40CastRoundTrip::FillAndVerifyCoreRequest(
const std::string& core_message_string) {
EXPECT_TRUE(
oemcrypto_core_message::deserialize::CoreProvisioning40RequestFromMessage(
core_message_string, &core_request_));
EXPECT_EQ(global_features.api_version, core_request_.api_major_version);
EXPECT_EQ(session()->nonce(), core_request_.nonce);
EXPECT_EQ(session()->session_id(), core_request_.session_id);
}
void Provisioning40CastRoundTrip::VerifyRequestSignature(
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
size_t /* core_message_length */) {
ASSERT_NO_FATAL_FAILURE(
session()->VerifySignature(data, generated_signature.data(),
generated_signature.size(), kSign_RSASSA_PSS));
}
// Creates a prov2 response
void Provisioning40CastRoundTrip::CreateDefaultResponse() {
uint32_t algorithm_n = htonl(allowed_schemes_);
memcpy(response_data_.rsa_key, "SIGN", 4);
memcpy(response_data_.rsa_key + 4, &algorithm_n, 4);
memcpy(response_data_.rsa_key + 8, encoded_rsa_key_.data(),
encoded_rsa_key_.size());
response_data_.rsa_key_length = 8 + encoded_rsa_key_.size();
response_data_.nonce = session_->nonce();
response_data_.enc_message_key_length = 0;
core_response_.key_type = OEMCrypto_RSA_Private_Key;
core_response_.enc_private_key =
FindSubstring(response_data_.rsa_key, response_data_.rsa_key_length);
core_response_.enc_private_key_iv = FindSubstring(
response_data_.rsa_key_iv, sizeof(response_data_.rsa_key_iv));
core_response_.encrypted_message_key = FindSubstring(
response_data_.enc_message_key, response_data_.enc_message_key_length);
}
void Provisioning40CastRoundTrip::EncryptAndSignResponse() {
session()->key_deriver().PadAndEncryptProvisioningMessage(
&response_data_, &encrypted_response_data_);
core_response_.enc_private_key.length =
encrypted_response_data_.rsa_key_length;
SignResponse();
}
void Provisioning40CastRoundTrip::SignResponse() {
CoreMessageFeatures features =
CoreMessageFeatures::DefaultFeatures(ODK_MAJOR_VERSION);
// Create prov 2 request struct from prov 4 request
oemcrypto_core_message::ODK_ProvisioningRequest core_request_prov2;
core_request_prov2.api_minor_version = core_request_.api_minor_version;
core_request_prov2.api_major_version = core_request_.api_major_version;
core_request_prov2.nonce = core_request_.nonce;
core_request_prov2.session_id = core_request_.session_id;
memcpy(&core_request_prov2.counter_info, &core_request_.counter_info,
sizeof(core_request_.counter_info));
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreProvisioningResponse(
features, core_response_, core_request_prov2, &serialized_core_message_));
// Resizing for huge core message length unit tests.
serialized_core_message_.resize(
std::max(required_core_message_size_, serialized_core_message_.size()));
// Make the message buffer a just big enough, or the
// required size, whichever is larger.
const size_t message_size =
std::max(required_message_size_, serialized_core_message_.size() +
sizeof(encrypted_response_data_));
// Stripe the encrypted message.
encrypted_response_.resize(message_size);
for (size_t i = 0; i < encrypted_response_.size(); i++) {
encrypted_response_[i] = i & 0xFF;
}
ASSERT_GE(encrypted_response_.size(), serialized_core_message_.size());
memcpy(encrypted_response_.data(), serialized_core_message_.data(),
serialized_core_message_.size());
ASSERT_GE(encrypted_response_.size(),
serialized_core_message_.size() + sizeof(encrypted_response_data_));
memcpy(encrypted_response_.data() + serialized_core_message_.size(),
reinterpret_cast<const uint8_t*>(&encrypted_response_data_),
sizeof(encrypted_response_data_));
session()->key_deriver().ServerSignBuffer(encrypted_response_.data(),
encrypted_response_.size(),
&response_signature_);
SetEncryptAndSignResponseLengths();
}
OEMCryptoResult Provisioning40CastRoundTrip::LoadResponse(Session* session) {
EXPECT_NE(session, nullptr);
// Write corpus for oemcrypto_load_provisioning_fuzz. Fuzz script expects
// unencrypted response from provisioning server as input corpus data.
// Data will be encrypted and signed again explicitly by fuzzer script after
// mutations.
if (ShouldGenerateCorpus()) {
const std::string file_name =
GetFileName("oemcrypto_load_provisioning_fuzz_seed_corpus");
// Corpus for license response fuzzer should be in the format:
// unencrypted (core_response + response_data).
AppendToFile(file_name, reinterpret_cast<const char*>(&core_response_),
sizeof(ODK_ParsedProvisioning));
AppendToFile(file_name, reinterpret_cast<const char*>(&response_data_),
sizeof(response_data_));
}
size_t wrapped_key_length = 0;
OEMCryptoResult sts = LoadResponseNoRetry(session, &wrapped_key_length);
if (sts != OEMCrypto_ERROR_SHORT_BUFFER) return sts;
wrapped_rsa_key_.assign(wrapped_key_length, 0);
sts = LoadResponseNoRetry(session, &wrapped_key_length);
if (sts == OEMCrypto_SUCCESS) {
wrapped_rsa_key_.resize(wrapped_key_length);
}
return sts;
}
OEMCryptoResult Provisioning40CastRoundTrip::LoadResponseNoRetry(
Session* session, size_t* wrapped_key_length) {
EXPECT_NE(session, nullptr);
VerifyEncryptAndSignResponseLengths();
return OEMCrypto_LoadProvisioning(
session->session_id(), encrypted_response_.data(),
encrypted_response_.size(), serialized_core_message_.size(),
response_signature_.data(), response_signature_.size(),
wrapped_rsa_key_.data(), wrapped_key_length);
}
void LicenseRoundTrip::VerifyRequestSignature(
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
size_t core_message_length) {
@@ -685,16 +840,14 @@ void LicenseRoundTrip::CreateDefaultResponse() {
// Fill in the default core_response_ fields, except the substrings, which are
// filled in the next function.
core_response_.nonce_required =
((wvoec::kControlNonceEnabled | wvoec::kControlNonceOrEntry |
wvoec::kControlNonceRequired) &
control_)
? 1
: 0;
(wvoec::kControlNonceEnabled | wvoec::kControlNonceOrEntry |
wvoec::kControlNonceRequired) &
control_;
core_response_.license_type = license_type_;
FillCoreResponseSubstrings();
}
void LicenseRoundTrip::ConvertDataToValidBools(ODK_ParsedLicense* t) {
void LicenseRoundTrip::ConvertDataToValidBools(ODK_Packing_ParsedLicense* t) {
t->nonce_required = ConvertByteToValidBoolean(&t->nonce_required);
t->timer_limits.soft_enforce_playback_duration = ConvertByteToValidBoolean(
&t->timer_limits.soft_enforce_playback_duration);
@@ -713,19 +866,19 @@ void LicenseRoundTrip::InjectFuzzedTimerLimits(
void LicenseRoundTrip::InjectFuzzedResponseData(const uint8_t* data,
size_t size) {
// Interpreting fuzz data as unencrypted core_response + message_data
// Interpreting fuzz data as unencrypted core_response + response_data +
// key_array
FuzzedData fuzzed_data(data, size);
// Copy core_response from data.
fuzzed_data.Fill(&core_response_, sizeof(core_response_));
// Maximum number of keys could be kMaxNumKeys(30). key_array_length can be
// any random value as it is read from fuzz data.
// Key data array(MessageKeyData keys[kMaxNumKeys]) will be looped over
// key_array_length number of times during LoadLicense. If key_array_length is
// more than kMaxNumKeys, setting it to max value of kMaxNumKeys as we should
// not go out of bounds of this array length. For corpus, this value is
// already hard coded to 4.
// Copy response_data from data.
fuzzed_data.Fill(&response_data_, sizeof(response_data_));
// If key_array_length is more than kMaxNumKeys, we set it to kMaxNumKeys to
// prevent it from going out of bounds. For corpus, this value is already hard
// coded to 4.
if (core_response_.key_array_length > kMaxNumKeys) {
core_response_.key_array_length = kMaxNumKeys;
}
@@ -733,6 +886,13 @@ void LicenseRoundTrip::InjectFuzzedResponseData(const uint8_t* data,
// For corpus data, this value gets set to 4, but we need to test other
// scenarios too, hence reading key_array_length value.
set_num_keys(core_response_.key_array_length);
// Copy key_array from data.
key_array_.resize(num_keys_);
core_response_.key_array = key_array_.data();
fuzzed_data.Fill(core_response_.key_array,
num_keys_ * sizeof(*core_response_.key_array));
ConvertDataToValidBools(&core_response_);
// TODO(b/157520981): Once assertion bug is fixed, for loop can be removed.
@@ -753,11 +913,9 @@ void LicenseRoundTrip::InjectFuzzedResponseData(const uint8_t* data,
}
}
// Copy response_data from data and set nonce to match one in request to pass
// nonce validations.
fuzzed_data.Fill(&response_data_, sizeof(response_data_));
// Set nonce to match one in request to pass nonce validations.
for (uint32_t i = 0; i < num_keys_; ++i) {
response_data_.keys[i].control.nonce = session()->nonce();
response_data_.keys[i].control.nonce = htonl(session()->nonce());
}
}
@@ -802,27 +960,30 @@ void LicenseRoundTrip::FillCoreResponseSubstrings() {
sizeof(response_data_.srm_restriction_data));
}
core_response_.key_array_length = num_keys_;
key_array_.clear();
for (unsigned int i = 0; i < num_keys_; i++) {
core_response_.key_array[i].key_id = FindSubstring(
response_data_.keys[i].key_id, response_data_.keys[i].key_id_length);
core_response_.key_array[i].key_data_iv = FindSubstring(
response_data_.keys[i].key_iv, sizeof(response_data_.keys[i].key_iv));
core_response_.key_array[i].key_data =
FindSubstring(response_data_.keys[i].key_data,
response_data_.keys[i].key_data_length);
OEMCrypto_KeyObject obj;
obj.key_id = FindSubstring(response_data_.keys[i].key_id,
response_data_.keys[i].key_id_length);
obj.key_data_iv = FindSubstring(response_data_.keys[i].key_iv,
sizeof(response_data_.keys[i].key_iv));
obj.key_data = FindSubstring(response_data_.keys[i].key_data,
response_data_.keys[i].key_data_length);
if (core_request().api_major_version < kClearControlBlockAPIMajor ||
(core_request().api_major_version == kClearControlBlockAPIMajor &&
core_request().api_minor_version < kClearControlBlockAPIMinor)) {
core_response_.key_array[i].key_control_iv =
obj.key_control_iv =
FindSubstring(response_data_.keys[i].control_iv,
sizeof(response_data_.keys[i].control_iv));
} else {
core_response_.key_array[i].key_control_iv = FindSubstring(nullptr, 0);
obj.key_control_iv = FindSubstring(nullptr, 0);
}
core_response_.key_array[i].key_control =
FindSubstring(&response_data_.keys[i].control,
sizeof(response_data_.keys[i].control));
obj.key_control = FindSubstring(&response_data_.keys[i].control,
sizeof(response_data_.keys[i].control));
key_array_.push_back(obj);
}
core_response_.key_array = key_array_.data();
core_response_.key_array_length = static_cast<uint32_t>(key_array_.size());
}
void LicenseRoundTrip::EncryptResponse(bool force_clear_kcb) {
@@ -947,11 +1108,14 @@ OEMCryptoResult LicenseRoundTrip::LoadResponse(Session* session,
const std::string file_name =
GetFileName("oemcrypto_load_license_fuzz_seed_corpus");
// Corpus for license response fuzzer should be in the format:
// core_response + response_data.
// core_response + response_data + key_array.
AppendToFile(file_name, reinterpret_cast<const char*>(&core_response_),
sizeof(ODK_ParsedLicense));
sizeof(core_response_));
AppendToFile(file_name, reinterpret_cast<const char*>(&response_data_),
sizeof(response_data_));
AppendToFile(
file_name, reinterpret_cast<const char*>(core_response_.key_array),
core_response_.key_array_length * sizeof(*core_response_.key_array));
}
// Some tests adjust the offset to be beyond the length of the message. Here,
@@ -1855,10 +2019,7 @@ bool Session::GenerateRsaSessionKey(vector<uint8_t>* session_key,
}
*session_key = wvutil::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
*enc_session_key = public_rsa_->EncryptSessionKey(*session_key);
if (enc_session_key->empty()) {
return false;
}
return true;
return !enc_session_key->empty();
}
bool Session::GenerateEccSessionKey(vector<uint8_t>* session_key,