Provisioning SDK release: 16.3.2
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
intermediate_passphrase
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
provider_passphrase
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Twas bryllyg, and ye slythy toves
|
|
||||||
Did gyre and gymble in ye wabe:
|
|
||||||
All mimsy were ye borogoves;
|
|
||||||
And ye mome raths outgrabe.
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
service_passphrase
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,113 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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 <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "provisioning_sdk/public/certificate_type.h"
|
|
||||||
#include "provisioning_sdk/public/provisioning_engine.h"
|
|
||||||
#include "provisioning_sdk/public/provisioning_session.h"
|
|
||||||
#include "provisioning_sdk/public/provisioning_status.h"
|
|
||||||
|
|
||||||
using widevine::OK;
|
|
||||||
using widevine::ProvisioningEngine;
|
|
||||||
using widevine::ProvisioningSession;
|
|
||||||
using widevine::kCertTesting;
|
|
||||||
|
|
||||||
std::string GetContents(const std::string& file_name) {
|
|
||||||
if (file_name.empty()) {
|
|
||||||
std::cout << "File name is empty." << std::endl;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
FILE* file = fopen(file_name.c_str(), "r");
|
|
||||||
if (!file) {
|
|
||||||
std::cout << "Unable to open file " << file_name << std::endl;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
std::string contents;
|
|
||||||
const size_t kReadSize = 0x1000;
|
|
||||||
char buffer[kReadSize];
|
|
||||||
while (true) {
|
|
||||||
size_t size_read = fread(buffer, sizeof(char), kReadSize, file);
|
|
||||||
if (size_read == 0) break;
|
|
||||||
contents.append(buffer, size_read);
|
|
||||||
}
|
|
||||||
if (!feof(file)) std::cout << "Failed to read all file contents.";
|
|
||||||
fclose(file);
|
|
||||||
return contents;;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
ProvisioningEngine engine;
|
|
||||||
|
|
||||||
// Call Initialize to setup the engine.
|
|
||||||
if (engine.Initialize(
|
|
||||||
kCertTesting, GetContents("example_data/service.cert"),
|
|
||||||
GetContents("example_data/service.encrypted.private"),
|
|
||||||
GetContents("example_data/service.passphrase"),
|
|
||||||
GetContents("example_data/provisioner.cert"),
|
|
||||||
GetContents("example_data/provisioner.encrypted.private"),
|
|
||||||
GetContents("example_data/provisioner.passphrase"),
|
|
||||||
GetContents("example_data/provisioner.spoid_secret")) != OK) {
|
|
||||||
std::cout << "Failed to initialize." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Certificate status list should be updated periodically. In this example,
|
|
||||||
// we'll just set it once. Note that in practice, the expiration should not be
|
|
||||||
// 10 years long.
|
|
||||||
if (engine.SetCertificateStatusList(
|
|
||||||
GetContents("example_data/certificate_list"),
|
|
||||||
10 * 365 * 24 * 3600 /* 10 years */) != OK) {
|
|
||||||
std::cout << "Failed to set certificate status list." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before being able to process provisioning request for a specific type of
|
|
||||||
// device, we need to generate the intermediate certificate and add it to the
|
|
||||||
// engine first. This only needs to be done once for every new type of device.
|
|
||||||
const int kSystemId = 2001;
|
|
||||||
std::string certificate;
|
|
||||||
if (engine.GenerateDrmIntermediateCertificate(
|
|
||||||
kSystemId, GetContents("example_data/intermediate.public"),
|
|
||||||
&certificate) != OK) {
|
|
||||||
std::cout << "Failed to generate intermediate certificate." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (engine.AddDrmIntermediateCertificate(
|
|
||||||
certificate,
|
|
||||||
GetContents("example_data/intermediate.encrypted.private"),
|
|
||||||
GetContents("example_data/intermediate.passphrase")) != OK) {
|
|
||||||
std::cout << "Failed to add intermediate certificate." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In order to process provisioning request, we need to create a session. The
|
|
||||||
// public/private key pairs should be unique - they cannot be reused if the
|
|
||||||
// message is processed successfully; if ProcessMessage fails, they can be
|
|
||||||
// reused on another session.
|
|
||||||
std::unique_ptr<ProvisioningSession> session;
|
|
||||||
if (engine.NewProvisioningSession(GetContents("example_data/user.public"),
|
|
||||||
GetContents("example_data/user.private"),
|
|
||||||
&session) != OK) {
|
|
||||||
std::cout << "Failed to create session." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
std::string response;
|
|
||||||
bool done;
|
|
||||||
if (session->ProcessMessage(GetContents("example_data/message"), &response,
|
|
||||||
&done) != OK) {
|
|
||||||
std::cout << "Failed to process message." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
std::cout << "Message processed successfully.";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,99 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Public protocol buffer definitions for Widevine Device Certificate
|
|
||||||
// Provisioning protocol.
|
|
||||||
|
|
||||||
syntax = "proto2";
|
|
||||||
|
|
||||||
package widevine;
|
|
||||||
option java_package = "com.google.video.widevine.protos";
|
|
||||||
|
|
||||||
import "protos/public/client_identification.proto";
|
|
||||||
|
|
||||||
// ProvisioningOptions specifies the type of certificate to specify and
|
|
||||||
// in the case of X509 certificates, the certificate authority to use.
|
|
||||||
message ProvisioningOptions {
|
|
||||||
enum CertificateType {
|
|
||||||
WIDEVINE_DRM = 0; // Default. The original certificate type.
|
|
||||||
X509 = 1; // X.509 certificate.
|
|
||||||
}
|
|
||||||
|
|
||||||
optional CertificateType certificate_type = 1 [default = WIDEVINE_DRM];
|
|
||||||
|
|
||||||
// Contains the application-specific name used to identify the certificate
|
|
||||||
// authority for signing the generated certificate. This is required iff the
|
|
||||||
// certificate type is X509.
|
|
||||||
optional string certificate_authority = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provisioning request sent by client devices to provisioning service.
|
|
||||||
message ProvisioningRequest {
|
|
||||||
oneof clear_or_encrypted_client_id {
|
|
||||||
// Device root of trust and other client identification. Required.
|
|
||||||
ClientIdentification client_id = 1;
|
|
||||||
EncryptedClientIdentification encrypted_client_id = 5;
|
|
||||||
}
|
|
||||||
// Nonce value used to prevent replay attacks. Required.
|
|
||||||
optional bytes nonce = 2;
|
|
||||||
// Options for type of certificate to generate. Optional.
|
|
||||||
optional ProvisioningOptions options = 3;
|
|
||||||
oneof spoid_param {
|
|
||||||
// Stable identifier, unique for each device + application (or origin).
|
|
||||||
// To be deprecated.
|
|
||||||
bytes stable_id = 4;
|
|
||||||
// Service provider ID from the service certificate's provider_id field.
|
|
||||||
// Preferred parameter.
|
|
||||||
bytes provider_id = 6;
|
|
||||||
// Client-generated stable per-origin identifier to be copied directly
|
|
||||||
// to the client certificate serial number.
|
|
||||||
bytes spoid = 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provisioning response sent by the provisioning server to client devices.
|
|
||||||
// This message is used for both regular Widevine DRM certificates and for
|
|
||||||
// application-specific X.509 certificates.
|
|
||||||
message ProvisioningResponse {
|
|
||||||
// AES-128 encrypted device private RSA key. PKCS#1 ASN.1 DER-encoded.
|
|
||||||
// Required. For X.509 certificates, the private RSA key may also include
|
|
||||||
// a prefix as specified by private_key_prefix in the X509CertificateMetadata
|
|
||||||
// proto message.
|
|
||||||
optional bytes device_rsa_key = 1;
|
|
||||||
// Initialization vector used to encrypt device_rsa_key. Required.
|
|
||||||
optional bytes device_rsa_key_iv = 2;
|
|
||||||
// For Widevine DRM certificates, this contains the serialized
|
|
||||||
// SignedDrmDeviceCertificate. For X.509 certificates, this contains the PEM
|
|
||||||
// encoded X.509 certificate. Required.
|
|
||||||
optional bytes device_certificate = 3;
|
|
||||||
// Nonce value matching nonce in ProvisioningRequest. Required.
|
|
||||||
optional bytes nonce = 4;
|
|
||||||
// Key used to wrap device_rsa_key when DRM provisioning an OEM factory
|
|
||||||
// provisioned device. Encrypted with the device OEM public key using
|
|
||||||
// RSA-OAEP.
|
|
||||||
optional bytes wrapping_key = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialized ProvisioningRequest or ProvisioningResponse signed with
|
|
||||||
// The message authentication key.
|
|
||||||
message SignedProvisioningMessage {
|
|
||||||
enum ProtocolVersion {
|
|
||||||
PROVISIONING_20 = 2; // Keybox factory-provisioned devices.
|
|
||||||
PROVISIONING_30 = 3; // OEM certificate factory-provisioned devices.
|
|
||||||
INTEL_SIGMA_101 = 101; // Intel Sigma 1.0.1 protocol.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialized ProvisioningRequest or ProvisioningResponse. Required.
|
|
||||||
optional bytes message = 1;
|
|
||||||
// HMAC-SHA256 (Keybox) or RSASSA-PSS (OEM) signature of message. Required.
|
|
||||||
optional bytes signature = 2;
|
|
||||||
// Version number of provisioning protocol.
|
|
||||||
optional ProtocolVersion protocol_version = 3 [default = PROVISIONING_20];
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// ClientIdentification messages used by provisioning and license protocols.
|
|
||||||
|
|
||||||
syntax = "proto2";
|
|
||||||
|
|
||||||
package widevine;
|
|
||||||
option java_package = "com.google.video.widevine.protos";
|
|
||||||
|
|
||||||
option java_outer_classname = "ClientIdentificationProtos";
|
|
||||||
|
|
||||||
// ClientIdentification message used to authenticate the client device.
|
|
||||||
message ClientIdentification {
|
|
||||||
enum TokenType {
|
|
||||||
KEYBOX = 0;
|
|
||||||
DRM_DEVICE_CERTIFICATE = 1;
|
|
||||||
REMOTE_ATTESTATION_CERTIFICATE = 2;
|
|
||||||
OEM_DEVICE_CERTIFICATE = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message NameValue {
|
|
||||||
optional string name = 1;
|
|
||||||
optional string value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Capabilities which not all clients may support. Used for the license
|
|
||||||
// exchange protocol only.
|
|
||||||
message ClientCapabilities {
|
|
||||||
enum HdcpVersion {
|
|
||||||
HDCP_NONE = 0;
|
|
||||||
HDCP_V1 = 1;
|
|
||||||
HDCP_V2 = 2;
|
|
||||||
HDCP_V2_1 = 3;
|
|
||||||
HDCP_V2_2 = 4;
|
|
||||||
HDCP_NO_DIGITAL_OUTPUT = 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CertificateKeyType {
|
|
||||||
RSA_2048 = 0;
|
|
||||||
RSA_3072 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional bool client_token = 1 [default = false];
|
|
||||||
optional bool session_token = 2 [default = false];
|
|
||||||
optional bool video_resolution_constraints = 3 [default = false];
|
|
||||||
optional HdcpVersion max_hdcp_version = 4 [default = HDCP_NONE];
|
|
||||||
optional uint32 oem_crypto_api_version = 5;
|
|
||||||
// Client has hardware support for protecting the usage table, such as
|
|
||||||
// storing the generation number in secure memory. For Details, see:
|
|
||||||
// https://docs.google.com/document/d/1Mm8oB51SYAgry62mEuh_2OEkabikBiS61kN7HsDnh9Y/edit#heading=h.xgjl2srtytjt
|
|
||||||
optional bool anti_rollback_usage_table = 6 [default = false];
|
|
||||||
// The client shall report |srm_version| if available.
|
|
||||||
optional uint32 srm_version = 7;
|
|
||||||
// A device may have SRM data, and report a version, but may not be capable
|
|
||||||
// of updating SRM data.
|
|
||||||
optional bool can_update_srm = 8 [default = false];
|
|
||||||
repeated CertificateKeyType supported_certificate_key_type = 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type of factory-provisioned device root of trust. Optional.
|
|
||||||
optional TokenType type = 1 [default = KEYBOX];
|
|
||||||
// Factory-provisioned device root of trust. Required.
|
|
||||||
optional bytes token = 2;
|
|
||||||
// Optional client information name/value pairs.
|
|
||||||
repeated NameValue client_info = 3;
|
|
||||||
// Client token generated by the content provider. Optional.
|
|
||||||
optional bytes provider_client_token = 4;
|
|
||||||
// Number of licenses received by the client to which the token above belongs.
|
|
||||||
// Only present if client_token is specified.
|
|
||||||
optional uint32 license_counter = 5;
|
|
||||||
// List of non-baseline client capabilities.
|
|
||||||
optional ClientCapabilities client_capabilities = 6;
|
|
||||||
// Serialized VmpData message. Optional.
|
|
||||||
optional bytes vmp_data = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptedClientIdentification message used to hold ClientIdentification
|
|
||||||
// messages encrypted for privacy purposes.
|
|
||||||
message EncryptedClientIdentification {
|
|
||||||
// Provider ID for which the ClientIdentifcation is encrypted (owner of
|
|
||||||
// service certificate).
|
|
||||||
optional string provider_id = 1;
|
|
||||||
// Serial number for the service certificate for which ClientIdentification is
|
|
||||||
// encrypted.
|
|
||||||
optional bytes service_certificate_serial_number = 2;
|
|
||||||
// Serialized ClientIdentification message, encrypted with the privacy key using
|
|
||||||
// AES-128-CBC with PKCS#5 padding.
|
|
||||||
optional bytes encrypted_client_id = 3;
|
|
||||||
// Initialization vector needed to decrypt encrypted_client_id.
|
|
||||||
optional bytes encrypted_client_id_iv = 4;
|
|
||||||
// AES-128 privacy key, encrypted with the service public key using RSA-OAEP.
|
|
||||||
optional bytes encrypted_privacy_key = 5;
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Description:
|
|
||||||
// Provisioned device info format definitions.
|
|
||||||
|
|
||||||
syntax = "proto2";
|
|
||||||
|
|
||||||
package widevine;
|
|
||||||
|
|
||||||
option java_package = "com.google.video.widevine.protos";
|
|
||||||
option java_outer_classname = "ProvisionedDeviceInfoProto";
|
|
||||||
|
|
||||||
// Contains device model information for a provisioned device.
|
|
||||||
message ProvisionedDeviceInfo {
|
|
||||||
enum WvSecurityLevel {
|
|
||||||
// Defined in Widevine Security Integration Guide for DASH on Android:
|
|
||||||
// http://doc/1Zum-fcJeoIw6KG1kDP_KepIE5h9gAZg0PaMtemBvk9c/edit#heading=h.1t3h5sf
|
|
||||||
LEVEL_UNSPECIFIED = 0;
|
|
||||||
LEVEL_1 = 1;
|
|
||||||
LEVEL_2 = 2;
|
|
||||||
LEVEL_3 = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Widevine system ID for the device. Mandatory.
|
|
||||||
optional uint32 system_id = 1;
|
|
||||||
// Name of system-on-a-chip. Optional.
|
|
||||||
optional string soc = 2;
|
|
||||||
// Name of manufacturer. Optional.
|
|
||||||
optional string manufacturer = 3;
|
|
||||||
// Manufacturer's model name. Matches "brand" in device metadata. Optional.
|
|
||||||
optional string model = 4;
|
|
||||||
// Type of device (Phone, Tablet, TV, etc).
|
|
||||||
optional string device_type = 5;
|
|
||||||
// Device model year. Optional.
|
|
||||||
optional uint32 model_year = 6;
|
|
||||||
// Widevine-defined security level. Optional.
|
|
||||||
optional WvSecurityLevel security_level = 7 [default = LEVEL_UNSPECIFIED];
|
|
||||||
// True if the certificate corresponds to a test (non production) device.
|
|
||||||
// Optional.
|
|
||||||
optional bool test_device = 8 [default = false];
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Signed device certificate definition.
|
|
||||||
|
|
||||||
syntax = "proto2";
|
|
||||||
|
|
||||||
package widevine;
|
|
||||||
|
|
||||||
option java_outer_classname = "SignedDeviceCertificateProtos";
|
|
||||||
option java_package = "com.google.video.widevine.protos";
|
|
||||||
|
|
||||||
// DrmDeviceCertificate signed by a higher (CA) DRM certificate.
|
|
||||||
message SignedDrmDeviceCertificate {
|
|
||||||
// Serialized certificate. Required.
|
|
||||||
optional bytes drm_certificate = 1;
|
|
||||||
// Signature of certificate. Signed with root or intermediate
|
|
||||||
// certificate specified below. Required.
|
|
||||||
optional bytes signature = 2;
|
|
||||||
// SignedDrmDeviceCertificate used to sign this certificate.
|
|
||||||
optional SignedDrmDeviceCertificate signer = 3;
|
|
||||||
}
|
|
||||||
BIN
provisioning_sdk-bin.tar
Normal file
BIN
provisioning_sdk-bin.tar
Normal file
Binary file not shown.
@@ -1,22 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef PROVISIONING_SDK_PUBLIC_CERTIFICATE_TYPE_H_
|
|
||||||
#define PROVISIONING_SDK_PUBLIC_CERTIFICATE_TYPE_H_
|
|
||||||
|
|
||||||
namespace widevine {
|
|
||||||
|
|
||||||
enum CertificateType {
|
|
||||||
kCertTesting = 0,
|
|
||||||
kCertDevelopment,
|
|
||||||
kCertProduction,
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace widevine
|
|
||||||
|
|
||||||
#endif // PROVISIONING_SDK_PUBLIC_CERTIFICATE_TYPE_H_
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef PROVISIONING_SDK_PUBLIC_PROVISIONING_ENGINE_H_
|
|
||||||
#define PROVISIONING_SDK_PUBLIC_PROVISIONING_ENGINE_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "provisioning_sdk/public/certificate_type.h"
|
|
||||||
#include "provisioning_sdk/public/provisioning_status.h"
|
|
||||||
|
|
||||||
namespace widevine {
|
|
||||||
|
|
||||||
class ProvisioningEngineImpl;
|
|
||||||
class ProvisioningSession;
|
|
||||||
|
|
||||||
// Class which is used to implement a Widevine DRM device provisioning engine.
|
|
||||||
// There should be only one instance of ProvisioningEngine. The engine should
|
|
||||||
// be "Initialized" before being used. ProvisioningEngine::Initialize is the
|
|
||||||
// only method that is not thread-safe. After initializing the engine, it can
|
|
||||||
// be safely used in different threads.
|
|
||||||
class ProvisioningEngine {
|
|
||||||
public:
|
|
||||||
ProvisioningEngine();
|
|
||||||
virtual ~ProvisioningEngine();
|
|
||||||
|
|
||||||
// Initializes the provisioning engine with required credentials.
|
|
||||||
// * |certificate_type| indicates which type of certificate chains will be
|
|
||||||
// used for device provisioning via this engine.
|
|
||||||
// * |service_drm_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& 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);
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
virtual 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.
|
|
||||||
virtual ProvisioningStatus AddDrmIntermediateCertificate(
|
|
||||||
const std::string& intermediate_cert,
|
|
||||||
const std::string& cert_private_key,
|
|
||||||
const std::string& cert_private_key_passphrase);
|
|
||||||
|
|
||||||
// Create a session to handle a provisioning exchange between a client device
|
|
||||||
// and the provisioning server.
|
|
||||||
// * |device_public_key| is a DER-encoded PKCS#1.5 RSAPublicKey message which
|
|
||||||
// will used to create the DRM certificate to be provisioned onto the
|
|
||||||
// device.
|
|
||||||
// * |device_private_key| is a DER-encoded PKCS#8 PrivateKeyInfo message
|
|
||||||
// which contains the private key matching |device_public_key|.
|
|
||||||
// * |new_session| will point, on successful return, to the newly created
|
|
||||||
// ProvisioningSession.
|
|
||||||
// * Returns OK if successful, or an appropriate error status code otherwise.
|
|
||||||
// The key pairs can be re-used if the created session failed to process the
|
|
||||||
// message.
|
|
||||||
// NOTE: All ProvisioningSession objects must be deleted before the
|
|
||||||
// ProvisioningEngine which created them.
|
|
||||||
virtual ProvisioningStatus NewProvisioningSession(
|
|
||||||
const std::string& device_public_key,
|
|
||||||
const std::string& device_private_key,
|
|
||||||
std::unique_ptr<ProvisioningSession>* new_session) const;
|
|
||||||
|
|
||||||
// Generate a new device DRM certificate to be provisioned by means other than
|
|
||||||
// the Widevine provisioning protocol.
|
|
||||||
// NOTE: This API should only be used to provision devices which were
|
|
||||||
// manufactured without Widevine DRM support. It is meant to be used as
|
|
||||||
// an exception, and not the norm. Most devices should be provisioned
|
|
||||||
// by means of a ProvisioningSession.
|
|
||||||
// * |system_id| is the Widevine system ID for the type of device being
|
|
||||||
// provisioned.
|
|
||||||
// * |public_key| is a DER-encoded PKCS#1.5 RSAPublicKey message which will
|
|
||||||
// be embedded in the generated 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.
|
|
||||||
ProvisioningStatus GenerateDeviceDrmCertificate(
|
|
||||||
uint32_t system_id,
|
|
||||||
const std::string& public_key,
|
|
||||||
const std::string& serial_number,
|
|
||||||
std::string* certificate) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
#ifndef SWIGPYTHON
|
|
||||||
ProvisioningEngine(const ProvisioningEngine&) = delete;
|
|
||||||
ProvisioningEngine& operator=(const ProvisioningEngine&) = delete;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::unique_ptr<ProvisioningEngineImpl> impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace widevine
|
|
||||||
|
|
||||||
#endif // PROVISIONING_SDK_PUBLIC_PROVISIONING_ENGINE_H_
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef PROVISIONING_SDK_PUBLIC_PROVISIONING_SESSION_H_
|
|
||||||
#define PROVISIONING_SDK_PUBLIC_PROVISIONING_SESSION_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "provisioning_sdk/public/provisioning_status.h"
|
|
||||||
|
|
||||||
namespace widevine {
|
|
||||||
|
|
||||||
class ProvisionedDeviceInfo;
|
|
||||||
class ProvisioningSessionImpl;
|
|
||||||
|
|
||||||
// Class which is used to implement the provisioning session state machine.
|
|
||||||
class ProvisioningSession {
|
|
||||||
public:
|
|
||||||
virtual ~ProvisioningSession();
|
|
||||||
|
|
||||||
// Process a message from the client device.
|
|
||||||
// * |message| is the message received from the client device.
|
|
||||||
// * |response| will contain, upon successful return, a message to be sent
|
|
||||||
// back to the client device as a response to |message|.
|
|
||||||
// * |done| will indicate, upon successful return, whether the provisioning
|
|
||||||
// exchange is complete, and the ProvisioningSession can be deleted.
|
|
||||||
// Returns OK if successful, or an appropriate error status code otherwise.
|
|
||||||
virtual ProvisioningStatus ProcessMessage(const std::string& message,
|
|
||||||
std::string* response,
|
|
||||||
bool* done);
|
|
||||||
|
|
||||||
// * Returns a ProvisioneddeviceInfo message containing information about the
|
|
||||||
// type of device being provisioned. May return nullptr.
|
|
||||||
virtual const ProvisionedDeviceInfo* GetDeviceInfo() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ProvisioningSession(); // To enable mocking.
|
|
||||||
|
|
||||||
private:
|
|
||||||
#ifndef SWIGPYTHON
|
|
||||||
friend class ProvisioningEngine;
|
|
||||||
|
|
||||||
ProvisioningSession(const ProvisioningSession&) = delete;
|
|
||||||
ProvisioningSession& operator=(const ProvisioningSession&) = delete;
|
|
||||||
#endif
|
|
||||||
explicit ProvisioningSession(std::unique_ptr<ProvisioningSessionImpl> impl);
|
|
||||||
|
|
||||||
std::unique_ptr<ProvisioningSessionImpl> impl_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace widevine
|
|
||||||
|
|
||||||
#endif // PROVISIONING_SDK_PUBLIC_PROVISIONING_SESSION_H_
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef PROVISIONING_SDK_PUBLIC_PROVISIONING_STATUS_H_
|
|
||||||
#define PROVISIONING_SDK_PUBLIC_PROVISIONING_STATUS_H_
|
|
||||||
|
|
||||||
namespace widevine {
|
|
||||||
|
|
||||||
enum ProvisioningStatus {
|
|
||||||
OK = 0,
|
|
||||||
INVALID_CERTIFICATE_TYPE = 1,
|
|
||||||
PROVISIONING_ENGINE_UNINITIALIZED = 2,
|
|
||||||
INVALID_SERVICE_DRM_CERTIFICATE = 3,
|
|
||||||
// Invalid service private key or private key passphrase.
|
|
||||||
INVALID_SERVICE_PRIVATE_KEY = 4,
|
|
||||||
INVALID_PROVISIONER_DRM_CERTIFICATE = 5,
|
|
||||||
// Invalid provisioner private key or private key passphrase.
|
|
||||||
INVALID_PROVISIONER_PRIVATE_KEY = 6,
|
|
||||||
INVALID_INTERMEDIATE_DRM_CERTIFICATE = 7,
|
|
||||||
INVALID_INTERMEDIATE_PUBLIC_KEY = 8,
|
|
||||||
// Invalid intermediate private key or private key passphrase.
|
|
||||||
INVALID_INTERMEDIATE_PRIVATE_KEY = 9,
|
|
||||||
INVALID_STATUS_LIST = 10,
|
|
||||||
STATUS_LIST_EXPIRED = 11,
|
|
||||||
UNKNOWN_SYSTEM_ID = 12,
|
|
||||||
INVALID_DEVICE_PUBLIC_KEY = 13,
|
|
||||||
INVALID_DEVICE_PRIVATE_KEY = 14,
|
|
||||||
INVALID_REQUEST_MESSAGE = 15,
|
|
||||||
INVALID_MAC = 16,
|
|
||||||
MISSING_DRM_INTERMEDIATE_CERT = 17,
|
|
||||||
DRM_DEVICE_CERTIFICATE_NOT_SET = 18,
|
|
||||||
DEVICE_REVOKED = 19,
|
|
||||||
INVALID_SERIAL_NUMBER = 20,
|
|
||||||
INTERNAL_ERROR = 21,
|
|
||||||
INVALID_SPOID_SAUCE = 22,
|
|
||||||
NUM_PROVISIONING_STATUS,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns the message std::string for the given ProvisioningStatus.
|
|
||||||
const char* GetProvisioningStatusMessage(ProvisioningStatus status);
|
|
||||||
|
|
||||||
} // namespace widevine
|
|
||||||
|
|
||||||
#endif // PROVISIONING_SDK_PUBLIC_PROVISIONING_STATUS_H_
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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 "std_string.i"
|
|
||||||
%include "typemaps.i"
|
|
||||||
|
|
||||||
%define %ignoreall %ignore ""; %enddef
|
|
||||||
%define %unignore %rename("%s") %enddef
|
|
||||||
%define %unignoreall %rename("%s") ""; %enddef
|
|
||||||
|
|
||||||
%define COPY_TYPEMAPS(oldtype, newtype)
|
|
||||||
typedef oldtype newtype;
|
|
||||||
%apply oldtype * OUTPUT { newtype * OUTPUT };
|
|
||||||
%apply oldtype & OUTPUT { newtype & OUTPUT };
|
|
||||||
%apply oldtype * INPUT { newtype * INPUT };
|
|
||||||
%apply oldtype & INPUT { newtype & INPUT };
|
|
||||||
%apply oldtype * INOUT { newtype * INOUT };
|
|
||||||
%apply oldtype & INOUT { newtype & INOUT };
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
COPY_TYPEMAPS(int, int32_t);
|
|
||||||
COPY_TYPEMAPS(unsigned int, uint32_t);
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Swig file to generate a Python library for:
|
|
||||||
// provisioning_sdk/public/certificate_type.h
|
|
||||||
|
|
||||||
%module pywrapcertificate_type
|
|
||||||
|
|
||||||
%include "base.i"
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "provisioning_sdk/public/certificate_type.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%ignoreall
|
|
||||||
|
|
||||||
%unignore widevine;
|
|
||||||
%unignore widevine::CertificateType;
|
|
||||||
%unignore widevine::kCertTesting;
|
|
||||||
%unignore widevine::kCertDevelopment;
|
|
||||||
%include "provisioning_sdk/public/certificate_type.h"
|
|
||||||
|
|
||||||
%unignoreall
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"""Utility functions for cryptography."""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from cryptography.hazmat import backends
|
|
||||||
from cryptography.hazmat.primitives import hashes
|
|
||||||
from cryptography.hazmat.primitives import serialization
|
|
||||||
from cryptography.hazmat.primitives.asymmetric import padding
|
|
||||||
|
|
||||||
|
|
||||||
def VerifySignature(public_key, signature, data):
|
|
||||||
hash_algorithm = hashes.SHA1()
|
|
||||||
salt_len = 20
|
|
||||||
|
|
||||||
logging.info('Verying signature.')
|
|
||||||
key = serialization.load_der_public_key(
|
|
||||||
public_key, backend=backends.default_backend())
|
|
||||||
key.verify(signature, data,
|
|
||||||
padding.PSS(padding.MGF1(hash_algorithm), salt_len),
|
|
||||||
hash_algorithm)
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import pywrapprovisioning_engine
|
|
||||||
import pywrapprovisioning_status
|
|
||||||
import test_data_utility
|
|
||||||
|
|
||||||
|
|
||||||
class AddDrmIntermediateTest(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._engine = pywrapprovisioning_engine.ProvisioningEngine()
|
|
||||||
test_data_utility.InitProvisionEngineWithTestData(
|
|
||||||
self._engine, verify_success=True)
|
|
||||||
|
|
||||||
def testGenerateDrmIntermediateCertificateWithValidExpirationPeriod(self):
|
|
||||||
test_data_utility.SetCertificateStatusListWithTestData(
|
|
||||||
self._engine, 0, verify_success=True)
|
|
||||||
|
|
||||||
test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 2001, verify_success=True)
|
|
||||||
|
|
||||||
def testSetCertificateStatusListInvalid(self):
|
|
||||||
set_cert_status_list = self._engine.SetCertificateStatusList(
|
|
||||||
'INVALID_STATUS_LIST', 0)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_STATUS_LIST,
|
|
||||||
set_cert_status_list)
|
|
||||||
|
|
||||||
def testAddDrmIntermediateCertificateWithoutCertificateStatusList(self):
|
|
||||||
# Users should not be able to add DRM certificate without having
|
|
||||||
# certificate status list.
|
|
||||||
status = test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 2001)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.STATUS_LIST_EXPIRED, status)
|
|
||||||
|
|
||||||
def testAddDrmIntermediateCertificateSystemIdInvalid(self):
|
|
||||||
test_data_utility.SetCertificateStatusListWithTestData(
|
|
||||||
self._engine, 0, verify_success=True)
|
|
||||||
|
|
||||||
# system_id 9999 is not in the sample certificate status list
|
|
||||||
add_ca_status = test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 9999)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.UNKNOWN_SYSTEM_ID, add_ca_status)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import crypto_utility
|
|
||||||
import pywrapcertificate_type
|
|
||||||
import pywrapprovisioning_engine
|
|
||||||
import pywrapprovisioning_status
|
|
||||||
import test_data_provider
|
|
||||||
import test_data_utility
|
|
||||||
from protos.public import signed_device_certificate_pb2
|
|
||||||
|
|
||||||
|
|
||||||
class EngineGenerateCertificateTest(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._engine = pywrapprovisioning_engine.ProvisioningEngine()
|
|
||||||
test_data_utility.InitProvisionEngineWithTestData(
|
|
||||||
self._engine, verify_success=True)
|
|
||||||
test_data_utility.SetCertificateStatusListWithTestData(
|
|
||||||
self._engine, 0, verify_success=True)
|
|
||||||
test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 2001, verify_success=True)
|
|
||||||
self._data_provider = test_data_provider.TestDataProvider(
|
|
||||||
pywrapcertificate_type.kCertTesting)
|
|
||||||
|
|
||||||
def testSuccess(self):
|
|
||||||
status, signed_cert_string = self._engine.GenerateDeviceDrmCertificate(
|
|
||||||
2001, self._data_provider.device_public_key, 'DEVICE_SERIAL_NUMBER')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.OK, status)
|
|
||||||
|
|
||||||
signed_cert = signed_device_certificate_pb2.SignedDrmDeviceCertificate()
|
|
||||||
signed_cert.ParseFromString(signed_cert_string)
|
|
||||||
crypto_utility.VerifySignature(self._data_provider.ca_public_key,
|
|
||||||
signed_cert.signature,
|
|
||||||
signed_cert.drm_certificate)
|
|
||||||
|
|
||||||
def testEmptySerialNumber(self):
|
|
||||||
status, _ = self._engine.GenerateDeviceDrmCertificate(
|
|
||||||
2001, self._data_provider.device_public_key, '')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERIAL_NUMBER, status)
|
|
||||||
|
|
||||||
def testEmptyPublicKey(self):
|
|
||||||
status, _ = self._engine.GenerateDeviceDrmCertificate(
|
|
||||||
2001, '', 'DEVICE_SERIAL_NUMBER')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_DEVICE_PUBLIC_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInvalidPublicKey(self):
|
|
||||||
status, _ = self._engine.GenerateDeviceDrmCertificate(
|
|
||||||
2001, 'PUBLIC_KEY_MUST_BE_IN_DER_ENCODED_PKCS1_FORMAT',
|
|
||||||
'DEVICE_SERIAL_NUMBER')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_DEVICE_PUBLIC_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testMissingIntermediateCertificate(self):
|
|
||||||
status, _ = self._engine.GenerateDeviceDrmCertificate(
|
|
||||||
2002, self._data_provider.device_public_key, 'DEVICE_SERIAL_NUMBER')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.DEVICE_REVOKED, status)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import pywrapcertificate_type
|
|
||||||
import pywrapprovisioning_engine
|
|
||||||
import pywrapprovisioning_status
|
|
||||||
import test_data_provider
|
|
||||||
import test_data_utility
|
|
||||||
|
|
||||||
|
|
||||||
class InitEngineTest(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._engine = pywrapprovisioning_engine.ProvisioningEngine()
|
|
||||||
self._data_provider = test_data_provider.TestDataProvider(
|
|
||||||
pywrapcertificate_type.kCertTesting)
|
|
||||||
|
|
||||||
def testInitEngineSucceed(self):
|
|
||||||
test_data_utility.InitProvisionEngineWithTestData(
|
|
||||||
self._engine, verify_success=True)
|
|
||||||
|
|
||||||
def testSetCertificateStatusListWithoutInit(self):
|
|
||||||
status = self._engine.SetCertificateStatusList('CERTIFICATE_STATUS_LIST',
|
|
||||||
3600)
|
|
||||||
self.assertEqual(
|
|
||||||
pywrapprovisioning_status.PROVISIONING_ENGINE_UNINITIALIZED, status)
|
|
||||||
|
|
||||||
def testGenerateDrmIntermediateCertificateWithoutInit(self):
|
|
||||||
status, _ = self._engine.GenerateDrmIntermediateCertificate(
|
|
||||||
100, 'INTERMEDIATE_PUBLIC_KEY')
|
|
||||||
self.assertEqual(
|
|
||||||
pywrapprovisioning_status.PROVISIONING_ENGINE_UNINITIALIZED, status)
|
|
||||||
|
|
||||||
def testAddDrmIntermediateCertificateWithoutInit(self):
|
|
||||||
status = self._engine.AddDrmIntermediateCertificate(
|
|
||||||
'INTERMEDIATE_CERTIFICATE', 'INTERMEDIATE_PRIVATE_KEY',
|
|
||||||
'INTERMEDIATE_PRIVATE_KEY_PASSPHRASE')
|
|
||||||
self.assertEqual(
|
|
||||||
pywrapprovisioning_status.PROVISIONING_ENGINE_UNINITIALIZED, status)
|
|
||||||
|
|
||||||
def testGenerateDeviceDrmCertificateWithoutInit(self):
|
|
||||||
status, _ = self._engine.GenerateDeviceDrmCertificate(
|
|
||||||
100, 'DEVICE_PUBLIC_KEY', 'DEVICE_SERIAL_NUMBER')
|
|
||||||
self.assertEqual(
|
|
||||||
pywrapprovisioning_status.PROVISIONING_ENGINE_UNINITIALIZED, status)
|
|
||||||
|
|
||||||
def testNewProvisioningSessionWithoutInit(self):
|
|
||||||
status, session = self._engine.NewProvisioningSession('DEVICE_PUBLIC_KEY',
|
|
||||||
'DEVICE_PRIVATE_KEY')
|
|
||||||
self.assertEqual(
|
|
||||||
pywrapprovisioning_status.PROVISIONING_ENGINE_UNINITIALIZED, status)
|
|
||||||
self.assertIsNone(session)
|
|
||||||
|
|
||||||
def testInitEngineInvalidServiceDrmCert(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting, 'INVALID_CERT',
|
|
||||||
self._data_provider.service_private_key,
|
|
||||||
self._data_provider.service_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_drm_cert,
|
|
||||||
self._data_provider.provisioner_private_key,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_DRM_CERTIFICATE,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInitEngineInvalidServicePrivateKey(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert, 'INVALID_KEY',
|
|
||||||
self._data_provider.service_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_drm_cert,
|
|
||||||
self._data_provider.provisioner_private_key,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInitEngineWrongServicePrivateKey(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert,
|
|
||||||
self._data_provider.provisioner_private_key,
|
|
||||||
self._data_provider.service_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_drm_cert,
|
|
||||||
self._data_provider.provisioner_private_key,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInitEngineInvalidServicePrivateKeyPassphrase(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert,
|
|
||||||
self._data_provider.service_private_key, 'INVALID_PASSPHRASE',
|
|
||||||
self._data_provider.provisioner_drm_cert,
|
|
||||||
self._data_provider.provisioner_private_key,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInitEngineInvalidDrmCert(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert,
|
|
||||||
self._data_provider.service_private_key,
|
|
||||||
self._data_provider.service_private_key_passphrase, 'INVALID_CERT',
|
|
||||||
self._data_provider.provisioner_private_key,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(
|
|
||||||
pywrapprovisioning_status.INVALID_PROVISIONER_DRM_CERTIFICATE, status)
|
|
||||||
|
|
||||||
def testInitEngineInvalidDrmPrivateKey(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert,
|
|
||||||
self._data_provider.service_private_key,
|
|
||||||
self._data_provider.service_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_drm_cert, 'INVALID_KEY',
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONER_PRIVATE_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInitEngineWrongDrmPrivateKey(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert,
|
|
||||||
self._data_provider.service_private_key,
|
|
||||||
self._data_provider.service_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_drm_cert,
|
|
||||||
self._data_provider.service_private_key,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONER_PRIVATE_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInitEngineInvalidDrmPrivateKeyPassphrase(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert,
|
|
||||||
self._data_provider.service_private_key,
|
|
||||||
self._data_provider.service_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_drm_cert,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase,
|
|
||||||
'INVALID_PASSPHRASE',
|
|
||||||
self._data_provider.provisioner_spoid_secret)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONER_PRIVATE_KEY,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testInitEngineInvalidSpoidSecret(self):
|
|
||||||
status = self._engine.Initialize(
|
|
||||||
pywrapcertificate_type.kCertTesting,
|
|
||||||
self._data_provider.service_drm_cert,
|
|
||||||
self._data_provider.service_private_key,
|
|
||||||
self._data_provider.service_private_key_passphrase,
|
|
||||||
self._data_provider.provisioner_drm_cert,
|
|
||||||
self._data_provider.provisioner_private_key,
|
|
||||||
self._data_provider.provisioner_private_key_passphrase, '')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_SPOID_SAUCE, status)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import crypto_utility
|
|
||||||
import pywrapcertificate_type
|
|
||||||
import pywrapprovisioning_engine
|
|
||||||
import pywrapprovisioning_status
|
|
||||||
import test_data_provider
|
|
||||||
import test_data_utility
|
|
||||||
from protos.public import certificate_provisioning_pb2
|
|
||||||
from protos.public import signed_device_certificate_pb2
|
|
||||||
|
|
||||||
|
|
||||||
class NewSessionTest(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._engine = pywrapprovisioning_engine.ProvisioningEngine()
|
|
||||||
test_data_utility.InitProvisionEngineWithTestData(
|
|
||||||
self._engine, verify_success=True)
|
|
||||||
test_data_utility.SetCertificateStatusListWithTestData(
|
|
||||||
self._engine, 0, verify_success=True)
|
|
||||||
self._data_provider = test_data_provider.TestDataProvider(
|
|
||||||
pywrapcertificate_type.kCertTesting)
|
|
||||||
|
|
||||||
def testNewSessionSuccess(self):
|
|
||||||
test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 2001, verify_success=True)
|
|
||||||
|
|
||||||
(_, new_session) = test_data_utility.NewProvisioningSessionWithTestData(
|
|
||||||
self._engine, verify_success=True)
|
|
||||||
(status, raw_response,
|
|
||||||
_) = new_session.ProcessMessage(self._data_provider.message)
|
|
||||||
test_data_utility.AssertSuccess(status, 'Failed to create session.')
|
|
||||||
|
|
||||||
signed_request = test_data_utility.ConvertToSignedProvisioningMessage(
|
|
||||||
self._data_provider.message)
|
|
||||||
|
|
||||||
unsigned_request = certificate_provisioning_pb2.ProvisioningRequest()
|
|
||||||
unsigned_request.ParseFromString(signed_request.message)
|
|
||||||
|
|
||||||
signed_response = test_data_utility.ConvertToSignedProvisioningMessage(
|
|
||||||
raw_response)
|
|
||||||
|
|
||||||
self._VerifyMessageSignature(self._data_provider.service_public_key,
|
|
||||||
signed_response)
|
|
||||||
|
|
||||||
unsigned_response = certificate_provisioning_pb2.ProvisioningResponse()
|
|
||||||
unsigned_response.ParseFromString(signed_response.message)
|
|
||||||
|
|
||||||
self._VerifyProvisioningResponse(unsigned_request, unsigned_response)
|
|
||||||
|
|
||||||
def testProcessInvalidMessage(self):
|
|
||||||
test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 2001, verify_success=True)
|
|
||||||
(_, new_session
|
|
||||||
) = test_data_utility.NewProvisioningSessionWithTestData(self._engine)
|
|
||||||
(status, _, _) = new_session.ProcessMessage('INVALID_MESSAGE')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_REQUEST_MESSAGE, status)
|
|
||||||
|
|
||||||
def testNewSessionWithoutIntermediateCert(self):
|
|
||||||
(_, new_session) = test_data_utility.NewProvisioningSessionWithTestData(
|
|
||||||
self._engine, verify_success=True)
|
|
||||||
(status, _, _) = new_session.ProcessMessage(
|
|
||||||
self._data_provider.message)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.MISSING_DRM_INTERMEDIATE_CERT,
|
|
||||||
status)
|
|
||||||
|
|
||||||
def testNewSessionInvalidDevicePublicKey(self):
|
|
||||||
test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 2001, verify_success=True)
|
|
||||||
(session_status, _) = self._engine.NewProvisioningSession(
|
|
||||||
'INVALID_PUBLIC_KEY', self._data_provider.device_private_key)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_DEVICE_PUBLIC_KEY,
|
|
||||||
session_status)
|
|
||||||
|
|
||||||
def testNewSessionInvalidDevicePrivateKey(self):
|
|
||||||
test_data_utility.AddDrmIntermediateCertificateWithTestData(
|
|
||||||
self._engine, 2001, verify_success=True)
|
|
||||||
(session_status, _) = self._engine.NewProvisioningSession(
|
|
||||||
self._data_provider.device_public_key, 'INVALID_PRIVATE_KEY')
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_DEVICE_PRIVATE_KEY,
|
|
||||||
session_status)
|
|
||||||
|
|
||||||
def _VerifyMessageSignature(self, public_key, signed_response):
|
|
||||||
crypto_utility.VerifySignature(public_key, signed_response.signature,
|
|
||||||
signed_response.message)
|
|
||||||
|
|
||||||
def _VerifyCertSignature(self, public_key, signed_cert):
|
|
||||||
crypto_utility.VerifySignature(public_key, signed_cert.signature,
|
|
||||||
signed_cert.drm_certificate)
|
|
||||||
|
|
||||||
def _VerifyProvisioningResponse(self, request, response):
|
|
||||||
self.assertEqual(request.nonce, response.nonce)
|
|
||||||
|
|
||||||
signed_cert = signed_device_certificate_pb2.SignedDrmDeviceCertificate()
|
|
||||||
signed_cert.ParseFromString(response.device_certificate)
|
|
||||||
|
|
||||||
self._VerifyCertSignature(self._data_provider.ca_public_key,
|
|
||||||
signed_cert)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Swig file to generate a Python library for:
|
|
||||||
// provisioning_sdk/public/provisioning_engine.h
|
|
||||||
|
|
||||||
%module pywrapprovisioning_engine
|
|
||||||
|
|
||||||
%include "base.i"
|
|
||||||
%include "unique_ptr.i"
|
|
||||||
%import(module="pywrapprovisioning_session") "provisioning_sdk/public/python/provisioning_session.i"
|
|
||||||
|
|
||||||
UNIQUE_PTR_ARGOUT(widevine::ProvisioningSession, new_session);
|
|
||||||
|
|
||||||
%apply int { CertificateType, ProvisioningStatus };
|
|
||||||
%apply std::string* OUTPUT { std::string* certificate };
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "provisioning_sdk/public/provisioning_engine.h"
|
|
||||||
#include "provisioning_sdk/public/provisioning_session.h"
|
|
||||||
using namespace widevine;
|
|
||||||
%}
|
|
||||||
|
|
||||||
%ignoreall
|
|
||||||
|
|
||||||
%unignore widevine;
|
|
||||||
%unignore widevine::ProvisioningSession;
|
|
||||||
|
|
||||||
%unignore widevine::ProvisioningEngine;
|
|
||||||
%unignore widevine::ProvisioningEngine::ProvisioningEngine;
|
|
||||||
%unignore widevine::ProvisioningEngine::~ProvisioningEngine;
|
|
||||||
%unignore widevine::ProvisioningEngine::SetCertificateStatusList;
|
|
||||||
%unignore widevine::ProvisioningEngine::Initialize;
|
|
||||||
%unignore widevine::ProvisioningEngine::GenerateDrmIntermediateCertificate;
|
|
||||||
%unignore widevine::ProvisioningEngine::AddDrmIntermediateCertificate;
|
|
||||||
%unignore widevine::ProvisioningEngine::NewProvisioningSession;
|
|
||||||
%unignore widevine::ProvisioningEngine::GenerateDeviceDrmCertificate;
|
|
||||||
|
|
||||||
%include "provisioning_sdk/public/provisioning_engine.h"
|
|
||||||
|
|
||||||
%unignoreall
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Swig file to generate a Python library for:
|
|
||||||
// provisioning_sdk/public/provisioning_session.h
|
|
||||||
|
|
||||||
%module pywrapprovisioning_session
|
|
||||||
|
|
||||||
%include "base.i"
|
|
||||||
|
|
||||||
%apply bool* OUTPUT { bool* done };
|
|
||||||
|
|
||||||
%apply int { ProvisioningStatus };
|
|
||||||
|
|
||||||
%apply std::string* OUTPUT { std::string* response };
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "provisioning_sdk/public/provisioning_session.h"
|
|
||||||
using namespace widevine;
|
|
||||||
%}
|
|
||||||
|
|
||||||
%ignoreall
|
|
||||||
|
|
||||||
%unignore widevine;
|
|
||||||
%unignore widevine::ProvisioningSession;
|
|
||||||
%unignore widevine::ProvisioningSession::~ProvisioningSession;
|
|
||||||
%unignore widevine::ProvisioningSession::ProcessMessage;
|
|
||||||
|
|
||||||
|
|
||||||
%include "provisioning_sdk/public/provisioning_session.h"
|
|
||||||
|
|
||||||
%unignoreall
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Swig file to generate a Python library for:
|
|
||||||
// provisioning_sdk/public/provisioning_status.h
|
|
||||||
|
|
||||||
%module pywrapprovisioning_status
|
|
||||||
|
|
||||||
%include "base.i"
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "provisioning_sdk/public/provisioning_status.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
%ignoreall
|
|
||||||
|
|
||||||
%unignore widevine;
|
|
||||||
%unignore widevine::ProvisioningStatus;
|
|
||||||
%unignore widevine::OK;
|
|
||||||
%unignore widevine::PROVISIONING_ENGINE_UNINITIALIZED;
|
|
||||||
%unignore widevine::INVALID_SERVICE_DRM_CERTIFICATE;
|
|
||||||
%unignore widevine::INVALID_SERVICE_PRIVATE_KEY;
|
|
||||||
%unignore widevine::INVALID_PROVISIONER_DRM_CERTIFICATE;
|
|
||||||
%unignore widevine::INVALID_PROVISIONER_PRIVATE_KEY;
|
|
||||||
%unignore widevine::INVALID_STATUS_LIST;
|
|
||||||
%unignore widevine::STATUS_LIST_EXPIRED;
|
|
||||||
%unignore widevine::UNKNOWN_SYSTEM_ID;
|
|
||||||
%unignore widevine::INVALID_DEVICE_PUBLIC_KEY;
|
|
||||||
%unignore widevine::INVALID_DEVICE_PRIVATE_KEY;
|
|
||||||
%unignore widevine::INVALID_REQUEST_MESSAGE;
|
|
||||||
%unignore widevine::MISSING_DRM_INTERMEDIATE_CERT;
|
|
||||||
%unignore widevine::DEVICE_REVOKED;
|
|
||||||
%unignore widevine::INVALID_SERIAL_NUMBER;
|
|
||||||
%unignore widevine::INVALID_SPOID_SAUCE;
|
|
||||||
%unignore widevine::GetProvisioningStatusMessage;
|
|
||||||
|
|
||||||
%include "provisioning_sdk/public/provisioning_status.h"
|
|
||||||
|
|
||||||
%unignoreall
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import pywrapprovisioning_engine
|
|
||||||
import pywrapprovisioning_status
|
|
||||||
import test_data_utility
|
|
||||||
|
|
||||||
|
|
||||||
class SetCertificateStatusListTest(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self._engine = pywrapprovisioning_engine.ProvisioningEngine()
|
|
||||||
test_data_utility.InitProvisionEngineWithTestData(
|
|
||||||
self._engine, verify_success=True)
|
|
||||||
|
|
||||||
def testSetCertificateStatusListSuccess(self):
|
|
||||||
test_data_utility.SetCertificateStatusListWithTestData(
|
|
||||||
self._engine, 0, verify_success=True)
|
|
||||||
|
|
||||||
def testSetCertificateStatusListInvalid(self):
|
|
||||||
set_cert_status_list = self._engine.SetCertificateStatusList(
|
|
||||||
'INVALID_STATUS_LIST', 0)
|
|
||||||
self.assertEqual(pywrapprovisioning_status.INVALID_STATUS_LIST,
|
|
||||||
set_cert_status_list)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"""setup script to build Python wrappers using swig configurations."""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from distutils import core
|
|
||||||
|
|
||||||
OUT_DIRNAME = 'test_genfiles'
|
|
||||||
|
|
||||||
|
|
||||||
def GetSdkRootDir():
|
|
||||||
"""Obtains folder containing |OUT_DIRNAME| that is considered as root dir."""
|
|
||||||
current_dir = os.path.realpath(os.path.dirname(__file__))
|
|
||||||
while not os.path.isdir(os.path.join(current_dir, OUT_DIRNAME)):
|
|
||||||
current_dir = os.path.dirname(current_dir)
|
|
||||||
return current_dir
|
|
||||||
|
|
||||||
|
|
||||||
SDK_ROOT_DIR = GetSdkRootDir()
|
|
||||||
|
|
||||||
SWIG_CONFIG_FILE = os.path.join(SDK_ROOT_DIR, OUT_DIRNAME, '%s.i')
|
|
||||||
SWIG_CONFIG_MODULE_PATH = OUT_DIRNAME + '.%s'
|
|
||||||
|
|
||||||
SDK_LIBRARY_DIR = os.path.join(SDK_ROOT_DIR, 'bazel-bin', 'provisioning_sdk',
|
|
||||||
'public')
|
|
||||||
|
|
||||||
|
|
||||||
def ProvisioningSwigExtension(extension_name):
|
|
||||||
return core.Extension(
|
|
||||||
name=SWIG_CONFIG_MODULE_PATH % ('_pywrap' + extension_name),
|
|
||||||
sources=[SWIG_CONFIG_FILE % extension_name],
|
|
||||||
include_dirs=[SDK_ROOT_DIR],
|
|
||||||
swig_opts=['-c++'],
|
|
||||||
library_dirs=[SDK_ROOT_DIR, SDK_LIBRARY_DIR],
|
|
||||||
runtime_library_dirs=[SDK_ROOT_DIR, SDK_LIBRARY_DIR],
|
|
||||||
libraries=['provisioning_sdk'],
|
|
||||||
extra_compile_args=['-std=c++11'])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
os.chdir(SDK_ROOT_DIR)
|
|
||||||
core.setup(
|
|
||||||
name='provisioning_sdk',
|
|
||||||
ext_modules=[
|
|
||||||
ProvisioningSwigExtension('certificate_type'),
|
|
||||||
ProvisioningSwigExtension('provisioning_status'),
|
|
||||||
ProvisioningSwigExtension('provisioning_session'),
|
|
||||||
ProvisioningSwigExtension('provisioning_engine')
|
|
||||||
],
|
|
||||||
py_modules=[
|
|
||||||
SWIG_CONFIG_MODULE_PATH % 'pywrapcertificate_type',
|
|
||||||
SWIG_CONFIG_MODULE_PATH % 'pywarpprovisioning_status',
|
|
||||||
SWIG_CONFIG_MODULE_PATH % 'pywrapprovisioning_session',
|
|
||||||
SWIG_CONFIG_MODULE_PATH % 'pywrapprovisioning_engine'
|
|
||||||
])
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2017 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"""Class that provides test data for Provisioning SDK testing."""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import pywrapcertificate_type
|
|
||||||
|
|
||||||
_TEST_CERT_DATA_FOLDER = os.path.join('example', 'example_data')
|
|
||||||
_DEV_CERT_DATA_FOLDER = os.path.join('example', 'dev_cert_example_data')
|
|
||||||
|
|
||||||
|
|
||||||
class TestDataProvider(object):
|
|
||||||
"""For for Test Data."""
|
|
||||||
|
|
||||||
def __init__(self, cert_type):
|
|
||||||
"""Initializes the TestData for Provisioning SDK tests."""
|
|
||||||
assert (cert_type in (
|
|
||||||
pywrapcertificate_type.kCertDevelopment,
|
|
||||||
pywrapcertificate_type.kCertTesting))
|
|
||||||
self._cert_type = cert_type
|
|
||||||
|
|
||||||
def _GetTestData(self, filename):
|
|
||||||
"""Helps read test data files such as certs and keys for SDK testing."""
|
|
||||||
current_dir = os.path.realpath(os.path.dirname(__file__))
|
|
||||||
if self._cert_type == pywrapcertificate_type.kCertDevelopment:
|
|
||||||
subfolder_path = _DEV_CERT_DATA_FOLDER
|
|
||||||
elif self._cert_type == pywrapcertificate_type.kCertTesting:
|
|
||||||
subfolder_path = _TEST_CERT_DATA_FOLDER
|
|
||||||
while not os.path.isdir(os.path.join(current_dir, subfolder_path)):
|
|
||||||
current_dir = os.path.dirname(current_dir)
|
|
||||||
filename = os.path.join(current_dir, subfolder_path, filename)
|
|
||||||
with open(filename, 'rb') as data_file:
|
|
||||||
data = data_file.read()
|
|
||||||
return data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def service_drm_cert(self):
|
|
||||||
return self._GetTestData('service.cert')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def service_public_key(self):
|
|
||||||
return self._GetTestData('service.public')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def service_private_key(self):
|
|
||||||
return self._GetTestData('service.encrypted.private')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def service_private_key_passphrase(self):
|
|
||||||
return self._GetTestData('service.passphrase')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def provisioner_drm_cert(self):
|
|
||||||
return self._GetTestData('provisioner.cert')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def provisioner_private_key(self):
|
|
||||||
return self._GetTestData('provisioner.encrypted.private')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def provisioner_private_key_passphrase(self):
|
|
||||||
return self._GetTestData('provisioner.passphrase')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def provisioner_spoid_secret(self):
|
|
||||||
return self._GetTestData('provisioner.spoid_secret')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def ca_public_key(self):
|
|
||||||
return self._GetTestData('intermediate.public')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def ca_private_key(self):
|
|
||||||
return self._GetTestData('intermediate.encrypted.private')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def ca_private_key_passphrase(self):
|
|
||||||
return self._GetTestData('intermediate.passphrase')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def device_public_key(self):
|
|
||||||
return self._GetTestData('user.public')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def device_private_key(self):
|
|
||||||
return self._GetTestData('user.private')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def message(self):
|
|
||||||
return self._GetTestData('message')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def certificate_list(self):
|
|
||||||
return self._GetTestData('certificate_list')
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
"""Utility class for Provisioning SDK testing."""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import pywrapcertificate_type
|
|
||||||
import pywrapprovisioning_status
|
|
||||||
import test_data_provider
|
|
||||||
from protos.public import certificate_provisioning_pb2
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
|
|
||||||
def InitProvisionEngineWithTestData(
|
|
||||||
engine, verify_success=False,
|
|
||||||
cert_type=pywrapcertificate_type.kCertTesting):
|
|
||||||
"""Initialize the provisioning engine with sample credentials.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
engine: a pywrapprovisioning_engine.ProvisioningEngine instance
|
|
||||||
verify_success: whether to verify that resulting status code equals OK
|
|
||||||
cert_type: The type of certificate to use for initializing SDK -
|
|
||||||
{kCertTesting/kCertDevelopment}
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
OK on success, or an appropriate error status code otherwise.
|
|
||||||
"""
|
|
||||||
logging.info('Initializing provisioning engine with test data.')
|
|
||||||
data_provider = test_data_provider.TestDataProvider(cert_type)
|
|
||||||
status = engine.Initialize(cert_type,
|
|
||||||
data_provider.service_drm_cert,
|
|
||||||
data_provider.service_private_key,
|
|
||||||
data_provider.service_private_key_passphrase,
|
|
||||||
data_provider.provisioner_drm_cert,
|
|
||||||
data_provider.provisioner_private_key,
|
|
||||||
data_provider.provisioner_private_key_passphrase,
|
|
||||||
data_provider.provisioner_spoid_secret)
|
|
||||||
if verify_success:
|
|
||||||
AssertSuccess(status, 'Failed to initialize.')
|
|
||||||
return status
|
|
||||||
|
|
||||||
|
|
||||||
def SetCertificateStatusListWithTestData(
|
|
||||||
engine, expiration_period_seconds, verify_success=False,
|
|
||||||
cert_type=pywrapcertificate_type.kCertTesting):
|
|
||||||
"""Set the certificate status list with sample certificate status list.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
engine: a pywrapprovisioning_engine.ProvisioningEngine instance
|
|
||||||
expiration_period_seconds: number of seconds until certificate_status_list
|
|
||||||
expires after its creation time
|
|
||||||
verify_success: whether to verify that resulting status code equals OK
|
|
||||||
cert_type: The type of certificate to use for initializing SDK -
|
|
||||||
{kCertTesting/kCertDevelopment}
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
OK on success, or an appropriate error status code otherwise.
|
|
||||||
"""
|
|
||||||
logging.info('Setting certificate status list with test data.')
|
|
||||||
data_provider = test_data_provider.TestDataProvider(cert_type)
|
|
||||||
certificate_status_list = data_provider.certificate_list
|
|
||||||
|
|
||||||
status = engine.SetCertificateStatusList(certificate_status_list,
|
|
||||||
expiration_period_seconds)
|
|
||||||
|
|
||||||
if verify_success:
|
|
||||||
AssertSuccess(status, 'Failed to set certificate status list.')
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
|
|
||||||
def AddDrmIntermediateCertificateWithTestData(
|
|
||||||
engine, system_id, verify_success=False,
|
|
||||||
cert_type=pywrapcertificate_type.kCertTesting):
|
|
||||||
"""Generate an intermediate DRM cert and add it to provisioning engine.
|
|
||||||
|
|
||||||
The intermediate DRM certificate is generated with sample public key and
|
|
||||||
is added to the provisioning engine with sample certificate private key and
|
|
||||||
passphrase.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
engine: a pywrapprovisioning_engine.ProvisioningEngine instance
|
|
||||||
system_id: Widevine system ID for the type of device
|
|
||||||
verify_success: whether to verify that resulting status code equals OK
|
|
||||||
cert_type: The type of certificate to use for initializing SDK -
|
|
||||||
{kCertTesting/kCertDevelopment}
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
OK on success, or an appropriate error status code otherwise.
|
|
||||||
"""
|
|
||||||
logging.info(
|
|
||||||
'Generating DRM intermediate certificate for system_id <%d>.', system_id)
|
|
||||||
data_provider = test_data_provider.TestDataProvider(cert_type)
|
|
||||||
gen_status, ca_certificate = engine.GenerateDrmIntermediateCertificate(
|
|
||||||
system_id, data_provider.ca_public_key)
|
|
||||||
AssertSuccess(gen_status, 'Failed to generate intermediate certificate.')
|
|
||||||
|
|
||||||
logging.info('Adding DRM intermediate certificate.')
|
|
||||||
add_ca_status = engine.AddDrmIntermediateCertificate(
|
|
||||||
ca_certificate, data_provider.ca_private_key,
|
|
||||||
data_provider.ca_private_key_passphrase)
|
|
||||||
|
|
||||||
if verify_success:
|
|
||||||
AssertSuccess(add_ca_status, 'Failed to add intermediate certificate.')
|
|
||||||
|
|
||||||
return add_ca_status
|
|
||||||
|
|
||||||
|
|
||||||
def GenerateDeviceDrmCertificate(engine, system_id, serial_number,
|
|
||||||
verify_success=False,
|
|
||||||
cert_type=pywrapcertificate_type.kCertTesting):
|
|
||||||
"""Generate a device DRM certificate.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
engine: a pywrapprovisioning_engine.ProvisioningEngine instance
|
|
||||||
system_id: Widevine system ID for the type of device
|
|
||||||
serial_number: The serial number for the device DRM certificate.
|
|
||||||
verify_success: whether to verify that resulting status code equals OK
|
|
||||||
cert_type: The type of certificate to use for initializing SDK -
|
|
||||||
{kCertTesting/kCertDevelopment}
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
OK on success, or an appropriate error status code otherwise.
|
|
||||||
"""
|
|
||||||
logging.info(
|
|
||||||
'Generating Device cert for system_id <%d> and serial_number <%s>.',
|
|
||||||
system_id, serial_number)
|
|
||||||
data_provider = test_data_provider.TestDataProvider(cert_type)
|
|
||||||
gen_status, ca_certificate = engine.GenerateDeviceDrmCertificate(
|
|
||||||
system_id, data_provider.device_public_key, serial_number)
|
|
||||||
if verify_success:
|
|
||||||
AssertSuccess(gen_status, 'Failed to generate device DRM certificate.')
|
|
||||||
return ca_certificate
|
|
||||||
|
|
||||||
|
|
||||||
def NewProvisioningSessionWithTestData(
|
|
||||||
engine, verify_success=False,
|
|
||||||
cert_type=pywrapcertificate_type.kCertTesting):
|
|
||||||
"""Create a provisioning session with sample device public and private keys.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
engine: a pywrapprovisioning_engine.ProvisioningEngine instance
|
|
||||||
verify_success: whether to verify that resulting status code equals OK
|
|
||||||
cert_type: The type of certificate to use for initializing SDK -
|
|
||||||
{kCertTesting/kCertDevelopment}
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
status: OK on success, or an appropriate error status code otherwise.
|
|
||||||
new_session: A new provisioning_session.
|
|
||||||
"""
|
|
||||||
logging.info('Starting a new provisioning session with'
|
|
||||||
'sample device public and private keys.')
|
|
||||||
data_provider = test_data_provider.TestDataProvider(cert_type)
|
|
||||||
status, new_session = engine.NewProvisioningSession(
|
|
||||||
data_provider.device_public_key, data_provider.device_private_key)
|
|
||||||
if verify_success:
|
|
||||||
AssertSuccess(status, 'Failed to create session.')
|
|
||||||
|
|
||||||
return status, new_session
|
|
||||||
|
|
||||||
|
|
||||||
def AssertSuccess(status, message=None):
|
|
||||||
"""Assert status equals OK."""
|
|
||||||
assert pywrapprovisioning_status.OK == status, message
|
|
||||||
|
|
||||||
|
|
||||||
def ConvertToSignedProvisioningMessage(serialized_message):
|
|
||||||
signed_message = certificate_provisioning_pb2.SignedProvisioningMessage()
|
|
||||||
signed_message.ParseFromString(serialized_message)
|
|
||||||
return signed_message
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright 2016 Google Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <class T> class unique_ptr {};
|
|
||||||
}
|
|
||||||
|
|
||||||
%define _UNIQUE_PTR_TEMPLATE(type)
|
|
||||||
template <> class std::unique_ptr <type> {};
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
%define UNIQUE_PTR(type)
|
|
||||||
_UNIQUE_PTR_TEMPLATE(type);
|
|
||||||
|
|
||||||
%typemap(out) std::unique_ptr<type> %{
|
|
||||||
$result = SWIG_NewPointerObj(
|
|
||||||
SWIG_as_voidptr($1.release()), $descriptor(type*), SWIG_POINTER_OWN);
|
|
||||||
%}
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
%define UNIQUE_PTR_WITH_ERROR(type, err_str)
|
|
||||||
_UNIQUE_PTR_TEMPLATE(type);
|
|
||||||
|
|
||||||
%typemap(out) std::unique_ptr<type> %{
|
|
||||||
if ($1) {
|
|
||||||
$result = SWIG_NewPointerObj(
|
|
||||||
SWIG_as_voidptr($1.release()), $descriptor(type*), SWIG_POINTER_OWN);
|
|
||||||
} else {
|
|
||||||
SWIG_exception(SWIG_ValueError, err_str);
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
%define UNIQUE_PTR_ARGOUT(type, arg_name)
|
|
||||||
_UNIQUE_PTR_TEMPLATE(type)
|
|
||||||
|
|
||||||
%typemap(in, numinputs=0) std::unique_ptr<type>* arg_name
|
|
||||||
(std::unique_ptr<type> temp) %{
|
|
||||||
$1 = &temp;
|
|
||||||
%}
|
|
||||||
|
|
||||||
%typemap(argout) std::unique_ptr<type>* arg_name %{
|
|
||||||
%append_output(SWIG_NewPointerObj(SWIG_as_voidptr($1->release()),
|
|
||||||
$descriptor(type*), SWIG_POINTER_OWN));
|
|
||||||
%}
|
|
||||||
%enddef
|
|
||||||
49
run_tests.sh
49
run_tests.sh
@@ -1,49 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
################################################################################
|
|
||||||
# Copyright 2016 Google Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
################################################################################
|
|
||||||
#
|
|
||||||
# This script generates a directory that stores the intermediate artifacts
|
|
||||||
# needed for testing.
|
|
||||||
#
|
|
||||||
# Prerequirements (if running the script directly):
|
|
||||||
# - Python 2.7 or later
|
|
||||||
# - pip: https://pip.pypa.io/en/latest/installing/
|
|
||||||
# - Python cryptography package: https://cryptography.io/en/latest/installation/
|
|
||||||
# - Protocol compiler: https://github.com/google/protobuf#protocol-compiler-installation
|
|
||||||
# On Ubuntu: sudo apt-get install protobuf-compiler
|
|
||||||
# - Protobuf Python runtime (version 3.0 or later): sudo pip install protobuf
|
|
||||||
# - swig: http://www.swig.org/download.html
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
hash protoc 2>/dev/null || { echo >&2 "protobuf is required but not installed. Aborting."; exit 1; }
|
|
||||||
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
|
|
||||||
rm -rf test_genfiles
|
|
||||||
mkdir test_genfiles
|
|
||||||
|
|
||||||
protoc -I="$(pwd)" --python_out="$(pwd)/test_genfiles" "$(pwd)/protos/public/client_identification.proto"
|
|
||||||
protoc -I="$(pwd)" --python_out="$(pwd)/test_genfiles" "$(pwd)/protos/public/provisioned_device_info.proto"
|
|
||||||
protoc -I="$(pwd)" --python_out="$(pwd)/test_genfiles" "$(pwd)/protos/public/certificate_provisioning.proto"
|
|
||||||
protoc -I="$(pwd)" --python_out="$(pwd)/test_genfiles" "$(pwd)/protos/public/signed_device_certificate.proto"
|
|
||||||
|
|
||||||
cp -a provisioning_sdk/public/python/* test_genfiles/
|
|
||||||
cd test_genfiles
|
|
||||||
python setup.py build_ext --inplace
|
|
||||||
|
|
||||||
shopt -s globstar
|
|
||||||
for d in "protos"/**/; do
|
|
||||||
touch -- "$d/__init__.py";
|
|
||||||
done;
|
|
||||||
|
|
||||||
python init_engine_test.py
|
|
||||||
python set_certificate_status_list_test.py
|
|
||||||
python drm_intermediate_certificate_test.py
|
|
||||||
python engine_generate_certificate_test.py
|
|
||||||
python new_session_test.py
|
|
||||||
Reference in New Issue
Block a user