Source release v3.0.2
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,5 +1,3 @@
|
||||
_auto_*
|
||||
|
||||
# GYP-generated files.
|
||||
Makefile
|
||||
*.Makefile
|
||||
@@ -14,3 +12,7 @@ out/
|
||||
|
||||
# Ignoring backup files.
|
||||
*~
|
||||
|
||||
# Configure logs from protobuf.
|
||||
config.status
|
||||
config.log
|
||||
|
||||
BIN
README.pdf
BIN
README.pdf
Binary file not shown.
1
build.py
1
build.py
@@ -88,6 +88,7 @@ def ImportPlatform(name, gyp_args):
|
||||
|
||||
if hasattr(target, 'export_variables'):
|
||||
for k, v in target.export_variables.iteritems():
|
||||
if not os.environ.get(k):
|
||||
os.environ[k] = v
|
||||
print ' set %s to %s' % (k, v)
|
||||
|
||||
|
||||
@@ -130,6 +130,20 @@ class CDM_EXPORT Cdm : public ITimerClient {
|
||||
// See Cdm::createSession().
|
||||
class IEventListener {
|
||||
public:
|
||||
// A URL to be added to a renewal request message.
|
||||
// This call will immediately precede the onMessage() call.
|
||||
// Do not override this call if the URL is not needed.
|
||||
//
|
||||
// WARNING: this call exists temporarily to allow interoperation with
|
||||
// older versions of Chromium and the prefixed EME API. This call will
|
||||
// be removed in a future release. Therefore: (1) Do not use this call
|
||||
// unless you are certain that it is needed on your platform for your
|
||||
// application, and (2) If it is needed, figure how move to a new version
|
||||
// of Chromium and the unprefixed EME API as soon as possible.
|
||||
// TODO: Remove this call (see b/24776024).
|
||||
virtual void onMessageUrl(const std::string& session_id,
|
||||
const std::string& server_url) {}
|
||||
|
||||
// A message (license request, renewal, etc.) to be dispatched to the
|
||||
// application's license server.
|
||||
// The response, if successful, should be provided back to the CDM via a
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// Widevine CE CDM Version
|
||||
#define CDM_VERSION "v3.0.1-0-g41710d9-ce"
|
||||
#define CDM_VERSION "v3.0.2-0-g161de1b-ce"
|
||||
|
||||
@@ -288,13 +288,20 @@ Cdm::Status CdmImpl::generateRequest(const std::string& session_id,
|
||||
return kInvalidAccess;
|
||||
}
|
||||
|
||||
InitializationData init_data_obj(init_data_type_name, init_data);
|
||||
|
||||
if (init_data_obj.IsEmpty()) {
|
||||
LOGE("Failed to parse init data.");
|
||||
if (init_data.empty()) {
|
||||
LOGE("Empty init data is not valid.");
|
||||
return kInvalidAccess;
|
||||
}
|
||||
|
||||
InitializationData init_data_obj(init_data_type_name, init_data);
|
||||
if (init_data_obj.IsEmpty()) {
|
||||
// Note that InitializationData's idea of "empty" includes "failed to find
|
||||
// and parse a Widevine PSSH". This should not happen for WebM init data,
|
||||
// which requires no parsing.
|
||||
LOGE("Failed to parse init data, may not contain a Widevine PSSH.");
|
||||
return kNotSupported;
|
||||
}
|
||||
|
||||
std::string key_request;
|
||||
CdmKeyRequestType key_request_type;
|
||||
std::string ignored_server_url;
|
||||
@@ -404,6 +411,8 @@ Cdm::Status CdmImpl::update(const std::string& session_id,
|
||||
bool predicted_to_be_server_cert_response =
|
||||
property_set_.use_privacy_mode() &&
|
||||
property_set_.service_certificate().empty();
|
||||
(void)predicted_to_be_server_cert_response;
|
||||
// predicted_to_be_server_cert_response is now used when assertions are off.
|
||||
|
||||
// NOTE: If the CdmSession object recognizes that this is not the first
|
||||
// AddKey(), it will internally delegate to RenewKey().
|
||||
@@ -640,6 +649,11 @@ void CdmImpl::OnSessionRenewalNeeded(const CdmSessionId& session_id) {
|
||||
|
||||
LOGI("A license renewal has been generated.");
|
||||
MessageType message_type = kLicenseRenewal;
|
||||
|
||||
// Post the server_url before providing the message.
|
||||
// For systems that still require the server URL,
|
||||
// the listener will add the URL to its renewal request.
|
||||
listener_->onMessageUrl(session_id, server_url);
|
||||
listener_->onMessage(session_id, message_type, message);
|
||||
}
|
||||
|
||||
@@ -650,7 +664,6 @@ void CdmImpl::OnSessionKeysChange(const CdmSessionId& session_id,
|
||||
|
||||
CdmKeyStatusMap::const_iterator it;
|
||||
for (it = keys_status.begin(); it != keys_status.end(); ++it) {
|
||||
KeyStatus status;
|
||||
switch (it->second) {
|
||||
case kKeyStatusUsable:
|
||||
map[it->first] = kUsable;
|
||||
@@ -835,7 +848,8 @@ int64_t Clock::GetCurrentTime() {
|
||||
return host.clock->now() / 1000;
|
||||
}
|
||||
|
||||
struct File::Impl {
|
||||
class File::Impl {
|
||||
public:
|
||||
std::string name;
|
||||
bool read_only;
|
||||
bool truncate;
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
struct Lock::Impl {
|
||||
class Lock::Impl {
|
||||
public:
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
|
||||
@@ -76,6 +76,16 @@ const std::string kCencPersistentInitData = a2bs_hex(
|
||||
// pssh data:
|
||||
"08011a0d7769646576696e655f746573"
|
||||
"74220d6f66666c696e655f636c697032");
|
||||
const std::string kInvalidCencInitData = a2bs_hex(
|
||||
"0000000c" // blob size
|
||||
"61736466" // "asdf" (wrong box type)
|
||||
"01020304"); // nonsense
|
||||
const std::string kNonWidevineCencInitData = a2bs_hex(
|
||||
"00000020" // blob size
|
||||
"70737368" // "pssh"
|
||||
"00000000" // flags
|
||||
"000102030405060708090a0b0c0d0e0f" // unknown system id
|
||||
"00000000"); // pssh data size
|
||||
const std::string kWebMInitData = a2bs_hex("deadbeefdeadbeefdeadbeefdeadbeef");
|
||||
const std::string kKeyIdsInitData =
|
||||
"{\"kids\":[\"67ef0gd8pvfd0\",\"77ef0gd8pvfd0\"]}";
|
||||
@@ -582,6 +592,23 @@ TEST_F(CdmTest, GenerateRequest) {
|
||||
EXPECT_EQ(Cdm::kInvalidAccess, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
|
||||
// Try to pass invalid CENC init data.
|
||||
status = cdm_->createSession(Cdm::kTemporary, &session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
|
||||
status = cdm_->generateRequest(session_id, Cdm::kCenc, kInvalidCencInitData);
|
||||
EXPECT_EQ(Cdm::kNotSupported, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
|
||||
// Try to pass non-Widevine CENC init data.
|
||||
status = cdm_->createSession(Cdm::kTemporary, &session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _)).Times(0);
|
||||
status = cdm_->generateRequest(session_id, Cdm::kCenc,
|
||||
kNonWidevineCencInitData);
|
||||
EXPECT_EQ(Cdm::kNotSupported, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
|
||||
// Try a bogus session ID.
|
||||
EXPECT_CALL(*this, onMessage(_, _, _)).Times(0);
|
||||
status = cdm_->generateRequest(kBogusSessionId, Cdm::kCenc, kCencInitData);
|
||||
|
||||
@@ -72,6 +72,7 @@ int main(int argc, char** argv) {
|
||||
Cdm::Status status = Cdm::initialize(
|
||||
Cdm::kNoSecureOutput, client_info, g_host, g_host, g_host, &cert_request,
|
||||
static_cast<Cdm::LogLevel>(verbosity));
|
||||
(void)status; // status is now used when assertions are turned off.
|
||||
assert(status == Cdm::kSuccess);
|
||||
assert(cert_request.needed == false);
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ class BufferReader {
|
||||
BufferReader(const uint8_t* buf, size_t size)
|
||||
: buf_(buf), size_(buf != NULL ? size : 0), pos_(0) {}
|
||||
|
||||
bool HasBytes(size_t count) { return (pos() + count <= size()); }
|
||||
bool HasBytes(size_t count) const { return pos_ + count <= size_; }
|
||||
bool IsEOF() const { return pos_ >= size_; }
|
||||
|
||||
// Read a value from the stream, performing endian correction,
|
||||
// and advance the stream pointer.
|
||||
|
||||
@@ -100,7 +100,8 @@ class CdmEngine {
|
||||
|
||||
// Query system information
|
||||
virtual CdmResponseType QueryStatus(SecurityLevel security_level,
|
||||
CdmQueryMap* info);
|
||||
const std::string& key,
|
||||
std::string* value);
|
||||
|
||||
// Query session information
|
||||
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
|
||||
|
||||
@@ -136,6 +136,7 @@ class DeviceFiles {
|
||||
FRIEND_TEST(WvCdmRequestLicenseTest, UnprovisionTest);
|
||||
FRIEND_TEST(WvCdmRequestLicenseTest, ForceL3Test);
|
||||
FRIEND_TEST(WvCdmRequestLicenseTest, UsageInfoRetryTest);
|
||||
FRIEND_TEST(WvCdmRequestLicenseTest, UsageReleaseAllTest);
|
||||
FRIEND_TEST(WvCdmUsageInfoTest, UsageInfo);
|
||||
FRIEND_TEST(WvCdmUsageTest, WithClientId);
|
||||
FRIEND_TEST(WvCdmExtendedDurationTest, UsageOverflowTest);
|
||||
|
||||
@@ -85,6 +85,8 @@ class PolicyEngine {
|
||||
|
||||
bool IsLicenseOrPlaybackDurationExpired(int64_t current_time);
|
||||
|
||||
bool CanRenew() { return policy_.can_renew(); }
|
||||
|
||||
private:
|
||||
friend class PolicyEngineTest;
|
||||
|
||||
|
||||
@@ -203,8 +203,10 @@ enum CdmResponseType {
|
||||
LICENSE_REQUEST_NONCE_GENERATION_ERROR,
|
||||
LICENSE_REQUEST_SIGNING_ERROR,
|
||||
EMPTY_LICENSE_REQUEST,
|
||||
EMPTY_PROVISIONING_CERTIFICATE_2,
|
||||
SECURE_BUFFER_REQUIRED,
|
||||
DUPLICATE_SESSION_ID_SPECIFIED,
|
||||
LICENSE_RENEWAL_PROHIBITED,
|
||||
EMPTY_PROVISIONING_CERTIFICATE_2,
|
||||
};
|
||||
|
||||
enum CdmKeyStatus {
|
||||
|
||||
@@ -405,91 +405,115 @@ CdmResponseType CdmEngine::RenewKey(const CdmSessionId& session_id,
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
CdmQueryMap* key_info) {
|
||||
const std::string& key,
|
||||
std::string* value) {
|
||||
LOGI("CdmEngine::QueryStatus");
|
||||
CryptoSession crypto_session;
|
||||
if (security_level == kLevel3) {
|
||||
CdmResponseType status = crypto_session.Open(kLevel3);
|
||||
if (NO_ERROR != status) return INVALID_QUERY_STATUS;
|
||||
}
|
||||
switch (crypto_session.GetSecurityLevel()) {
|
||||
|
||||
if (key == QUERY_KEY_SECURITY_LEVEL) {
|
||||
CdmSecurityLevel security_level = crypto_session.GetSecurityLevel();
|
||||
switch (security_level) {
|
||||
case kSecurityLevelL1:
|
||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||
*value = QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||
break;
|
||||
case kSecurityLevelL2:
|
||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L2;
|
||||
*value = QUERY_VALUE_SECURITY_LEVEL_L2;
|
||||
break;
|
||||
case kSecurityLevelL3:
|
||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||
*value = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||
break;
|
||||
case kSecurityLevelUninitialized:
|
||||
case kSecurityLevelUnknown:
|
||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] =
|
||||
QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
|
||||
*value = QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
|
||||
break;
|
||||
default:
|
||||
return INVALID_QUERY_KEY;
|
||||
LOGW("CdmEngine::QueryStatus: Unknown security level: %d",
|
||||
security_level);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
} else if (key == QUERY_KEY_DEVICE_ID) {
|
||||
std::string deviceId;
|
||||
bool success = crypto_session.GetDeviceUniqueId(&deviceId);
|
||||
if (success) {
|
||||
(*key_info)[QUERY_KEY_DEVICE_ID] = deviceId;
|
||||
if (!crypto_session.GetDeviceUniqueId(&deviceId)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetDeviceUniqueId failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
*value = deviceId;
|
||||
} else if (key == QUERY_KEY_SYSTEM_ID) {
|
||||
uint32_t system_id;
|
||||
success = crypto_session.GetSystemId(&system_id);
|
||||
if (success) {
|
||||
if (!crypto_session.GetSystemId(&system_id)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetSystemId failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
std::ostringstream system_id_stream;
|
||||
system_id_stream << system_id;
|
||||
(*key_info)[QUERY_KEY_SYSTEM_ID] = system_id_stream.str();
|
||||
}
|
||||
|
||||
*value = system_id_stream.str();
|
||||
} else if (key == QUERY_KEY_PROVISIONING_ID) {
|
||||
std::string provisioning_id;
|
||||
success = crypto_session.GetProvisioningId(&provisioning_id);
|
||||
if (success) {
|
||||
(*key_info)[QUERY_KEY_PROVISIONING_ID] = provisioning_id;
|
||||
if (!crypto_session.GetProvisioningId(&provisioning_id)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetProvisioningId failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
*value = provisioning_id;
|
||||
} else if (key == QUERY_KEY_CURRENT_HDCP_LEVEL ||
|
||||
key == QUERY_KEY_MAX_HDCP_LEVEL) {
|
||||
CryptoSession::HdcpCapability current_hdcp;
|
||||
CryptoSession::HdcpCapability max_hdcp;
|
||||
success = crypto_session.GetHdcpCapabilities(¤t_hdcp, &max_hdcp);
|
||||
if (success) {
|
||||
(*key_info)[QUERY_KEY_CURRENT_HDCP_LEVEL] = MapHdcpVersion(current_hdcp);
|
||||
(*key_info)[QUERY_KEY_MAX_HDCP_LEVEL] = MapHdcpVersion(max_hdcp);
|
||||
if (!crypto_session.GetHdcpCapabilities(¤t_hdcp, &max_hdcp)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetHdcpCapabilities failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
*value = MapHdcpVersion(key == QUERY_KEY_CURRENT_HDCP_LEVEL ? current_hdcp
|
||||
: max_hdcp);
|
||||
} else if (key == QUERY_KEY_USAGE_SUPPORT) {
|
||||
bool supports_usage_reporting;
|
||||
success = crypto_session.UsageInformationSupport(&supports_usage_reporting);
|
||||
if (success) {
|
||||
(*key_info)[QUERY_KEY_USAGE_SUPPORT] =
|
||||
supports_usage_reporting ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
||||
if (!crypto_session.UsageInformationSupport(&supports_usage_reporting)) {
|
||||
LOGW("CdmEngine::QueryStatus: UsageInformationSupport failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
*value = supports_usage_reporting ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE;
|
||||
} else if (key == QUERY_KEY_NUMBER_OF_OPEN_SESSIONS) {
|
||||
size_t number_of_open_sessions;
|
||||
success = crypto_session.GetNumberOfOpenSessions(&number_of_open_sessions);
|
||||
if (success) {
|
||||
if (!crypto_session.GetNumberOfOpenSessions(&number_of_open_sessions)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetNumberOfOpenSessions failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
std::ostringstream open_sessions_stream;
|
||||
open_sessions_stream << number_of_open_sessions;
|
||||
(*key_info)[QUERY_KEY_NUMBER_OF_OPEN_SESSIONS] =
|
||||
open_sessions_stream.str();
|
||||
*value = open_sessions_stream.str();
|
||||
} else if (key == QUERY_KEY_MAX_NUMBER_OF_SESSIONS) {
|
||||
size_t maximum_number_of_sessions;
|
||||
if (!crypto_session.GetMaxNumberOfSessions(&maximum_number_of_sessions)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetMaxNumberOfOpenSessions failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
size_t maximum_number_of_sessions;
|
||||
success = crypto_session.GetMaxNumberOfSessions(&maximum_number_of_sessions);
|
||||
if (success) {
|
||||
std::ostringstream max_sessions_stream;
|
||||
max_sessions_stream << maximum_number_of_sessions;
|
||||
(*key_info)[QUERY_KEY_MAX_NUMBER_OF_SESSIONS] =
|
||||
max_sessions_stream.str();
|
||||
*value = max_sessions_stream.str();
|
||||
} else if (key == QUERY_KEY_OEMCRYPTO_API_VERSION) {
|
||||
uint32_t api_version;
|
||||
if (!crypto_session.GetApiVersion(&api_version)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetApiVersion failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t api_version;
|
||||
success = crypto_session.GetApiVersion(&api_version);
|
||||
if (success) {
|
||||
std::ostringstream api_version_stream;
|
||||
api_version_stream << api_version;
|
||||
(*key_info)[QUERY_KEY_OEMCRYPTO_API_VERSION] = api_version_stream.str();
|
||||
*value = api_version_stream.str();
|
||||
} else {
|
||||
LOGW("CdmEngine::QueryStatus: Unknown status requested, key = %s",
|
||||
key.c_str());
|
||||
return INVALID_QUERY_KEY;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
@@ -844,6 +868,11 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
if (NULL == usage_property_set_.get()) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
}
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
|
||||
CdmResponseType status = NO_ERROR;
|
||||
for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) {
|
||||
DeviceFiles handle;
|
||||
@@ -854,6 +883,14 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
"stops", j);
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_1;
|
||||
} else {
|
||||
SecurityLevel security_level =
|
||||
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
usage_property_set_->set_security_level(security_level);
|
||||
usage_session_.reset(
|
||||
new CdmSession(usage_property_set_.get(),
|
||||
EMPTY_ORIGIN, NULL, NULL));
|
||||
CdmResponseType status2 = usage_session_->
|
||||
DeleteMultipleUsageInformation(provider_session_tokens);
|
||||
if (status2 != NO_ERROR) {
|
||||
@@ -866,6 +903,7 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) {
|
||||
status = RELEASE_ALL_USAGE_INFO_ERROR_2;
|
||||
}
|
||||
}
|
||||
usage_session_.reset(NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ CdmSession::CdmSession(CdmClientPropertySet* cdm_client_property_set,
|
||||
key_set_id_ = *forced_session_id;
|
||||
} else {
|
||||
bool ok = GenerateKeySetId(&key_set_id_);
|
||||
(void)ok; // ok is now used when assertions are turned off.
|
||||
assert(ok);
|
||||
}
|
||||
session_id_ = key_set_id_;
|
||||
|
||||
@@ -641,6 +641,11 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
buffer_descriptor.type =
|
||||
params.is_secure ? destination_buffer_type_ : OEMCrypto_BufferType_Clear;
|
||||
|
||||
if (params.is_secure &&
|
||||
buffer_descriptor.type == OEMCrypto_BufferType_Clear) {
|
||||
return SECURE_BUFFER_REQUIRED;
|
||||
}
|
||||
|
||||
switch (buffer_descriptor.type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
buffer_descriptor.buffer.clear.address =
|
||||
|
||||
@@ -55,7 +55,7 @@ bool InitializationData::ExtractWidevinePssh(const CdmInitData& init_data,
|
||||
// (optional, if version == 1) K * 16 byte key ID.
|
||||
// 4 byte size of PSSH data, exclusive. (N)
|
||||
// N byte PSSH data.
|
||||
while (1) {
|
||||
while (!reader.IsEOF()) {
|
||||
size_t start_pos = reader.pos();
|
||||
|
||||
// atom size, used for skipping.
|
||||
@@ -128,6 +128,7 @@ bool InitializationData::ExtractWidevinePssh(const CdmInitData& init_data,
|
||||
"the atom.");
|
||||
return false;
|
||||
}
|
||||
LOGV("CdmEngine::ExtractWidevinePssh: Skipping non-Widevine PSSH.");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -327,6 +327,11 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
|
||||
return INVALID_PARAMETERS_LIC_2;
|
||||
}
|
||||
|
||||
if (is_renewal && !policy_engine_->CanRenew()) {
|
||||
LOGE("CdmLicense::PrepareKeyUpdateRequest: license renewal prohibited");
|
||||
return LICENSE_RENEWAL_PROHIBITED;
|
||||
}
|
||||
|
||||
LicenseRequest license_request;
|
||||
if (is_renewal)
|
||||
license_request.set_type(LicenseRequest::RENEWAL);
|
||||
|
||||
374
core/src/privacy_crypto_apple.cpp
Normal file
374
core/src/privacy_crypto_apple.cpp
Normal file
@@ -0,0 +1,374 @@
|
||||
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Description:
|
||||
// Privacy crypto implementation for iOS. This fully implements the
|
||||
// privacy_crypto methods. This assumes this is compiled on a Mac and is
|
||||
// being compiled for iOS. Requires iOS 2.0 or later.
|
||||
//
|
||||
// This is never included in the default builds. If compiling using the gyp
|
||||
// files, setting privacy_crypto_impl to "apple" with use this file rather
|
||||
// than the openssl version.
|
||||
|
||||
#include "privacy_crypto.h"
|
||||
|
||||
#include <CommonCrypto/CommonCryptor.h>
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <memory>
|
||||
#include <Security/Security.h>
|
||||
#include <Security/SecKey.h>
|
||||
|
||||
#include "string_conversions.h"
|
||||
#include "log.h"
|
||||
|
||||
#define KEYSTORE_NAME "com.google.widevine.publicKey"
|
||||
|
||||
namespace {
|
||||
|
||||
const int kPssSaltLength = 20;
|
||||
const int kOaepMinPadding = 2 * CC_SHA1_DIGEST_LENGTH + 1;
|
||||
|
||||
template<typename T>
|
||||
struct CFDeleter {
|
||||
void operator()(T arg) {
|
||||
CFRelease(arg);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using CF =
|
||||
std::unique_ptr<typename std::remove_pointer<T>::type, CFDeleter<T> >;
|
||||
|
||||
SecKeyRef ImportPublicKey(const std::string& key) {
|
||||
std::string peerStr = KEYSTORE_NAME;
|
||||
CF<CFDataRef> peerData(CFDataCreate(NULL,
|
||||
reinterpret_cast<const UInt8*>(peerStr.c_str()), peerStr.length()));
|
||||
CF<CFDataRef> keyData(CFDataCreate(NULL,
|
||||
reinterpret_cast<const UInt8*>(key.c_str()), key.length()));
|
||||
|
||||
// Create a selector and delete all old keys.
|
||||
CF<CFMutableDictionaryRef> deleteAttributes(CFDictionaryCreateMutable(
|
||||
NULL, 0, NULL, NULL));
|
||||
CFDictionarySetValue(deleteAttributes.get(), kSecClass, kSecClassKey);
|
||||
CFDictionarySetValue(deleteAttributes.get(), kSecAttrKeyType,
|
||||
kSecAttrKeyTypeRSA);
|
||||
CFDictionarySetValue(deleteAttributes.get(), kSecAttrApplicationTag,
|
||||
peerData.get());
|
||||
SecItemDelete(deleteAttributes.get());
|
||||
|
||||
// Create attributes to add to the keystore.
|
||||
CF<CFMutableDictionaryRef> addAttributes(CFDictionaryCreateMutable(
|
||||
NULL, 0, NULL, NULL));
|
||||
CFDictionarySetValue(addAttributes.get(), kSecClass, kSecClassKey);
|
||||
CFDictionarySetValue(addAttributes.get(), kSecAttrKeyType,
|
||||
kSecAttrKeyTypeRSA);
|
||||
CFDictionarySetValue(addAttributes.get(), kSecAttrApplicationTag,
|
||||
peerData.get());
|
||||
CFDictionarySetValue(addAttributes.get(), kSecValueData,
|
||||
keyData.get());
|
||||
CFDictionarySetValue(addAttributes.get(), kSecAttrKeyClass,
|
||||
kSecAttrKeyClassPublic);
|
||||
CFDictionarySetValue(addAttributes.get(), kSecReturnPersistentRef,
|
||||
kCFBooleanTrue);
|
||||
|
||||
// Add the key to the keystore.
|
||||
CFTypeRef temp;
|
||||
OSStatus status = SecItemAdd(addAttributes.get(), &temp);
|
||||
CF<CFTypeRef> peer(temp);
|
||||
if (!peer || (status != noErr && status != errSecDuplicateItem)) {
|
||||
LOGE("RsaPublicKey::Init: Error adding key to keychain %d", status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create attributes for for the query.
|
||||
CF<CFMutableDictionaryRef> queryAttributes(CFDictionaryCreateMutable(
|
||||
NULL, 0, NULL, NULL));
|
||||
CFDictionarySetValue(queryAttributes.get(), kSecClass, kSecClassKey);
|
||||
CFDictionarySetValue(queryAttributes.get(), kSecAttrApplicationTag,
|
||||
peerData.get());
|
||||
CFDictionarySetValue(queryAttributes.get(), kSecAttrKeyType,
|
||||
kSecAttrKeyTypeRSA);
|
||||
CFDictionarySetValue(queryAttributes.get(), kSecAttrKeyClass,
|
||||
kSecAttrKeyClassPublic);
|
||||
CFDictionarySetValue(queryAttributes.get(), kSecReturnRef, kCFBooleanTrue);
|
||||
|
||||
// Query the keychain to get the public key ref.
|
||||
CFTypeRef keyRef = NULL;
|
||||
status = SecItemCopyMatching(queryAttributes.get(), &keyRef);
|
||||
if (status != noErr) {
|
||||
LOGE("RsaPublicKey::Init: Error getting key from keystore %d", status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return reinterpret_cast<SecKeyRef>(const_cast<void*>(keyRef));
|
||||
}
|
||||
|
||||
// Apply a custom mask generation function (MGF) using the hash function SHA1,
|
||||
// this is from OpenSSL.
|
||||
void ApplyMGF1_SHA1(uint8_t *output, size_t outputLength,
|
||||
const uint8_t* seed, size_t seedLength) {
|
||||
size_t outputIndex = 0;
|
||||
for (int i = 0; outputIndex < outputLength; i++) {
|
||||
uint8_t extra[4];
|
||||
extra[0] = (uint8_t)((i >> 24) & 0xFF);
|
||||
extra[1] = (uint8_t)((i >> 16) & 0xFF);
|
||||
extra[2] = (uint8_t)((i >> 8) & 0xFF);
|
||||
extra[3] = (uint8_t)(i & 0xFF);
|
||||
|
||||
CC_SHA1_CTX ctx;
|
||||
CC_SHA1_Init(&ctx);
|
||||
CC_SHA1_Update(&ctx, seed, seedLength);
|
||||
CC_SHA1_Update(&ctx, extra, 4);
|
||||
|
||||
if (outputIndex + CC_SHA1_DIGEST_LENGTH <= outputLength) {
|
||||
CC_SHA1_Final(output + outputIndex, &ctx);
|
||||
} else {
|
||||
uint8_t temp[CC_SHA1_DIGEST_LENGTH];
|
||||
CC_SHA1_Final(temp, &ctx);
|
||||
memcpy(output + outputIndex, temp, outputLength - outputIndex);
|
||||
}
|
||||
outputIndex += CC_SHA1_DIGEST_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ApplyOAEPPadding(const std::string& messageStr, size_t rsaSize) {
|
||||
if (messageStr.length() > rsaSize - kOaepMinPadding ) {
|
||||
LOGE("RsaPublicKey::Encrypt: message too large to be encrypted (actual %d",
|
||||
" max allowed %d)", messageStr.size(),
|
||||
rsaSize - kOaepMinPadding );
|
||||
return "";
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc2437#section-9.1.1.2
|
||||
//
|
||||
// result db
|
||||
// |------------------------------------------------------------------------|
|
||||
// |0| seed | pHash |000000000|1| M |
|
||||
// |------------------------------------------------------------------------|
|
||||
// | |<-mdLength->|<-mdLength->|<-psLen->| |<-------messageLength---------->|
|
||||
// |<------------paddingLength------------>|
|
||||
|
||||
std::string ret;
|
||||
ret.resize(rsaSize);
|
||||
size_t messageLength = messageStr.length();
|
||||
size_t paddingLength = rsaSize - messageLength;
|
||||
size_t psLen = paddingLength - kOaepMinPadding;
|
||||
const uint8_t *message = reinterpret_cast<const uint8_t*>(messageStr.data());
|
||||
uint8_t *result = reinterpret_cast<uint8_t*>(&ret[0]);
|
||||
uint8_t *seed = result + 1;
|
||||
uint8_t *db = result + CC_SHA1_DIGEST_LENGTH + 1;
|
||||
|
||||
// Initialize db and message
|
||||
CC_SHA1(NULL, 0, db); // Hash of empty string.
|
||||
result[rsaSize - messageLength - 1] = 0x1;
|
||||
memcpy(result + paddingLength, message, messageLength);
|
||||
|
||||
// Initialize seed
|
||||
if (SecRandomCopyBytes(kSecRandomDefault, CC_SHA1_DIGEST_LENGTH, seed)) {
|
||||
LOGE("RsaPublicKey::Encrypt: unable to get random data %d", errno);
|
||||
return "";
|
||||
}
|
||||
|
||||
// Create the first mask
|
||||
std::vector<uint8_t> dbmask;
|
||||
dbmask.resize(rsaSize - CC_SHA1_DIGEST_LENGTH - 1);
|
||||
ApplyMGF1_SHA1(dbmask.data(), dbmask.size(), seed, CC_SHA1_DIGEST_LENGTH);
|
||||
for (int i = 0; i < dbmask.size(); i++) {
|
||||
db[i] ^= dbmask[i];
|
||||
}
|
||||
|
||||
// Create the second mask
|
||||
uint8_t seedmask[CC_SHA1_DIGEST_LENGTH];
|
||||
ApplyMGF1_SHA1(seedmask, CC_SHA1_DIGEST_LENGTH, db, dbmask.size());
|
||||
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
|
||||
seed[i] ^= seedmask[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PSSVerify(const uint8_t *message, size_t messageLength,
|
||||
const uint8_t *encodedMessage, size_t encodedMessageLength) {
|
||||
// https://tools.ietf.org/html/rfc3447#section-9.1.2
|
||||
//
|
||||
// M'
|
||||
// |---------------------------------------------------|
|
||||
// | 00 00 00 00 00 00 00 00 | mHash | salt |
|
||||
// |---------------------------------------------------|
|
||||
//
|
||||
// H = hash(M')
|
||||
// dbMask = MGF(H)
|
||||
//
|
||||
// db
|
||||
// |------------------------|
|
||||
// | 00 00 ... 00 01 | salt |
|
||||
// |------------------------|
|
||||
// |<----messageLength----->|
|
||||
//
|
||||
// maskedDb = db ^ dbMask
|
||||
// encodedMessage
|
||||
// |--------------------------------------------------|
|
||||
// | maskedDb | H | bc |
|
||||
// |--------------------------------------------------|
|
||||
|
||||
if (encodedMessage[encodedMessageLength - 1] != 0xbc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t *maskedDb = encodedMessage;
|
||||
size_t dbLength = encodedMessageLength - CC_SHA1_DIGEST_LENGTH - 1;
|
||||
const uint8_t *H = maskedDb + dbLength;
|
||||
|
||||
// Decode db
|
||||
std::vector<uint8_t> dbMask;
|
||||
dbMask.resize(dbLength);
|
||||
ApplyMGF1_SHA1(dbMask.data(), dbMask.size(), H, CC_SHA1_DIGEST_LENGTH);
|
||||
for (int i = 0; i < dbLength; i++) {
|
||||
dbMask[i] ^= maskedDb[i];
|
||||
}
|
||||
|
||||
// Verify db
|
||||
for (int i = 0; i < dbLength - kPssSaltLength - 1; i++) {
|
||||
if (dbMask[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (dbMask[dbLength - kPssSaltLength - 1] != 0x01) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *salt = dbMask.data() + (dbLength - kPssSaltLength);
|
||||
uint8_t mHash[CC_SHA1_DIGEST_LENGTH];
|
||||
CC_SHA1(message, messageLength, mHash);
|
||||
|
||||
// Create our version of the message data (M')
|
||||
std::vector<uint8_t> dataVec;
|
||||
dataVec.resize(8 + CC_SHA1_DIGEST_LENGTH + kPssSaltLength);
|
||||
uint8_t *data = dataVec.data();
|
||||
memcpy(data + 8, mHash, CC_SHA1_DIGEST_LENGTH);
|
||||
memcpy(data + 8 + CC_SHA1_DIGEST_LENGTH, salt, kPssSaltLength);
|
||||
|
||||
// Verify the hash of the message data.
|
||||
uint8_t H2[CC_SHA1_DIGEST_LENGTH];
|
||||
CC_SHA1(data, dataVec.size(), H2);
|
||||
return !memcmp(H, H2, CC_SHA1_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
AesCbcKey::AesCbcKey() {}
|
||||
|
||||
AesCbcKey::~AesCbcKey() {}
|
||||
|
||||
bool AesCbcKey::Init(const std::string& key) {
|
||||
assert(key.size() == kCCBlockSizeAES128);
|
||||
this->key_ = key;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AesCbcKey::Encrypt(const std::string& in, std::string* out,
|
||||
std::string* iv) {
|
||||
assert(!in.empty());
|
||||
assert(iv != NULL);
|
||||
assert(iv->size() == kCCBlockSizeAES128);
|
||||
assert(out != NULL);
|
||||
assert(!key_.empty());
|
||||
|
||||
std::string temp;
|
||||
temp.resize(in.length() + kCCBlockSizeAES128);
|
||||
size_t length;
|
||||
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
|
||||
kCCOptionPKCS7Padding, key_.c_str(), key_.length(), iv->c_str(),
|
||||
in.c_str(), in.length(), &temp[0], temp.size(), &length);
|
||||
|
||||
if (result != kCCSuccess) {
|
||||
LOGE("AesCbcKey::Encrypt: Encryption failure: %d", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
out->assign(temp, 0, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
RsaPublicKey::RsaPublicKey() {}
|
||||
|
||||
RsaPublicKey::~RsaPublicKey() {}
|
||||
|
||||
bool RsaPublicKey::Init(const std::string& serialized_key) {
|
||||
assert(!serialized_key.empty());
|
||||
|
||||
this->serialized_key_ = serialized_key;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsaPublicKey::Encrypt(const std::string& clear_message,
|
||||
std::string* encrypted_message) {
|
||||
assert(!clear_message.empty());
|
||||
assert(encrypted_message != NULL);
|
||||
|
||||
SecKeyRef key = ImportPublicKey(serialized_key_);
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t rsaSize = SecKeyGetBlockSize(key);
|
||||
std::string paddedMessage = ApplyOAEPPadding(clear_message, rsaSize);
|
||||
if (paddedMessage.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = paddedMessage.length();
|
||||
std::string buffer;
|
||||
buffer.resize(size);
|
||||
OSStatus status = SecKeyEncrypt(key, kSecPaddingNone,
|
||||
reinterpret_cast<const uint8_t*>(paddedMessage.c_str()),
|
||||
paddedMessage.length(),
|
||||
reinterpret_cast<uint8_t*>(&buffer[0]), &size);
|
||||
if (status != errSecSuccess) {
|
||||
LOGE("RsaPublicKey::Encrypt: Unable to encrypt data %d", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
encrypted_message->assign(buffer, 0, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsaPublicKey::VerifySignature(const std::string& message,
|
||||
const std::string& signature) {
|
||||
assert(!message.empty());
|
||||
assert(!signature.empty());
|
||||
|
||||
SecKeyRef key = ImportPublicKey(serialized_key_);
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// "decrypt" the signature
|
||||
std::vector<uint8_t> buffer;
|
||||
buffer.resize(signature.length());
|
||||
size_t size = buffer.size();
|
||||
OSStatus status = SecKeyEncrypt(key, kSecPaddingNone,
|
||||
reinterpret_cast<const uint8_t*>(signature.c_str()),
|
||||
signature.length(),
|
||||
buffer.data(), &size);
|
||||
if (status != errSecSuccess) {
|
||||
LOGE("RsaPublicKey::VerifySignature: Unable to decrypt signature %d",
|
||||
status);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the signature
|
||||
if (!PSSVerify(reinterpret_cast<const uint8_t*>(message.c_str()),
|
||||
message.length(),
|
||||
buffer.data(), buffer.size())) {
|
||||
LOGE("RsaPublicKey::VerifySignature: Unable to verify signature %d",
|
||||
status);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
@@ -230,7 +230,6 @@ TEST_F(CdmSessionTest, ReInitFail) {
|
||||
}
|
||||
|
||||
TEST_F(CdmSessionTest, InitFailCryptoError) {
|
||||
CdmSecurityLevel level = kSecurityLevelL1;
|
||||
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||
.WillOnce(Return(UNKNOWN_ERROR));
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming,
|
||||
if (!streaming) {
|
||||
key_id_ = license_servers[server_id].offline_key_id;
|
||||
|
||||
if (wvcdm::kGooglePlayServer == server_id) {
|
||||
if (kGooglePlayServer == server_id) {
|
||||
if (renew) {
|
||||
client_auth_.append(kGpClientOfflineRenewalQueryParameters);
|
||||
} else if (release) {
|
||||
|
||||
@@ -1469,7 +1469,6 @@ class DeviceFilesTest : public ::testing::Test {
|
||||
CdmAppParameterMap app_parameters;
|
||||
size_t start_pos = 0;
|
||||
size_t len = str.length();
|
||||
bool more = true;
|
||||
while (start_pos < len) {
|
||||
size_t name_end_pos = str.find(' ', start_pos);
|
||||
if (name_end_pos == std::string::npos) return app_parameters;
|
||||
@@ -1841,7 +1840,6 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
|
||||
DeviceFiles device_files;
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
device_files.SetTestFile(&file);
|
||||
DeviceFiles::LicenseState license_state;
|
||||
CdmInitData pssh_data;
|
||||
CdmKeyMessage key_request;
|
||||
CdmKeyResponse key_response;
|
||||
|
||||
@@ -47,6 +47,7 @@ SSL_CTX* InitSslContext() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// unused, may be useful for debugging SSL-related issues.
|
||||
void ShowServerCertificate(const SSL* ssl) {
|
||||
// gets the server certificate
|
||||
@@ -64,6 +65,7 @@ void ShowServerCertificate(const SSL* ssl) {
|
||||
LOGE("Failed to get server certificate");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wait for a socket to be ready for reading or writing.
|
||||
// Establishing a connection counts as "ready for write".
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace wvcdm {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kAesBlockSize = 16;
|
||||
const std::string kAesKey = a2bs_hex("000102030405060708090a0b0c0d0e0f");
|
||||
const std::string kAesIv = a2bs_hex("000102030405060708090a0b0c0d0e0f");
|
||||
const std::string kCencInitDataHdr = a2bs_hex(
|
||||
|
||||
@@ -338,6 +338,8 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case EMPTY_LICENSE_REQUEST: *os << "EMPTY_LICENSE_REQUEST";
|
||||
break;
|
||||
case DUPLICATE_SESSION_ID_SPECIFIED: *os << "DUPLICATE_SESSION_ID_SPECIFIED";
|
||||
case LICENSE_RENEWAL_PROHIBITED: *os << "LICENSE_RENEWAL_PROHIBITED";
|
||||
break;
|
||||
default:
|
||||
*os << "Unknown CdmResponseType";
|
||||
break;
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
ROOT=$(dirname "$0")
|
||||
if [ ! -e "$ROOT"/third_party ]; then
|
||||
# Potentially run from a different folder before packaging.
|
||||
ROOT=$(dirname "$ROOT")
|
||||
fi
|
||||
|
||||
if [ ! -e "$ROOT"/third_party ]; then
|
||||
echo "Unable to find third_party sources!" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROOT=$(realpath "$ROOT")
|
||||
TMP=$(mktemp -d)
|
||||
trap "rm -rf $TMP" EXIT
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
cd $TMP
|
||||
|
||||
# Check out and install gyp locally
|
||||
svn checkout https://gyp.googlecode.com/svn/trunk/ gyp -r1846
|
||||
rm -rf "$ROOT"/third_party/gyp
|
||||
mv gyp/pylib/gyp "$ROOT"/third_party/
|
||||
|
||||
# Check out and install stringencoders locally
|
||||
wget https://stringencoders.googlecode.com/files/stringencoders-v3.10.3.tar.gz
|
||||
tar xzf stringencoders-v3.10.3.tar.gz
|
||||
(
|
||||
cd stringencoders-v3.10.3
|
||||
./configure --with-b64wchars='-_='
|
||||
make modp_b64w_data.h
|
||||
make src/modp_b64w.c
|
||||
mkdir -p "$ROOT"/third_party/stringencoders/src
|
||||
cp src/modp_b64w.c "$ROOT"/third_party/stringencoders/src/modp_b64w.cpp
|
||||
cp src/modp_b64w.h modp_b64w_data.h "$ROOT"/third_party/stringencoders/src/
|
||||
>"$ROOT"/third_party/stringencoders/src/config.h
|
||||
)
|
||||
|
||||
# Check out and install gmock locally
|
||||
wget https://googlemock.googlecode.com/files/gmock-1.7.0.zip
|
||||
unzip gmock-1.7.0.zip
|
||||
rm -rf "$ROOT"/third_party/gmock
|
||||
mv gmock-1.7.0 "$ROOT"/third_party/gmock
|
||||
|
||||
# Check out and install protobuf locally
|
||||
wget https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.gz
|
||||
tar xzf protobuf-2.5.0.tar.gz
|
||||
(cd protobuf-2.5.0 && ./configure)
|
||||
rm -rf "$ROOT"/third_party/protobuf
|
||||
mv protobuf-2.5.0 "$ROOT"/third_party/protobuf
|
||||
@@ -243,7 +243,7 @@ typedef enum OEMCrypto_HDCP_Capability {
|
||||
HDCP_V1 = 1, // HDCP version 1.0
|
||||
HDCP_V2 = 2, // HDCP version 2.0
|
||||
HDCP_V2_1 = 3, // HDCP version 2.1
|
||||
HDCP_V2_2 = 4, // HDCP version 2.2
|
||||
HDCP_V2_2 = 4, // HDCP version 2.2 Type 1.
|
||||
HDCP_NO_DIGITAL_OUTPUT = 0xff // No digital output.
|
||||
} OEMCrypto_HDCP_Capability;
|
||||
|
||||
|
||||
@@ -72,9 +72,9 @@ typedef struct {
|
||||
|
||||
// Note: The API does not specify a maximum key id length. We specify a
|
||||
// maximum just for these tests, so that we have a fixed message size.
|
||||
const size_t kTestKeyIdMaxLength = 48;
|
||||
// Most content will use a key id that is 12 bytes long.
|
||||
const int kDefaultKeyIdLength = 12;
|
||||
const size_t kTestKeyIdMaxLength = 16;
|
||||
// Most content will use a key id that is 16 bytes long.
|
||||
const int kDefaultKeyIdLength = 16;
|
||||
typedef struct {
|
||||
uint8_t key_id[kTestKeyIdMaxLength];
|
||||
size_t key_id_length;
|
||||
@@ -101,11 +101,6 @@ struct RSAPrivateKeyMessage {
|
||||
uint32_t nonce;
|
||||
};
|
||||
|
||||
struct PaddedPSTReport {
|
||||
OEMCrypto_PST_Report report;
|
||||
uint8_t padding[256];
|
||||
};
|
||||
|
||||
// These are test keyboxes. They will not be accepted by production systems.
|
||||
// By using known keyboxes for these tests, the results for a given set of
|
||||
// inputs to a test are predictable and can be compared to the actual results.
|
||||
@@ -364,239 +359,6 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
|
||||
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18,
|
||||
0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03 };
|
||||
|
||||
// A 2048 bit RSA Public key
|
||||
// Used to verify the functions that manipulate RSA keys.
|
||||
static const uint8_t kTestRSAPublicKey2_2048[] = {
|
||||
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
|
||||
0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd,
|
||||
0x54, 0x5a, 0x2a, 0x40, 0xb4, 0xe1, 0x15, 0x94,
|
||||
0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde, 0xa7,
|
||||
0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61,
|
||||
0x57, 0x67, 0x5e, 0x56, 0x7e, 0xee, 0x27, 0x8f,
|
||||
0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4, 0x4e,
|
||||
0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1,
|
||||
0x4e, 0x9f, 0xe3, 0x34, 0xf7, 0x3d, 0xb7, 0xc9,
|
||||
0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce, 0x31,
|
||||
0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92,
|
||||
0xf9, 0xaf, 0xfb, 0x3e, 0x68, 0xda, 0xee, 0x1a,
|
||||
0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e, 0x39,
|
||||
0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71,
|
||||
0x8e, 0xb5, 0xa4, 0xf2, 0xc2, 0x3e, 0xcd, 0x0a,
|
||||
0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b, 0x54,
|
||||
0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a,
|
||||
0x67, 0xad, 0xda, 0xb3, 0x4e, 0xb3, 0xfa, 0x82,
|
||||
0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54, 0x71,
|
||||
0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a,
|
||||
0x8b, 0x24, 0x03, 0x96, 0x88, 0xbe, 0x97, 0x66,
|
||||
0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51, 0x5a,
|
||||
0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b,
|
||||
0xf1, 0x61, 0x5b, 0x4c, 0xc8, 0x1e, 0xf4, 0xc2,
|
||||
0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12, 0x7f,
|
||||
0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe,
|
||||
0x40, 0xfb, 0x01, 0xca, 0x2e, 0x37, 0x0e, 0xce,
|
||||
0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a, 0x77,
|
||||
0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e,
|
||||
0x86, 0x5b, 0xed, 0x27, 0x29, 0xdf, 0x03, 0x97,
|
||||
0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb, 0x9c,
|
||||
0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04,
|
||||
0x6b, 0xbb, 0xbb, 0x2c, 0x5f, 0xcf, 0xb3, 0x7a,
|
||||
0x05, 0x02, 0x03, 0x01, 0x00, 0x01 };
|
||||
|
||||
// A second 2048 bit RSA key in PKCS#8 PrivateKeyInfo format
|
||||
// Used to verify the functions that manipulate RSA keys.
|
||||
static const uint8_t kTestRSAPKCS8PrivateKeyInfo3_2048[] = {
|
||||
0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01,
|
||||
0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0xd0,
|
||||
0xd7, 0x3e, 0x0e, 0x2d, 0xfb, 0x43, 0x51, 0x99,
|
||||
0xea, 0x40, 0x1e, 0x2d, 0x89, 0xe4, 0xa2, 0x3e,
|
||||
0xfc, 0x51, 0x3d, 0x0e, 0x83, 0xa7, 0xe0, 0xa5,
|
||||
0x41, 0x04, 0x1e, 0x14, 0xc5, 0xa7, 0x5c, 0x61,
|
||||
0x36, 0x44, 0xb3, 0x08, 0x05, 0x5b, 0x14, 0xde,
|
||||
0x01, 0x0c, 0x32, 0x3c, 0x9a, 0x91, 0x00, 0x50,
|
||||
0xa8, 0x1d, 0xcc, 0x9f, 0x8f, 0x35, 0xb7, 0xc2,
|
||||
0x75, 0x08, 0x32, 0x8b, 0x10, 0x3a, 0x86, 0xf9,
|
||||
0xd7, 0x78, 0xa3, 0x9d, 0x74, 0x10, 0xc6, 0x24,
|
||||
0xb1, 0x7f, 0xa5, 0xbf, 0x5f, 0xc2, 0xd7, 0x15,
|
||||
0xa3, 0x1d, 0xe0, 0x15, 0x6b, 0x1b, 0x0e, 0x38,
|
||||
0xba, 0x34, 0xbc, 0x95, 0x47, 0x94, 0x40, 0x70,
|
||||
0xac, 0x99, 0x1f, 0x0b, 0x8e, 0x56, 0x93, 0x36,
|
||||
0x2b, 0x6d, 0x04, 0xe7, 0x95, 0x1a, 0x37, 0xda,
|
||||
0x16, 0x57, 0x99, 0xee, 0x03, 0x68, 0x16, 0x31,
|
||||
0xaa, 0xc3, 0xb7, 0x92, 0x75, 0x53, 0xfc, 0xf6,
|
||||
0x20, 0x55, 0x44, 0xf8, 0xd4, 0x8d, 0x78, 0x15,
|
||||
0xc7, 0x1a, 0xb6, 0xde, 0x6c, 0xe8, 0x49, 0x5d,
|
||||
0xaf, 0xa8, 0x4e, 0x6f, 0x7c, 0xe2, 0x6a, 0x4c,
|
||||
0xd5, 0xe7, 0x8c, 0x8f, 0x0b, 0x5d, 0x3a, 0x09,
|
||||
0xd6, 0xb3, 0x44, 0xab, 0xe0, 0x35, 0x52, 0x7c,
|
||||
0x66, 0x85, 0xa4, 0x40, 0xd7, 0x20, 0xec, 0x24,
|
||||
0x05, 0x06, 0xd9, 0x84, 0x51, 0x5a, 0xd2, 0x38,
|
||||
0xd5, 0x1d, 0xea, 0x70, 0x2a, 0x21, 0xe6, 0x82,
|
||||
0xfd, 0xa4, 0x46, 0x1c, 0x4f, 0x59, 0x6e, 0x29,
|
||||
0x3d, 0xae, 0xb8, 0x8e, 0xee, 0x77, 0x1f, 0x15,
|
||||
0x33, 0xcf, 0x94, 0x1d, 0x87, 0x3c, 0x37, 0xc5,
|
||||
0x89, 0xe8, 0x7d, 0x85, 0xb3, 0xbc, 0xe8, 0x62,
|
||||
0x6a, 0x84, 0x7f, 0xfe, 0x9a, 0x85, 0x3f, 0x39,
|
||||
0xe8, 0xaa, 0x16, 0xa6, 0x8f, 0x87, 0x7f, 0xcb,
|
||||
0xc1, 0xd6, 0xf2, 0xec, 0x2b, 0xa7, 0xdd, 0x49,
|
||||
0x98, 0x7b, 0x6f, 0xdd, 0x69, 0x6d, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x43,
|
||||
0x8f, 0x19, 0x83, 0xb1, 0x27, 0x4e, 0xee, 0x98,
|
||||
0xba, 0xcb, 0x54, 0xa0, 0x77, 0x11, 0x6d, 0xd4,
|
||||
0x25, 0x31, 0x8c, 0xb0, 0x01, 0xcf, 0xe6, 0x80,
|
||||
0x83, 0x14, 0x40, 0x67, 0x39, 0x33, 0x67, 0x03,
|
||||
0x1e, 0xa0, 0x8b, 0xd1, 0x1d, 0xfd, 0x80, 0xa4,
|
||||
0xb9, 0xe7, 0x57, 0x5e, 0xc8, 0x8e, 0x79, 0x71,
|
||||
0xd5, 0x6b, 0x09, 0xe9, 0x2b, 0x41, 0xa0, 0x33,
|
||||
0x64, 0xc9, 0x66, 0x33, 0xa1, 0xb1, 0x55, 0x07,
|
||||
0x55, 0x98, 0x53, 0x10, 0xe6, 0xc0, 0x39, 0x6d,
|
||||
0x61, 0xd9, 0xe8, 0x16, 0x52, 0x28, 0xe4, 0x2b,
|
||||
0xda, 0x27, 0x01, 0xaf, 0x21, 0x4a, 0xe8, 0x55,
|
||||
0x1d, 0x0b, 0xd1, 0x1c, 0xdc, 0xfd, 0xb3, 0x0b,
|
||||
0xa6, 0x5c, 0xcc, 0x6e, 0x77, 0xb8, 0xe0, 0xd1,
|
||||
0x4e, 0x0a, 0xd7, 0x7a, 0x5e, 0x18, 0xc3, 0xfb,
|
||||
0xe9, 0xa1, 0x9c, 0xc3, 0x9c, 0xd4, 0x4a, 0x7e,
|
||||
0x70, 0x72, 0x11, 0x18, 0x24, 0x56, 0x24, 0xdf,
|
||||
0xf8, 0xba, 0xac, 0x5b, 0x54, 0xd3, 0xc4, 0x65,
|
||||
0x69, 0xc8, 0x79, 0x94, 0x16, 0x88, 0x9a, 0x68,
|
||||
0x1c, 0xbc, 0xd4, 0xca, 0xec, 0x5e, 0x07, 0x4a,
|
||||
0xc9, 0x54, 0x7a, 0x4b, 0xdb, 0x19, 0x88, 0xf6,
|
||||
0xbe, 0x50, 0x9d, 0x9e, 0x9d, 0x88, 0x5b, 0x4a,
|
||||
0x23, 0x86, 0x2b, 0xa9, 0xa6, 0x6c, 0x70, 0x7d,
|
||||
0xe1, 0x11, 0xba, 0xbf, 0x03, 0x2e, 0xf1, 0x46,
|
||||
0x7e, 0x1b, 0xed, 0x06, 0x11, 0x57, 0xad, 0x4a,
|
||||
0xcb, 0xe5, 0xb1, 0x11, 0x05, 0x0a, 0x30, 0xb1,
|
||||
0x73, 0x79, 0xcd, 0x7a, 0x04, 0xcc, 0x70, 0xe9,
|
||||
0x95, 0xe4, 0x27, 0xc2, 0xd5, 0x2d, 0x92, 0x44,
|
||||
0xdf, 0xb4, 0x94, 0xa8, 0x73, 0xa1, 0x4a, 0xc3,
|
||||
0xcc, 0xc4, 0x0e, 0x8d, 0xa1, 0x6a, 0xc2, 0xd8,
|
||||
0x03, 0x7f, 0xfa, 0xa7, 0x76, 0x0d, 0xad, 0x87,
|
||||
0x88, 0xa0, 0x77, 0xaf, 0x3b, 0x23, 0xd1, 0x66,
|
||||
0x0b, 0x31, 0x2b, 0xaf, 0xef, 0xd5, 0x41, 0x02,
|
||||
0x81, 0x81, 0x00, 0xdb, 0xc1, 0xe7, 0xdd, 0xba,
|
||||
0x3c, 0x1f, 0x9c, 0x64, 0xca, 0xa0, 0x63, 0xdb,
|
||||
0xd2, 0x47, 0x5c, 0x6e, 0x8a, 0xa3, 0x16, 0xd5,
|
||||
0xda, 0xc2, 0x25, 0x64, 0x0a, 0x02, 0xbc, 0x7d,
|
||||
0x7f, 0x50, 0xab, 0xe0, 0x66, 0x03, 0x53, 0x7d,
|
||||
0x77, 0x6d, 0x6c, 0x61, 0x58, 0x09, 0x73, 0xcd,
|
||||
0x18, 0xe9, 0x53, 0x0b, 0x5c, 0xa2, 0x71, 0x14,
|
||||
0x02, 0xfd, 0x55, 0xda, 0xe9, 0x77, 0x24, 0x7c,
|
||||
0x2a, 0x4e, 0xb9, 0xd9, 0x5d, 0x58, 0xf6, 0x26,
|
||||
0xd0, 0xd8, 0x3d, 0xcf, 0x8c, 0x89, 0x65, 0x6c,
|
||||
0x35, 0x19, 0xb6, 0x63, 0xff, 0xa0, 0x71, 0x49,
|
||||
0xcd, 0x6d, 0x5b, 0x3d, 0x8f, 0xea, 0x6f, 0xa9,
|
||||
0xba, 0x43, 0xe5, 0xdd, 0x39, 0x3a, 0x78, 0x8f,
|
||||
0x07, 0xb8, 0xab, 0x58, 0x07, 0xb7, 0xd2, 0xf8,
|
||||
0x07, 0x02, 0x9b, 0x79, 0x26, 0x32, 0x22, 0x38,
|
||||
0x91, 0x01, 0x90, 0x81, 0x29, 0x94, 0xad, 0x77,
|
||||
0xeb, 0x86, 0xb9, 0x02, 0x81, 0x81, 0x00, 0xc1,
|
||||
0x29, 0x88, 0xbd, 0x96, 0x31, 0x33, 0x7b, 0x77,
|
||||
0x5d, 0x32, 0x12, 0x5e, 0xdf, 0x28, 0x0c, 0x96,
|
||||
0x0d, 0xa8, 0x22, 0xdf, 0xd3, 0x35, 0xd7, 0xb0,
|
||||
0x41, 0xcb, 0xe7, 0x94, 0x8a, 0xa4, 0xed, 0xd2,
|
||||
0xfb, 0xd2, 0xf3, 0xf2, 0x95, 0xff, 0xd8, 0x33,
|
||||
0x3f, 0x8c, 0xd7, 0x65, 0xe4, 0x0c, 0xcc, 0xfe,
|
||||
0x32, 0x66, 0xfa, 0x50, 0xe2, 0xcf, 0xf0, 0xbe,
|
||||
0x05, 0xb1, 0xbc, 0xbe, 0x44, 0x09, 0xb4, 0xfe,
|
||||
0x95, 0x06, 0x18, 0xd7, 0x59, 0xc6, 0xef, 0x2d,
|
||||
0x22, 0xa0, 0x73, 0x5e, 0x77, 0xdf, 0x8d, 0x09,
|
||||
0x2c, 0xb8, 0xcc, 0xeb, 0x10, 0x4d, 0xa7, 0xd0,
|
||||
0x4b, 0x46, 0xba, 0x7d, 0x8b, 0x6a, 0x55, 0x47,
|
||||
0x55, 0xd3, 0xd7, 0xb1, 0x88, 0xfd, 0x27, 0x3e,
|
||||
0xf9, 0x5b, 0x7b, 0xae, 0x6d, 0x08, 0x9f, 0x0c,
|
||||
0x2a, 0xe1, 0xdd, 0xb9, 0xe3, 0x55, 0x13, 0x55,
|
||||
0xa3, 0x6d, 0x06, 0xbb, 0xe0, 0x1e, 0x55, 0x02,
|
||||
0x81, 0x80, 0x61, 0x73, 0x3d, 0x64, 0xff, 0xdf,
|
||||
0x05, 0x8d, 0x8e, 0xcc, 0xa4, 0x0f, 0x64, 0x3d,
|
||||
0x7d, 0x53, 0xa9, 0xd9, 0x64, 0xb5, 0x0d, 0xa4,
|
||||
0x72, 0x8f, 0xae, 0x2b, 0x1a, 0x47, 0x87, 0xc7,
|
||||
0x5b, 0x78, 0xbc, 0x8b, 0xc0, 0x51, 0xd7, 0xc3,
|
||||
0x8c, 0x0c, 0x91, 0xa6, 0x3e, 0x9a, 0xd1, 0x8a,
|
||||
0x88, 0x7d, 0x40, 0xfe, 0x95, 0x32, 0x5b, 0xd3,
|
||||
0x6f, 0x90, 0x11, 0x01, 0x92, 0xc9, 0xe5, 0x1d,
|
||||
0xc5, 0xc7, 0x78, 0x72, 0x82, 0xae, 0xb5, 0x4b,
|
||||
0xcb, 0x78, 0xad, 0x7e, 0xfe, 0xb6, 0xb1, 0x23,
|
||||
0x63, 0x01, 0x94, 0x9a, 0x99, 0x05, 0x63, 0xda,
|
||||
0xea, 0xf1, 0x98, 0xfd, 0x26, 0xd2, 0xd9, 0x8b,
|
||||
0x35, 0xec, 0xcb, 0x0b, 0x43, 0xb8, 0x8e, 0x84,
|
||||
0xb8, 0x09, 0x93, 0x81, 0xe8, 0xac, 0x6f, 0x3c,
|
||||
0x7c, 0x95, 0x81, 0x45, 0xc4, 0xd9, 0x94, 0x08,
|
||||
0x09, 0x8f, 0x91, 0x17, 0x65, 0x4c, 0xff, 0x6e,
|
||||
0xbc, 0x51, 0x02, 0x81, 0x81, 0x00, 0xc1, 0x0d,
|
||||
0x9d, 0xd8, 0xbd, 0xaf, 0x56, 0xe0, 0xe3, 0x1f,
|
||||
0x85, 0xd7, 0xce, 0x72, 0x02, 0x38, 0xf2, 0x0f,
|
||||
0x9c, 0x27, 0x9e, 0xc4, 0x1d, 0x60, 0x00, 0x8d,
|
||||
0x02, 0x19, 0xe5, 0xdf, 0xdb, 0x8e, 0xc5, 0xfb,
|
||||
0x61, 0x8e, 0xe6, 0xb8, 0xfc, 0x07, 0x3c, 0xd1,
|
||||
0x1b, 0x16, 0x7c, 0x83, 0x3c, 0x37, 0xf5, 0x26,
|
||||
0xb2, 0xbd, 0x22, 0xf2, 0x4d, 0x19, 0x33, 0x11,
|
||||
0xc5, 0xdd, 0xf9, 0xdb, 0x4e, 0x48, 0x52, 0xd8,
|
||||
0xe6, 0x4b, 0x15, 0x90, 0x68, 0xbe, 0xca, 0xc1,
|
||||
0x7c, 0xd3, 0x51, 0x6b, 0x45, 0x46, 0x54, 0x11,
|
||||
0x1a, 0x71, 0xd3, 0xcd, 0x6b, 0x8f, 0x79, 0x22,
|
||||
0x83, 0x02, 0x08, 0x4f, 0xba, 0x6a, 0x98, 0xed,
|
||||
0x32, 0xd8, 0xb4, 0x5b, 0x51, 0x88, 0x53, 0xec,
|
||||
0x2c, 0x7e, 0xa4, 0x89, 0xdc, 0xbf, 0xf9, 0x0d,
|
||||
0x32, 0xc8, 0xc3, 0xec, 0x6d, 0x2e, 0xf1, 0xbc,
|
||||
0x70, 0x4e, 0xf6, 0x9e, 0xbc, 0x31, 0x02, 0x81,
|
||||
0x81, 0x00, 0xd3, 0x35, 0x1b, 0x19, 0x75, 0x3f,
|
||||
0x61, 0xf2, 0x55, 0x03, 0xce, 0x25, 0xa9, 0xdf,
|
||||
0x0c, 0x0a, 0x3b, 0x47, 0x42, 0xdc, 0x38, 0x4b,
|
||||
0x13, 0x4d, 0x1f, 0x86, 0x58, 0x4f, 0xd8, 0xee,
|
||||
0xfa, 0x76, 0x15, 0xfb, 0x6e, 0x55, 0x31, 0xf2,
|
||||
0xd2, 0x62, 0x32, 0xa5, 0xc4, 0x23, 0x5e, 0x08,
|
||||
0xa9, 0x83, 0x07, 0xac, 0x8c, 0xa3, 0x7e, 0x18,
|
||||
0xc0, 0x1c, 0x57, 0x63, 0x8d, 0x05, 0x17, 0x47,
|
||||
0x1b, 0xd3, 0x74, 0x73, 0x20, 0x04, 0xfb, 0xc8,
|
||||
0x1a, 0x43, 0x04, 0x36, 0xc8, 0x19, 0xbe, 0xdc,
|
||||
0xa6, 0xe5, 0x0f, 0x25, 0x62, 0x24, 0x96, 0x92,
|
||||
0xb6, 0xb3, 0x97, 0xad, 0x57, 0x9a, 0x90, 0x37,
|
||||
0x4e, 0x31, 0x44, 0x74, 0xfa, 0x7c, 0xb4, 0xea,
|
||||
0xfc, 0x15, 0xa7, 0xb0, 0x51, 0xcc, 0xee, 0x1e,
|
||||
0xed, 0x5b, 0x98, 0x18, 0x0e, 0x65, 0xb6, 0x4b,
|
||||
0x69, 0x0b, 0x21, 0xdc, 0x86, 0x17, 0x6e, 0xc8,
|
||||
0xee, 0x24 };
|
||||
|
||||
// A second 2048 bit RSA Public key
|
||||
// Used to verify the functions that manipulate RSA keys.
|
||||
static const uint8_t kTestRSAPublicKey3_2048[] = {
|
||||
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
|
||||
0x00, 0xa5, 0xd0, 0xd7, 0x3e, 0x0e, 0x2d, 0xfb,
|
||||
0x43, 0x51, 0x99, 0xea, 0x40, 0x1e, 0x2d, 0x89,
|
||||
0xe4, 0xa2, 0x3e, 0xfc, 0x51, 0x3d, 0x0e, 0x83,
|
||||
0xa7, 0xe0, 0xa5, 0x41, 0x04, 0x1e, 0x14, 0xc5,
|
||||
0xa7, 0x5c, 0x61, 0x36, 0x44, 0xb3, 0x08, 0x05,
|
||||
0x5b, 0x14, 0xde, 0x01, 0x0c, 0x32, 0x3c, 0x9a,
|
||||
0x91, 0x00, 0x50, 0xa8, 0x1d, 0xcc, 0x9f, 0x8f,
|
||||
0x35, 0xb7, 0xc2, 0x75, 0x08, 0x32, 0x8b, 0x10,
|
||||
0x3a, 0x86, 0xf9, 0xd7, 0x78, 0xa3, 0x9d, 0x74,
|
||||
0x10, 0xc6, 0x24, 0xb1, 0x7f, 0xa5, 0xbf, 0x5f,
|
||||
0xc2, 0xd7, 0x15, 0xa3, 0x1d, 0xe0, 0x15, 0x6b,
|
||||
0x1b, 0x0e, 0x38, 0xba, 0x34, 0xbc, 0x95, 0x47,
|
||||
0x94, 0x40, 0x70, 0xac, 0x99, 0x1f, 0x0b, 0x8e,
|
||||
0x56, 0x93, 0x36, 0x2b, 0x6d, 0x04, 0xe7, 0x95,
|
||||
0x1a, 0x37, 0xda, 0x16, 0x57, 0x99, 0xee, 0x03,
|
||||
0x68, 0x16, 0x31, 0xaa, 0xc3, 0xb7, 0x92, 0x75,
|
||||
0x53, 0xfc, 0xf6, 0x20, 0x55, 0x44, 0xf8, 0xd4,
|
||||
0x8d, 0x78, 0x15, 0xc7, 0x1a, 0xb6, 0xde, 0x6c,
|
||||
0xe8, 0x49, 0x5d, 0xaf, 0xa8, 0x4e, 0x6f, 0x7c,
|
||||
0xe2, 0x6a, 0x4c, 0xd5, 0xe7, 0x8c, 0x8f, 0x0b,
|
||||
0x5d, 0x3a, 0x09, 0xd6, 0xb3, 0x44, 0xab, 0xe0,
|
||||
0x35, 0x52, 0x7c, 0x66, 0x85, 0xa4, 0x40, 0xd7,
|
||||
0x20, 0xec, 0x24, 0x05, 0x06, 0xd9, 0x84, 0x51,
|
||||
0x5a, 0xd2, 0x38, 0xd5, 0x1d, 0xea, 0x70, 0x2a,
|
||||
0x21, 0xe6, 0x82, 0xfd, 0xa4, 0x46, 0x1c, 0x4f,
|
||||
0x59, 0x6e, 0x29, 0x3d, 0xae, 0xb8, 0x8e, 0xee,
|
||||
0x77, 0x1f, 0x15, 0x33, 0xcf, 0x94, 0x1d, 0x87,
|
||||
0x3c, 0x37, 0xc5, 0x89, 0xe8, 0x7d, 0x85, 0xb3,
|
||||
0xbc, 0xe8, 0x62, 0x6a, 0x84, 0x7f, 0xfe, 0x9a,
|
||||
0x85, 0x3f, 0x39, 0xe8, 0xaa, 0x16, 0xa6, 0x8f,
|
||||
0x87, 0x7f, 0xcb, 0xc1, 0xd6, 0xf2, 0xec, 0x2b,
|
||||
0xa7, 0xdd, 0x49, 0x98, 0x7b, 0x6f, 0xdd, 0x69,
|
||||
0x6d, 0x02, 0x03, 0x01, 0x00, 0x01 };
|
||||
|
||||
DeviceFeatures global_features;
|
||||
|
||||
void DeviceFeatures::Initialize(bool is_cast_receiver, bool force_load_test_keybox) {
|
||||
@@ -1364,7 +1126,8 @@ class Session {
|
||||
int status = RSA_public_encrypt(session_key.size(), &session_key[0],
|
||||
&(enc_session_key->front()), public_rsa_,
|
||||
RSA_PKCS1_OAEP_PADDING);
|
||||
if (static_cast<unsigned>(status) != RSA_size(public_rsa_)) {
|
||||
int size = static_cast<int>(RSA_size(public_rsa_));
|
||||
if (status != size) {
|
||||
cout << "GenerateRSASessionKey error encrypting session key. ";
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
@@ -1403,16 +1166,17 @@ class Session {
|
||||
size_t length = 0;
|
||||
OEMCryptoResult sts = OEMCrypto_ReportUsage(
|
||||
session_id(), reinterpret_cast<const uint8_t*>(pst.c_str()),
|
||||
pst.length(), &pst_report_.report, &length);
|
||||
pst.length(), pst_report(), &length);
|
||||
if (expect_success) {
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
||||
}
|
||||
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||
ASSERT_GE(sizeof(PaddedPSTReport), length);
|
||||
ASSERT_LE(sizeof(OEMCrypto_PST_Report), length);
|
||||
pst_report_buffer_.resize(length);
|
||||
}
|
||||
sts = OEMCrypto_ReportUsage(session_id(),
|
||||
reinterpret_cast<const uint8_t*>(pst.c_str()),
|
||||
pst.length(), &pst_report_.report, &length);
|
||||
pst.length(), pst_report(), &length);
|
||||
if (!expect_success) {
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
return;
|
||||
@@ -1421,16 +1185,19 @@ class Session {
|
||||
vector<uint8_t> computed_signature(SHA_DIGEST_LENGTH);
|
||||
unsigned int sig_len = SHA_DIGEST_LENGTH;
|
||||
HMAC(EVP_sha1(), &mac_key_client_[0], mac_key_client_.size(),
|
||||
reinterpret_cast<uint8_t*>(&pst_report_.report) + SHA_DIGEST_LENGTH,
|
||||
reinterpret_cast<uint8_t*>(pst_report()) + SHA_DIGEST_LENGTH,
|
||||
length - SHA_DIGEST_LENGTH, &computed_signature[0], &sig_len);
|
||||
EXPECT_EQ(0, memcmp(&computed_signature[0], pst_report_.report.signature,
|
||||
EXPECT_EQ(0, memcmp(&computed_signature[0], pst_report()->signature,
|
||||
SHA_DIGEST_LENGTH));
|
||||
EXPECT_GE(kInactive, pst_report_.report.status);
|
||||
EXPECT_GE(kHardwareSecureClock, pst_report_.report.clock_security_level);
|
||||
EXPECT_EQ(pst.length(), pst_report_.report.pst_length);
|
||||
EXPECT_EQ(0, memcmp(pst.c_str(), pst_report_.report.pst, pst.length()));
|
||||
EXPECT_GE(kInactive, pst_report()->status);
|
||||
EXPECT_GE(kHardwareSecureClock, pst_report()->clock_security_level);
|
||||
EXPECT_EQ(pst.length(), pst_report()->pst_length);
|
||||
EXPECT_EQ(0, memcmp(pst.c_str(), pst_report()->pst, pst.length()));
|
||||
}
|
||||
|
||||
OEMCrypto_PST_Report* pst_report() {
|
||||
return reinterpret_cast<OEMCrypto_PST_Report*>(&pst_report_buffer_[0]);
|
||||
}
|
||||
OEMCrypto_PST_Report* pst_report() { return &pst_report_.report; }
|
||||
|
||||
void DeleteEntry(const std::string& pst) {
|
||||
uint8_t* pst_ptr = encrypted_license_.pst;
|
||||
@@ -1465,7 +1232,7 @@ class Session {
|
||||
vector<uint8_t> enc_key_;
|
||||
uint32_t nonce_;
|
||||
RSA* public_rsa_;
|
||||
PaddedPSTReport pst_report_;
|
||||
vector<uint8_t> pst_report_buffer_;
|
||||
MessageData license_;
|
||||
MessageData encrypted_license_;
|
||||
OEMCrypto_KeyObject key_array_[kNumKeys];
|
||||
@@ -2445,7 +2212,6 @@ INSTANTIATE_TEST_CASE_P(TestRefreshEachKeys, SessionTestRefreshKeyTest,
|
||||
// Decrypt Tests
|
||||
//
|
||||
TEST_F(OEMCryptoSessionTests, Decrypt) {
|
||||
OEMCryptoResult sts;
|
||||
Session s;
|
||||
s.open();
|
||||
|
||||
@@ -2526,7 +2292,6 @@ TEST_F(OEMCryptoSessionTests, DecryptPerformance) {
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, DecryptZeroDuration) {
|
||||
OEMCryptoResult sts;
|
||||
Session s;
|
||||
s.open();
|
||||
|
||||
@@ -2592,9 +2357,9 @@ class OEMCryptoSessionTestsDecryptEdgeCases : public OEMCryptoSessionTests {
|
||||
s.FillSimpleMessage(kDuration, 0, 0);
|
||||
s.EncryptAndSign();
|
||||
s.LoadTestKeys();
|
||||
// Select the key (from FillSimpleMessage)
|
||||
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
|
||||
sts = OEMCrypto_SelectKey(s.session_id(), &keyId[0], keyId.size());
|
||||
sts = OEMCrypto_SelectKey(s.session_id(),
|
||||
s.license().keys[0].key_id,
|
||||
s.license().keys[0].key_id_length);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
|
||||
// We decrypt three subsamples. each with a block offset.
|
||||
@@ -2797,7 +2562,6 @@ TEST_F(OEMCryptoSessionTests, DecryptUnencryptedNoKey) {
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, DecryptSecureToClear) {
|
||||
OEMCryptoResult sts;
|
||||
Session s;
|
||||
s.open();
|
||||
s.GenerateTestSessionKeys();
|
||||
@@ -2809,7 +2573,6 @@ TEST_F(OEMCryptoSessionTests, DecryptSecureToClear) {
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, KeyDuration) {
|
||||
OEMCryptoResult sts;
|
||||
Session s;
|
||||
s.open();
|
||||
s.GenerateTestSessionKeys();
|
||||
@@ -2846,7 +2609,8 @@ class OEMCryptoLoadsCertificate : public OEMCryptoSessionTestKeyboxTest {
|
||||
s.RewrapRSAKey(encrypted, signature, wrapped_key, force);
|
||||
// Verify that the clear key is not contained in the wrapped key.
|
||||
// It should be encrypted.
|
||||
ASSERT_EQ(NULL, find(*wrapped_key, encoded_rsa_key_)); }
|
||||
ASSERT_EQ(NULL, find(*wrapped_key, encoded_rsa_key_));
|
||||
}
|
||||
|
||||
std::vector<uint8_t> encoded_rsa_key_;
|
||||
};
|
||||
@@ -4622,7 +4386,6 @@ TEST_F(GenericCryptoTest, KeyDurationDecrypt) {
|
||||
}
|
||||
|
||||
TEST_F(GenericCryptoTest, KeyDurationSign) {
|
||||
OEMCryptoResult sts;
|
||||
EncryptAndLoadKeys();
|
||||
|
||||
unsigned int key_index = 2;
|
||||
@@ -4655,7 +4418,6 @@ TEST_F(GenericCryptoTest, KeyDurationSign) {
|
||||
}
|
||||
|
||||
TEST_F(GenericCryptoTest, KeyDurationVerify) {
|
||||
OEMCryptoResult sts;
|
||||
EncryptAndLoadKeys();
|
||||
|
||||
unsigned int key_index = 3;
|
||||
@@ -4692,10 +4454,20 @@ class GenericCryptoKeyIdLengthTest : public GenericCryptoTest {
|
||||
session_.FillSimpleMessage(kDuration, wvoec_mock::kControlAllowDecrypt,
|
||||
kNoNonce);
|
||||
// We are testing that the key ids do not have to have the same length.
|
||||
session_.SetKeyId(0, "123456789012"); // 12 bytes (default key id length).
|
||||
session_.SetKeyId(0, "123456789012"); // 12 bytes (common key id length).
|
||||
session_.SetKeyId(1, "12345"); // short key id.
|
||||
session_.SetKeyId(2, "123456789012-very-long-key-id");
|
||||
ASSERT_EQ(2, kLongKeyId);
|
||||
session_.SetKeyId(2, "1234567890123456"); // 16 byte key id. (default)
|
||||
session_.SetKeyId(3, "12345678901234"); // 14 byte. (uncommon)
|
||||
ASSERT_EQ(2u, kLongKeyId);
|
||||
}
|
||||
|
||||
// Make all four keys have the same length.
|
||||
void SetUniformKeyIdLength(size_t key_id_length) {
|
||||
for(unsigned int i = 0; i < 4; i++) {
|
||||
string key_id;
|
||||
key_id.resize(key_id_length, i + 'a');
|
||||
session_.SetKeyId(i, key_id);
|
||||
}
|
||||
}
|
||||
|
||||
void TestWithKey(unsigned int key_index) {
|
||||
@@ -4738,6 +4510,16 @@ TEST_F(GenericCryptoKeyIdLengthTest, LongKeyId) {
|
||||
TestWithKey(2);
|
||||
}
|
||||
|
||||
TEST_F(GenericCryptoKeyIdLengthTest, UniformShortKeyId) {
|
||||
SetUniformKeyIdLength(5);
|
||||
TestWithKey(2);
|
||||
}
|
||||
|
||||
TEST_F(GenericCryptoKeyIdLengthTest, UniformLongKeyId) {
|
||||
SetUniformKeyIdLength(kTestKeyIdMaxLength);
|
||||
TestWithKey(2);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoClientTest, UpdateUsageTableTest) {
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export_variables = {
|
||||
'CC': 'gcc',
|
||||
'CXX': 'g++',
|
||||
'CC': 'clang',
|
||||
'CXX': 'clang++',
|
||||
'AR': 'ar',
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
'cflags': [
|
||||
'-fPIC',
|
||||
'-fno-exceptions',
|
||||
# Enable all warnings, and treat warnings as errors.
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
],
|
||||
|
||||
# These are flags passed to the compiler for plain C only.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
./build.py x86-64 -r
|
||||
./out/x86-64/Release/widevine_ce_cdm_unittest
|
||||
@@ -1 +0,0 @@
|
||||
# dummy
|
||||
|
||||
1
third_party/gyp/generator/__init__.py
vendored
1
third_party/gyp/generator/__init__.py
vendored
@@ -1 +0,0 @@
|
||||
# dummy
|
||||
|
||||
14
third_party/protobuf.gypi
vendored
14
third_party/protobuf.gypi
vendored
@@ -31,6 +31,20 @@
|
||||
'<(protobuf_source)/src/google/protobuf/stubs/stringprintf.cc',
|
||||
],
|
||||
},
|
||||
'target_defaults': {
|
||||
# These flags silence warnings that appear in protobuf upstream.
|
||||
# We will not maintain a divergent copy of protobuf to fix them.
|
||||
'cflags': [
|
||||
# Ignore unknown warning options, to support both gcc & clang at once.
|
||||
'-Wno-unknown-warning-option',
|
||||
# GCC:
|
||||
'-Wno-sign-compare',
|
||||
'-Wno-unused-local-typedefs',
|
||||
# Clang:
|
||||
'-Wno-unused-const-variable',
|
||||
'-Wno-unused-function',
|
||||
],
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'protobuf_lite',
|
||||
|
||||
1737
third_party/protobuf/config.log
vendored
1737
third_party/protobuf/config.log
vendored
File diff suppressed because it is too large
Load Diff
2334
third_party/protobuf/config.status
vendored
2334
third_party/protobuf/config.status
vendored
File diff suppressed because it is too large
Load Diff
1020
third_party/protobuf/gtest/config.log
vendored
1020
third_party/protobuf/gtest/config.log
vendored
File diff suppressed because it is too large
Load Diff
2296
third_party/protobuf/gtest/config.status
vendored
2296
third_party/protobuf/gtest/config.status
vendored
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
# dummy
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
# dummy
|
||||
|
||||
1
third_party/stringencoders/src/config.h
vendored
1
third_party/stringencoders/src/config.h
vendored
@@ -1 +0,0 @@
|
||||
// dummy
|
||||
|
||||
Reference in New Issue
Block a user