Release provisioning sdk b3889b8

Change-Id: Ib423c4bada1ec2c47eff174b0d99dc9c8813a5ed
This commit is contained in:
Kongqun Yang
2016-11-14 10:47:48 -08:00
commit 131a00206c
38 changed files with 1332 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
intermediate_passphrase

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
provider_passphrase

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
service_passphrase

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,104 @@
#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::kCertDevelopment;
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(
kCertDevelopment, GetContents("example_data/service.cert"),
GetContents("example_data/service.encrypted.private"),
GetContents("example_data/service.passphrase"),
GetContents("example_data/provider.cert"),
GetContents("example_data/provider.encrypted.private"),
GetContents("example_data/provider.passphrase")) != 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;
}

BIN
libprovisioning_sdk.so Executable file

Binary file not shown.

View File

@@ -0,0 +1,88 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// Author: tinskip@google.com (Thomas Inskip)
//
// 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 origin_id {
// Stable identifier, unique for each device + application (or origin).
// Required if doing per-origin provisioning.
bytes stable_id = 4;
// Stable content provider ID.
bytes provider_id = 6;
}
}
// 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 {
VERSION_2 = 2; // Keybox factory-provisioned devices.
VERSION_3 = 3; // OEM certificate factory-provisioned devices.
}
// 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 = VERSION_2];
}

View File

@@ -0,0 +1,82 @@
// Copyright 2013 Google Inc. All Rights Reserved.
// Author: tinskip@google.com (Thomas Inskip)
//
// 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;
}
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];
}
// 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;
}
// EncryptedClientIdentification message used to hold ClientIdentification
// messages encrypted for privacy purposes.
message EncryptedClientIdentification {
// Service ID for which the ClientIdentifcation is encrypted (owner of service
// certificate).
optional string service_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;
}

View File

@@ -0,0 +1,39 @@
// 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];
}

View File

@@ -0,0 +1,19 @@
// 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;
}

View File

@@ -0,0 +1,14 @@
#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_

View File

@@ -0,0 +1,142 @@
// Copyright 2016 Google Inc. All rights reserved.
#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();
~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.
// * 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);
// Set the certificate status list for this engine.
// * |certificate_status_list| is a certificate status list generated by the
// Widevine Provisioning Service.
// * |expiration_period| is the number of seconds until the
// |certificate_status_list| expires after its creation time
// (creation_time_seconds). Zero means it will never expire.
// * Returns OK on success, or an appropriate error status code otherwise.
ProvisioningStatus SetCertificateStatusList(
const std::string& certificate_status_list,
uint32_t expiration_period_seconds);
// Generate an intermediate DRM certificate.
// * |system_id| is the Widevine system ID for the type of device.
// * |public_key| is a DER-encoded PKCS#1.5 RSAPublicKey message which will
// be embedded in the generated certificate.
// * |certificate| will contain the new intermediate certificate, upon
// successful return.
// * Returns OK on success, or an appropriate error status code otherwise.
// NOTE: The generated certificate and associated private key should be stored
// securely to be reused. They should also be propagated to all
// engines, including this one, by invoking
// |AddIntermediatedrmcertificate| on all active ProvisioningEngine(s).
ProvisioningStatus GenerateDrmIntermediateCertificate(
uint32_t system_id,
const std::string& public_key,
std::string* certificate) const;
// Add an intermediate DRM certificate to the provisioning engine. This is
// usually done once for each supported device type.
// * |intermediate_cert| is the intermediate DRM certificate to be added.
// * |cert_private_key| is a PKCS#8 private key corresponding to
// |intermediate_cert|.
// * |cert_private_key_passphrase| is the passphrase for cert_private_key,
// if any.
// * Returns OK on success, or an appropriate error status code otherwise.
ProvisioningStatus AddDrmIntermediateCertificate(
const std::string& intermediate_cert,
const std::string& cert_private_key,
const std::string& cert_private_key_passphrase);
// 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.
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.
// * |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_

