//////////////////////////////////////////////////////////////////////////////// // 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 #include #include #include #include #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 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; }