Source release 18.7.0
This commit is contained in:
@@ -31,7 +31,7 @@ class SystemIdExtractor {
|
||||
// |security_level|
|
||||
// - Requested security level, uses the |crypto_session| handle
|
||||
// to convert to a concrete security level.
|
||||
// |crypto_sesssion|
|
||||
// |crypto_session|
|
||||
// - Handle into the OEMCrypto platform. If handle is open,
|
||||
// then the session's real security level should match
|
||||
// |security_level|.
|
||||
|
||||
@@ -151,7 +151,6 @@ void AdvanceDestBuffer(OEMCrypto_DestBufferDesc* dest_buffer, size_t bytes) {
|
||||
switch (dest_buffer->type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
dest_buffer->buffer.clear.clear_buffer += bytes;
|
||||
dest_buffer->buffer.clear.clear_buffer_length -= bytes;
|
||||
return;
|
||||
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
@@ -2511,6 +2510,17 @@ bool CryptoSession::GetBuildInformation(RequestedSecurityLevel security_level,
|
||||
return false;
|
||||
}
|
||||
info->resize(info_length);
|
||||
// Some OEMCrypto implementations may include trailing null
|
||||
// bytes in the output. Trim them here.
|
||||
while (!info->empty() && info->back() == '\0') {
|
||||
info->pop_back();
|
||||
}
|
||||
if (info->empty()) {
|
||||
LOGE("BuildInformation() returned corrupted data: length = %zu",
|
||||
info_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3219,6 +3229,11 @@ OEMCryptoResult CryptoSession::DecryptSample(
|
||||
}
|
||||
|
||||
fake_sample.buffers.input_data_length = length;
|
||||
if (fake_sample.buffers.output_descriptor.type ==
|
||||
OEMCrypto_BufferType_Clear) {
|
||||
fake_sample.buffers.output_descriptor.buffer.clear
|
||||
.clear_buffer_length = length;
|
||||
}
|
||||
fake_sample.subsamples = &clear_subsample;
|
||||
fake_sample.subsamples_length = 1;
|
||||
|
||||
@@ -3246,6 +3261,11 @@ OEMCryptoResult CryptoSession::DecryptSample(
|
||||
}
|
||||
|
||||
fake_sample.buffers.input_data_length = length;
|
||||
if (fake_sample.buffers.output_descriptor.type ==
|
||||
OEMCrypto_BufferType_Clear) {
|
||||
fake_sample.buffers.output_descriptor.buffer.clear
|
||||
.clear_buffer_length = length;
|
||||
}
|
||||
fake_sample.subsamples = &encrypted_subsample;
|
||||
fake_sample.subsamples_length = 1;
|
||||
|
||||
@@ -3338,6 +3358,10 @@ OEMCryptoResult CryptoSession::LegacyCopyBufferInChunks(
|
||||
// Calculate the size of the next chunk.
|
||||
const size_t chunk_size = std::min(remaining_input_data, max_chunk_size);
|
||||
|
||||
if (output_descriptor.type == OEMCrypto_BufferType_Clear) {
|
||||
output_descriptor.buffer.clear.clear_buffer_length = chunk_size;
|
||||
}
|
||||
|
||||
// Re-add "last subsample" flag if this is the last subsample.
|
||||
if (chunk_size == remaining_input_data) {
|
||||
subsample_flags |= OEMCrypto_LastSubsample;
|
||||
@@ -3385,6 +3409,11 @@ OEMCryptoResult CryptoSession::LegacyDecryptInChunks(
|
||||
// Calculate the size of the next chunk.
|
||||
const size_t chunk_size = std::min(remaining_input_data, max_chunk_size);
|
||||
fake_sample.buffers.input_data_length = chunk_size;
|
||||
if (fake_sample.buffers.output_descriptor.type ==
|
||||
OEMCrypto_BufferType_Clear) {
|
||||
fake_sample.buffers.output_descriptor.buffer.clear.clear_buffer_length =
|
||||
chunk_size;
|
||||
}
|
||||
if (is_protected) {
|
||||
fake_subsample.num_bytes_encrypted = chunk_size;
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "certificate_provisioning.h"
|
||||
#include "license_holder.h"
|
||||
#include "log.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "provisioning_holder.h"
|
||||
#include "test_base.h"
|
||||
#include "wv_cdm_types.h"
|
||||
@@ -135,6 +136,9 @@ class CoreIntegrationTest : public WvCdmTestBaseWithEngine {
|
||||
* different apps. Test using two different apps and origins.
|
||||
*/
|
||||
TEST_F(CoreIntegrationTest, ProvisioningStableSpoidTest) {
|
||||
if (wvoec::global_features.provisioning_method == OEMCrypto_DrmCertificate) {
|
||||
GTEST_SKIP() << "Device does not provision.";
|
||||
}
|
||||
std::string level;
|
||||
ASSERT_EQ(
|
||||
NO_ERROR,
|
||||
|
||||
@@ -94,7 +94,7 @@ void LicenseHolder::GenerateAndPostRenewalRequest(
|
||||
void LicenseHolder::FetchRenewal() {
|
||||
ASSERT_NE(renewal_in_flight_, nullptr) << "Failed for " << content_id();
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
renewal_in_flight_->AssertOkResponse(&renewal_response_))
|
||||
renewal_in_flight_->AssertOkResponseWithRetry(&renewal_response_))
|
||||
<< "Renewal failed for " << content_id();
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ void LicenseHolder::GetKeyResponse(const CdmKeyRequest& key_request) {
|
||||
|
||||
std::string http_response;
|
||||
url_request.PostRequest(key_request.message);
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponse(&http_response))
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponseWithRetry(&http_response))
|
||||
<< "Failed for " << content_id();
|
||||
LicenseRequest license_request;
|
||||
license_request.GetDrmMessage(http_response, key_response_);
|
||||
|
||||
@@ -69,7 +69,7 @@ void ProvisioningHolder::Provision(CdmCertificateType cert_type,
|
||||
url_request.PostCertRequestInQueryString(request);
|
||||
|
||||
// Receive and parse response.
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponse(&response_))
|
||||
ASSERT_NO_FATAL_FAILURE(url_request.AssertOkResponseWithRetry(&response_))
|
||||
<< "Failed to fetch provisioning response. "
|
||||
<< DumpProvAttempt(request, response_, cert_type);
|
||||
|
||||
|
||||
@@ -329,9 +329,12 @@ void WvCdmTestBase::InstallTestRootOfTrust() {
|
||||
sizeof(test_keybox)));
|
||||
break;
|
||||
case wvoec::DeviceFeatures::LOAD_TEST_RSA_KEY:
|
||||
// Rare case: used by devices with baked in DRM cert.
|
||||
// Rare case: used by devices with baked in production DRM cert.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
|
||||
break;
|
||||
case wvoec::DeviceFeatures::PRELOADED_RSA_KEY:
|
||||
// Rare case: used by devices with baked in test DRM cert.
|
||||
break;
|
||||
case wvoec::DeviceFeatures::TEST_PROVISION_30:
|
||||
// Can use oem certificate to install test rsa key.
|
||||
break;
|
||||
@@ -361,6 +364,10 @@ void WvCdmTestBase::Provision() {
|
||||
}
|
||||
|
||||
void WvCdmTestBase::EnsureProvisioned() {
|
||||
if (wvoec::global_features.provisioning_method == OEMCrypto_DrmCertificate) {
|
||||
LOGD("Device is preprovisioned.");
|
||||
return;
|
||||
}
|
||||
CdmSessionId session_id;
|
||||
std::unique_ptr<wvutil::FileSystem> file_system(CreateTestFileSystem());
|
||||
// OpenSession will check if a DRM certificate exists, while
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#include "url_request.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
@@ -24,11 +26,15 @@ const int kConnectTimeoutMs = 15000;
|
||||
const int kWriteTimeoutMs = 12000;
|
||||
const int kReadTimeoutMs = 12000;
|
||||
constexpr int kHttpOk = 200;
|
||||
const std::vector<int> kRetryCodes = {502, 504};
|
||||
|
||||
const std::string kGoogleHeaderUpper("X-Google");
|
||||
const std::string kGoogleHeaderLower("x-google");
|
||||
const std::string kCrLf("\r\n");
|
||||
|
||||
constexpr unsigned kRetryCount = 3;
|
||||
constexpr unsigned kRetryIntervalSeconds = 1;
|
||||
|
||||
// Concatenate all chunks into one blob and returns the response with
|
||||
// header information.
|
||||
void ConcatenateChunkedResponse(const std::string http_response,
|
||||
@@ -127,13 +133,34 @@ bool UrlRequest::GetResponse(std::string* message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void UrlRequest::AssertOkResponse(std::string* message) {
|
||||
void UrlRequest::AssertOkResponseWithRetry(std::string* message) {
|
||||
ASSERT_TRUE(message);
|
||||
ASSERT_TRUE(GetResponse(message));
|
||||
const int status_code = GetStatusCode(*message);
|
||||
ASSERT_EQ(kHttpOk, status_code) << "HTTP response from " << socket_.url()
|
||||
<< ": (" << message->size() << ") :\n"
|
||||
<< *message;
|
||||
int status_code = 0;
|
||||
for (unsigned i = 0; i < kRetryCount; i++) {
|
||||
*message = "";
|
||||
ASSERT_TRUE(GetResponse(message)) << "For attempt " << (i + 1);
|
||||
status_code = GetStatusCode(*message);
|
||||
// If we didn't get a retry status, then we're done.
|
||||
if (std::find(kRetryCodes.begin(), kRetryCodes.end(), status_code) ==
|
||||
kRetryCodes.end()) {
|
||||
ASSERT_EQ(kHttpOk, status_code) << "HTTP response from " << socket_.url()
|
||||
<< ": (" << message->size() << ") :\n"
|
||||
<< *message;
|
||||
return;
|
||||
}
|
||||
std::cerr << "Temporary failure HTTP response from " << socket_.url()
|
||||
<< ": (" << message->size() << ") :\n"
|
||||
<< *message << "\n"
|
||||
<< "Attempt " << (i + 1) << "\n";
|
||||
socket_.CloseSocket();
|
||||
is_connected_ = false;
|
||||
sleep(kRetryIntervalSeconds << i);
|
||||
Reconnect();
|
||||
SendRequestOnce();
|
||||
}
|
||||
GTEST_FAIL() << "HTTP response from " << socket_.url() << ": ("
|
||||
<< message->size() << ") :\n"
|
||||
<< *message;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -190,36 +217,35 @@ bool UrlRequest::GetDebugHeaderFields(
|
||||
|
||||
bool UrlRequest::PostRequestWithPath(const std::string& path,
|
||||
const std::string& data) {
|
||||
std::string request;
|
||||
request_.clear();
|
||||
|
||||
request.append("POST ");
|
||||
request.append(path);
|
||||
request.append(" HTTP/1.1\r\n");
|
||||
request_.append("POST ");
|
||||
request_.append(path);
|
||||
request_.append(" HTTP/1.1\r\n");
|
||||
|
||||
request.append("Host: ");
|
||||
request.append(socket_.domain_name());
|
||||
request.append("\r\n");
|
||||
request_.append("Host: ");
|
||||
request_.append(socket_.domain_name());
|
||||
request_.append("\r\n");
|
||||
|
||||
request.append("Connection: close\r\n");
|
||||
request.append("User-Agent: Widevine CDM v1.0\r\n");
|
||||
request.append("X-Return-Encrypted-Headers: request_and_response\r\n");
|
||||
request_.append("Connection: close\r\n");
|
||||
request_.append("User-Agent: Widevine CDM v1.0\r\n");
|
||||
request_.append("X-Return-Encrypted-Headers: request_and_response\r\n");
|
||||
|
||||
// buffer to store length of data as a string
|
||||
char data_size_buffer[32] = {0};
|
||||
snprintf(data_size_buffer, sizeof(data_size_buffer), "%zu", data.size());
|
||||
request_.append("Content-Length: ");
|
||||
request_.append(std::to_string(data.size()));
|
||||
request_.append("\r\n");
|
||||
|
||||
request.append("Content-Length: ");
|
||||
request.append(data_size_buffer); // appends size of data
|
||||
request.append("\r\n");
|
||||
request_.append("\r\n"); // empty line to terminate headers
|
||||
|
||||
request.append("\r\n"); // empty line to terminate headers
|
||||
|
||||
request.append(data);
|
||||
request_.append(data);
|
||||
return SendRequestOnce();
|
||||
}
|
||||
|
||||
bool UrlRequest::SendRequestOnce() {
|
||||
const int ret = socket_.WriteAndLogErrors(
|
||||
request.c_str(), static_cast<int>(request.size()), kWriteTimeoutMs);
|
||||
LOGV("HTTP request: (%zu): %s", request.size(), request.c_str());
|
||||
LOGV("HTTP request hex: %s", wvutil::b2a_hex(request).c_str());
|
||||
request_.c_str(), static_cast<int>(request_.size()), kWriteTimeoutMs);
|
||||
LOGV("HTTP request: (%zu): %s", request_.size(), request_.c_str());
|
||||
LOGV("HTTP request hex: %s", wvutil::b2a_hex(request_).c_str());
|
||||
return ret != -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@ class UrlRequest {
|
||||
bool GetResponse(std::string* message);
|
||||
static int GetStatusCode(const std::string& response);
|
||||
// Get the response, and expect the status is OK.
|
||||
void AssertOkResponse(std::string* message);
|
||||
// It will retry if the response code is in the 500 range.
|
||||
void AssertOkResponseWithRetry(std::string* message);
|
||||
|
||||
static bool GetDebugHeaderFields(
|
||||
const std::string& response,
|
||||
@@ -37,9 +38,11 @@ class UrlRequest {
|
||||
|
||||
private:
|
||||
bool PostRequestWithPath(const std::string& path, const std::string& data);
|
||||
bool SendRequestOnce();
|
||||
|
||||
bool is_connected_;
|
||||
HttpSocket socket_;
|
||||
std::string request_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(UrlRequest);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user