View File

@@ -0,0 +1,50 @@
// Copyright 2016 Google Inc. All rights reserved.
#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:
~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.
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.
const ProvisionedDeviceInfo* GetDeviceInfo() const;
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_

View File

@@ -0,0 +1,41 @@
// Copyright 2016 Google Inc. All rights reserved.
#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_PROVISIONING_DRM_CERTIFICATE = 5,
// Invalid provisioning private key or private key passphrase.
INVALID_PROVISIONING_PRIVATE_KEY = 6,
INVALID_INTERMEDIATE_DRM_CERTIFICATE = 7,
// Invalid intermediate private key or private key passphrase.
INVALID_INTERMEDIATE_PRIVATE_KEY = 8,
INVALID_STATUS_LIST = 9,
STATUS_LIST_EXPIRED = 10,
UNKNOWN_SYSTEM_ID = 11,
INVALID_DEVICE_PUBLIC_KEY = 12,
INVALID_DEVICE_PRIVATE_KEY = 13,
INVALID_REQUEST_MESSAGE = 14,
INVALID_MAC = 15,
MISSING_DRM_INTERMEDIATE_CERT = 16,
DRM_DEVICE_CERTIFICATE_NOT_SET = 17,
DEVICE_REVOKED = 18,
INVALID_SERIAL_NUMBER = 19,
INTERNAL_ERROR = 20,
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_

View File

@@ -0,0 +1,19 @@
%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);
COPY_TYPEMAPS(unsigned int, uint32);

View File

@@ -0,0 +1,20 @@
// 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::kCertDevelopment;
%include "provisioning_sdk/public/certificate_type.h"
%unignoreall

View File

@@ -0,0 +1,46 @@
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()

View File

