Export provisioning sdk
Change-Id: I4d47d80444c9507f84896767dc676112ca11e901
This commit is contained in:
40
example/BUILD
Normal file
40
example/BUILD
Normal file
@@ -0,0 +1,40 @@
|
||||
################################################################################
|
||||
# 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.
|
||||
################################################################################
|
||||
|
||||
# Build file for the example code.
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "example_data",
|
||||
srcs = glob(["example_data/*"]),
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "provisioning_example",
|
||||
srcs = ["provisioning_example.cc"],
|
||||
deps = [
|
||||
"//provisioning_sdk/public:libprovisioning_sdk",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "provisioning_message_generator",
|
||||
srcs = ["provisioning_message_generator.cc"],
|
||||
deps = [
|
||||
"//base",
|
||||
"//common:aes_cbc_util",
|
||||
"//common:file_util",
|
||||
"//common:random_util",
|
||||
"//common:rsa_key",
|
||||
"//protos/public:certificate_provisioning_proto",
|
||||
"//protos/public:client_identification_proto",
|
||||
],
|
||||
)
|
||||
BIN
example/example_data/certificate_list
Normal file
BIN
example/example_data/certificate_list
Normal file
Binary file not shown.
BIN
example/example_data/intermediate.encrypted.private
Normal file
BIN
example/example_data/intermediate.encrypted.private
Normal file
Binary file not shown.
1
example/example_data/intermediate.passphrase
Normal file
1
example/example_data/intermediate.passphrase
Normal file
@@ -0,0 +1 @@
|
||||
intermediate_passphrase
|
||||
BIN
example/example_data/intermediate.public
Normal file
BIN
example/example_data/intermediate.public
Normal file
Binary file not shown.
BIN
example/example_data/message
Normal file
BIN
example/example_data/message
Normal file
Binary file not shown.
BIN
example/example_data/provisioner.cert
Normal file
BIN
example/example_data/provisioner.cert
Normal file
Binary file not shown.
BIN
example/example_data/provisioner.encrypted.private
Normal file
BIN
example/example_data/provisioner.encrypted.private
Normal file
Binary file not shown.
1
example/example_data/provisioner.passphrase
Normal file
1
example/example_data/provisioner.passphrase
Normal file
@@ -0,0 +1 @@
|
||||
provider_passphrase
|
||||
4
example/example_data/provisioner.spoid_secret
Normal file
4
example/example_data/provisioner.spoid_secret
Normal file
@@ -0,0 +1,4 @@
|
||||
Twas bryllyg, and ye slythy toves
|
||||
Did gyre and gymble in ye wabe:
|
||||
All mimsy were ye borogoves;
|
||||
And ye mome raths outgrabe.
|
||||
BIN
example/example_data/root.private
Normal file
BIN
example/example_data/root.private
Normal file
Binary file not shown.
BIN
example/example_data/service.cert
Normal file
BIN
example/example_data/service.cert
Normal file
Binary file not shown.
BIN
example/example_data/service.encrypted.private
Normal file
BIN
example/example_data/service.encrypted.private
Normal file
Binary file not shown.
1
example/example_data/service.passphrase
Normal file
1
example/example_data/service.passphrase
Normal file
@@ -0,0 +1 @@
|
||||
service_passphrase
|
||||
BIN
example/example_data/service.public
Normal file
BIN
example/example_data/service.public
Normal file
Binary file not shown.
BIN
example/example_data/user.private
Normal file
BIN
example/example_data/user.private
Normal file
Binary file not shown.
BIN
example/example_data/user.public
Normal file
BIN
example/example_data/user.public
Normal file
Binary file not shown.
113
example/provisioning_example.cc
Normal file
113
example/provisioning_example.cc
Normal file
@@ -0,0 +1,113 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
||||
95
example/provisioning_message_generator.cc
Normal file
95
example/provisioning_message_generator.cc
Normal file
@@ -0,0 +1,95 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gflags/gflags.h"
|
||||
#include "glog/logging.h"
|
||||
#include "common/aes_cbc_util.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/random_util.h"
|
||||
#include "common/rsa_key.h"
|
||||
#include "protos/public/certificate_provisioning.pb.h"
|
||||
#include "protos/public/client_identification.pb.h"
|
||||
|
||||
DEFINE_string(service_public_key_path, "example_data/service.public",
|
||||
"Indicates the file path to service public key. If omitted, the "
|
||||
"token is not encrypted.");
|
||||
DEFINE_string(
|
||||
certificate_path, "",
|
||||
"Indicates the file path to the certificate chain. Should not be empty.");
|
||||
DEFINE_string(certificate_private_key_path, "",
|
||||
"Indicaets the file path to the certificate private key. Should "
|
||||
"not be empty.");
|
||||
DEFINE_string(
|
||||
output_path, "",
|
||||
"Specifies where to write the output message. Should not be empty.");
|
||||
|
||||
namespace widevine {
|
||||
|
||||
bool GenerateProvisioningMessage(const std::string& service_public_key,
|
||||
const std::string& certificate,
|
||||
const std::string& private_key, std::string* message) {
|
||||
ClientIdentification client_id;
|
||||
client_id.set_token(certificate);
|
||||
client_id.set_type(ClientIdentification::OEM_DEVICE_CERTIFICATE);
|
||||
|
||||
ProvisioningRequest request;
|
||||
if (service_public_key.empty()) {
|
||||
*request.mutable_client_id() = client_id;
|
||||
} else {
|
||||
auto encrypted_id = request.mutable_encrypted_client_id();
|
||||
CHECK(RandomBytes(16, encrypted_id->mutable_encrypted_client_id_iv()));
|
||||
std::string privacy_key;
|
||||
CHECK(RandomBytes(16, &privacy_key));
|
||||
encrypted_id->set_encrypted_client_id(crypto_util::EncryptAesCbc(
|
||||
privacy_key, encrypted_id->encrypted_client_id_iv(),
|
||||
client_id.SerializeAsString()));
|
||||
std::unique_ptr<RsaPublicKey> service_key(
|
||||
RsaPublicKey::Create(service_public_key));
|
||||
if (!service_key) return false;
|
||||
CHECK(service_key->Encrypt(privacy_key,
|
||||
encrypted_id->mutable_encrypted_privacy_key()));
|
||||
}
|
||||
|
||||
CHECK(RandomBytes(4, request.mutable_nonce()));
|
||||
|
||||
SignedProvisioningMessage signed_message;
|
||||
signed_message.set_message(request.SerializeAsString());
|
||||
std::unique_ptr<RsaPrivateKey> signer(RsaPrivateKey::Create(private_key));
|
||||
CHECK(signer->GenerateSignature(signed_message.message(),
|
||||
signed_message.mutable_signature()));
|
||||
*message = signed_message.SerializeAsString();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
using widevine::GetContents;
|
||||
using widevine::SetContents;
|
||||
using widevine::GenerateProvisioningMessage;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
std::string service_public_key;
|
||||
if (!FLAGS_service_public_key_path.empty()) {
|
||||
if (!GetContents(FLAGS_service_public_key_path, &service_public_key))
|
||||
return 1;
|
||||
}
|
||||
std::string certificate;
|
||||
if (!GetContents(FLAGS_certificate_path, &certificate)) return 1;
|
||||
std::string private_key;
|
||||
if (!GetContents(FLAGS_certificate_private_key_path, &private_key)) return 1;
|
||||
std::string message;
|
||||
if (!GenerateProvisioningMessage(service_public_key, certificate, private_key,
|
||||
&message))
|
||||
return 1;
|
||||
if (!SetContents(FLAGS_output_path, message)) return 1;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user