217 lines
9.5 KiB
C++
217 lines
9.5 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.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ProvisioningEngine internal implementation. This class is thread-safe.
|
|
|
|
#ifndef PROVISIONING_SDK_INTERNAL_PROVISIONING_ENGINE_IMPL_H_
|
|
#define PROVISIONING_SDK_INTERNAL_PROVISIONING_ENGINE_IMPL_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include <cstdint>
|
|
#include "absl/base/thread_annotations.h"
|
|
#include "absl/synchronization/mutex.h"
|
|
#include "common/certificate_type.h"
|
|
#include "common/drm_root_certificate.h"
|
|
#include "common/rsa_key.h"
|
|
#include "provisioning_sdk/internal/oem_device_cert.h"
|
|
#include "provisioning_sdk/public/provisioning_status.h"
|
|
#include "protos/public/certificate_provisioning.pb.h"
|
|
#include "protos/public/device_certificate_status.pb.h"
|
|
#include "protos/public/drm_certificate.pb.h"
|
|
#include "protos/public/provisioned_device_info.pb.h"
|
|
#include "protos/public/signed_drm_certificate.pb.h"
|
|
|
|
namespace widevine {
|
|
|
|
class DrmRootCertificate;
|
|
class ProvisioningSession;
|
|
class RsaPublicKey;
|
|
|
|
class ProvisioningEngineImpl {
|
|
public:
|
|
ProvisioningEngineImpl();
|
|
virtual ~ProvisioningEngineImpl();
|
|
|
|
// Initializes the provisioning engine with required credentials.
|
|
// * |certificate_type| indicates which type of certificate chains will be
|
|
// used for device provisioning via this engine.
|
|
// * |drm_service_certificate| is a Google-generated certificate used to
|
|
// authenticate the service provider for purposes of user privacy.
|
|
// * |service_private_key| is the encrypted PKCS#8 private RSA key
|
|
// corresponding to the service certificate.
|
|
// * |service_private_key_passphrase| is the password required to decrypt
|
|
// |service_private_key|, if any.
|
|
// * |provisioning_drm_certificate| is a Google-generated certificate used to
|
|
// sign intermediate DRM certificates.
|
|
// * |provisioning_private_key| is the encrypted PKCS#8 private RSA key
|
|
// corresponding to the provisioning certificate.
|
|
// * |provisioning_private_key_passphrase| is the password required to
|
|
// decrypt |provisioning_private_key|, if any.
|
|
// * |secret_spoid_sauce| is a stable secret used as a factor in the
|
|
// derivation of Stable Per-Origin IDentifiers.
|
|
// * Returns OK on success, or an appropriate error status code otherwise.
|
|
ProvisioningStatus Initialize(
|
|
CertificateType certificate_type,
|
|
const std::string& drm_service_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);
|
|
|
|
// Set the certificate status list for this engine.
|
|
// * |certificate_status_list| is a certificate status list generated by the
|
|
// Widevine Provisioning Service.
|
|
// * |expiration_period| is the number of seconds until the
|
|
// |certificate_status_list| expires after its creation time
|
|
// (creation_time_seconds). Zero means it will never expire.
|
|
// * Returns OK on success, or an appropriate error status code otherwise.
|
|
ProvisioningStatus SetCertificateStatusList(
|
|
const std::string& certificate_status_list,
|
|
uint32_t expiration_period_seconds);
|
|
|
|
// Generate an intermediate DRM certificate.
|
|
// * |system_id| is the Widevine system ID for the type of device.
|
|
// * |public_key| is a DER-encoded PKCS#1.5 RSAPublicKey message which will
|
|
// be embedded in the generated certificate.
|
|
// * |certificate| will contain the new intermediate certificate, upon
|
|
// successful return.
|
|
// * Returns OK on success, or an appropriate error status code otherwise.
|
|
// NOTE: The generated certificate and associated private key should be stored
|
|
// securely to be reused. They should also be propagated to all
|
|
// engines, including this one, by invoking
|
|
// |AddIntermediatedrmcertificate| on all active ProvisioningEngine(s).
|
|
ProvisioningStatus GenerateDrmIntermediateCertificate(
|
|
uint32_t system_id, const std::string& public_key,
|
|
std::string* certificate) const;
|
|
|
|
// Add an intermediate DRM certificate to the provisioning engine. This is
|
|
// usually done once for each supported device type.
|
|
// * |intermediate_cert| is the intermediate DRM certificate to be added.
|
|
// * |cert_private_key| is a PKCS#8 private key corresponding to
|
|
// |intermediate_cert|.
|
|
// * |cert_private_key_passphrase| is the passphrase for cert_private_key,
|
|
// if any.
|
|
// * Returns OK on success, or an appropriate error status code otherwise.
|
|
ProvisioningStatus AddDrmIntermediateCertificate(
|
|
const std::string& intermediate_cert, const std::string& cert_private_key,
|
|
const std::string& cert_private_key_passphrase);
|
|
|
|
// Generate a new device DRM certificate to be provisioned.
|
|
// * |system_id| is the Widevine system ID for the type of device being
|
|
// provisioned.
|
|
// * |oem_ca_serial_number| is the oem serial number for the type of device
|
|
// being provisioned. ProvisioningEngine uses |system_id| and
|
|
// |oem_ca_serial_number| to determine if the device is valid, e.g. whether
|
|
// it has been revoked. |oem_ca_serial_number| can be empty if we do not
|
|
// care about serial number matches or not.
|
|
// * |public_key| is a DER-encoded PKCS#1.5 RSAPublicKey message which will
|
|
// be embedded in the generated certificate.
|
|
// * |certificate_serial_number| is a binary std::string to be used as the
|
|
// generated DRM certificate serial number.
|
|
// * |certificate| will contain, upon successful return the generated
|
|
// certificate.
|
|
// * Returns OK on success, or an appropriate error status code otherwise.
|
|
// Virtual for mocking.
|
|
virtual ProvisioningStatus GenerateDeviceDrmCertificate(
|
|
uint32_t system_id, const std::string& oem_ca_serial_number,
|
|
const std::string& public_key,
|
|
const std::string& certificate_serial_number,
|
|
std::string* certificate) const;
|
|
|
|
// Internal version of the method above. Allows specifying |provider_id|.
|
|
virtual ProvisioningStatus GenerateProviderDeviceDrmCertificate(
|
|
uint32_t system_id, const std::string& oem_ca_serial_number,
|
|
const std::string& provider_id, const std::string& public_key,
|
|
const std::string& certificate_serial_number,
|
|
std::string* certificate) const;
|
|
|
|
// Get the device info for the given |system_id|.
|
|
virtual std::shared_ptr<ProvisionedDeviceInfo> GetDeviceInfo(
|
|
uint32_t system_id) const;
|
|
|
|
// Encrypt, store, and sign context/state data.
|
|
virtual ProvisioningStatus StoreContext(
|
|
const std::string& context_data,
|
|
SignedProvisioningContext* context) const;
|
|
|
|
// Verify, decrypt, and retrieve context/state data.
|
|
virtual ProvisioningStatus RetrieveContext(
|
|
const SignedProvisioningContext& context,
|
|
std::string* context_data) const;
|
|
|
|
const DrmRootCertificate* drm_root_certificate() const {
|
|
return drm_root_certificate_.get();
|
|
}
|
|
const OemDeviceCert& oem_device_cert() const { return oem_device_cert_; }
|
|
const std::string& secret_spoid_sauce() const { return secret_spoid_sauce_; }
|
|
|
|
private:
|
|
friend class ProvisioningEngineImplTest;
|
|
friend class ProvisioningEngineImplProvTest;
|
|
friend class Sigma101ProvisioningSessionImplTest;
|
|
friend class Sigma210ProvisioningSessionImplTest;
|
|
|
|
ProvisioningEngineImpl(const ProvisioningEngineImpl&) = delete;
|
|
ProvisioningEngineImpl& operator=(const ProvisioningEngineImpl&) = delete;
|
|
|
|
// Check device status.
|
|
// If |oem_ca_serial_number| is empty, we do not care whether serial number
|
|
// matches or not.
|
|
// * Returns OK on success, or an appropriate error status code otherwise.
|
|
ProvisioningStatus CheckDeviceStatus(
|
|
uint32_t system_id, const std::string& oem_ca_serial_number) const;
|
|
|
|
// Inject DRM root certificate for testing.
|
|
void set_drm_root_certificate(
|
|
std::unique_ptr<DrmRootCertificate> drm_root_certificate) {
|
|
drm_root_certificate_ = std::move(drm_root_certificate);
|
|
}
|
|
|
|
// Inject rsa_key_factory for testing.
|
|
void set_rsa_key_factory(std::unique_ptr<RsaKeyFactory> rsa_key_factory) {
|
|
rsa_key_factory_ = std::move(rsa_key_factory);
|
|
}
|
|
|
|
std::unique_ptr<RsaKeyFactory> rsa_key_factory_;
|
|
std::unique_ptr<DrmRootCertificate> drm_root_certificate_;
|
|
std::unique_ptr<RsaPublicKey> drm_root_public_key_;
|
|
SignedDrmCertificate signed_provisioning_cert_;
|
|
std::unique_ptr<RsaPublicKey> provisioning_public_key_;
|
|
std::unique_ptr<RsaPrivateKey> provisioning_private_key_;
|
|
std::string secret_spoid_sauce_;
|
|
std::string context_encryption_key_;
|
|
std::string context_mac_key_;
|
|
OemDeviceCert oem_device_cert_;
|
|
|
|
mutable absl::Mutex cert_status_mutex_;
|
|
// POSIX time, in seconds, when the list would be expired.
|
|
uint32_t certificate_expiration_seconds_utc_
|
|
ABSL_GUARDED_BY(cert_status_mutex_);
|
|
// Maps with system_id as the key.
|
|
std::map<uint32_t, DeviceCertificateStatus> certificate_status_map_
|
|
ABSL_GUARDED_BY(cert_status_mutex_);
|
|
struct IntermediateCertificateInfo {
|
|
SignedDrmCertificate signed_drm_certificate;
|
|
std::shared_ptr<ProvisionedDeviceInfo> device_info;
|
|
std::shared_ptr<RsaPrivateKey> private_key;
|
|
};
|
|
std::map<uint32_t, IntermediateCertificateInfo> intermediate_certs_info_;
|
|
};
|
|
|
|
} // namespace widevine
|
|
|
|
#endif // PROVISIONING_SDK_INTERNAL_PROVISIONING_ENGINE_IMPL_H_
|