@@ -0,0 +1,142 @@
import unittest
import pywrapcertificate_type
import pywrapprovisioning_engine
import pywrapprovisioning_status
import test_data_utility
class InitEngineTest(unittest.TestCase):
def setUp(self):
self._engine = pywrapprovisioning_engine.ProvisioningEngine()
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.kCertDevelopment, 'INVALID_CERT',
test_data_utility.SERVICE_PRIVATE_KEY,
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
test_data_utility.PROVISIONING_DRM_CERT,
test_data_utility.PROVISIONING_PRIVATE_KEY,
test_data_utility.PROVISIONING_PRIVATE_KEY_PASS)
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_DRM_CERTIFICATE,
status)
def testInitEngineInvalidServicePrivateKey(self):
status = self._engine.Initialize(
pywrapcertificate_type.kCertDevelopment,
test_data_utility.SERVICE_DRM_CERT, 'INVALID_KEY',
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
test_data_utility.PROVISIONING_DRM_CERT,
test_data_utility.PROVISIONING_PRIVATE_KEY,
test_data_utility.PROVISIONING_PRIVATE_KEY_PASS)
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
status)
def testInitEngineWrongServicePrivateKey(self):
status = self._engine.Initialize(
pywrapcertificate_type.kCertDevelopment,
test_data_utility.SERVICE_DRM_CERT,
test_data_utility.PROVISIONING_PRIVATE_KEY,
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
test_data_utility.PROVISIONING_DRM_CERT,
test_data_utility.PROVISIONING_PRIVATE_KEY,
test_data_utility.PROVISIONING_PRIVATE_KEY_PASS)
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
status)
def testInitEngineInvalidServicePrivateKeyPassphrase(self):
status = self._engine.Initialize(
pywrapcertificate_type.kCertDevelopment,
test_data_utility.SERVICE_DRM_CERT,
test_data_utility.SERVICE_PRIVATE_KEY, 'INVALID_PASSPHRASE',
test_data_utility.PROVISIONING_DRM_CERT,
test_data_utility.PROVISIONING_PRIVATE_KEY,
test_data_utility.PROVISIONING_PRIVATE_KEY_PASS)
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
status)
def testInitEngineInvalidDrmCert(self):
status = self._engine.Initialize(
pywrapcertificate_type.kCertDevelopment,
test_data_utility.SERVICE_DRM_CERT,
test_data_utility.SERVICE_PRIVATE_KEY,
test_data_utility.SERVICE_PRIVATE_KEY_PASS, 'INVALID_CERT',
test_data_utility.PROVISIONING_PRIVATE_KEY,
test_data_utility.PROVISIONING_PRIVATE_KEY_PASS)
self.assertEqual(
pywrapprovisioning_status.INVALID_PROVISIONING_DRM_CERTIFICATE, status)
def testInitEngineInvalidDrmPrivateKey(self):
status = self._engine.Initialize(
pywrapcertificate_type.kCertDevelopment,
test_data_utility.SERVICE_DRM_CERT,
test_data_utility.SERVICE_PRIVATE_KEY,
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
test_data_utility.PROVISIONING_DRM_CERT, 'INVALID_KEY',
test_data_utility.PROVISIONING_PRIVATE_KEY_PASS)
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONING_PRIVATE_KEY,
status)
def testInitEngineWrongDrmPrivateKey(self):
status = self._engine.Initialize(
pywrapcertificate_type.kCertDevelopment,
test_data_utility.SERVICE_DRM_CERT,
test_data_utility.SERVICE_PRIVATE_KEY,
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
test_data_utility.PROVISIONING_DRM_CERT,
test_data_utility.SERVICE_PRIVATE_KEY,
test_data_utility.PROVISIONING_PRIVATE_KEY_PASS)
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONING_PRIVATE_KEY,
status)
def testInitEngineInvalidDrmPrivateKeyPassphrase(self):
status = self._engine.Initialize(pywrapcertificate_type.kCertDevelopment,
test_data_utility.SERVICE_DRM_CERT,
test_data_utility.SERVICE_PRIVATE_KEY,
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
test_data_utility.PROVISIONING_DRM_CERT,
test_data_utility.PROVISIONING_PRIVATE_KEY,
'INVALID_PASSPHRASE')
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONING_PRIVATE_KEY,
status)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,107 @@
import unittest
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import load_der_public_key
import pywrapprovisioning_engine
import pywrapprovisioning_status
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)
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(test_data_utility.MESSAGE)
test_data_utility.AssertSuccess(status, 'Failed to create session.')
signed_request = test_data_utility.ConvertToSignedProvisioningMessage(
test_data_utility.MESSAGE)
unsigned_request = certificate_provisioning_pb2.ProvisioningRequest()
unsigned_request.ParseFromString(signed_request.message)
signed_response = test_data_utility.ConvertToSignedProvisioningMessage(
raw_response)
self._VerifyMessageSignature(test_data_utility.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(test_data_utility.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', test_data_utility.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(
test_data_utility.DEVICE_PUBLIC_KEY, 'INVALID_PRIVATE_KEY')
self.assertEqual(pywrapprovisioning_status.INVALID_DEVICE_PRIVATE_KEY,
session_status)
def _VerifyMessageSignature(self, public_key, signed_response):
self._VerifySignature(public_key, signed_response.signature,
signed_response.message)
def _VerifyCertSignature(self, public_key, signed_cert):
self._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(test_data_utility.CA_PUBLIC_KEY, signed_cert)
def _VerifySignature(self, public_key, signature, data):
key = load_der_public_key(public_key, backend=default_backend())
key.verify(signature, data,
padding.PSS(
padding.MGF1(test_data_utility.HASH_ALGORITHM),
test_data_utility.SALT_LEN),
test_data_utility.HASH_ALGORITHM)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,41 @@
// 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 int32 { int32_t };
%apply uint32 { uint32_t };
%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

View File

@@ -0,0 +1,29 @@
// 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

View File

@@ -0,0 +1,34 @@
// 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_PROVISIONING_DRM_CERTIFICATE;
%unignore widevine::INVALID_PROVISIONING_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::GetProvisioningStatusMessage;
%include "provisioning_sdk/public/provisioning_status.h"
%unignoreall

View File

@@ -0,0 +1,27 @@
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()

View File

@@ -0,0 +1,55 @@
"""setup script to build Python wrappers using swig configurations."""
import os
from distutils.core import Extension
from distutils.core import setup
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 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)
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'
])

