//////////////////////////////////////////////////////////////////////////////// // 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 #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 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* new_session) { *new_session = absl::make_unique( 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* 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 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( new ProvisioningSession(std::move(session_impl))); return OK; } std::unique_ptr ProvisioningEngine::NewProvisioningSession( const std::string& device_public_key, const std::string& device_private_key, ProvisioningStatus* status) const { std::unique_ptr 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 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