131 lines
4.6 KiB
C++
131 lines
4.6 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// Copyright 2019 Google LLC.
|
|
//
|
|
// This software is licensed under the terms defined in the Widevine Master
|
|
// License Agreement. For a copy of this agreement, please contact
|
|
// widevine-licensing@google.com.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "common/client_cert.h"
|
|
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "glog/logging.h"
|
|
#include "absl/memory/memory.h"
|
|
#include "absl/strings/escaping.h"
|
|
#include "common/certificate_client_cert.h"
|
|
#include "common/crypto_util.h"
|
|
#include "common/dual_certificate_client_cert.h"
|
|
#include "common/error_space.h"
|
|
#include "common/keybox_client_cert.h"
|
|
#include "common/random_util.h"
|
|
#include "common/rsa_key.h"
|
|
#include "common/sha_util.h"
|
|
#include "common/signing_key_util.h"
|
|
#include "common/status.h"
|
|
#include "common/wvm_token_handler.h"
|
|
#include "protos/public/drm_certificate.pb.h"
|
|
#include "protos/public/errors.pb.h"
|
|
#include "protos/public/signed_drm_certificate.pb.h"
|
|
|
|
namespace widevine {
|
|
|
|
void KeyboxClientCert::SetPreProvisioningKeys(
|
|
const std::multimap<uint32_t, std::string>& keymap) {
|
|
std::vector<WvmTokenHandler::PreprovKey> keyvector;
|
|
keyvector.reserve(keymap.size());
|
|
for (std::multimap<uint32_t, std::string>::const_iterator it = keymap.begin();
|
|
it != keymap.end(); ++it) {
|
|
std::string key = absl::HexStringToBytes(it->second);
|
|
DCHECK_EQ(key.size(), 16);
|
|
keyvector.push_back(WvmTokenHandler::PreprovKey(it->first, key));
|
|
}
|
|
WvmTokenHandler::SetPreprovKeys(keyvector);
|
|
}
|
|
|
|
bool KeyboxClientCert::IsSystemIdKnown(const uint32_t system_id) {
|
|
return WvmTokenHandler::IsSystemIdKnown(system_id);
|
|
}
|
|
|
|
uint32_t KeyboxClientCert::GetSystemId(const std::string& keybox_bytes) {
|
|
return WvmTokenHandler::GetSystemId(keybox_bytes);
|
|
}
|
|
|
|
Status ClientCert::Create(const DrmRootCertificate* root_certificate,
|
|
const widevine::ClientIdentification& client_id,
|
|
std::unique_ptr<ClientCert>* client_cert) {
|
|
CHECK(client_cert);
|
|
|
|
switch (client_id.type()) {
|
|
case ClientIdentification::KEYBOX:
|
|
return CreateWithKeybox(client_id.token(), client_cert);
|
|
case ClientIdentification::DRM_DEVICE_CERTIFICATE:
|
|
if (!client_id.has_device_credentials()) {
|
|
return CreateWithDrmCertificate(root_certificate, client_id.token(),
|
|
client_cert);
|
|
}
|
|
// Assumes |client_id.token| is the signing cert and
|
|
// |client_id.device_credentials().token| is the encryption cert.
|
|
if (client_id.device_credentials().type() !=
|
|
ClientIdentification::DRM_DEVICE_CERTIFICATE)
|
|
return Status(error_space, INVALID_DRM_CERTIFICATE,
|
|
"unsupported-encryption-certificate");
|
|
|
|
return CreateWithDualDrmCertificates(
|
|
root_certificate, client_id.token(),
|
|
client_id.device_credentials().token(), client_cert);
|
|
default:
|
|
return Status(error_space, error::UNIMPLEMENTED,
|
|
"client-type-not-implemented");
|
|
}
|
|
|
|
return OkStatus();
|
|
}
|
|
|
|
// Creates a Device Certificate based ClientCert. The |client_cert| is a
|
|
// caller supplied unique_ptr to receive the new ClientCert.
|
|
Status ClientCert::CreateWithDrmCertificate(
|
|
const DrmRootCertificate* root_certificate,
|
|
const std::string& drm_certificate,
|
|
std::unique_ptr<ClientCert>* client_cert) {
|
|
CHECK(root_certificate);
|
|
CHECK(client_cert);
|
|
auto device_cert = absl::make_unique<CertificateClientCert>();
|
|
Status status = device_cert->Initialize(root_certificate, drm_certificate);
|
|
if (status.ok()) {
|
|
*client_cert = std::move(device_cert);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
Status ClientCert::CreateWithDualDrmCertificates(
|
|
const DrmRootCertificate* root_certificate,
|
|
const std::string& signing_drm_certificate,
|
|
const std::string& encryption_drm_certificate,
|
|
std::unique_ptr<ClientCert>* client_cert) {
|
|
CHECK(root_certificate);
|
|
CHECK(client_cert);
|
|
auto device_cert = absl::make_unique<DualCertificateClientCert>();
|
|
Status status = device_cert->Initialize(
|
|
root_certificate, signing_drm_certificate, encryption_drm_certificate);
|
|
if (status.ok()) {
|
|
*client_cert = std::move(device_cert);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
Status ClientCert::CreateWithKeybox(const std::string& keybox_token,
|
|
std::unique_ptr<ClientCert>* client_cert) {
|
|
CHECK(client_cert);
|
|
auto kbx_cert = absl::make_unique<KeyboxClientCert>();
|
|
Status status = kbx_cert->Initialize(keybox_token);
|
|
if (status.ok()) {
|
|
*client_cert = std::move(kbx_cert);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
} // namespace widevine
|