From c38775089758b1a90e5b73a5d7fba4cfe1e13350 Mon Sep 17 00:00:00 2001 From: Lu Chen Date: Tue, 7 Sep 2021 18:08:13 -0700 Subject: [PATCH] Add AES-ECB as a supported encryption mode in ECMG --- common/BUILD | 4 +++- common/crypto_util.cc | 7 ++++++- common/ec_key.h | 8 +++----- common/rsa_key.cc | 12 ++++++++++++ common/rsa_key.h | 3 +++ common/security_profile_list.h | 16 ++++++++++++++-- .../internal/ecm_serializer_v3.cc | 2 ++ .../internal/ecm_serializer_v3_test.cc | 3 ++- media_cas_packager_sdk/public/wv_cas_types.h | 1 + protos/public/media_cas.proto | 1 + protos/public/media_cas_encryption.proto | 1 + 11 files changed, 48 insertions(+), 10 deletions(-) diff --git a/common/BUILD b/common/BUILD index c1b310f..2c3b28b 100644 --- a/common/BUILD +++ b/common/BUILD @@ -101,6 +101,7 @@ cc_library( ":error_space", ":hash_algorithm", ":hash_algorithm_util", + ":output_protection_util", ":rsa_key", ":status", "//base", @@ -127,6 +128,7 @@ cc_test( ":error_space", ":hash_algorithm", ":hash_algorithm_util", + ":output_protection_util", ":rsa_key", ":rsa_test_keys", ":security_profile_list", @@ -431,7 +433,6 @@ cc_library( ":rsa_util", ":sha_util", "//base", - "@abseil_repo//absl/base:core_headers", "//external:openssl", ], ) @@ -870,6 +871,7 @@ cc_library( ":drm_service_certificate", ":error_space", ":rsa_key", + ":rsa_util", ":status", ":x509_cert", "//base", diff --git a/common/crypto_util.cc b/common/crypto_util.cc index 3f7c0ef..7850d02 100644 --- a/common/crypto_util.cc +++ b/common/crypto_util.cc @@ -95,7 +95,12 @@ std::string CreateSignatureHmac(const EVP_MD* hash_algorithm, bool VerifySignatureHmacSha256(absl::string_view key, absl::string_view signature, absl::string_view message) { - return CreateSignatureHmacSha256(key, message) == signature; + std::string actual_signature = CreateSignatureHmacSha256(key, message); + bool result = actual_signature == signature; + if (!result) { + VLOG(1) << "Invalid signature. actual signature: " << actual_signature; + } + return result; } // Compares the SHA-384 HMAC against the provided signature. diff --git a/common/ec_key.h b/common/ec_key.h index f1527a2..67868cb 100644 --- a/common/ec_key.h +++ b/common/ec_key.h @@ -145,13 +145,11 @@ class ECPublicKey { // Returns true on success and false on error. virtual bool GetRawPublicKey(std::string* raw_public_key) const; - private: - friend class ECPrivateKey; - - ECPublicKey& operator=(const ECPublicKey&) = delete; - const EC_KEY* key() const { return key_.get(); } + private: + ECPublicKey& operator=(const ECPublicKey&) = delete; + ScopedECKEY key_; }; diff --git a/common/rsa_key.cc b/common/rsa_key.cc index 9bcabd5..99d5aae 100644 --- a/common/rsa_key.cc +++ b/common/rsa_key.cc @@ -363,6 +363,18 @@ bool RsaPublicKey::MatchesPublicKey(const RsaPublicKey& public_key) const { uint32_t RsaPublicKey::KeySize() const { return RSA_size(key_); } +bool RsaPublicKey::SerializedKey(std::string* serialized_key) const { + if (serialized_key == nullptr) { + return false; + } + std::string tmp_serialized_key; + if (!rsa_util::SerializeRsaPublicKey(key(), &tmp_serialized_key)) { + return false; + } + *serialized_key = tmp_serialized_key; + return true; +} + RsaKeyFactory::RsaKeyFactory() {} RsaKeyFactory::~RsaKeyFactory() {} diff --git a/common/rsa_key.h b/common/rsa_key.h index 1071981..4577eba 100644 --- a/common/rsa_key.h +++ b/common/rsa_key.h @@ -125,6 +125,9 @@ class RsaPublicKey { // Returns the RSA key size (modulus) in bytes. virtual uint32_t KeySize() const; + // Returns true if the key is successfully serialized into |serialized_key|. + virtual bool SerializedKey(std::string* serialized_key) const; + private: friend class RsaPrivateKey; friend class X509CertificateBuilder; // TODO(user): Get rid of this. diff --git a/common/security_profile_list.h b/common/security_profile_list.h index 10a4e5b..df18b46 100644 --- a/common/security_profile_list.h +++ b/common/security_profile_list.h @@ -18,6 +18,7 @@ #include "absl/synchronization/mutex.h" #include "common/hash_algorithm.h" +#include "common/output_protection_util.h" #include "common/status.h" #include "protos/public/client_identification.pb.h" #include "protos/public/device_security_profile_data.pb.h" @@ -26,6 +27,7 @@ #include "protos/public/security_profile.pb.h" namespace widevine { + using ClientCapabilities = ClientIdentification::ClientCapabilities; const char kDefaultProfileOwnerName[] = "Widevine"; @@ -56,13 +58,16 @@ class SecurityProfileList { const std::vector& profiles_to_check, const std::string& owner, const ClientIdentification& client_id, const ProvisionedDeviceInfo& device_info, + PlatformVerificationStatus device_vmp_status, std::vector* qualified_profiles) const; // Populates |profiles_to_allow| with a list of profiles that meet the // requirements for the this device. The number of profiles is returned. virtual int GetQualifiedProfiles( const ClientIdentification& client_id, - const ProvisionedDeviceInfo& device_info, const std::string& owner, + const ProvisionedDeviceInfo& device_info, + const PlatformVerificationStatus device_vmp_status, + const std::string& owner, std::vector* qualified_profiles) const; // Return true if a profile exist matching the specified parameters {|name|, @@ -121,6 +126,8 @@ class SecurityProfileList { void ClearAllProfiles(); private: + friend class SecurityProfileListTest; + // Add Widevine default profiles into profile_list. The number of added // default profiles will be returned. virtual int AddDefaultProfiles(); @@ -133,7 +140,8 @@ class SecurityProfileList { bool DoesProfileQualify(const SecurityProfile& profile, const ClientIdentification& client_id, - const ProvisionedDeviceInfo& device_info) const; + const ProvisionedDeviceInfo& device_info, + PlatformVerificationStatus device_vmp_status) const; int64_t GetCurrentTimeSeconds() const; @@ -149,6 +157,10 @@ class SecurityProfileList { void ClearAllDefaultProfilesLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); void ClearAllCustomProfilesLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Return true is the client is a Chrome browser. + virtual bool IsChromeBrowser(const std::string& device_model) const; + mutable absl::Mutex mutex_; // Security profiles std::string profile_namespace_; diff --git a/media_cas_packager_sdk/internal/ecm_serializer_v3.cc b/media_cas_packager_sdk/internal/ecm_serializer_v3.cc index 6881f16..ae5fba6 100644 --- a/media_cas_packager_sdk/internal/ecm_serializer_v3.cc +++ b/media_cas_packager_sdk/internal/ecm_serializer_v3.cc @@ -136,6 +136,8 @@ EcmMetaData::CipherMode ConvertCryptoModeToProtoCipherMode( return EcmMetaData::AES_OFB; case CryptoMode::kAesScte: return EcmMetaData::AES_SCTE52; + case CryptoMode::kAesEcb: + return EcmMetaData::AES_ECB; case CryptoMode::kInvalid: default: LOG(ERROR) << "Unknown crypto mode."; diff --git a/media_cas_packager_sdk/internal/ecm_serializer_v3_test.cc b/media_cas_packager_sdk/internal/ecm_serializer_v3_test.cc index e901d81..a520928 100644 --- a/media_cas_packager_sdk/internal/ecm_serializer_v3_test.cc +++ b/media_cas_packager_sdk/internal/ecm_serializer_v3_test.cc @@ -274,7 +274,8 @@ INSTANTIATE_TEST_SUITE_P( std::make_tuple(CryptoMode::kDvbCsa2, EcmMetaData::DVB_CSA2), std::make_tuple(CryptoMode::kDvbCsa3, EcmMetaData::DVB_CSA3), std::make_tuple(CryptoMode::kAesOfb, EcmMetaData::AES_OFB), - std::make_tuple(CryptoMode::kAesScte, EcmMetaData::AES_SCTE52))); + std::make_tuple(CryptoMode::kAesScte, EcmMetaData::AES_SCTE52), + std::make_tuple(CryptoMode::kAesEcb, EcmMetaData::AES_ECB))); TEST_F(EcmSerializerV3Test, SerializeEcmDoubleKey8ByteIvs) { EcmSerializerV3 ecm_serializer; diff --git a/media_cas_packager_sdk/public/wv_cas_types.h b/media_cas_packager_sdk/public/wv_cas_types.h index 08256f2..36f9e4e 100644 --- a/media_cas_packager_sdk/public/wv_cas_types.h +++ b/media_cas_packager_sdk/public/wv_cas_types.h @@ -30,6 +30,7 @@ enum class CryptoMode : int { kDvbCsa3 = 3, kAesOfb = 4, kAesScte = 5, + kAesEcb = 6, }; enum class ScramblingLevel : int { kPES = 0, kTS = 1 }; diff --git a/protos/public/media_cas.proto b/protos/public/media_cas.proto index 9427e59..4f92f25 100644 --- a/protos/public/media_cas.proto +++ b/protos/public/media_cas.proto @@ -71,6 +71,7 @@ message EcmMetaData { DVB_CSA3 = 4; AES_OFB = 5; AES_SCTE52 = 6; + AES_ECB = 7; } // Required. The cipher mode used to encrypt/decrypt the content. optional CipherMode cipher_mode = 1; diff --git a/protos/public/media_cas_encryption.proto b/protos/public/media_cas_encryption.proto index 12c3b27..a7e3d4d 100644 --- a/protos/public/media_cas_encryption.proto +++ b/protos/public/media_cas_encryption.proto @@ -61,6 +61,7 @@ message CasEncryptionResponse { // Optional label used for the key. optional string track_type = 3; optional KeySlot key_slot = 4; + optional uint32 period_index = 5; } optional Status status = 1; optional string status_message = 2;