From 97e826412dd0c693e6e289e5fb8b229e3796ca1f Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Thu, 7 Jan 2016 15:31:08 -0800 Subject: [PATCH] Add cipher mode and pattern encryption support [ Merge of http://go/wvgerrit/16364 ] http://go/wvgerrit/16249 changed the name of the encryption pattern structure from OEMCrypto_PatternDesc to OEMCrypto_CENCEncryptPatternDesc to remove ambiguity. These are matching changes to CDM core. [ Merge of http://go/wvgerrit/16340 ] This CL passes the cipher mode in the license to OEMCrypto when keys are loaded and specifies the pattern encryption scheme to OEMCrypto_DecryptCENC. b/20630275 Change-Id: I86b82bbdc891fd0100beb9fad385ca2082176271 --- libwvdrmengine/cdm/core/include/crypto_key.h | 5 +++++ .../cdm/core/include/wv_cdm_types.h | 21 +++++++++++++++++++ .../cdm/core/src/crypto_session.cpp | 10 +++++++-- libwvdrmengine/cdm/core/src/license.cpp | 3 +++ .../include/wv_content_decryption_module.h | 1 + .../cdm/src/wv_content_decryption_module.cpp | 4 ++++ 6 files changed, 42 insertions(+), 2 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/crypto_key.h b/libwvdrmengine/cdm/core/include/crypto_key.h index d973a021..921517e6 100644 --- a/libwvdrmengine/cdm/core/include/crypto_key.h +++ b/libwvdrmengine/cdm/core/include/crypto_key.h @@ -17,6 +17,7 @@ class CryptoKey { const std::string& key_data_iv() const { return key_data_iv_; } const std::string& key_control() const { return key_control_; } const std::string& key_control_iv() const { return key_control_iv_; } + CdmCipherMode cipher_mode() const { return cipher_mode_; } void set_key_id(const std::string& key_id) { key_id_ = key_id; } void set_key_data(const std::string& key_data) { key_data_ = key_data; } void set_key_data_iv(const std::string& iv) { key_data_iv_ = iv; } @@ -24,6 +25,9 @@ class CryptoKey { void set_key_control_iv(const std::string& ctl_iv) { key_control_iv_ = ctl_iv; } + void set_cipher_mode(CdmCipherMode cipher_mode) { + cipher_mode_ = cipher_mode; + } bool HasKeyControl() const { return key_control_.size() >= 16; } @@ -33,6 +37,7 @@ class CryptoKey { std::string key_data_; std::string key_control_; std::string key_control_iv_; + CdmCipherMode cipher_mode_; }; } // namespace wvcdm diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 0507ef08..ce42d718 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -271,6 +271,26 @@ struct CdmHlsData { std::string uri; }; +enum CdmCipherMode { + kCipherModeCtr, + kCipherModeCbc, +}; + +// For schemes that do not use pattern encryption (cenc and cbc1), encrypt +// and skip should be set to 0. For those that do (cens and cbcs), it is +// recommended that encrypt+skip bytes sum to 10 and for cbcs that a 1:9 +// encrypt:skip ratio be used. See ISO/IEC DIS 23001-7, section 10.4.2 for +// more information. +struct CdmCencPatternEncryptionDescriptor { + size_t encrypt_blocks; // number of 16 byte blocks to decrypt + size_t skip_blocks; // number of 16 byte blocks to leave in clear + size_t offset_blocks; // offset into the pattern for this call, in blocks + CdmCencPatternEncryptionDescriptor() + : encrypt_blocks(0), + skip_blocks(0), + offset_blocks(0) {} +}; + struct CdmDecryptionParameters { bool is_encrypted; bool is_secure; @@ -284,6 +304,7 @@ struct CdmDecryptionParameters { size_t decrypt_buffer_offset; uint8_t subsample_flags; bool is_video; + CdmCencPatternEncryptionDescriptor pattern_descriptor; CdmDecryptionParameters() : is_encrypted(true), is_secure(true), diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 4e81d428..e721dcf3 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -412,6 +412,9 @@ CdmResponseType CryptoSession::LoadKeys( ko->key_control_iv = NULL; ko->key_control = NULL; } + ko->cipher_mode = ki->cipher_mode() == kCipherModeCbc + ? OEMCrypto_CipherMode_CBC + : OEMCrypto_CipherMode_CTR; } uint8_t* pst = NULL; if (!provider_session_token.empty()) { @@ -672,6 +675,10 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) { &buffer_descriptor, params.subsample_flags); } if (params.is_encrypted || sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) { + OEMCrypto_CENCEncryptPatternDesc pattern_descriptor; + pattern_descriptor.encrypt = params.pattern_descriptor.encrypt_blocks; + pattern_descriptor.skip = params.pattern_descriptor.skip_blocks; + pattern_descriptor.offset = params.pattern_descriptor.offset_blocks; AutoLock auto_lock(crypto_lock_); // Check if key needs to be selected if (params.is_encrypted) { @@ -683,11 +690,10 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) { } } } - // TODO(rfrias): add encrypt pattern parameter. sts = OEMCrypto_DecryptCENC( oec_session_id_, params.encrypt_buffer, params.encrypt_length, params.is_encrypted, &(*params.iv).front(), params.block_offset, - &buffer_descriptor, NULL, params.subsample_flags); + &buffer_descriptor, &pattern_descriptor, params.subsample_flags); } switch (sts) { diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 72af4db7..adbbdd6a 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -106,6 +106,9 @@ static std::vector ExtractContentKeys(const License& license) { key.set_key_control(license.key(i).key_control().key_control_block()); key.set_key_control_iv(license.key(i).key_control().iv()); } + // TODO(rfrias): Set cipher mode when the license protocol provides + // it (b/26190665). Set to default for now. + key.set_cipher_mode(kCipherModeCtr); key_array.push_back(key); break; case License_KeyContainer::KEY_CONTROL: diff --git a/libwvdrmengine/cdm/include/wv_content_decryption_module.h b/libwvdrmengine/cdm/include/wv_content_decryption_module.h index e6d206aa..a1fc9cdd 100644 --- a/libwvdrmengine/cdm/include/wv_content_decryption_module.h +++ b/libwvdrmengine/cdm/include/wv_content_decryption_module.h @@ -25,6 +25,7 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler { static bool IsSupported(const std::string& init_data_type); static bool IsCenc(const std::string& init_data_type); static bool IsWebm(const std::string& init_data_type); + static bool IsHls(const std::string& init_data_type); // Session related methods virtual CdmResponseType OpenSession(const CdmKeySystem& key_system, diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index b99ca892..e052a560 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -38,6 +38,10 @@ bool WvContentDecryptionModule::IsWebm(const std::string& init_data_type) { return InitializationData(init_data_type).is_webm(); } +bool WvContentDecryptionModule::IsHls(const std::string& init_data_type) { + return InitializationData(init_data_type).is_hls(); +} + CdmResponseType WvContentDecryptionModule::OpenSession( const CdmKeySystem& key_system, CdmClientPropertySet* property_set, const std::string& origin, WvCdmEventListener* event_listener,