280 lines
12 KiB
C++
280 lines
12 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
// Copyright 2017 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.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// DeviceStatusList class header.
|
|
|
|
#ifndef COMMON_DEVICE_STATUS_LIST_H__
|
|
#define COMMON_DEVICE_STATUS_LIST_H__
|
|
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
|
|
#include "absl/synchronization/mutex.h"
|
|
#include "common/hash_algorithm.h"
|
|
#include "common/status.h"
|
|
#include "protos/public/device_certificate_status.pb.h"
|
|
#include "protos/public/provisioned_device_info.pb.h"
|
|
|
|
namespace widevine {
|
|
|
|
class ClientCert;
|
|
// Manages the certificate status of devices. The list of
|
|
// DeviceCertificateStatus is provided by the DRM server. Each license
|
|
// request is checked to ensure the certificate in the request is valid and
|
|
// not revoked. Also checks to see if the intermediate certificates were
|
|
// updated where the system Id is the same, but the serial number changes.
|
|
// This case should cause the clients to re-provision.
|
|
class DeviceStatusList {
|
|
public:
|
|
// Returns a pointer to a singleton DeviceStatusList.
|
|
static DeviceStatusList* Instance();
|
|
|
|
DeviceStatusList();
|
|
|
|
DeviceStatusList(const DeviceStatusList&) = delete;
|
|
DeviceStatusList& operator=(const DeviceStatusList&) = delete;
|
|
|
|
virtual ~DeviceStatusList();
|
|
|
|
// Takes |serialized_device_certificate_status_list| and copies to an
|
|
// internal map of device certificate status list. The internal map is used
|
|
// to verify a device was not revoked. Returns true is the list was
|
|
// successfully parsed.
|
|
Status UpdateStatusList(
|
|
const std::string& root_certificate_public_key,
|
|
const std::string& serialized_device_certificate_status_list,
|
|
HashAlgorithm hash_algorithm, const std::string& signature,
|
|
uint32_t expiration_period_seconds);
|
|
void set_allow_unknown_devices(bool flag) { allow_unknown_devices_ = flag; }
|
|
bool allow_unknown_devices() const { return allow_unknown_devices_; }
|
|
void set_allow_test_only_devices(bool allow) {
|
|
allow_test_only_devices_ = allow;
|
|
}
|
|
bool allow_test_only_devices() const { return allow_test_only_devices_; }
|
|
|
|
// Checks the device status list and handles the case when a TEST_ONLY device
|
|
// made the request. Returns one of
|
|
// OK
|
|
// UNSUPPORTED_SYSTEM_ID
|
|
// INVALID_DRM_CERTIFICATE
|
|
// DRM_DEVICE_CERTIFICATE_REVOKED
|
|
// DRM_DEVICE_CERTIFICATE_UNKNOWN
|
|
// DEVELOPMENT_CERTIFICATE_NOT_ALLOWED
|
|
// |provider| is the service provider making the license request.
|
|
// If status is OK, a copy of the device certificate status is copied
|
|
// into |device_certificate_status|. Caller owns |device_certificate_status|
|
|
// and it must not be null.
|
|
Status GetCertStatus(
|
|
const ClientCert& client_cert, const std::string& make,
|
|
const std::string& provider, bool allow_revoked_system_id,
|
|
widevine::DeviceCertificateStatus* device_certificate_status);
|
|
// Returns true if the pre-provisioning key or certificate for the specified
|
|
// system ID are active (not disallowed or revoked).
|
|
bool IsSystemIdActive(uint32_t system_id);
|
|
|
|
// Returns true if the system ID
|
|
// Returns true is a ProvisionedDeviceInfo exist based on <client_cert>.
|
|
// Caller owns <device_info> and it must not be null.
|
|
bool GetDeviceInfo(const ClientCert& client_cert,
|
|
widevine::ProvisionedDeviceInfo* device_info);
|
|
|
|
// Returns true if device certificate status list contains revoked_identifiers
|
|
// with specific |system_id|.
|
|
// Caller owns <revoked_identifiers> and it must not be null.
|
|
bool GetRevokedIdentifiers(
|
|
uint32_t system_id,
|
|
DeviceCertificateStatus::RevokedIdentifiers* revoked_identifiers);
|
|
|
|
// Returns the current POSIX time.
|
|
virtual uint32_t GetCurrentTime() const;
|
|
|
|
// Enable delivery of licenses to revoked client devices. |system_id_list| is
|
|
// a comma separated list of systems Ids to allow even if revoked.
|
|
virtual void AllowRevokedDevices(const std::string& system_id_list);
|
|
|
|
// Enable delivery of licenses to TEST_ONLY client devices. |device_list| is
|
|
// a comma separated list of devices to allow even if the device state is
|
|
// TEST_ONLY. Each device is specified by a colon separated system_id and
|
|
// manufacturer. If the manufacturer is not specified, all manufacturers for
|
|
// that system_id are allowed.
|
|
// 'device_list' is expected to be of the format <device>,<device>..., and
|
|
// each 'device' will contain a 'system_id' and 'manufacturer' OR will contain
|
|
// only a 'system_id'.
|
|
// 'device' is expected to be of the format <system_id>:<manufacturer> OR
|
|
// of the format <system_id>:
|
|
// Example usage:
|
|
// const std::string device_list = "4121:LG,7912:*"
|
|
// AllowTestOnlyDevicesByMake(device_list_by_make);
|
|
virtual void AllowTestOnlyDevicesByMake(
|
|
const std::string& device_list_by_make);
|
|
|
|
// Same as above, except by providers instead of by manufacturers.
|
|
// Example usage:
|
|
// const std::string device_list = "4121:YouTube,4121:AndroidVideo"
|
|
// AllowTestOnlyDevicesByProvider(device_list);
|
|
virtual void AllowTestOnlyDevicesByProvider(
|
|
const std::string& device_list_by_provider);
|
|
|
|
// A comma separated list of DRM Certificate Serial Numbers that are revoked.
|
|
virtual void RevokedDrmCertificateSerialNumbers(
|
|
const std::string& drm_certificate_serial_numbers);
|
|
|
|
// Return true, if the specified |device_certificate_serial_number| was
|
|
// revoked ... else, false.
|
|
bool IsDrmCertificateRevoked(
|
|
const std::string& device_certificate_serial_number);
|
|
|
|
// Returns OK if |system_id| was found in the device certificate status list
|
|
// and |device_certificate_status| is populated. If |system_id| is not found,
|
|
// this call returns an error.
|
|
virtual Status GetDeviceCertificateStatusBySystemId(
|
|
uint32_t system_id, DeviceCertificateStatus* device_certificate_status);
|
|
|
|
// Parses the serialized certificate status list and the signature from the
|
|
// service_response. The service_response is the JSON payload that comes
|
|
// in the response to a certificate status list request. Both the legacy
|
|
// format and the newer SignedDeviceInfo format are supported.
|
|
//
|
|
// |service_response| is the response provided from the Widevine API that
|
|
// produces the certificate list. The response can be in one of a few
|
|
// formats:
|
|
// 1) The JSON response from the legacy API.
|
|
// 2) The Base 64 encoded payload within the JSON response that contains
|
|
// the serialized certificate list (Web safe or regular base64).
|
|
// 3) The raw bytes of the serialized PublishedDevices proto returned from
|
|
// the new Widevine API that generates the serialized certificate list.
|
|
// The |certificate_status_list| is the deserialized list from the
|
|
// service_response.
|
|
// The |serialized_certificate_status_list| is the binary serialized status
|
|
// list. This is an out parameter which allows the caller to verify the
|
|
// serialized proto against the |signature|.
|
|
// The |signature| is the signature of the serialized_certificate_status_list
|
|
// using RSASSA-PSS signed with the root certificate private key.
|
|
// The |hash_algorithm| is the hash algorithm used in signature.
|
|
// Returns WvPLStatus - Status::OK if success, else error.
|
|
static Status DetermineAndDeserializeServiceResponse(
|
|
const std::string& service_response,
|
|
DeviceCertificateStatusList* certificate_status_list,
|
|
std::string* serialized_certificate_status_list,
|
|
HashAlgorithm* hash_algorithm, std::string* signature);
|
|
|
|
/**
|
|
* Constructs signed device certificate status list request string.
|
|
*
|
|
* @param signed_device_certificate_status_list_request
|
|
* @param version
|
|
* @return Status - Status::OK if success, else error.
|
|
*/
|
|
static Status GenerateSignedDeviceCertificateStatusListRequest(
|
|
const std::string& version,
|
|
const std::string& serialized_service_certificate,
|
|
std::string* signed_device_certificate_status_list_request);
|
|
|
|
// Returns true if the system ID is allowed to be revoked.
|
|
// Caller owns |system_id|. They must not be null.
|
|
bool IsRevokedSystemIdAllowed(uint32_t system_id);
|
|
|
|
// Returns true if the device, which is identified by system_id and
|
|
// device_manufacturer, is present in |allowed_test_only_devices_by_make_|.
|
|
bool IsTestOnlyDeviceAllowedByMake(uint32_t system_id,
|
|
const std::string& device_manufacturer);
|
|
|
|
// Returns true if the device, which is identified by system_id and
|
|
// provider, is present in |allowed_test_only_devices_by_provider_|.
|
|
bool IsTestOnlyDeviceAllowedByProvider(uint32_t system_id,
|
|
const std::string& provider);
|
|
|
|
private:
|
|
friend class DeviceStatusListTest;
|
|
|
|
/**
|
|
* Parses the serialized legacy device certificate status list and signature.
|
|
* The certificate_provisioning_service_response is the JSON payload that
|
|
* comes in the response to a certificate status list request.
|
|
*
|
|
* @param legacy_certificate_provisioning_service_response
|
|
* @param serialized_certificate_status_list
|
|
* @param hash_algorithm
|
|
* @param signature
|
|
* @return WvPLStatus - Status::OK if success, else error.
|
|
*/
|
|
static Status ExtractLegacyDeviceList(
|
|
const std::string& raw_certificate_provisioning_service_response,
|
|
std::string* serialized_certificate_status_list,
|
|
HashAlgorithm* hash_algorithm, std::string* signature);
|
|
|
|
/**
|
|
* Parses the serialized published devices response.
|
|
* The published_devices_info_response is the JSON payload that comes in the
|
|
* response to a PublishedDevices request.
|
|
*
|
|
* @param published_devices_response the serialized PublishedDevices proto
|
|
* containing the certificate status list.
|
|
* @param serialized_certificate_status_list
|
|
* @param hash_algorithm
|
|
* @param signature
|
|
* @return WvPLStatus - Status::OK if success, else error.
|
|
*/
|
|
static Status ExtractPublishedDevicesInfo(
|
|
const std::string& serialized_published_devices,
|
|
std::string* serialized_certificate_status_list,
|
|
HashAlgorithm* hash_algorithm, std::string* signature);
|
|
|
|
/**
|
|
* Returns a |serialized_device_certificate_status_list| in its output
|
|
* parameter by parsing |serialized_signed_device_certificate_status_list|
|
|
* returned from Widevine Certificate Provisioning Server.
|
|
*
|
|
* @param serialized_signed_device_certificate_status_list
|
|
* @param serialized_device_certificate_status_list
|
|
* @param hash_algorithm
|
|
* @return Status - Status::OK if success, else error.
|
|
*/
|
|
static Status ParseLegacySignedDeviceCertificateStatusList(
|
|
const std::string& serialized_signed_device_certificate_status_list,
|
|
std::string* serialized_device_certificate_status_list,
|
|
HashAlgorithm* hash_algorithm, std::string* signature);
|
|
|
|
virtual size_t allowed_test_only_devices_by_make_size() {
|
|
absl::ReaderMutexLock lock(&allowed_test_only_devices_mutex_);
|
|
return allowed_test_only_devices_by_make_.size();
|
|
}
|
|
|
|
virtual size_t allowed_test_only_devices_by_provider_size() {
|
|
absl::ReaderMutexLock lock(&allowed_test_only_devices_mutex_);
|
|
return allowed_test_only_devices_by_provider_.size();
|
|
}
|
|
|
|
mutable absl::Mutex status_map_lock_;
|
|
// Key is the system id for the device.
|
|
std::map<uint32_t, widevine::DeviceCertificateStatus> device_status_map_
|
|
ABSL_GUARDED_BY(status_map_lock_);
|
|
uint32_t creation_time_seconds_ = 0;
|
|
uint32_t expiration_period_seconds_ = 0;
|
|
bool allow_unknown_devices_ = false;
|
|
bool allow_test_only_devices_ = false;
|
|
// Contains the list of system_id values that are allowed to succeed even if
|
|
// revoked.
|
|
std::vector<uint32_t> allowed_revoked_devices_;
|
|
mutable absl::Mutex allowed_test_only_devices_mutex_;
|
|
// Contains a map of 'system_id' to 'manufacturer'. If manufacturer value is
|
|
// "*", any manufacturer using that system_id is allowed.
|
|
std::multimap<uint32_t, std::string> allowed_test_only_devices_by_make_
|
|
ABSL_GUARDED_BY(allowed_test_only_devices_mutex_);
|
|
// Contains a map of 'system_id' to 'provider'. If provider value is "*", any
|
|
// provider using that system_id is allowed.
|
|
std::multimap<uint32_t, std::string> allowed_test_only_devices_by_provider_
|
|
ABSL_GUARDED_BY(allowed_test_only_devices_mutex_);
|
|
// Revoked DRM certificate serial numbers.
|
|
std::set<std::string> revoked_drm_certificate_serial_numbers_;
|
|
};
|
|
|
|
} // namespace widevine
|
|
#endif // COMMON_DEVICE_STATUS_LIST_H__
|