Merges to android Pi release (part 12)
These are a set of CLs merged from the wv cdm repo to the android repo. * Correct error logging Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/40000 ] In tests, we set the cipher list to avoid using insecure ciphers when connecting to the provisioning/license service. The result of setting the cipher list was being incorrectly validated. Bug: 64847919 * Move mips cache headers to clear_cache_function.h Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/39700 ] Since the clear_cache function has been moved away from the dynamic adapter, we need these conditional includes to be migrated as well for MIPS. * Comment out Level 3 debug call until merge Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/39761 ] This call was introduced in go/wvgerrit/34260/. Since the haystack tool in google3 still needs this merge, this should be commented out so the tool can still build until the merge has finished. * Add logging for MAC keys to mock Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/39740 ] Bug: 70637842 * Move external interfaces into level3.h + refactor Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/39673 ] As part of b/70523618, this CL moves interfaces that partners are responsible for in Level 3 to level3.h so they can be visible as part of the CDM release process. It also cleans up some of the names of the files and adds documentation. * Corrected close session logging level Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/39676 ] Bug: 69460963 * Remove Security Level Path Backward Compatibility Support Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/39505 ] From the android K release onwards certificates were stored in security level specific directories. If upgrading from previous releases persistent information needed to be moved to those directories. Since no device is likely to upgrade from J to Pi, comptibility support can be removed. Bug: 70160032 * Rename privacy_crypto_openssl To privacy_crypto_boringssl Author: John W. Bruce <juce@google.com> [ Merge of http://go/wvgerrit/37122 ] Now that we no longer support OpenSSL in the Shared Source CDM, the name of this file can be updated. Bug: 67907873 Test: build.py x86-64 Test: wv_ce_cdm_unittest Test: jenkins/linux_unit_tests * Remove Conditional Compilation from OpenSSL/BoringSSL Author: John W. Bruce <juce@google.com> [ Merge of http://go/wvgerrit/39460 ] This change removes the usages of conditional compilation to support both BoringSSL and OpenSSL, as well as to support multiple versions of the OpenSSL API. All code is now compiled against one of the two versions of BoringSSL in third_party/. Note that in some cases, the kit/ and legacy_kit/ versions of BoringSSL had different APIs, so when removing the OpenSSL version compatibility conditional compilation, sometimes the older branch was kept and sometimes the newer branch was kept. Bug: 67907873 Test: build.py x86-64 Test: wv_ce_cdm_unittest Test: jenkins/linux_unit_tests * Build CE & Jenkins CDMs With BoringSSL from third_party/ Author: John W. Bruce <juce@google.com> [ Merge of http://go/wvgerrit/37120 ] Up until now, integrators have been responsible for providing a compatible crypto library for use by the CE CDM. (either OpenSSL or BoringSSL) After this change, this decision will no longer be in their hands. The CE CDM build will always use the copy of BoringSSL in third_party/, which will be statically linked with our library with hidden visibility. This allows us to better control what crypto library we use and will prevent continuing problems with trying to support both OpenSSL and BoringSSL. Unfortunately, BoringSSL began using C++11 in mid-2017, and we can't support C++11 right now. Until we can, we need to use a C++11-free version of BoringSSL for libssl. The CDM itself will continue to use a recent BoringSSL, as it only needs libcrypto. But the unit tests that need libssl have to use the legacy version. Bug: 67907873 Test: build.py x86-64 Test: wv_ce_cdm_unittest Test: jenkins/linux_unit_tests * Modified RNG for Level3 to use more entropy Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/39220 ] Bug: 65165076 Modified seed generation to use an xor of clock_gettime and client-implemented code to supply random seeds to the RNG. Modified the RNG as well to use xoroshiro128+ instead of xorshift, since it uses more than one seed/state (which are 64-bit) and has higher "statistical quality". The default implementations for the seed generation use /dev/urandom. * Configure base path for Level3FileSystem Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/39506 ] This is in response to b/70354006. This change makes the Android Level3FileSystem use the existing properties method GetDevicesFilesBasePath for binderization. The same is done for the Linux implementation. * Add legacy_kit/ to BoringSSL Directory Author: John W. Bruce <juce@google.com> [ Merge of http://go/wvgerrit/38861 ] This adds a second copy of BoringSSL to the third_party/boringssl/ directory. This second copy is pinned to the last revision of BoringSSL not to require C++11 and is not updated by the UPDATE_BORINGSSL.sh script. This second copy will be used to provide libssl to the tests on devices that do not support C++11. Once we support C++11 in the CDM again, this weight should be removed and all targets should use the copy of BoringSSL in the kit/ directory. Bug: 67907873 * Use Shared Libraries for Unit Tests Author: John W. Bruce <juce@google.com> [ Merge of http://go/wvgerrit/38860 ] Some unit tests were using a statically-linked CDM instead of a dynamically-linked one. (Or, in one case, trying to link both ways into the same binary.) For now, we need to only link dynamically, so that the unit tests and the CDM can use different versions of BoringSSL. Long-term, we would like to test both kinds of linkage. (See b/69548115 for that.) Some unit tests were also using a dynamicaly-linked CDM that was named such that it appeared to be statically-linked. This patch renames some targets to make the linkage clearer. Bug: 67907873 * Change CDM_Backwards_Compatiblity_Tests to dedicated brances Author: Fred Gylys-Colwell <fredgc@google.com> [ Merge of http://go/wvgerrit/39003 ] The build scripts used by CDM_Backwards_Compatiblity_Tests now pull old versions of oemcrypto from the dedicated branches oemcrypto-v*, which [will eventually] contain old oemcrypto versions, that build with the current build system with a current boringssl version. bug: 67907873 * Fix spacing on level3 header Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/38760 ] * Correct Query status calls Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/38640 ] Bug: 70160032 * Refactoring to allow encryption of client ID Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/37460 ] The code has been restructured to allow encryption of client identification in provisioning requests. This will be enabled when server side changes have been made (b/69427217). * Additional information is included in the Client Identification portion of the provisioning request. * Client identification will be encrypted with a service certificate provided by the app/client. Platform changes to enable passing this to core are needed. If a service certificate is not provided, a default one associated with the production Keysmith will be used. * Switched APIs in CdmEngine to take a service certificate for provisioning rather than licensing. Service certificates for licensing are session based and passed as properties from platform code. Bug: 30737060 * Allow some CDM errors to be reported from multiple locations Author: Rahul Frias <rfrias@google.com> [ Merge of http://go/wvgerrit/38360 ] This creates some CdmResponseType errors which may be reused PARAMETER_NULL, NOT_INITIALIZED_ERROR, REINIT_ERROR. I have made changes to a few classes to report these errors. Will work on additional classes in a separate CL. Bug: 69864404 BUG: 71650075 Test: WV Unit/integration tests Change-Id: Icc048770d424ac537d11ff327cda2cb142da802d
This commit is contained in:
@@ -86,13 +86,13 @@ CdmEngine::~CdmEngine() {
|
||||
M_RECORD(&metrics_, cdm_engine_life_span_, life_span_.AsMs());
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::SetServiceCertificate(
|
||||
CdmResponseType CdmEngine::SetProvisioningServiceCertificate(
|
||||
const std::string& certificate) {
|
||||
return service_certificate_.Init(certificate);
|
||||
return provisioning_service_certificate_.Init(certificate);
|
||||
}
|
||||
|
||||
bool CdmEngine::HasServiceCertificate() {
|
||||
return service_certificate_.has_certificate();
|
||||
bool CdmEngine::HasProvisioningServiceCertificate() {
|
||||
return provisioning_service_certificate_.has_certificate();
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::OpenSession(
|
||||
@@ -121,7 +121,7 @@ CdmResponseType CdmEngine::OpenSession(
|
||||
|
||||
if (!session_id && !forced_session_id) {
|
||||
LOGE("CdmEngine::OpenSession: no (forced/)session ID destination provided");
|
||||
return INVALID_PARAMETERS_ENG_1;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
if (forced_session_id) {
|
||||
@@ -190,7 +190,7 @@ CdmResponseType CdmEngine::OpenKeySetSession(
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::CloseSession(const CdmSessionId& session_id) {
|
||||
LOGV("CdmEngine::CloseSession: %s", session_id.c_str());
|
||||
LOGI("CdmEngine::CloseSession: %s", session_id.c_str());
|
||||
if (!session_map_.CloseSession(session_id)) {
|
||||
LOGE("CdmEngine::CloseSession: session not found = %s", session_id.c_str());
|
||||
return SESSION_NOT_FOUND_1;
|
||||
@@ -271,7 +271,7 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
|
||||
|
||||
if (!key_request) {
|
||||
LOGE("CdmEngine::GenerateKeyRequest: output destination provided");
|
||||
return INVALID_PARAMETERS_ENG_2;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
key_request->message.clear();
|
||||
@@ -318,7 +318,7 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
|
||||
if (license_type_release) {
|
||||
if (!key_set_id) {
|
||||
LOGE("CdmEngine::AddKey: no key set id provided");
|
||||
return INVALID_PARAMETERS_ENG_3;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
if (key_set_id->empty()) {
|
||||
@@ -428,7 +428,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
|
||||
|
||||
if (!key_request) {
|
||||
LOGE("CdmEngine::GenerateRenewalRequest: no request destination");
|
||||
return INVALID_PARAMETERS_ENG_4;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
key_request->message.clear();
|
||||
@@ -494,7 +494,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
|
||||
if (!query_response) {
|
||||
LOGE("CdmEngine::QueryStatus: no query response destination");
|
||||
return INVALID_PARAMETERS_ENG_6;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
if (query_token == QUERY_KEY_SECURITY_LEVEL) {
|
||||
@@ -598,7 +598,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
|
||||
*query_response = max_sessions_stream.str();
|
||||
} else if (query_token == QUERY_KEY_OEMCRYPTO_API_VERSION) {
|
||||
uint32_t api_version;
|
||||
if (crypto_session.GetApiVersion(&api_version)) {
|
||||
if (!crypto_session.GetApiVersion(&api_version)) {
|
||||
LOGW("CdmEngine::QueryStatus: GetApiVersion failed");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
@@ -689,7 +689,7 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id,
|
||||
LOGI("CdmEngine::QueryKeyAllowedUsage");
|
||||
if (!key_usage) {
|
||||
LOGE("CdmEngine::QueryKeyAllowedUsage: no response destination");
|
||||
return INVALID_PARAMETERS_ENG_12;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
shared_ptr<CdmSession> session;
|
||||
if (!session_map_.FindSession(session_id, &session)) {
|
||||
@@ -708,7 +708,7 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
|
||||
bool found = false;
|
||||
if (!key_usage) {
|
||||
LOGE("CdmEngine::QueryKeyAllowedUsage: no response destination");
|
||||
return INVALID_PARAMETERS_ENG_7;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
key_usage->Clear();
|
||||
|
||||
@@ -774,8 +774,10 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
|
||||
if (NULL == cert_provisioning_.get()) {
|
||||
cert_provisioning_.reset(
|
||||
new CertificateProvisioning(metrics_.GetCryptoMetrics(),
|
||||
&service_certificate_));
|
||||
new CertificateProvisioning(metrics_.GetCryptoMetrics()));
|
||||
CdmResponseType status = cert_provisioning_->Init(
|
||||
provisioning_service_certificate_.certificate());
|
||||
if (status != NO_ERROR) return status;
|
||||
}
|
||||
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
|
||||
cert_provisioning_requested_security_level_, cert_type, cert_authority,
|
||||
@@ -991,7 +993,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
}
|
||||
if (!usage_info) {
|
||||
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
|
||||
return INVALID_PARAMETERS_ENG_8;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
usage_property_set_->set_security_level(kLevelDefault);
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
@@ -1063,7 +1065,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
CdmResponseType status = UNKNOWN_ERROR;
|
||||
if (!usage_info) {
|
||||
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
|
||||
return INVALID_PARAMETERS_ENG_9;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
do {
|
||||
status = GetUsageInfo(app_id, security_level, usage_info);
|
||||
@@ -1115,7 +1117,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
|
||||
if (!usage_info) {
|
||||
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
|
||||
return INVALID_PARAMETERS_ENG_10;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
if (0 == usage_data.size()) {
|
||||
usage_info->resize(0);
|
||||
@@ -1307,7 +1309,7 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
|
||||
if (!release_message) {
|
||||
LOGE("CdmEngine::LoadUsageSession: no release message destination");
|
||||
return INVALID_PARAMETERS_ENG_11;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
DeviceFiles handle(file_system_);
|
||||
@@ -1420,6 +1422,10 @@ CdmResponseType CdmEngine::GenericEncrypt(
|
||||
const std::string& session_id, const std::string& in_buffer,
|
||||
const std::string& key_id, const std::string& iv,
|
||||
CdmEncryptionAlgorithm algorithm, std::string* out_buffer) {
|
||||
if (out_buffer == NULL) {
|
||||
LOGE("CdmEngine::GenericEncrypt: no out_buffer provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
shared_ptr<CdmSession> session;
|
||||
if (!session_map_.FindSession(session_id, &session)) {
|
||||
LOGE("CdmEngine::GenericEncrypt: session_id not found = %s ",
|
||||
@@ -1434,6 +1440,10 @@ CdmResponseType CdmEngine::GenericDecrypt(
|
||||
const std::string& key_id, const std::string& iv,
|
||||
CdmEncryptionAlgorithm algorithm,
|
||||
std::string* out_buffer) {
|
||||
if (out_buffer == NULL) {
|
||||
LOGE("CdmEngine::GenericDecrypt: no out_buffer provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
shared_ptr<CdmSession> session;
|
||||
if (!session_map_.FindSession(session_id, &session)) {
|
||||
LOGE("CdmEngine::GenericDecrypt: session_id not found = %s ",
|
||||
@@ -1447,6 +1457,10 @@ CdmResponseType CdmEngine::GenericSign(
|
||||
const std::string& session_id, const std::string& message,
|
||||
const std::string& key_id, CdmSigningAlgorithm algorithm,
|
||||
std::string* signature) {
|
||||
if (signature == NULL) {
|
||||
LOGE("CdmEngine::GenericSign: no signature buffer provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
shared_ptr<CdmSession> session;
|
||||
if (!session_map_.FindSession(session_id, &session)) {
|
||||
LOGE("CdmEngine::GenericSign: session_id not found = %s ",
|
||||
|
||||
@@ -74,7 +74,7 @@ CdmResponseType CdmSession::Init(
|
||||
const CdmSessionId* forced_session_id, WvCdmEventListener* event_listener) {
|
||||
if (initialized_) {
|
||||
LOGE("CdmSession::Init: Failed due to previous initialization");
|
||||
return SESSION_INIT_ERROR_2;
|
||||
return REINIT_ERROR;
|
||||
}
|
||||
|
||||
if (cdm_client_property_set &&
|
||||
@@ -186,6 +186,10 @@ CdmResponseType CdmSession::Init(
|
||||
|
||||
CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
const CdmKeySetId& key_set_id, const CdmLicenseType license_type) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::RestoreOfflineSession: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
if (!key_set_id_.empty()) {
|
||||
file_handle_->UnreserveLicenseId(key_set_id_);
|
||||
}
|
||||
@@ -270,6 +274,10 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
|
||||
CdmResponseType CdmSession::RestoreUsageSession(
|
||||
const DeviceFiles::CdmUsageData& usage_data) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::RestoreUsageSession: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
if (!key_set_id_.empty()) {
|
||||
file_handle_->UnreserveLicenseId(key_set_id_);
|
||||
}
|
||||
@@ -321,19 +329,14 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
const CdmAppParameterMap& app_parameters,
|
||||
CdmKeyRequest* key_request) {
|
||||
|
||||
if (crypto_session_.get() == NULL) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: Invalid crypto session");
|
||||
return INVALID_CRYPTO_SESSION_1;
|
||||
}
|
||||
|
||||
if (!crypto_session_->IsOpen()) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: Crypto session not open");
|
||||
return CRYPTO_SESSION_OPEN_ERROR_1;
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::GenerateKeyRequest: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
|
||||
if (!key_request) {
|
||||
LOGE("CdmSession::GenerateKeyRequest: No output destination provided");
|
||||
return INVALID_PARAMETERS_ENG_5;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
switch (license_type) {
|
||||
@@ -409,14 +412,9 @@ CdmResponseType CdmSession::GenerateKeyRequest(
|
||||
|
||||
// AddKey() - Accept license response and extract key info.
|
||||
CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
if (crypto_session_.get() == NULL) {
|
||||
LOGW("CdmSession::AddKey: Invalid crypto session");
|
||||
return INVALID_CRYPTO_SESSION_2;
|
||||
}
|
||||
|
||||
if (!crypto_session_->IsOpen()) {
|
||||
LOGW("CdmSession::AddKey: Crypto session not open");
|
||||
return CRYPTO_SESSION_OPEN_ERROR_2;
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::AddKey: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
|
||||
if (is_release_) {
|
||||
@@ -490,14 +488,9 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::QueryStatus(CdmQueryMap* query_response) {
|
||||
if (crypto_session_.get() == NULL) {
|
||||
LOGE("CdmSession::QueryStatus: Invalid crypto session");
|
||||
return INVALID_CRYPTO_SESSION_3;
|
||||
}
|
||||
|
||||
if (!crypto_session_->IsOpen()) {
|
||||
LOGE("CdmSession::QueryStatus: Crypto session not open");
|
||||
return CRYPTO_SESSION_OPEN_ERROR_3;
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::QueryStatus: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
|
||||
switch (security_level_) {
|
||||
@@ -535,14 +528,9 @@ CdmResponseType CdmSession::QueryKeyAllowedUsage(
|
||||
|
||||
CdmResponseType CdmSession::QueryOemCryptoSessionId(
|
||||
CdmQueryMap* query_response) {
|
||||
if (crypto_session_.get() == NULL) {
|
||||
LOGW("CdmSession::QueryOemCryptoSessionId: Invalid crypto session");
|
||||
return INVALID_CRYPTO_SESSION_4;
|
||||
}
|
||||
|
||||
if (!crypto_session_->IsOpen()) {
|
||||
LOGW("CdmSession::QueryOemCryptoSessionId: Crypto session not open");
|
||||
return CRYPTO_SESSION_OPEN_ERROR_4;
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::QueryOemCryptoSessionId: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
@@ -553,14 +541,9 @@ CdmResponseType CdmSession::QueryOemCryptoSessionId(
|
||||
|
||||
// Decrypt() - Accept encrypted buffer and return decrypted data.
|
||||
CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
if (crypto_session_.get() == NULL) {
|
||||
LOGW("CdmSession::Decrypt: Invalid crypto session");
|
||||
return INVALID_CRYPTO_SESSION_5;
|
||||
}
|
||||
|
||||
if (!crypto_session_->IsOpen()) {
|
||||
LOGW("CdmSession::Decrypt: Crypto session not open");
|
||||
return DECRYPT_NOT_READY;
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::Decrypt: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
|
||||
// Playback may not begin until either the start time passes or the license
|
||||
@@ -601,6 +584,10 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
// session keys.
|
||||
CdmResponseType CdmSession::GenerateRenewalRequest(
|
||||
CdmKeyRequest* key_request) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::GenerateRenewalRequest: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
|
||||
true, app_parameters_, NULL, &key_request->message, &key_request->url);
|
||||
|
||||
@@ -616,6 +603,10 @@ CdmResponseType CdmSession::GenerateRenewalRequest(
|
||||
|
||||
// RenewKey() - Accept renewal response and update key info.
|
||||
CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::RenewKey: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
CdmResponseType sts =
|
||||
license_parser_->HandleKeyUpdateResponse(true, key_response);
|
||||
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RENEW_KEY_ERROR_1 : sts;
|
||||
@@ -630,6 +621,10 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
|
||||
|
||||
CdmResponseType CdmSession::GenerateReleaseRequest(
|
||||
CdmKeyRequest* key_request) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::GenerateReleaseRequest: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
is_release_ = true;
|
||||
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
|
||||
false, app_parameters_, usage_table_header_ == NULL ? NULL : this,
|
||||
@@ -664,6 +659,10 @@ CdmResponseType CdmSession::GenerateReleaseRequest(
|
||||
|
||||
// ReleaseKey() - Accept release response and release license.
|
||||
CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::ReleaseKey: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
CdmResponseType sts =
|
||||
license_parser_->HandleKeyUpdateResponse(false, key_response);
|
||||
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RELEASE_KEY_ERROR : sts;
|
||||
@@ -681,6 +680,10 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
|
||||
if (!initialized_) {
|
||||
LOGE("CdmSession::DeleteUsageEntry: not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
}
|
||||
if (usage_support_type_ != kUsageEntrySupport) {
|
||||
LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d",
|
||||
usage_support_type_);
|
||||
@@ -919,7 +922,7 @@ CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer,
|
||||
std::string* out_buffer) {
|
||||
if (!out_buffer) {
|
||||
LOGE("CdmSession::GenericEncrypt: No output destination provided");
|
||||
return INVALID_PARAMETERS_ENG_6;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
@@ -944,7 +947,7 @@ CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer,
|
||||
std::string* out_buffer) {
|
||||
if (!out_buffer) {
|
||||
LOGE("CdmSession::GenericDecrypt: No output destination provided");
|
||||
return INVALID_PARAMETERS_ENG_7;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
@@ -968,7 +971,7 @@ CdmResponseType CdmSession::GenericSign(const std::string& message,
|
||||
std::string* signature) {
|
||||
if (!signature) {
|
||||
LOGE("CdmSession::GenericSign: No output destination provided");
|
||||
return INVALID_PARAMETERS_ENG_8;
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
CdmResponseType sts;
|
||||
M_TIME(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||
|
||||
#include "certificate_provisioning.h"
|
||||
#include "client_identification.h"
|
||||
#include "device_files.h"
|
||||
#include "file_store.h"
|
||||
#include "license_protocol.pb.h"
|
||||
@@ -20,6 +21,33 @@ const std::string kProvisioningServerUrl =
|
||||
"certificateprovisioning/v1/devicecertificates/create"
|
||||
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
|
||||
|
||||
// NOTE: Provider ID = staging.google.com
|
||||
const std::string kCpProductionServiceCertificate = wvcdm::a2bs_hex(
|
||||
"0ABF020803121028703454C008F63618ADE7443DB6C4C8188BE7F9900522"
|
||||
"8E023082010A0282010100B52112B8D05D023FCC5D95E2C251C1C649B417"
|
||||
"7CD8D2BEEF355BB06743DE661E3D2ABC3182B79946D55FDC08DFE9540781"
|
||||
"5E9A6274B322A2C7F5E067BB5F0AC07A89D45AEA94B2516F075B66EF811D"
|
||||
"0D26E1B9A6B894F2B9857962AA171C4F66630D3E4C602718897F5E1EF9B6"
|
||||
"AAF5AD4DBA2A7E14176DF134A1D3185B5A218AC05A4C41F081EFFF80A3A0"
|
||||
"40C50B09BBC740EEDCD8F14D675A91980F92CA7DDC646A06ADAD5101F74A"
|
||||
"0E498CC01F00532BAC217850BD905E90923656B7DFEFEF42486767F33EF6"
|
||||
"283D4F4254AB72589390BEE55808F1D668080D45D893C2BCA2F74D60A0C0"
|
||||
"D0A0993CEF01604703334C3638139486BC9DAF24FD67A07F9AD943020301"
|
||||
"00013A1273746167696E672E676F6F676C652E636F6D128003983E303526"
|
||||
"75F40BA715FC249BDAE5D4AC7249A2666521E43655739529721FF880E0AA"
|
||||
"EFC5E27BC980DAEADABF3FC386D084A02C82537848CC753FF497B011A7DA"
|
||||
"97788A00E2AA6B84CD7D71C07A48EBF61602CCA5A3F32030A7295C30DA91"
|
||||
"5B91DC18B9BC9593B8DE8BB50F0DEDC12938B8E9E039CDDE18FA82E81BB0"
|
||||
"32630FE955D85A566CE154300BF6D4C1BD126966356B287D657B18CE63D0"
|
||||
"EFD45FC5269E97EAB11CB563E55643B26FF49F109C2101AFCAF35B832F28"
|
||||
"8F0D9D45960E259E85FB5D24DBD2CF82764C5DD9BF727EFBE9C861F86932"
|
||||
"1F6ADE18905F4D92F9A6DA6536DB8475871D168E870BB2303CF70C6E9784"
|
||||
"C93D2DE845AD8262BE7E0D4E2E4A0759CEF82D109D2592C72429F8C01742"
|
||||
"BAE2B3DECADBC33C3E5F4BAF5E16ECB74EADBAFCB7C6705F7A9E3B6F3940"
|
||||
"383F9C5116D202A20C9229EE969C2519718303B50D0130C3352E06B014D8"
|
||||
"38540F8A0C227C0011E0F5B38E4E298ED2CB301EB4564965F55C5D79757A"
|
||||
"250A4EB9C84AB3E6539F6B6FDF56899EA29914");
|
||||
|
||||
/*
|
||||
* Provisioning response is a base64-encoded protobuf, optionally within a
|
||||
* JSON wrapper. If the JSON wrapper is present, extract the embedded response
|
||||
@@ -70,34 +98,20 @@ void ExtractAndDecodeSignedMessage(const std::string& provisioning_response,
|
||||
|
||||
namespace wvcdm {
|
||||
// Protobuf generated classes.
|
||||
using video_widevine::ClientIdentification;
|
||||
using video_widevine::ClientIdentification_ClientCapabilities;
|
||||
using video_widevine::ClientIdentification_NameValue;
|
||||
using video_widevine::EncryptedClientIdentification;
|
||||
using video_widevine::ProvisioningOptions;
|
||||
using video_widevine::ProvisioningRequest;
|
||||
using video_widevine::ProvisioningResponse;
|
||||
using video_widevine::SignedProvisioningMessage;
|
||||
|
||||
/*
|
||||
* Return the ClientIdentification message token type for provisioning request.
|
||||
* NOTE: a DRM Cert should never be presented to the provisioning server.
|
||||
*/
|
||||
bool CertificateProvisioning::GetProvisioningTokenType(
|
||||
ClientIdentification::TokenType* token_type) {
|
||||
CdmClientTokenType token = crypto_session_.GetPreProvisionTokenType();
|
||||
switch (token) {
|
||||
case kClientTokenKeybox:
|
||||
*token_type = ClientIdentification::KEYBOX;
|
||||
return true;
|
||||
case kClientTokenOemCert:
|
||||
*token_type = ClientIdentification::OEM_DEVICE_CERTIFICATE;
|
||||
return true;
|
||||
case kClientTokenDrmCert:
|
||||
default:
|
||||
// shouldn't happen
|
||||
LOGE("CertificateProvisioning::GetProvisioningTokenType: unexpected "
|
||||
"provisioning type: %d", token);
|
||||
return false;
|
||||
}
|
||||
CdmResponseType CertificateProvisioning::Init(
|
||||
const std::string& service_certificate) {
|
||||
|
||||
std::string certificate = service_certificate.empty() ?
|
||||
kCpProductionServiceCertificate : service_certificate;
|
||||
return service_certificate_->Init(certificate);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -177,36 +191,32 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
|
||||
// Prepare device provisioning request.
|
||||
ProvisioningRequest provisioning_request;
|
||||
std::string token;
|
||||
ClientIdentification* client_id = provisioning_request.mutable_client_id();
|
||||
ClientIdentification::TokenType token_type;
|
||||
|
||||
if (!GetProvisioningTokenType(&token_type)) {
|
||||
LOGE("GetProvisioningRequest: bad token type");
|
||||
return CERT_PROVISIONING_CLIENT_TOKEN_ERROR_1;
|
||||
}
|
||||
if (!crypto_session_.GetProvisioningToken(&token)) {
|
||||
LOGE("GetProvisioningRequest: failure getting provisioning token");
|
||||
return CERT_PROVISIONING_CLIENT_TOKEN_ERROR_2;
|
||||
}
|
||||
client_id->set_token(token);
|
||||
client_id->set_type(token_type);
|
||||
wvcdm::ClientIdentification id;
|
||||
status = id.Init(&crypto_session_);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
#if 0 // TODO(gmorgan) Encrypt ClientIdentification. Pending Design.
|
||||
if (service_certificate_->has_certificate()) {
|
||||
EncryptedClientIdentification* encrypted_client_id =
|
||||
provisioning_request.mutable_encrypted_client_id();
|
||||
CdmResponseType status;
|
||||
status = service_certificate_->EncryptClientId(&crypto_session_, client_id,
|
||||
encrypted_client_id);
|
||||
if (status == NO_ERROR) {
|
||||
provisioning_request.clear_client_id();
|
||||
} else {
|
||||
provisioning_request.clear_encrypted_client_id();
|
||||
}
|
||||
return status;
|
||||
video_widevine::ClientIdentification* client_id =
|
||||
provisioning_request.mutable_client_id();
|
||||
CdmAppParameterMap app_parameter;
|
||||
status = id.Prepare(app_parameter, client_id);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
if (!service_certificate_->has_certificate()) {
|
||||
LOGE("CertificateProvisioning::GetProvisioningRequest: Service Certificate "
|
||||
"not staged");
|
||||
return CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO(rfrias): Uncomment when b/69427217 is addressed
|
||||
/*
|
||||
EncryptedClientIdentification* encrypted_client_id =
|
||||
provisioning_request->mutable_encrypted_client_id();
|
||||
CdmResponseType status =
|
||||
service_certificate_->EncryptClientId(&crypto_session_, client_id,
|
||||
encrypted_client_id);
|
||||
provisioning_request->clear_client_id();
|
||||
*/
|
||||
|
||||
uint32_t nonce;
|
||||
if (!crypto_session_.GenerateNonce(&nonce)) {
|
||||
|
||||
259
libwvdrmengine/cdm/core/src/client_identification.cpp
Normal file
259
libwvdrmengine/cdm/core/src/client_identification.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
#include "client_identification.h"
|
||||
|
||||
#include "crypto_session.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
namespace {
|
||||
const std::string kKeyCompanyName = "company_name";
|
||||
const std::string kKeyModelName = "model_name";
|
||||
const std::string kKeyArchitectureName = "architecture_name";
|
||||
const std::string kKeyDeviceName = "device_name";
|
||||
const std::string kKeyProductName = "product_name";
|
||||
const std::string kKeyBuildInfo = "build_info";
|
||||
const std::string kKeyDeviceId = "device_id";
|
||||
const std::string kKeyWvCdmVersion = "widevine_cdm_version";
|
||||
const std::string kKeyOemCryptoSecurityPatchLevel =
|
||||
"oem_crypto_security_patch_level";
|
||||
} // unnamed namespace
|
||||
|
||||
namespace wvcdm {
|
||||
// Protobuf generated classes.
|
||||
using video_widevine::ClientIdentification_ClientCapabilities;
|
||||
using video_widevine::ClientIdentification_NameValue;
|
||||
using video_widevine::EncryptedClientIdentification;
|
||||
using video_widevine::ProvisioningOptions;
|
||||
using video_widevine::ProvisioningRequest;
|
||||
using video_widevine::ProvisioningResponse;
|
||||
using video_widevine::SignedProvisioningMessage;
|
||||
|
||||
CdmResponseType ClientIdentification::Init(CryptoSession* crypto_session) {
|
||||
if (crypto_session == NULL) {
|
||||
LOGE("ClientIdentification::Init: crypto_session not provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
is_license_request_ = false;
|
||||
crypto_session_ = crypto_session;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType ClientIdentification::Init(const std::string& client_token,
|
||||
const std::string& device_id,
|
||||
CryptoSession* crypto_session) {
|
||||
if (crypto_session == NULL) {
|
||||
LOGE("ClientIdentification::Init: crypto_session not provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
if (client_token.empty()) {
|
||||
LOGE("ClientIdentification::Init: crypto_session not provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
is_license_request_ = true;
|
||||
device_id_ = device_id;
|
||||
client_token_ = client_token;
|
||||
crypto_session_ = crypto_session;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the ClientIdentification message token type for provisioning request.
|
||||
* NOTE: a DRM Cert should never be presented to the provisioning server.
|
||||
*/
|
||||
CdmResponseType ClientIdentification::Prepare(
|
||||
const CdmAppParameterMap& app_parameters,
|
||||
video_widevine::ClientIdentification* client_id) {
|
||||
|
||||
if (is_license_request_) {
|
||||
client_id->set_type(
|
||||
video_widevine::ClientIdentification::DRM_DEVICE_CERTIFICATE);
|
||||
client_id->set_token(client_token_);
|
||||
} else {
|
||||
video_widevine::ClientIdentification::TokenType token_type;
|
||||
if (!GetProvisioningTokenType(&token_type)) {
|
||||
LOGE("ClientIdentification::Prepare: failure getting provisioning token "
|
||||
"type");
|
||||
return CLIENT_IDENTIFICATION_TOKEN_ERROR_1;
|
||||
}
|
||||
client_id->set_type(token_type);
|
||||
|
||||
std::string token;
|
||||
if (!crypto_session_->GetProvisioningToken(&token)) {
|
||||
LOGE("ClientIdentification::Prepare: failure getting provisioning token");
|
||||
return CLIENT_IDENTIFICATION_TOKEN_ERROR_2;
|
||||
}
|
||||
client_id->set_token(token);
|
||||
}
|
||||
|
||||
ClientIdentification_NameValue* client_info;
|
||||
if (is_license_request_) {
|
||||
CdmAppParameterMap::const_iterator iter;
|
||||
for (iter = app_parameters.begin(); iter != app_parameters.end(); iter++) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(iter->first);
|
||||
client_info->set_value(iter->second);
|
||||
}
|
||||
}
|
||||
std::string value;
|
||||
if (Properties::GetCompanyName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyCompanyName);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetModelName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyModelName);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetArchitectureName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyArchitectureName);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetDeviceName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyDeviceName);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetProductName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyProductName);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetBuildInfo(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyBuildInfo);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (!device_id_.empty()) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyDeviceId);
|
||||
client_info->set_value(b2a_hex(device_id_));
|
||||
} else if (crypto_session_->GetInternalDeviceUniqueId(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyDeviceId);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetWVCdmVersion(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyWvCdmVersion);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kKeyOemCryptoSecurityPatchLevel);
|
||||
std::stringstream ss;
|
||||
ss << (uint32_t)crypto_session_->GetSecurityPatchLevel();
|
||||
client_info->set_value(ss.str());
|
||||
|
||||
ClientIdentification_ClientCapabilities* client_capabilities =
|
||||
client_id->mutable_client_capabilities();
|
||||
|
||||
if (is_license_request_) {
|
||||
bool supports_usage_information;
|
||||
if (crypto_session_->UsageInformationSupport(&supports_usage_information)) {
|
||||
client_capabilities->set_session_token(supports_usage_information);
|
||||
}
|
||||
|
||||
client_capabilities->set_anti_rollback_usage_table(
|
||||
crypto_session_->IsAntiRollbackHwPresent());
|
||||
}
|
||||
|
||||
uint32_t api_version = 0;
|
||||
if (crypto_session_->GetApiVersion(&api_version)) {
|
||||
client_capabilities->set_oem_crypto_api_version(api_version);
|
||||
}
|
||||
|
||||
if (is_license_request_) {
|
||||
CryptoSession::HdcpCapability current_version, max_version;
|
||||
if (crypto_session_->GetHdcpCapabilities(¤t_version, &max_version)) {
|
||||
switch (max_version) {
|
||||
case HDCP_NONE:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE);
|
||||
break;
|
||||
case HDCP_V1:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1);
|
||||
break;
|
||||
case HDCP_V2:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2);
|
||||
break;
|
||||
case HDCP_V2_1:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1);
|
||||
break;
|
||||
case HDCP_V2_2:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2);
|
||||
break;
|
||||
case HDCP_NO_DIGITAL_OUTPUT:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NO_DIGITAL_OUTPUT);
|
||||
break;
|
||||
default:
|
||||
LOGW(
|
||||
"ClientIdentification::PrepareClientId: unexpected HDCP max "
|
||||
"capability version %d", max_version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CryptoSession::SupportedCertificateTypes supported_certs;
|
||||
if (crypto_session_->GetSupportedCertificateTypes(&supported_certs)) {
|
||||
if (supported_certs.rsa_2048_bit) {
|
||||
client_capabilities->add_supported_certificate_key_type(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_2048);
|
||||
}
|
||||
if (supported_certs.rsa_3072_bit) {
|
||||
client_capabilities->add_supported_certificate_key_type(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_3072);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_license_request_) {
|
||||
client_capabilities->set_can_update_srm(
|
||||
crypto_session_->IsSrmUpdateSupported());
|
||||
uint16_t srm_version;
|
||||
if (crypto_session_->GetSrmVersion(&srm_version))
|
||||
client_capabilities->set_srm_version(srm_version);
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool ClientIdentification::GetProvisioningTokenType(
|
||||
video_widevine::ClientIdentification::TokenType* token_type) {
|
||||
CdmClientTokenType token = crypto_session_->GetPreProvisionTokenType();
|
||||
switch (token) {
|
||||
case kClientTokenKeybox:
|
||||
*token_type = video_widevine::ClientIdentification::KEYBOX;
|
||||
return true;
|
||||
case kClientTokenOemCert:
|
||||
*token_type =
|
||||
video_widevine::ClientIdentification::OEM_DEVICE_CERTIFICATE;
|
||||
return true;
|
||||
case kClientTokenDrmCert:
|
||||
default:
|
||||
// shouldn't happen
|
||||
LOGE("CertificateProvisioning::GetProvisioningTokenType: unexpected "
|
||||
"provisioning type: %d", token);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
@@ -82,12 +82,12 @@ const size_t kOemCryptoApiVersionSupportsBigUsageTables = 13;
|
||||
const int kExtensionOidSize = 64;
|
||||
const char* const kWidevineSystemIdExtensionOid = "1.3.6.1.4.1.11129.4.1.1";
|
||||
|
||||
// Helpers for working with OpenSSL / BoringSSL
|
||||
// Helpers for working with BoringSSL
|
||||
template <typename T, void (*func)(T*)>
|
||||
class openssl_ptr {
|
||||
class boringssl_ptr {
|
||||
public:
|
||||
explicit openssl_ptr(T* p = NULL) : ptr_(p) {}
|
||||
~openssl_ptr() {
|
||||
explicit boringssl_ptr(T* p = NULL) : ptr_(p) {}
|
||||
~boringssl_ptr() {
|
||||
if (ptr_) func(ptr_);
|
||||
}
|
||||
T& operator*() const { return *ptr_; }
|
||||
@@ -96,13 +96,13 @@ class openssl_ptr {
|
||||
|
||||
private:
|
||||
T* ptr_;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(openssl_ptr);
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
|
||||
};
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
|
||||
void DeleteX509Stack(STACK_OF(X509)* stack) {
|
||||
sk_X509_pop_free(stack, X509_free);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -722,7 +722,7 @@ CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
|
||||
is_destination_buffer_type_valid_(false),
|
||||
requested_security_level_(kLevelDefault),
|
||||
is_usage_support_type_valid_(false),
|
||||
usage_support_type_(kNonSecureUsageSupport),
|
||||
usage_support_type_(kUnknownUsageSupport),
|
||||
usage_table_header_(NULL),
|
||||
request_id_base_(0),
|
||||
cipher_mode_(kCipherModeCtr) {
|
||||
@@ -811,6 +811,10 @@ void CryptoSession::Terminate() {
|
||||
}
|
||||
|
||||
bool CryptoSession::GetTokenFromKeybox(std::string* token) {
|
||||
if (token == NULL) {
|
||||
LOGE("CryptoSession::GetTokenFromKeybox: token not provided");
|
||||
return false;
|
||||
}
|
||||
std::string temp_buffer(KEYBOX_KEY_DATA_SIZE, '\0');
|
||||
// lock is held by caller
|
||||
size_t buf_size = temp_buffer.size();
|
||||
@@ -974,6 +978,10 @@ bool CryptoSession::GetInternalDeviceUniqueId(std::string* device_id) {
|
||||
}
|
||||
|
||||
bool CryptoSession::GetExternalDeviceUniqueId(std::string* device_id) {
|
||||
if (device_id == NULL) {
|
||||
LOGE("CryptoSession::GetExternalDeviceUniqueId: device_id not provided");
|
||||
return false;
|
||||
}
|
||||
std::string temp;
|
||||
if (!GetInternalDeviceUniqueId(&temp)) return false;
|
||||
|
||||
@@ -1066,9 +1074,8 @@ bool CryptoSession::GetSystemId(uint32_t* system_id) {
|
||||
|
||||
bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
uint32_t* system_id) {
|
||||
// Load the certificate chain into an OpenSSL X509 Stack
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
const openssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||
// Load the certificate chain into a BoringSSL X509 Stack
|
||||
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||
sk_X509_new_null());
|
||||
if (x509_stack.get() == NULL) {
|
||||
LOGE("CryptoSession::GetSystemId: Unable to allocate X509 Stack.");
|
||||
@@ -1084,27 +1091,6 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
}
|
||||
|
||||
STACK_OF(X509)* certs = x509_stack.get();
|
||||
#else
|
||||
openssl_ptr<BIO, BIO_vfree> bio(
|
||||
// This const_cast is safe because BIO_new_mem_buf() creates a read-only
|
||||
// buffer from the data given and does not mutate it. Its first parameter
|
||||
// could be const, but it isn't.
|
||||
BIO_new_mem_buf(
|
||||
reinterpret_cast<uint8_t*>(const_cast<char*>(oem_cert.data())),
|
||||
oem_cert.size()));
|
||||
if (bio.get() == NULL) {
|
||||
LOGE("CryptoSession::GetSystemId: Unable to allocate BIO buffer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
openssl_ptr<PKCS7, PKCS7_free> cert(d2i_PKCS7_bio(bio.get(), NULL));
|
||||
if (cert.get() == NULL) {
|
||||
LOGE("CryptoSession::GetSystemId: Unable to allocate PKCS#7 buffer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
STACK_OF(X509)* certs = cert->d.sign->cert;
|
||||
#endif
|
||||
|
||||
// Get the Widevine intermediate cert from the stack
|
||||
if (sk_X509_num(certs) != 2) {
|
||||
@@ -2325,7 +2311,10 @@ CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer,
|
||||
CdmEncryptionAlgorithm algorithm,
|
||||
std::string* out_buffer) {
|
||||
LOGV("GenericEncrypt: id=%ld", (uint32_t)oec_session_id_);
|
||||
if (!out_buffer) return INVALID_PARAMETERS_ENG_9;
|
||||
if (!out_buffer) {
|
||||
LOGE("CryptoSession::GenericEncrypt: out_buffer not provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
OEMCrypto_Algorithm oec_algorithm = GenericEncryptionAlgorithm(algorithm);
|
||||
if (iv.size() != GenericEncryptionBlockSize(algorithm) ||
|
||||
@@ -2375,7 +2364,10 @@ CdmResponseType CryptoSession::GenericDecrypt(const std::string& in_buffer,
|
||||
CdmEncryptionAlgorithm algorithm,
|
||||
std::string* out_buffer) {
|
||||
LOGV("GenericDecrypt: id=%ld", (uint32_t)oec_session_id_);
|
||||
if (!out_buffer) return INVALID_PARAMETERS_ENG_10;
|
||||
if (!out_buffer) {
|
||||
LOGE("CryptoSession::GenericDecrypt: out_buffer not provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
OEMCrypto_Algorithm oec_algorithm = GenericEncryptionAlgorithm(algorithm);
|
||||
if (iv.size() != GenericEncryptionBlockSize(algorithm) ||
|
||||
@@ -2425,8 +2417,8 @@ CdmResponseType CryptoSession::GenericSign(const std::string& message,
|
||||
std::string* signature) {
|
||||
LOGV("GenericSign: id=%ld", (uint32_t)oec_session_id_);
|
||||
if (!signature) {
|
||||
LOGE("GenerateSign: null signature string");
|
||||
return INVALID_PARAMETERS_ENG_11;
|
||||
LOGE("CryptoSession::GenericSign: signature not provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
|
||||
OEMCrypto_Algorithm oec_algorithm = GenericSigningAlgorithm(algorithm);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "clock.h"
|
||||
#include "cdm_session.h"
|
||||
#include "client_identification.h"
|
||||
#include "crypto_key.h"
|
||||
#include "crypto_session.h"
|
||||
#include "device_files.h"
|
||||
@@ -20,17 +21,6 @@
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace {
|
||||
const std::string kCompanyNameKey = "company_name";
|
||||
const std::string kModelNameKey = "model_name";
|
||||
const std::string kArchitectureNameKey = "architecture_name";
|
||||
const std::string kDeviceNameKey = "device_name";
|
||||
const std::string kProductNameKey = "product_name";
|
||||
const std::string kBuildInfoKey = "build_info";
|
||||
const std::string kDeviceIdKey = "device_id";
|
||||
const std::string kWVCdmVersionKey = "widevine_cdm_version";
|
||||
const std::string kOemCryptoSecurityPatchLevelKey =
|
||||
"oem_crypto_security_patch_level";
|
||||
|
||||
const uint32_t kFourCcCbc1 = 0x63626331;
|
||||
const uint32_t kFourCcCbcs = 0x63626373;
|
||||
const uint32_t kFourCcLittleEndianCbc1 = 0x31636263;
|
||||
@@ -42,7 +32,6 @@ const uint32_t kFourCcCenc = 0x63656e63;
|
||||
namespace wvcdm {
|
||||
|
||||
// Protobuf generated classes.
|
||||
using video_widevine::ClientIdentification;
|
||||
using video_widevine::ClientIdentification_ClientCapabilities;
|
||||
using video_widevine::ClientIdentification_NameValue;
|
||||
using video_widevine::DrmDeviceCertificate;
|
||||
@@ -986,169 +975,17 @@ CdmResponseType CdmLicense::HandleKeyErrorResponse(
|
||||
}
|
||||
}
|
||||
|
||||
// Return the ClientIdentification message token type for license request.
|
||||
// NOTE: an OEM Cert should never be presented to the provisioning server.
|
||||
bool CdmLicense::GetClientTokenType(
|
||||
ClientIdentification::TokenType* token_type) {
|
||||
switch (client_token_type_) {
|
||||
case kClientTokenKeybox:
|
||||
*token_type = ClientIdentification::KEYBOX;
|
||||
return true;
|
||||
case kClientTokenDrmCert:
|
||||
*token_type = ClientIdentification::DRM_DEVICE_CERTIFICATE;
|
||||
return true;
|
||||
case kClientTokenOemCert:
|
||||
default:
|
||||
// shouldn't happen
|
||||
LOGE("GetClientTokenType: BAD TOKEN TYPE");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::PrepareClientId(
|
||||
const CdmAppParameterMap& app_parameters, LicenseRequest* license_request) {
|
||||
ClientIdentification* client_id = license_request->mutable_client_id();
|
||||
|
||||
ClientIdentification::TokenType token_type;
|
||||
if (!GetClientTokenType(&token_type)) {
|
||||
return LICENSING_CLIENT_TOKEN_ERROR_1;
|
||||
}
|
||||
client_id->set_type(token_type);
|
||||
client_id->set_token(client_token_);
|
||||
wvcdm::ClientIdentification id;
|
||||
CdmResponseType status = id.Init(client_token_, device_id_, crypto_session_);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
ClientIdentification_NameValue* client_info;
|
||||
CdmAppParameterMap::const_iterator iter;
|
||||
for (iter = app_parameters.begin(); iter != app_parameters.end(); iter++) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(iter->first);
|
||||
client_info->set_value(iter->second);
|
||||
}
|
||||
std::string value;
|
||||
if (Properties::GetCompanyName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kCompanyNameKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetModelName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kModelNameKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetArchitectureName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kArchitectureNameKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetDeviceName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kDeviceNameKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetProductName(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kProductNameKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetBuildInfo(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kBuildInfoKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (!device_id_.empty()) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kDeviceIdKey);
|
||||
client_info->set_value(b2a_hex(device_id_));
|
||||
} else if (crypto_session_->GetInternalDeviceUniqueId(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kDeviceIdKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
if (Properties::GetWVCdmVersion(&value)) {
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kWVCdmVersionKey);
|
||||
client_info->set_value(value);
|
||||
}
|
||||
client_info = client_id->add_client_info();
|
||||
client_info->set_name(kOemCryptoSecurityPatchLevelKey);
|
||||
std::stringstream ss;
|
||||
ss << (uint32_t)crypto_session_->GetSecurityPatchLevel();
|
||||
client_info->set_value(ss.str());
|
||||
|
||||
ClientIdentification_ClientCapabilities* client_capabilities =
|
||||
client_id->mutable_client_capabilities();
|
||||
bool supports_usage_information;
|
||||
if (crypto_session_->UsageInformationSupport(&supports_usage_information)) {
|
||||
client_capabilities->set_session_token(supports_usage_information);
|
||||
}
|
||||
|
||||
client_capabilities->set_anti_rollback_usage_table(
|
||||
crypto_session_->IsAntiRollbackHwPresent());
|
||||
|
||||
uint32_t api_version = 0;
|
||||
if (crypto_session_->GetApiVersion(&api_version)) {
|
||||
client_capabilities->set_oem_crypto_api_version(api_version);
|
||||
}
|
||||
|
||||
CryptoSession::HdcpCapability current_version, max_version;
|
||||
if (crypto_session_->GetHdcpCapabilities(¤t_version, &max_version)) {
|
||||
switch (max_version) {
|
||||
case HDCP_NONE:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE);
|
||||
break;
|
||||
case HDCP_V1:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1);
|
||||
break;
|
||||
case HDCP_V2:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2);
|
||||
break;
|
||||
case HDCP_V2_1:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1);
|
||||
break;
|
||||
case HDCP_V2_2:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2);
|
||||
break;
|
||||
case HDCP_NO_DIGITAL_OUTPUT:
|
||||
client_capabilities->set_max_hdcp_version(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NO_DIGITAL_OUTPUT);
|
||||
break;
|
||||
default:
|
||||
LOGW(
|
||||
"CdmLicense::PrepareClientId: unexpected HDCP max capability "
|
||||
"version %d",
|
||||
max_version);
|
||||
}
|
||||
}
|
||||
|
||||
CryptoSession::SupportedCertificateTypes supported_certs;
|
||||
if (crypto_session_->GetSupportedCertificateTypes(&supported_certs)) {
|
||||
if (supported_certs.rsa_2048_bit) {
|
||||
client_capabilities->add_supported_certificate_key_type(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_2048);
|
||||
}
|
||||
if (supported_certs.rsa_3072_bit) {
|
||||
client_capabilities->add_supported_certificate_key_type(
|
||||
video_widevine::
|
||||
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_3072);
|
||||
}
|
||||
}
|
||||
|
||||
client_capabilities->set_can_update_srm(
|
||||
crypto_session_->IsSrmUpdateSupported());
|
||||
uint16_t srm_version;
|
||||
if (crypto_session_->GetSrmVersion(&srm_version))
|
||||
client_capabilities->set_srm_version(srm_version);
|
||||
video_widevine::ClientIdentification* client_id =
|
||||
license_request->mutable_client_id();
|
||||
status = id.Prepare(app_parameters, client_id);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
if (Properties::UsePrivacyMode(session_id_)) {
|
||||
if (!service_certificate_.has_certificate()) {
|
||||
@@ -1157,7 +994,6 @@ CdmResponseType CdmLicense::PrepareClientId(
|
||||
}
|
||||
EncryptedClientIdentification* encrypted_client_id =
|
||||
license_request->mutable_encrypted_client_id();
|
||||
CdmResponseType status;
|
||||
status = service_certificate_.EncryptClientId(crypto_session_, client_id,
|
||||
encrypted_client_id);
|
||||
if (NO_ERROR == status) {
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if __mips__
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/cachectl.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
@@ -300,7 +300,8 @@ CdmResponseType PolicyEngine::Query(CdmQueryMap* query_response) {
|
||||
CdmResponseType PolicyEngine::QueryKeyAllowedUsage(
|
||||
const KeyId& key_id, CdmKeyAllowedUsage* key_usage) {
|
||||
if (NULL == key_usage) {
|
||||
return INVALID_PARAMETERS_ENG_12;
|
||||
LOGE("PolicyEngine::QueryKeyAllowedUsage: no key_usage provided");
|
||||
return PARAMETER_NULL;
|
||||
}
|
||||
if (license_keys_->GetAllowedUsage(key_id, key_usage)) {
|
||||
return NO_ERROR;
|
||||
|
||||
@@ -14,7 +14,6 @@ bool Properties::oem_crypto_use_fifo_;
|
||||
bool Properties::oem_crypto_use_userspace_buffers_;
|
||||
bool Properties::provisioning_messages_are_binary_;
|
||||
bool Properties::allow_service_certificate_requests_;
|
||||
bool Properties::security_level_path_backward_compatibility_support_;
|
||||
scoped_ptr<CdmClientPropertySetMap> Properties::session_property_set_;
|
||||
|
||||
bool Properties::AddSessionPropertySet(
|
||||
|
||||
@@ -24,6 +24,7 @@ UsageTableHeader::UsageTableHeader()
|
||||
: security_level_(kSecurityLevelUninitialized),
|
||||
requested_security_level_(kLevelDefault),
|
||||
is_inited_(false) {
|
||||
file_system_.reset(new FileSystem());
|
||||
file_handle_.reset(new DeviceFiles(file_system_.get()));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user