Files
provisioning_sdk_source/provisioning_sdk/public/provisioning_engine.cc
2020-09-21 15:54:27 -07:00

162 lines
6.2 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// Copyright 2016 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 "provisioning_sdk/public/provisioning_engine.h"
#include <utility>
#include "glog/logging.h"
#include "absl/memory/memory.h"
#include "common/certificate_type.h"
#include "common/drm_service_certificate.h"
#include "common/rsa_key.h"
#include "provisioning_sdk/internal/provisioning30_session_impl.h"
#include "provisioning_sdk/internal/provisioning_engine_impl.h"
#include "provisioning_sdk/internal/provisioning_session_impl.h"
#include "provisioning_sdk/public/provisioning_session.h"
namespace widevine {
ProvisioningEngine::ProvisioningEngine() {}
ProvisioningEngine::~ProvisioningEngine() {}
ProvisioningStatus ProvisioningEngine::Initialize(
CertificateType certificate_type,
const std::string& service_drm_certificate,
const std::string& service_private_key,
const std::string& service_private_key_passphrase,
const std::string& provisioning_drm_certificate,
const std::string& provisioning_private_key,
const std::string& provisioning_private_key_passphrase,
const std::string& secret_spoid_sauce) {
if (impl_) {
LOG(WARNING) << "ProvisioningEngine is already initialized.";
return INTERNAL_ERROR;
}
std::unique_ptr<ProvisioningEngineImpl> impl(new ProvisioningEngineImpl);
ProvisioningStatus status =
impl->Initialize(certificate_type, service_drm_certificate,
service_private_key, service_private_key_passphrase,
provisioning_drm_certificate, provisioning_private_key,
provisioning_private_key_passphrase, secret_spoid_sauce);
if (status != OK) return status;
impl_ = std::move(impl);
// Register Provisioning 3.0 session factory.
RegisterProtocol(
SignedProvisioningMessage::PROVISIONING_30,
[](const ProvisioningEngineImpl& engine,
std::unique_ptr<ProvisioningSessionImpl>* new_session) {
*new_session = absl::make_unique<Provisioning30SessionImpl>(
engine, engine.oem_device_cert(),
*DrmServiceCertificate::GetDefaultDrmServiceCertificateOrDie()
->private_key());
return OK;
});
return OK;
}
void ProvisioningEngine::RegisterProtocol(
int protocol,
SessionFactory session_factory) {
protocol_registry_[protocol] = std::move(session_factory);
}
ProvisioningStatus ProvisioningEngine::SetCertificateStatusList(
const std::string& certificate_status_list,
uint32_t expiration_period_seconds) {
if (!impl_) return PROVISIONING_ENGINE_UNINITIALIZED;
return impl_->SetCertificateStatusList(certificate_status_list,
expiration_period_seconds);
}
ProvisioningStatus ProvisioningEngine::GenerateDrmIntermediateCertificate(
uint32_t system_id, const std::string& public_key,
std::string* certificate) const {
if (!impl_) return PROVISIONING_ENGINE_UNINITIALIZED;
if (!certificate) {
LOG(WARNING) << "|certificate| should not be a nullptr.";
return INTERNAL_ERROR;
}
return impl_->GenerateDrmIntermediateCertificate(system_id, public_key,
certificate);
}
ProvisioningStatus ProvisioningEngine::AddDrmIntermediateCertificate(
const std::string& intermediate_cert, const std::string& cert_private_key,
const std::string& cert_private_key_passphrase) {
if (!impl_) return PROVISIONING_ENGINE_UNINITIALIZED;
return impl_->AddDrmIntermediateCertificate(
intermediate_cert, cert_private_key, cert_private_key_passphrase);
}
ProvisioningStatus ProvisioningEngine::NewProvisioningSession(
const std::string& device_public_key, const std::string& device_private_key,
std::unique_ptr<ProvisioningSession>* new_session) const {
if (!impl_) return PROVISIONING_ENGINE_UNINITIALIZED;
if (!new_session) {
LOG(WARNING) << "|new_session| should not be a nullptr.";
return INTERNAL_ERROR;
}
const int protocol = 3; // Provisioning 3.0
auto factory = protocol_registry_.find(protocol);
if (factory == protocol_registry_.end()) {
LOG(WARNING) << "Provisioning protocol not supported (" << protocol << ")";
return INVALID_PROTOCOL;
}
std::unique_ptr<ProvisioningSessionImpl> session_impl;
ProvisioningStatus status = (factory->second)(*impl_, &session_impl);
if (status != OK) return status;
status = session_impl->Initialize(device_public_key, device_private_key);
if (status != OK) return status;
*new_session = std::unique_ptr<ProvisioningSession>(
new ProvisioningSession(std::move(session_impl)));
return OK;
}
std::unique_ptr<ProvisioningSession> ProvisioningEngine::NewProvisioningSession(
const std::string& device_public_key, const std::string& device_private_key,
ProvisioningStatus* status) const {
std::unique_ptr<ProvisioningSession> new_session;
*status = NewProvisioningSession(device_public_key,
device_private_key, &new_session);
return new_session;
}
ProvisioningStatus ProvisioningEngine::GenerateDeviceDrmCertificate(
uint32_t system_id, const std::string& public_key,
const std::string& serial_number, std::string* certificate) const {
if (!impl_) return PROVISIONING_ENGINE_UNINITIALIZED;
if (!certificate) {
LOG(WARNING) << "|certificate| should not be a nullptr.";
return INTERNAL_ERROR;
}
// Validate public key. This validation is done here instead of inside
// |impl_->GenerateDeviceDrmCertificate| is because the latter is an internal
// function which expect the input to be already validated.
std::unique_ptr<RsaPublicKey> rsa_public_key(
RsaPublicKey::Create(public_key));
if (!rsa_public_key) return INVALID_DRM_DEVICE_PUBLIC_KEY;
if (serial_number.empty()) return INVALID_SERIAL_NUMBER;
const std::string empty_oem_ca_serial_number;
return impl_->GenerateDeviceDrmCertificate(
system_id, empty_oem_ca_serial_number, public_key, serial_number,
certificate);
}
} // namespace widevine