View File

@@ -0,0 +1,146 @@
"""Utility class for Provisioning SDK testing."""
import os
from cryptography.hazmat.primitives import hashes
import pywrapcertificate_type
import pywrapprovisioning_status
from protos.public import certificate_provisioning_pb2
HASH_ALGORITHM = hashes.SHA1()
SALT_LEN = 20
TEST_DATA_FOLDER = os.path.join('example', 'example_data')
def GetTestData(filename):
current_dir = os.path.realpath(os.path.dirname(__file__))
while not os.path.isdir(os.path.join(current_dir, TEST_DATA_FOLDER)):
current_dir = os.path.dirname(current_dir)
filename = os.path.join(current_dir, TEST_DATA_FOLDER, filename)
with open(filename, 'rb') as data_file:
data = data_file.read()
return data
SERVICE_DRM_CERT = GetTestData('service.cert')
SERVICE_PUBLIC_KEY = GetTestData('service.public')
SERVICE_PRIVATE_KEY = GetTestData('service.encrypted.private')
SERVICE_PRIVATE_KEY_PASS = GetTestData('service.passphrase')
PROVISIONING_DRM_CERT = GetTestData('provider.cert')
PROVISIONING_PRIVATE_KEY = GetTestData('provider.encrypted.private')
PROVISIONING_PRIVATE_KEY_PASS = GetTestData('provider.passphrase')
CA_PUBLIC_KEY = GetTestData('intermediate.public')
DEVICE_PUBLIC_KEY = GetTestData('user.public')
DEVICE_PRIVATE_KEY = GetTestData('user.private')
MESSAGE = GetTestData('message')
def InitProvisionEngineWithTestData(engine, verify_success=False):
"""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
Returns:
OK on success, or an appropriate error status code otherwise.
"""
status = engine.Initialize(pywrapcertificate_type.kCertDevelopment,
SERVICE_DRM_CERT, SERVICE_PRIVATE_KEY,
SERVICE_PRIVATE_KEY_PASS, PROVISIONING_DRM_CERT,
PROVISIONING_PRIVATE_KEY,
PROVISIONING_PRIVATE_KEY_PASS)
if verify_success:
AssertSuccess(status, 'Failed to initialize.')
return status
def SetCertificateStatusListWithTestData(engine,
expiration_period_seconds,
verify_success=False):
"""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
Returns:
OK on success, or an appropriate error status code otherwise.
"""
certificate_status_list = GetTestData('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):
"""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
Returns:
OK on success, or an appropriate error status code otherwise.
"""
ca_private_key = GetTestData('intermediate.encrypted.private')
ca_private_key_passphrase = GetTestData('intermediate.passphrase')
gen_status, ca_certificate = engine.GenerateDrmIntermediateCertificate(
system_id, CA_PUBLIC_KEY)
AssertSuccess(gen_status, 'Failed to generate intermediate certificate.')
add_ca_status = engine.AddDrmIntermediateCertificate(
ca_certificate, ca_private_key, ca_private_key_passphrase)
if verify_success:
AssertSuccess(add_ca_status, 'Failed to add intermediate certificate.')
return add_ca_status
def NewProvisioningSessionWithTestData(engine, verify_success=False):
"""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
Returns:
status: OK on success, or an appropriate error status code otherwise.
new_session: A new provisioning_session.
"""
status, new_session = engine.NewProvisioningSession(DEVICE_PUBLIC_KEY,
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

View File

@@ -0,0 +1,43 @@
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

41
run_tests.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/bash
#
# 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.i.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 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 new_session_test.py