diff --git a/api/license_builder.cc b/api/license_builder.cc deleted file mode 100644 index ec412ca..0000000 --- a/api/license_builder.cc +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2020 Google LLC. All Rights Reserved. - -#include "api/license_builder.h" - -#include - -#include "base/logging.h" -#include "cdm/keys/certs.h" -#include "crypto_utils/aes_cbc_encryptor.h" -#include "crypto_utils/crypto_util.h" -#include "crypto_utils/sha_util.h" - -namespace widevine { - -namespace { - -void InitializeRequest(video_widevine::LicenseRequest* request) { - request->set_request_time(std::time(nullptr)); // Use time=now. - - auto* client_id = request->mutable_client_id(); - auto* capabilities = client_id->mutable_client_capabilities(); - capabilities->set_video_resolution_constraints(true); - capabilities->set_client_token(true); - capabilities->set_session_token(false); - capabilities->set_max_hdcp_version( - video_widevine::ClientIdentification::ClientCapabilities::HDCP_V1); - - auto* client_info = client_id->add_client_info(); - client_info->set_name("architecture_name"); - client_info->set_value("x86-64"); - client_info = client_id->add_client_info(); - client_info->set_name("company_name"); - client_info->set_value("Google"); - client_info = client_id->add_client_info(); - client_info->set_name("model_name"); - client_info->set_value("ChromeCDM"); - client_info = client_id->add_client_info(); - client_info->set_name("platform_name"); - client_info->set_value("Windows"); - client_info = client_id->add_client_info(); - client_info->set_name("widevine_cdm_version"); - client_info->set_value("4.10.1686.29"); - - client_id->set_type( - video_widevine::ClientIdentification_TokenType_DRM_DEVICE_CERTIFICATE); - client_id->set_token(wvcdm::kRsaDrmCertificate, - wvcdm::kRsaDrmCertificateSize); - - auto* content_id = request->mutable_content_id(); - auto* webm_key_id = content_id->mutable_webm_key_id(); - webm_key_id->set_license_type(video_widevine::STREAMING); - webm_key_id->set_request_id("REQUEST_ID"); - webm_key_id->set_header("01234567890123456"); - - request->set_protocol_version(video_widevine::VERSION_2_1); - request->set_type(video_widevine::LicenseRequest::NEW); -} - -void InitializeResponse(const video_widevine::LicenseRequest& request, - video_widevine::License* response) { - auto* id = response->mutable_id(); - id->set_request_id("REQUEST_ID"); - id->set_session_id("SESSION_ID"); - id->set_type(video_widevine::STREAMING); - id->set_version(0); - - auto* policy = response->mutable_policy(); - policy->set_can_play(true); - policy->set_can_persist(false); - policy->set_can_renew(true); - policy->set_license_duration_seconds(600); - policy->set_renewal_delay_seconds(30); - policy->set_renewal_retry_interval_seconds(10); - policy->set_renew_with_usage(false); - - response->set_license_start_time(request.request_time()); - response->set_remote_attestation_verified(false); - response->set_platform_verification_status( - video_widevine::PlatformVerificationStatus::PLATFORM_UNVERIFIED); -} - -std::string EncryptKey(const std::string& key, - const std::string& iv, - const std::vector& plaintext) { - AesCbcEncryptor encryptor; - encryptor.SetKey(reinterpret_cast(key.data()), key.size()); - - std::vector ciphertext(plaintext.size()); - CHECK(encryptor.Encrypt(reinterpret_cast(iv.data()), - iv.size(), plaintext.data(), plaintext.size(), - ciphertext.data())); - - return std::string(ciphertext.begin(), ciphertext.end()); -} - -std::string DeriveIV(const std::vector& context) { - const std::string context_str(context.begin(), context.end()); - return crypto_util::DeriveIv(context_str); -} - -} // namespace - -// static -std::vector LicenseBuilder::NoPadding() { - return {}; -} - -// static -std::vector LicenseBuilder::PKSC8Padding() { - return { - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - }; -} - -// static -std::vector LicenseBuilder::DefaultSigningKey() { - return { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - }; -} - -LicenseBuilder::LicenseBuilder() { - DCHECK_EQ(session_key_.size(), 16u); - - // Initialize the request and the response with the static fields that will - // be common across all licences. - InitializeRequest(&request_); - InitializeResponse(request_, &response_); - - serialized_request_ = request_.SerializeAsString(); - container_key_ = crypto_util::DeriveKey( - session_key_, crypto_util::kWrappingKeyLabel, serialized_request_, - crypto_util::kWrappingKeySizeBits); -} - -void LicenseBuilder::AddSigningKey(const std::vector& key, - const std::vector& padding) { - DCHECK_EQ(key.size(), 64u); // 512 bits - - auto* container = response_.add_key(); - container->set_type(video_widevine::License_KeyContainer_KeyType_SIGNING); - - // To avoid having to define a key iv for each key, derive a key iv from the - // key. This will allows us to have a different IVs between keys but keep it - // deterministic. - const auto key_iv = DeriveIV(key); - container->set_iv(key_iv); - - std::vector final_key = key; - final_key.insert(final_key.end(), padding.begin(), padding.end()); - container->set_key(EncryptKey(container_key_, key_iv, final_key)); -} - -void LicenseBuilder::AddStubbedContentKey() { - auto* container = response_.add_key(); - - container->set_type(video_widevine::License_KeyContainer_KeyType_CONTENT); - container->set_id("stubbed-content-key"); - container->set_level( - video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_CRYPTO); - container->set_iv("0000000000000000"); - - // We don't bother encrypting the key, it should never be used and there is no - // way to verify it. - container->set_key("0000000000000000"); -} - -void LicenseBuilder::AddContentKey( - video_widevine::License_KeyContainer_SecurityLevel level, - const std::vector& key_id, - const std::vector& key, - const std::vector& padding) { - DCHECK_GT(key_id.size(), 0u); - DCHECK_EQ(key.size(), 16u); - - auto* container = response_.add_key(); - - container->set_type(video_widevine::License_KeyContainer_KeyType_CONTENT); - container->set_id(key_id.data(), key_id.size()); - container->set_level(level); - - // To avoid having to define a key iv for each key, derive a key iv from the - // key. This will allows us to have a different IVs between keys but keep it - // deterministic. - const auto key_iv = DeriveIV(key); - container->set_iv(key_iv); - - std::vector final_key = key; - final_key.insert(final_key.end(), padding.begin(), padding.end()); - container->set_key(EncryptKey(container_key_, key_iv, final_key)); -} - -void LicenseBuilder::AddOperatorSessionKey(const std::vector& key_id) { - DCHECK_GT(key_id.size(), 0u); - - // We only set the type and id because the key should not actually be used. - auto* container = response_.add_key(); - container->set_type( - video_widevine::License_KeyContainer_KeyType_OPERATOR_SESSION); - container->set_id(key_id.data(), key_id.size()); -} - -void LicenseBuilder::Build(const RsaPublicKey& public_key, - License* license) const { - DCHECK(license); - - const std::string message_str = response_.SerializeAsString(); - - std::string signing_key = crypto_util::DeriveKey( - session_key_, crypto_util::kSigningKeyLabel, serialized_request_, - crypto_util::kSigningKeySizeBits * 2); - signing_key.resize(crypto_util::kSigningKeySizeBytes); - - const std::string signature_str = - crypto_util::CreateSignatureHmacSha256(signing_key, message_str); - - std::string session_key_str; - CHECK(public_key.Encrypt(session_key_, &session_key_str)); - - license->request = std::vector(serialized_request_.begin(), - serialized_request_.end()); - license->message = - std::vector(message_str.begin(), message_str.end()); - license->signature = - std::vector(signature_str.begin(), signature_str.end()); - license->session_key = - std::vector(session_key_str.begin(), session_key_str.end()); -} -} // namespace widevine diff --git a/api/license_builder.h b/api/license_builder.h deleted file mode 100644 index 93fa525..0000000 --- a/api/license_builder.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2020 Google LLC. All Rights Reserved. - -#ifndef WHITEBOX_API_LICENSE_BUILDER_H_ -#define WHITEBOX_API_LICENSE_BUILDER_H_ - -#include -#include -#include - -#include "cdm/protos/license_protocol.pb.h" -#include "crypto_utils/rsa_key.h" - -namespace widevine { - -struct License { - std::vector request; - std::vector message; - std::vector signature; - - // |session_key_| encrypted using the public key. The white-box expects the - // session key to be encrypted, so we use the name "session_key_" (even if it - // is encrypted), we omit the term "encrypted" to match the naming in the API. - std::vector session_key; -}; - -class LicenseBuilder { - public: - // Returns padding data the can be used as |padding| when calling - // AddSigningKey() or AddContentKey(). - static std::vector NoPadding(); - static std::vector PKSC8Padding(); - - // Returns a default signing key that can be used with AddSigningKey(). - static std::vector DefaultSigningKey(); - - LicenseBuilder(); - - void AddSigningKey(const std::vector& key, - const std::vector& padding = NoPadding()); - - // Add a content key so that there is some key in the license. This should not - // be used with AddContentKey(). - void AddStubbedContentKey(); - - void AddContentKey(video_widevine::License_KeyContainer_SecurityLevel level, - const std::vector& key_id, - const std::vector& key, - const std::vector& padding = NoPadding()); - - // The key id will matter as we will need to reference it, but the key won't - // matter since we are only using it as a means to verify that a non-content - // key can't be used as a content key. - void AddOperatorSessionKey(const std::vector& key_id); - - // Gets the serialized license request and response (in components) that would - // have been used in the license exchange. - void Build(const RsaPublicKey& public_key, License* license) const; - - private: - const std::string session_key_ = "0123456789ABCDEF"; - - video_widevine::LicenseRequest request_; - video_widevine::License response_; - std::string serialized_request_; - std::string container_key_; -}; - -} // namespace widevine - -#endif // WHITEBOX_API_LICENSE_BUILDER_H_