Source release 19.1.0
This commit is contained in:
@@ -218,9 +218,12 @@ class boringssl_ptr {
|
||||
|
||||
Test_PST_Report::Test_PST_Report(const std::string& pst_in,
|
||||
OEMCrypto_Usage_Entry_Status status_in)
|
||||
: status(status_in), pst(pst_in) {
|
||||
time_created = wvutil::Clock().GetCurrentTime();
|
||||
}
|
||||
: status(status_in),
|
||||
seconds_since_license_received(0),
|
||||
seconds_since_first_decrypt(0),
|
||||
seconds_since_last_decrypt(0),
|
||||
pst(pst_in),
|
||||
time_created(wvutil::Clock().GetCurrentTime()) {}
|
||||
|
||||
template <class CoreRequest, PrepAndSignRequest_t PrepAndSignRequest,
|
||||
class CoreResponse, class ResponseData>
|
||||
@@ -231,7 +234,8 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
|
||||
// verified by the server. This simulates that.
|
||||
size_t gen_signature_length = 0;
|
||||
size_t core_message_length = 0;
|
||||
constexpr size_t small_size = 42; // arbitrary.
|
||||
const vector<uint8_t> context = session()->GetDefaultContext();
|
||||
const size_t small_size = context.size(); // arbitrary.
|
||||
if (RequestHasNonce()) {
|
||||
session()->GenerateNonce();
|
||||
}
|
||||
@@ -249,7 +253,10 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
|
||||
size_t message_size =
|
||||
std::max(required_message_size_, core_message_length + small_size);
|
||||
vector<uint8_t> data(message_size);
|
||||
for (size_t i = 0; i < data.size(); i++) data[i] = i & 0xFF;
|
||||
memcpy(&data[core_message_length], context.data(), context.size());
|
||||
for (size_t i = context.size() + core_message_length; i < data.size(); i++) {
|
||||
data[i] = i & 0xFF;
|
||||
}
|
||||
if (ShouldGenerateCorpus()) {
|
||||
WriteRequestApiCorpus<CoreRequest>(gen_signature_length,
|
||||
core_message_length, data);
|
||||
@@ -345,29 +352,37 @@ void ProvisioningRoundTrip::PrepareSession(
|
||||
const wvoec::WidevineKeybox& keybox) {
|
||||
ASSERT_NO_FATAL_FAILURE(session_->open());
|
||||
if (global_features.provisioning_method == OEMCrypto_Keybox) {
|
||||
session_->GenerateDerivedKeysFromKeybox(keybox);
|
||||
encryptor_ = session_->key_deriver();
|
||||
keybox_ = &keybox;
|
||||
} else if (global_features.provisioning_method ==
|
||||
OEMCrypto_BootCertificateChain) {
|
||||
// TODO(chelu): change this to CSR provisioning.
|
||||
session_->LoadOEMCert(true);
|
||||
session_->GenerateRsaSessionKey(&message_key_, &encrypted_message_key_);
|
||||
encryptor_.set_enc_key(message_key_);
|
||||
session_->GenerateRsaSessionKey();
|
||||
encryptor_.set_enc_key(session_->session_key());
|
||||
} else {
|
||||
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_OEMCertificate);
|
||||
session_->LoadOEMCert(true);
|
||||
session_->GenerateRsaSessionKey(&message_key_, &encrypted_message_key_);
|
||||
encryptor_.set_enc_key(message_key_);
|
||||
session_->GenerateRsaSessionKey();
|
||||
encryptor_.set_enc_key(session_->session_key());
|
||||
}
|
||||
}
|
||||
|
||||
void ProvisioningRoundTrip::VerifyRequestSignature(
|
||||
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
|
||||
size_t /* core_message_length */) {
|
||||
if (global_features.provisioning_method == OEMCrypto_OEMCertificate) {
|
||||
size_t core_message_length) {
|
||||
if (keybox_ == nullptr) {
|
||||
session()->VerifyRsaSignature(data, generated_signature.data(),
|
||||
generated_signature.size(), kSign_RSASSA_PSS);
|
||||
} else {
|
||||
// Setup the derived keys using the proto message (ignoring the core
|
||||
// message).
|
||||
ASSERT_LE(core_message_length, data.size());
|
||||
const std::vector<uint8_t> base_message(data.begin() + core_message_length,
|
||||
data.end());
|
||||
session()->GenerateDerivedKeysFromKeybox(*keybox_, base_message);
|
||||
encryptor_ = session()->key_deriver();
|
||||
request_ = base_message;
|
||||
|
||||
EXPECT_EQ(global_features.provisioning_method, OEMCrypto_Keybox);
|
||||
ASSERT_EQ(HMAC_SHA256_SIGNATURE_SIZE, generated_signature.size());
|
||||
std::vector<uint8_t> expected_signature;
|
||||
@@ -400,11 +415,11 @@ void ProvisioningRoundTrip::CreateDefaultResponse() {
|
||||
response_data_.rsa_key_length = encoded_rsa_key_.size();
|
||||
}
|
||||
response_data_.nonce = session_->nonce();
|
||||
if (encrypted_message_key_.size() > 0) {
|
||||
ASSERT_LE(encrypted_message_key_.size(), kMaxTestRSAKeyLength);
|
||||
memcpy(response_data_.enc_message_key, encrypted_message_key_.data(),
|
||||
encrypted_message_key_.size());
|
||||
response_data_.enc_message_key_length = encrypted_message_key_.size();
|
||||
if (session_->enc_session_key().size() > 0) {
|
||||
ASSERT_LE(session_->enc_session_key().size(), kMaxTestRSAKeyLength);
|
||||
memcpy(response_data_.enc_message_key, session_->enc_session_key().data(),
|
||||
session_->enc_session_key().size());
|
||||
response_data_.enc_message_key_length = session_->enc_session_key().size();
|
||||
} else {
|
||||
response_data_.enc_message_key_length = 0;
|
||||
}
|
||||
@@ -460,9 +475,6 @@ void ProvisioningRoundTrip::SignResponse() {
|
||||
memcpy(encrypted_response_.data() + serialized_core_message_.size(),
|
||||
reinterpret_cast<const uint8_t*>(&encrypted_response_data_),
|
||||
sizeof(encrypted_response_data_));
|
||||
if (global_features.provisioning_method == OEMCrypto_OEMCertificate) {
|
||||
session()->GenerateDerivedKeysFromSessionKey();
|
||||
}
|
||||
session()->key_deriver().ServerSignBuffer(encrypted_response_.data(),
|
||||
encrypted_response_.size(),
|
||||
&response_signature_);
|
||||
@@ -528,11 +540,24 @@ OEMCryptoResult ProvisioningRoundTrip::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);
|
||||
if (allowed_schemes_ == kSign_RSASSA_PSS) {
|
||||
return OEMCrypto_LoadProvisioning(
|
||||
session->session_id(), request_.data(), request_.size(),
|
||||
encrypted_response_.data(), encrypted_response_.size(),
|
||||
serialized_core_message_.size(), response_signature_.data(),
|
||||
response_signature_.size(), wrapped_rsa_key_.data(),
|
||||
wrapped_key_length);
|
||||
} else {
|
||||
// TODO(b/316053127): Clean this up a lot.
|
||||
const uint8_t* derivation_key = nullptr;
|
||||
const size_t derivation_key_length = 0;
|
||||
return OEMCrypto_LoadProvisioningCast(
|
||||
session->session_id(), derivation_key, derivation_key_length,
|
||||
request_.data(), request_.size(), encrypted_response_.data(),
|
||||
encrypted_response_.size(), serialized_core_message_.size(),
|
||||
response_signature_.data(), response_signature_.size(),
|
||||
wrapped_rsa_key_.data(), wrapped_key_length);
|
||||
}
|
||||
}
|
||||
|
||||
void ProvisioningRoundTrip::VerifyLoadFailed() {
|
||||
@@ -560,12 +585,12 @@ void Provisioning40RoundTrip::PrepareSession(bool is_oem_key) {
|
||||
public_key.resize(public_key_size);
|
||||
|
||||
if (is_oem_key) {
|
||||
wrapped_oem_key_ = wrapped_private_key;
|
||||
oem_public_key_ = public_key;
|
||||
wrapped_oem_key_ = std::move(wrapped_private_key);
|
||||
oem_public_key_ = std::move(public_key);
|
||||
oem_key_type_ = key_type;
|
||||
} else {
|
||||
wrapped_drm_key_ = wrapped_private_key;
|
||||
drm_public_key_ = public_key;
|
||||
wrapped_drm_key_ = std::move(wrapped_private_key);
|
||||
drm_public_key_ = std::move(public_key);
|
||||
drm_key_type_ = key_type;
|
||||
}
|
||||
}
|
||||
@@ -621,8 +646,8 @@ void Provisioning40CastRoundTrip::PrepareSession() {
|
||||
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;
|
||||
wrapped_drm_key_ = std::move(wrapped_private_key);
|
||||
drm_public_key_ = std::move(public_key);
|
||||
drm_key_type_ = key_type;
|
||||
}
|
||||
|
||||
@@ -751,11 +776,13 @@ 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);
|
||||
const std::vector<uint8_t> context = session->GetDefaultContext();
|
||||
return OEMCrypto_LoadProvisioningCast(
|
||||
session->session_id(), session->enc_session_key().data(),
|
||||
session->enc_session_key().size(), context.data(), context.size(),
|
||||
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(
|
||||
@@ -768,17 +795,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(
|
||||
@@ -984,7 +1012,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);
|
||||
@@ -1115,6 +1144,9 @@ OEMCryptoResult LicenseRoundTrip::LoadResponse(Session* session,
|
||||
core_response_.key_array_length * sizeof(*core_response_.key_array));
|
||||
}
|
||||
|
||||
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
|
||||
// not point to garbage data. The goal is to make sure OEMCrypto is verifying
|
||||
@@ -1131,7 +1163,9 @@ OEMCryptoResult LicenseRoundTrip::LoadResponse(Session* session,
|
||||
reinterpret_cast<const uint8_t*>(&encrypted_response_data_) +
|
||||
sizeof(encrypted_response_data_));
|
||||
OEMCryptoResult result = OEMCrypto_LoadLicense(
|
||||
session->session_id(), double_message.data(), encrypted_response_.size(),
|
||||
session->session_id(), context.data(), context.size(),
|
||||
session->enc_session_key().data(), session->enc_session_key().size(),
|
||||
double_message.data(), encrypted_response_.size(),
|
||||
serialized_core_message_.size(), response_signature_.data(),
|
||||
response_signature_.size());
|
||||
if (verify_keys && result == OEMCrypto_SUCCESS) {
|
||||
@@ -1495,27 +1529,9 @@ void RenewalRoundTrip::FillAndVerifyCoreRequest(
|
||||
}
|
||||
}
|
||||
|
||||
void RenewalRoundTrip::CreateDefaultResponse() {
|
||||
if (is_release_) {
|
||||
uint32_t control = 0;
|
||||
uint32_t nonce = 0;
|
||||
// A single key object with no key id should update all keys.
|
||||
constexpr size_t index = 0;
|
||||
response_data_.keys[index].key_id_length = 0;
|
||||
response_data_.keys[index].key_id[0] = '\0';
|
||||
const uint32_t renewal_api =
|
||||
std::max<uint32_t>(core_request_.api_major_version, 15u);
|
||||
std::string kcVersion = "kc" + std::to_string(renewal_api);
|
||||
memcpy(response_data_.keys[index].control.verification, kcVersion.c_str(),
|
||||
4);
|
||||
const uint32_t duration = static_cast<uint32_t>(
|
||||
license_messages_->core_response()
|
||||
.timer_limits.initial_renewal_duration_seconds);
|
||||
response_data_.keys[index].control.duration = htonl(duration);
|
||||
response_data_.keys[index].control.nonce = htonl(nonce);
|
||||
response_data_.keys[index].control.control_bits = htonl(control);
|
||||
}
|
||||
}
|
||||
// Nothing is needed for this function but it needs a definition since it's
|
||||
// declared as a virtual function in the RoundTrip class.
|
||||
void RenewalRoundTrip::CreateDefaultResponse() {}
|
||||
|
||||
void RenewalRoundTrip::EncryptAndSignResponse() {
|
||||
// Renewal messages are not encrypted.
|
||||
@@ -1593,7 +1609,7 @@ OEMCryptoResult RenewalRoundTrip::LoadResponse(Session* session) {
|
||||
GetFileName("oemcrypto_load_renewal_fuzz_seed_corpus");
|
||||
// Corpus for renewal response fuzzer should be in the format:
|
||||
// OEMCrypto_Renewal_Response_Fuzz + license_renewal_response.
|
||||
OEMCrypto_Renewal_Response_Fuzz renewal_response_fuzz;
|
||||
OEMCrypto_Renewal_Response_Fuzz renewal_response_fuzz = {};
|
||||
renewal_response_fuzz.core_request = core_request_;
|
||||
renewal_response_fuzz.renewal_duration_seconds = renewal_duration_seconds_;
|
||||
AppendToFile(file_name,
|
||||
@@ -1610,6 +1626,81 @@ OEMCryptoResult RenewalRoundTrip::LoadResponse(Session* session) {
|
||||
response_signature_.data(), response_signature_.size());
|
||||
}
|
||||
|
||||
void ReleaseRoundTrip::VerifyRequestSignature(
|
||||
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
|
||||
size_t core_message_length) {
|
||||
(void)core_message_length;
|
||||
ASSERT_EQ(HMAC_SHA256_SIGNATURE_SIZE, generated_signature.size());
|
||||
std::vector<uint8_t> expected_signature;
|
||||
session()->key_deriver().ClientSignBuffer(data, &expected_signature);
|
||||
ASSERT_EQ(expected_signature, generated_signature);
|
||||
}
|
||||
|
||||
void ReleaseRoundTrip::FillAndVerifyCoreRequest(
|
||||
const std::string& core_message_string) {
|
||||
EXPECT_TRUE(
|
||||
oemcrypto_core_message::deserialize::CoreReleaseRequestFromMessage(
|
||||
core_message_string, &core_request_));
|
||||
EXPECT_EQ(license_messages_->api_version(), core_request_.api_major_version);
|
||||
EXPECT_EQ(license_messages_->core_request().nonce, core_request_.nonce);
|
||||
EXPECT_EQ(license_messages_->core_request().session_id,
|
||||
core_request_.session_id);
|
||||
}
|
||||
|
||||
// Nothing is needed for this function but it needs a definition since it's
|
||||
// declared as a virtual function in the RoundTrip class.
|
||||
void ReleaseRoundTrip::CreateDefaultResponse() {}
|
||||
|
||||
void ReleaseRoundTrip::EncryptAndSignResponse() {
|
||||
// Release messages are not encrypted.
|
||||
encrypted_response_data_ = response_data_;
|
||||
// Create a core response for a call to LoadRelease.
|
||||
// TODO(b/191724203): Test release server has different version from license
|
||||
// server.
|
||||
ASSERT_NE(license_messages_, nullptr);
|
||||
CoreMessageFeatures features =
|
||||
CoreMessageFeatures::DefaultFeatures(license_messages_->api_version());
|
||||
ASSERT_TRUE(oemcrypto_core_message::serialize::CreateCoreReleaseResponse(
|
||||
features, core_request_, seconds_since_license_received_,
|
||||
seconds_since_first_decrypt_, &serialized_core_message_));
|
||||
// Resize serialize core message to be just big enough or required core
|
||||
// message size, whichever is larger.
|
||||
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 % 0x100;
|
||||
}
|
||||
// Concatenate the core message and the response.
|
||||
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 ReleaseRoundTrip::LoadResponse(Session* session) {
|
||||
// TODO(vickymin): Write corpus for oemcrypto_load_release_fuzz.
|
||||
VerifyEncryptAndSignResponseLengths();
|
||||
return OEMCrypto_LoadRelease(
|
||||
session->session_id(), encrypted_response_.data(),
|
||||
encrypted_response_.size(), serialized_core_message_.size(),
|
||||
response_signature_.data(), response_signature_.size());
|
||||
}
|
||||
|
||||
std::unordered_map<util::EccCurve, std::unique_ptr<util::EccPrivateKey>,
|
||||
std::hash<int>>
|
||||
Session::server_ephemeral_keys_;
|
||||
@@ -1659,63 +1750,48 @@ void Session::GenerateNonce(int* error_counter) {
|
||||
}
|
||||
}
|
||||
|
||||
void Session::FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
vector<uint8_t>* enc_context) {
|
||||
/* Context strings
|
||||
* These context strings are normally created by the CDM layer
|
||||
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.
|
||||
*/
|
||||
*mac_context = wvutil::a2b_hex(
|
||||
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
|
||||
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
|
||||
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
|
||||
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
|
||||
"34333231180120002a0c31383836373837343035000000000200");
|
||||
*enc_context = wvutil::a2b_hex(
|
||||
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
|
||||
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
|
||||
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
|
||||
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
|
||||
"180120002a0c31383836373837343035000000000080");
|
||||
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
|
||||
// this function is probably caused by a bad keybox.
|
||||
void Session::GenerateDerivedKeysFromKeybox(
|
||||
const wvoec::WidevineKeybox& keybox) {
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateDerivedKeys(
|
||||
session_id(), mac_context.data(), mac_context.size(),
|
||||
enc_context.data(), enc_context.size()));
|
||||
return GenerateDerivedKeysFromKeybox(keybox, GetDefaultContext());
|
||||
}
|
||||
|
||||
void Session::GenerateDerivedKeysFromKeybox(
|
||||
const wvoec::WidevineKeybox& keybox, const std::vector<uint8_t>& context) {
|
||||
key_deriver_.DeriveKeys(keybox.device_key_, sizeof(keybox.device_key_),
|
||||
mac_context, enc_context);
|
||||
context);
|
||||
}
|
||||
|
||||
void Session::GenerateDerivedKeysFromSessionKey() {
|
||||
// Uses test certificate.
|
||||
vector<uint8_t> session_key;
|
||||
vector<uint8_t> enc_session_key;
|
||||
ASSERT_TRUE(public_rsa_ || public_ec_)
|
||||
<< "No public RSA/ECC key loaded in test code";
|
||||
// A failure here probably indicates that there is something wrong with the
|
||||
// test program and its dependency on BoringSSL.
|
||||
ASSERT_TRUE(GenerateSessionKey(&session_key, &enc_session_key));
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
// A failure here is probably caused by having the wrong RSA key loaded.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DeriveKeysFromSessionKey(
|
||||
session_id(), enc_session_key.data(), enc_session_key.size(),
|
||||
mac_context.data(), mac_context.size(), enc_context.data(),
|
||||
enc_context.size()));
|
||||
GenerateDerivedKeysFromSessionKey(GetDefaultContext());
|
||||
}
|
||||
|
||||
key_deriver_.DeriveKeys(session_key.data(), session_key.size(), mac_context,
|
||||
enc_context);
|
||||
void Session::GenerateDerivedKeysFromSessionKey(
|
||||
const std::vector<uint8_t>& context) {
|
||||
// Uses test certificate.
|
||||
ASSERT_TRUE(GenerateSessionKey());
|
||||
key_deriver_.DeriveKeys(session_key_.data(), session_key_.size(), context);
|
||||
}
|
||||
|
||||
void Session::TestDecryptCTR(bool get_fresh_key_handle_first,
|
||||
@@ -1872,7 +1948,6 @@ void Session::LoadOEMCert(bool verify_cert) {
|
||||
util::RsaPublicKey::FromSslHandle(EVP_PKEY_get0_RSA(pubkey.get()));
|
||||
ASSERT_TRUE(public_rsa_)
|
||||
<< "Failed to extract public RSA key from OEM certificate";
|
||||
return;
|
||||
}
|
||||
if (verify_cert) {
|
||||
vector<char> buffer(80);
|
||||
@@ -2017,19 +2092,17 @@ void Session::VerifySignature(const vector<uint8_t>& message,
|
||||
FAIL() << "No public RSA or ECC key loaded in test code";
|
||||
}
|
||||
|
||||
bool Session::GenerateRsaSessionKey(vector<uint8_t>* session_key,
|
||||
vector<uint8_t>* enc_session_key) {
|
||||
bool Session::GenerateRsaSessionKey() {
|
||||
if (!public_rsa_) {
|
||||
cerr << "No public RSA key loaded in test code\n";
|
||||
return false;
|
||||
}
|
||||
*session_key = wvutil::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
|
||||
*enc_session_key = public_rsa_->EncryptSessionKey(*session_key);
|
||||
return !enc_session_key->empty();
|
||||
session_key_ = wvutil::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
|
||||
enc_session_key_ = public_rsa_->EncryptSessionKey(session_key_);
|
||||
return !enc_session_key_.empty();
|
||||
}
|
||||
|
||||
bool Session::GenerateEccSessionKey(vector<uint8_t>* session_key,
|
||||
vector<uint8_t>* ecdh_public_key_data) {
|
||||
bool Session::GenerateEccSessionKey() {
|
||||
if (!public_ec_) {
|
||||
cerr << "No public ECC key loaded in test code\n";
|
||||
return false;
|
||||
@@ -2044,24 +2117,23 @@ bool Session::GenerateEccSessionKey(vector<uint8_t>* session_key,
|
||||
<< util::EccCurveToString(curve) << std::endl;
|
||||
return false;
|
||||
}
|
||||
*session_key = server_ephemeral_keys_[curve]->DeriveSessionKey(*public_ec_);
|
||||
if (session_key->empty()) {
|
||||
session_key_ = server_ephemeral_keys_[curve]->DeriveSessionKey(*public_ec_);
|
||||
if (session_key_.empty()) {
|
||||
return false;
|
||||
}
|
||||
*ecdh_public_key_data = server_ephemeral_keys_[curve]->SerializeAsPublicKey();
|
||||
if (ecdh_public_key_data->empty()) {
|
||||
session_key->clear();
|
||||
enc_session_key_ = server_ephemeral_keys_[curve]->SerializeAsPublicKey();
|
||||
if (enc_session_key_.empty()) {
|
||||
session_key_.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Session::GenerateSessionKey(vector<uint8_t>* session_key,
|
||||
vector<uint8_t>* key_material) {
|
||||
bool Session::GenerateSessionKey() {
|
||||
if (public_rsa_ != nullptr) {
|
||||
return GenerateRsaSessionKey(session_key, key_material);
|
||||
return GenerateRsaSessionKey();
|
||||
} else if (public_ec_ != nullptr) {
|
||||
return GenerateEccSessionKey(session_key, key_material);
|
||||
return GenerateEccSessionKey();
|
||||
}
|
||||
cerr << "No public RSA or ECC key loaded in test code\n";
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user