Export provisioning sdk
Change-Id: I4d47d80444c9507f84896767dc676112ca11e901
This commit is contained in:
73
provisioning_sdk/public/python/BUILD
Normal file
73
provisioning_sdk/public/python/BUILD
Normal file
@@ -0,0 +1,73 @@
|
||||
################################################################################
|
||||
# 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.
|
||||
################################################################################
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
py_library(
|
||||
name = "test_data_utility",
|
||||
srcs = ["test_data_utility.py"],
|
||||
data = ["//example:example_data"],
|
||||
deps = [
|
||||
"//protos/public:certificate_provisioning_py_pb2",
|
||||
],
|
||||
)
|
||||
|
||||
py_library(
|
||||
name = "crypto_utility",
|
||||
srcs = ["crypto_utility.py"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "init_engine_test",
|
||||
size = "small",
|
||||
srcs = ["init_engine_test.py"],
|
||||
deps = [
|
||||
":test_data_utility",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "set_certificate_status_list_test",
|
||||
size = "small",
|
||||
srcs = ["set_certificate_status_list_test.py"],
|
||||
deps = [
|
||||
":test_data_utility",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "drm_intermediate_certificate_test",
|
||||
size = "small",
|
||||
srcs = ["drm_intermediate_certificate_test.py"],
|
||||
deps = [
|
||||
":test_data_utility",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "engine_generate_certificate_test",
|
||||
size = "small",
|
||||
srcs = ["engine_generate_certificate_test.py"],
|
||||
deps = [
|
||||
":crypto_utility",
|
||||
":test_data_utility",
|
||||
"//protos/public:signed_device_certificate_py_pb2",
|
||||
],
|
||||
)
|
||||
|
||||
py_test(
|
||||
name = "new_session_test",
|
||||
size = "small",
|
||||
srcs = ["new_session_test.py"],
|
||||
deps = [
|
||||
":crypto_utility",
|
||||
":test_data_utility",
|
||||
"//protos/public:certificate_provisioning_py_pb2",
|
||||
"//protos/public:signed_device_certificate_py_pb2",
|
||||
],
|
||||
)
|
||||
27
provisioning_sdk/public/python/base.i
Normal file
27
provisioning_sdk/public/python/base.i
Normal file
@@ -0,0 +1,27 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
COPY_TYPEMAPS(unsigned int, uint32);
|
||||
28
provisioning_sdk/public/python/certificate_type.i
Normal file
28
provisioning_sdk/public/python/certificate_type.i
Normal file
@@ -0,0 +1,28 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
25
provisioning_sdk/public/python/crypto_utility.py
Normal file
25
provisioning_sdk/public/python/crypto_utility.py
Normal file
@@ -0,0 +1,25 @@
|
||||
################################################################################
|
||||
# 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."""
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
@@ -0,0 +1,54 @@
|
||||
################################################################################
|
||||
# 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()
|
||||
@@ -0,0 +1,64 @@
|
||||
################################################################################
|
||||
# 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 pywrapprovisioning_engine
|
||||
import pywrapprovisioning_status
|
||||
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)
|
||||
|
||||
def testSuccess(self):
|
||||
status, signed_cert_string = self._engine.GenerateDeviceDrmCertificate(
|
||||
2001, test_data_utility.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(test_data_utility.CA_PUBLIC_KEY,
|
||||
signed_cert.signature,
|
||||
signed_cert.drm_certificate)
|
||||
|
||||
def testEmptySerialNumber(self):
|
||||
status, _ = self._engine.GenerateDeviceDrmCertificate(
|
||||
2001, test_data_utility.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, test_data_utility.DEVICE_PUBLIC_KEY, 'DEVICE_SERIAL_NUMBER')
|
||||
self.assertEqual(pywrapprovisioning_status.DEVICE_REVOKED, status)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
170
provisioning_sdk/public/python/init_engine_test.py
Normal file
170
provisioning_sdk/public/python/init_engine_test.py
Normal file
@@ -0,0 +1,170 @@
|
||||
################################################################################
|
||||
# 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_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.kCertTesting, 'INVALID_CERT',
|
||||
test_data_utility.SERVICE_PRIVATE_KEY,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_DRM_CERT,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_DRM_CERTIFICATE,
|
||||
status)
|
||||
|
||||
def testInitEngineInvalidServicePrivateKey(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT, 'INVALID_KEY',
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_DRM_CERT,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
|
||||
status)
|
||||
|
||||
def testInitEngineWrongServicePrivateKey(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_DRM_CERT,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
|
||||
status)
|
||||
|
||||
def testInitEngineInvalidServicePrivateKeyPassphrase(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY, 'INVALID_PASSPHRASE',
|
||||
test_data_utility.PROVISIONER_DRM_CERT,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_SERVICE_PRIVATE_KEY,
|
||||
status)
|
||||
|
||||
def testInitEngineInvalidDrmCert(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS, 'INVALID_CERT',
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(
|
||||
pywrapprovisioning_status.INVALID_PROVISIONER_DRM_CERTIFICATE, status)
|
||||
|
||||
def testInitEngineInvalidDrmPrivateKey(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_DRM_CERT, 'INVALID_KEY',
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONER_PRIVATE_KEY,
|
||||
status)
|
||||
|
||||
def testInitEngineWrongDrmPrivateKey(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_DRM_CERT,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONER_PRIVATE_KEY,
|
||||
status)
|
||||
|
||||
def testInitEngineInvalidDrmPrivateKeyPassphrase(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_DRM_CERT,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
'INVALID_PASSPHRASE',
|
||||
test_data_utility.PROVISIONER_SPOID_SECRET)
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_PROVISIONER_PRIVATE_KEY,
|
||||
status)
|
||||
|
||||
def testInitEngineInvalidSpoidSecret(self):
|
||||
status = self._engine.Initialize(
|
||||
pywrapcertificate_type.kCertTesting,
|
||||
test_data_utility.SERVICE_DRM_CERT,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY,
|
||||
test_data_utility.SERVICE_PRIVATE_KEY_PASS,
|
||||
test_data_utility.PROVISIONER_DRM_CERT,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY,
|
||||
test_data_utility.PROVISIONER_PRIVATE_KEY_PASS,
|
||||
'')
|
||||
self.assertEqual(pywrapprovisioning_status.INVALID_SPOID_SAUCE, status)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
103
provisioning_sdk/public/python/new_session_test.py
Normal file
103
provisioning_sdk/public/python/new_session_test.py
Normal file
@@ -0,0 +1,103 @@
|
||||
################################################################################
|
||||
# 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 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):
|
||||
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(test_data_utility.CA_PUBLIC_KEY, signed_cert)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
49
provisioning_sdk/public/python/provisioning_engine.i
Normal file
49
provisioning_sdk/public/python/provisioning_engine.i
Normal file
@@ -0,0 +1,49 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 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
|
||||
37
provisioning_sdk/public/python/provisioning_session.i
Normal file
37
provisioning_sdk/public/python/provisioning_session.i
Normal file
@@ -0,0 +1,37 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
44
provisioning_sdk/public/python/provisioning_status.i
Normal file
44
provisioning_sdk/public/python/provisioning_status.i
Normal file
@@ -0,0 +1,44 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
@@ -0,0 +1,35 @@
|
||||
################################################################################
|
||||
# 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()
|
||||
62
provisioning_sdk/public/python/setup.py
Normal file
62
provisioning_sdk/public/python/setup.py
Normal file
@@ -0,0 +1,62 @@
|
||||
################################################################################
|
||||
# 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'
|
||||
])
|
||||
151
provisioning_sdk/public/python/test_data_utility.py
Normal file
151
provisioning_sdk/public/python/test_data_utility.py
Normal file
@@ -0,0 +1,151 @@
|
||||
################################################################################
|
||||
# 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 os
|
||||
|
||||
import pywrapcertificate_type
|
||||
import pywrapprovisioning_status
|
||||
from protos.public import certificate_provisioning_pb2
|
||||
|
||||
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')
|
||||
PROVISIONER_DRM_CERT = GetTestData('provisioner.cert')
|
||||
PROVISIONER_PRIVATE_KEY = GetTestData('provisioner.encrypted.private')
|
||||
PROVISIONER_PRIVATE_KEY_PASS = GetTestData('provisioner.passphrase')
|
||||
PROVISIONER_SPOID_SECRET = GetTestData('provisioner.spoid_secret')
|
||||
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.kCertTesting,
|
||||
SERVICE_DRM_CERT, SERVICE_PRIVATE_KEY,
|
||||
SERVICE_PRIVATE_KEY_PASS, PROVISIONER_DRM_CERT,
|
||||
PROVISIONER_PRIVATE_KEY,
|
||||
PROVISIONER_PRIVATE_KEY_PASS,
|
||||
PROVISIONER_SPOID_SECRET)
|
||||
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
|
||||
51
provisioning_sdk/public/python/unique_ptr.i
Normal file
51
provisioning_sdk/public/python/unique_ptr.i
Normal file
@@ -0,0 +1,51 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
Reference in New Issue
Block a user