Files
provisioning_sdk_source/common/device_status_list.h
2020-09-21 15:54:27 -07:00

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__