Remove Dead License Builder Code
This change removes the "license_builder.*" files as they are not used. They were replaced by the "test_license_builder.*" files but were not deleted.
This commit is contained in:
@@ -1,233 +0,0 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#include "api/license_builder.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#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<uint8_t>& plaintext) {
|
||||
AesCbcEncryptor encryptor;
|
||||
encryptor.SetKey(reinterpret_cast<const uint8_t*>(key.data()), key.size());
|
||||
|
||||
std::vector<uint8_t> ciphertext(plaintext.size());
|
||||
CHECK(encryptor.Encrypt(reinterpret_cast<const uint8_t*>(iv.data()),
|
||||
iv.size(), plaintext.data(), plaintext.size(),
|
||||
ciphertext.data()));
|
||||
|
||||
return std::string(ciphertext.begin(), ciphertext.end());
|
||||
}
|
||||
|
||||
std::string DeriveIV(const std::vector<uint8_t>& context) {
|
||||
const std::string context_str(context.begin(), context.end());
|
||||
return crypto_util::DeriveIv(context_str);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
std::vector<uint8_t> LicenseBuilder::NoPadding() {
|
||||
return {};
|
||||
}
|
||||
|
||||
// static
|
||||
std::vector<uint8_t> LicenseBuilder::PKSC8Padding() {
|
||||
return {
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
};
|
||||
}
|
||||
|
||||
// static
|
||||
std::vector<uint8_t> 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<uint8_t>& key,
|
||||
const std::vector<uint8_t>& 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<uint8_t> 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<uint8_t>& key_id,
|
||||
const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& 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<uint8_t> 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<uint8_t>& 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<uint8_t>(serialized_request_.begin(),
|
||||
serialized_request_.end());
|
||||
license->message =
|
||||
std::vector<uint8_t>(message_str.begin(), message_str.end());
|
||||
license->signature =
|
||||
std::vector<uint8_t>(signature_str.begin(), signature_str.end());
|
||||
license->session_key =
|
||||
std::vector<uint8_t>(session_key_str.begin(), session_key_str.end());
|
||||
}
|
||||
} // namespace widevine
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved.
|
||||
|
||||
#ifndef WHITEBOX_API_LICENSE_BUILDER_H_
|
||||
#define WHITEBOX_API_LICENSE_BUILDER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cdm/protos/license_protocol.pb.h"
|
||||
#include "crypto_utils/rsa_key.h"
|
||||
|
||||
namespace widevine {
|
||||
|
||||
struct License {
|
||||
std::vector<uint8_t> request;
|
||||
std::vector<uint8_t> message;
|
||||
std::vector<uint8_t> 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<uint8_t> session_key;
|
||||
};
|
||||
|
||||
class LicenseBuilder {
|
||||
public:
|
||||
// Returns padding data the can be used as |padding| when calling
|
||||
// AddSigningKey() or AddContentKey().
|
||||
static std::vector<uint8_t> NoPadding();
|
||||
static std::vector<uint8_t> PKSC8Padding();
|
||||
|
||||
// Returns a default signing key that can be used with AddSigningKey().
|
||||
static std::vector<uint8_t> DefaultSigningKey();
|
||||
|
||||
LicenseBuilder();
|
||||
|
||||
void AddSigningKey(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& 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<uint8_t>& key_id,
|
||||
const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& 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<uint8_t>& 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_
|
||||
Reference in New Issue
Block a user