OEMCrypto v16.1

Merge of http://go/wvgerrit/93404

This CL updates the Widevine CDM to support OEMCrypto v16.1

Test: Tested in 16.2 CL
Bug: 141247171
Change-Id: I69bd993500f6fb63bf6010c8b0250dc7acc3d71b
This commit is contained in:
Fred Gylys-Colwell
2020-01-18 10:11:24 -08:00
parent 7e2619e379
commit 7665614b2e
132 changed files with 12331 additions and 9341 deletions

View File

@@ -7,12 +7,17 @@
//
// OEMCrypto unit tests
//
#include <gtest/gtest.h>
#include <openssl/rsa.h>
#include <time.h>
#include <string>
#include <vector>
#include "core_message_deserialize.h"
#include "core_message_serialize.h"
#include "odk.h"
#include "oec_device_features.h"
#include "oec_key_deriver.h"
#include "oemcrypto_types.h"
#include "pst_report.h"
@@ -29,21 +34,21 @@ void PrintTo(const vector<uint8_t>& value, ostream* os);
namespace wvoec {
// Make sure this is larger than kMaxKeysPerSession, in oemcrypto_test.cpp
const size_t kMaxNumKeys = 20;
constexpr size_t kMaxNumKeys = 30;
namespace {
#if defined(TEST_SPEED_MULTIPLIER) // Can slow test time limits when
// debugging is slowing everything.
const int kSpeedMultiplier = TEST_SPEED_MULTIPLIER;
constexpr int kSpeedMultiplier = TEST_SPEED_MULTIPLIER;
#else
const int kSpeedMultiplier = 1;
constexpr int kSpeedMultiplier = 1;
#endif
const int kShortSleep = 1 * kSpeedMultiplier;
const int kLongSleep = 2 * kSpeedMultiplier;
const uint32_t kDuration = 2 * kSpeedMultiplier;
const uint32_t kLongDuration = 5 * kSpeedMultiplier;
const int32_t kTimeTolerance = 3 * kSpeedMultiplier;
const time_t kUsageTableTimeTolerance = 10 * kSpeedMultiplier;
constexpr int kShortSleep = 1 * kSpeedMultiplier;
constexpr int kLongSleep = 2 * kSpeedMultiplier;
constexpr uint32_t kDuration = 2 * kSpeedMultiplier;
constexpr uint32_t kLongDuration = 5 * kSpeedMultiplier;
constexpr int32_t kTimeTolerance = 3 * kSpeedMultiplier;
constexpr int64_t kUsageTableTimeTolerance = 10 * kSpeedMultiplier;
} // namespace
typedef struct {
@@ -55,14 +60,12 @@ typedef struct {
// Note: The API does not specify a maximum key id length. We specify a
// maximum just for these tests, so that we have a fixed message size.
const size_t kTestKeyIdMaxLength = 16;
constexpr size_t kTestKeyIdMaxLength = 16;
// Most content will use a key id that is 16 bytes long.
const int kDefaultKeyIdLength = 16;
const size_t kMaxTestRSAKeyLength = 2000; // Rough estimate.
const size_t kMaxPSTLength = 255; // In specification.
const size_t kMaxMessageSize = 8 * 1024; // In specification.
constexpr int kDefaultKeyIdLength = 16;
constexpr size_t kMaxPSTLength = 255; // In specification.
constexpr size_t kMaxCoreMessage = 200 * kMaxNumKeys + 200; // Rough estimate.
typedef struct {
uint8_t key_id[kTestKeyIdMaxLength];
@@ -84,37 +87,40 @@ struct MessageData {
uint8_t padding[KEY_IV_SIZE];
uint8_t mac_keys[2 * MAC_KEY_SIZE];
uint8_t pst[kMaxPSTLength];
};
// This structure will be signed to simulate a provisioning response from the
// server.
struct RSAPrivateKeyMessage {
uint8_t rsa_key[kMaxTestRSAKeyLength];
uint8_t rsa_key_iv[KEY_IV_SIZE];
size_t rsa_key_length;
uint32_t nonce;
SRM_Restriction_Data srm_restriction_data;
};
struct Test_PST_Report {
Test_PST_Report(const std::string& pst_in,
OEMCrypto_Usage_Entry_Status status_in)
: status(status_in), pst(pst_in), time_created(time(NULL)) {}
OEMCrypto_Usage_Entry_Status status_in);
OEMCrypto_Usage_Entry_Status status;
int64_t seconds_since_license_received;
int64_t seconds_since_first_decrypt;
int64_t seconds_since_last_decrypt;
std::string pst;
time_t time_created;
int64_t time_created;
};
struct EntitledContentKeyData {
uint8_t entitlement_key_id[KEY_SIZE];
uint8_t content_key_id[KEY_SIZE];
uint8_t content_key_data_iv[KEY_SIZE];
uint8_t entitlement_key_id[kTestKeyIdMaxLength];
size_t entitlement_key_id_length;
uint8_t content_key_id[kTestKeyIdMaxLength];
size_t content_key_id_length;
uint8_t content_key_data_iv[KEY_IV_SIZE];
uint8_t content_key_data[KEY_SIZE];
uint8_t encrypted_content_key_data[KEY_SIZE];
size_t key_index; // Index into the license's key array. Only for testing.
};
// returns 1 on success, -1 if not supported, or 0 if other failure.
int GetRandBytes(unsigned char* buf, int num);
void GenerateSimpleSampleDescription(const std::vector<uint8_t>& in,
std::vector<uint8_t>& out,
OEMCrypto_SampleDescription* sample,
OEMCrypto_SubSampleDescription* subsample);
// Increment counter for AES-CTR. The CENC spec specifies we increment only
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This
// is different from the OpenSSL implementation, so we implement the CTR loop
@@ -134,6 +140,288 @@ OEMCrypto_Substring GetSubstring(const std::string& message = "",
const std::string& field = "",
bool set_zero = false);
class Session;
// The prototype of the OEMCrypto function to prepare and sign a request.
typedef OEMCryptoResult (*PrepAndSignRequest_t)(
OEMCrypto_SESSION session, uint8_t* message, size_t message_length,
size_t* core_message_length, uint8_t* signature, size_t* signature_length);
// A RoundTrip helps generate and verify a request message, helps generate the
// corresponding response, and then helps verify loading the response.
template <class CoreRequest, PrepAndSignRequest_t PrepAndSignRequest,
class CoreResponse, class ResponseData>
class RoundTrip {
public:
RoundTrip() = delete;
RoundTrip(Session* session)
: session_(session),
core_request_(),
core_response_(),
response_data_(),
encrypted_response_data_(),
message_size_(sizeof(ResponseData) + kMaxCoreMessage){};
virtual ~RoundTrip() {}
// Have OEMCrypto sign a request message and then verify the signature and the
// core message.
virtual void SignAndVerifyRequest();
// Create a default |response_data| and |core_response|.
virtual void CreateDefaultResponse() = 0;
// Copy fields from |response_data| to |padded_response_data|, encrypting
// those that should be encrypted. Serialize the core message. Then sign the
// response.
virtual void EncryptAndSignResponse() = 0;
// Attempt to load the response and return the error. Short buffer errors are
// handled by LoadResponse, not the caller. All other errors should be
// handled by the caller.
virtual OEMCryptoResult LoadResponse() { return LoadResponse(session_); }
// As with LoadResponse, but load into a different session.
virtual OEMCryptoResult LoadResponse(Session* session) = 0;
// Accessors are all read/write because tests modify default values.
Session* session() { return session_; }
void set_session(Session* session) { session_ = session; }
CoreRequest& core_request() { return core_request_; }
CoreResponse& core_response() { return core_response_; }
ResponseData& response_data() { return response_data_; }
ResponseData& encrypted_response_data() { return encrypted_response_data_; }
std::vector<uint8_t>& encrypted_response_buffer() {
return encrypted_response_;
}
// Set the size of the buffer used the encrypted license.
void set_message_size(size_t size) { message_size_ = size; }
// The size of the encrypted message.
size_t message_size() { return message_size_; }
std::vector<uint8_t>& response_signature() { return response_signature_; }
const std::string& serialized_core_message() const {
return serialized_core_message_;
}
protected:
// ----------------------------------------------------------------------
// Specialized functionality for each message type.
// Verify the signature of the request.
virtual void VerifyRequestSignature(
const vector<uint8_t>& data, const vector<uint8_t>& generated_signature,
size_t core_message_length) = 0;
// Verify the values of the core response.
virtual void FillAndVerifyCoreRequest(
const std::string& core_message_string) = 0;
// Find the given pointer in the response_data_.
virtual OEMCrypto_Substring FindSubstring(const void* pointer, size_t length);
// ----------------------------------------------------------------------
// Member variables.
Session* session_;
CoreRequest core_request_;
CoreResponse core_response_;
ResponseData response_data_, encrypted_response_data_;
size_t message_size_; // How much of the padded message to use.
std::vector<uint8_t> response_signature_;
std::string serialized_core_message_;
std::vector<uint8_t> encrypted_response_;
};
class ProvisioningRoundTrip
: public RoundTrip<
/* CoreRequest */ oemcrypto_core_message::ODK_ProvisioningRequest,
OEMCrypto_PrepAndSignProvisioningRequest,
/* CoreResponse */ ODK_ParsedProvisioning,
/* ResponseData */ RSAPrivateKeyMessage> {
public:
ProvisioningRoundTrip(Session* session,
const std::vector<uint8_t>& encoded_rsa_key)
: RoundTrip(session),
allowed_schemes_(kSign_RSASSA_PSS),
encryptor_(),
encoded_rsa_key_(encoded_rsa_key) {}
// Prepare the session for signing the request.
virtual void PrepareSession(const wvoec::WidevineKeybox& keybox);
void CreateDefaultResponse() override;
void EncryptAndSignResponse() override;
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
OEMCryptoResult LoadResponse(Session* session) override;
void VerifyLoadFailed();
const std::vector<uint8_t>& encoded_rsa_key() { return encoded_rsa_key_; }
const std::vector<uint8_t>& wrapped_rsa_key() { return wrapped_rsa_key_; }
void set_allowed_schemes(uint32_t allowed_schemes) {
allowed_schemes_ = allowed_schemes;
}
protected:
void VerifyRequestSignature(const vector<uint8_t>& data,
const vector<uint8_t>& generated_signature,
size_t core_message_length) override;
// Verify the values of the core response.
virtual void FillAndVerifyCoreRequest(
const std::string& core_message_string) override;
uint32_t allowed_schemes_;
Encryptor encryptor_;
// The message key used for Prov 3.0.
std::vector<uint8_t> message_key_;
std::vector<uint8_t> encrypted_message_key_;
std::vector<uint8_t> encoded_rsa_key_;
std::vector<uint8_t> wrapped_rsa_key_;
};
class LicenseRoundTrip
: public RoundTrip<
/* CoreRequest */ oemcrypto_core_message::ODK_LicenseRequest,
OEMCrypto_PrepAndSignLicenseRequest,
/* CoreResponse */ ODK_ParsedLicense,
/* ResponseData */ MessageData> {
public:
LicenseRoundTrip(Session* session)
: RoundTrip(session),
control_(wvoec::kControlNonceEnabled),
num_keys_(4),
pst_(""),
minimum_srm_version_(0),
update_mac_keys_(true),
api_version_(kCurrentAPI),
expect_request_has_correct_nonce_(true),
license_type_(OEMCrypto_ContentLicense) {}
void CreateDefaultResponse() override;
// Create a license with four keys. Each key is responsible for one of generic
// encrypt (key 0), decrypt (key 1), sign (key 2) and verify (key 3). Each key
// is allowed only one type of operation.
void CreateResponseWithGenericCryptoKeys();
// Fill the |core_response| substrings.
virtual void FillCoreResponseSubstrings();
void EncryptAndSignResponse() override;
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
OEMCryptoResult LoadResponse(Session* session) override;
// Reload an offline license into a different session. This derives new mac
// keys and then calls LoadResponse.
OEMCryptoResult ReloadResponse(Session* session);
void VerifyTestKeys();
// Set the default key control block for all keys. This is used in
// CreateDefaultResponse. The key control block determines the restrictions
// that OEMCrypto should place on a key's use. For example, it specifies the
// minimum HDCP requirement and whether the key can only be used with a secure
// video path. See the section "Key Control Block" in the document "Widevine
// Modular DRM Security Integration Guide for CENC".
void set_control(uint32_t control) { control_ = control; }
uint32_t control() const { return control_; }
// Set the number of keys to use in the license.
void set_num_keys(uint32_t num_keys) { num_keys_ = num_keys; }
uint32_t num_keys() const { return num_keys_; }
// Get/Set the pst for the license and usage table entry.
const std::string& pst() const { return pst_; }
void set_pst(const std::string& pst) { pst_ = pst; }
// Set the minimum SRM version for the license.
void set_minimum_srm_version(uint32_t minimum_srm_version) {
minimum_srm_version_ = minimum_srm_version;
}
// Change the hash of the core request. This should cause the response to be
// rejected.
void BreakRequestHash() { core_response_.request_hash[3] ^= 42; }
// Set the API version for the license itself. This will be used in
// CreateDefaultResponse.
void set_api_version(uint32_t api_version) { api_version_ = api_version; }
uint32_t api_version() const { return api_version_; }
void set_update_mac_keys(bool update_mac_keys) {
update_mac_keys_ = update_mac_keys;
}
void set_license_type(OEMCrypto_LicenseType license_type) {
license_type_ = license_type;
}
// Skip the nonce check when verifying the license request.
void skip_nonce_check() { expect_request_has_correct_nonce_ = false; }
// This sets the key id of the specified key to the specified string.
// This is used to test with different key id lengths.
void SetKeyId(size_t index, const string& key_id);
protected:
void VerifyRequestSignature(const vector<uint8_t>& data,
const vector<uint8_t>& generated_signature,
size_t core_message_length) override;
// Verify the values of the core response.
virtual void FillAndVerifyCoreRequest(
const std::string& core_message_string) override;
// The default key control bits used with CreateDefaultResponse.
uint32_t control_;
// The number of keys in the license response.
uint32_t num_keys_;
// If non-empty, the license's provider session token.
std::string pst_;
// If non-zero, the minimum SRM version.
uint32_t minimum_srm_version_;
// If true, the license contains new mac keys for signing renewals.
bool update_mac_keys_;
// API version for the license itself. If this is 0 when the license request
// is signed, it will be set to the same as OEMCrypto's API version. It may
// be set to a lower value in order to test backwards compatibility.
uint32_t api_version_;
// If true, then we expect the nonce in the core request to match that in
// session. This is usually true, but when we are testing how OEMCrypto
// handles a bad nonce, we don't want to.
bool expect_request_has_correct_nonce_;
// Whether this is a content license or an entitlement license. Used in
// CreateDefaultResponse.
OEMCrypto_LicenseType license_type_;
};
class RenewalRoundTrip
: public RoundTrip<
/* CoreRequest */ oemcrypto_core_message::ODK_RenewalRequest,
OEMCrypto_PrepAndSignRenewalRequest,
// Renewal response info is same as request:
/* CoreResponse */ oemcrypto_core_message::ODK_RenewalRequest,
/* ResponseData */ MessageData> {
public:
RenewalRoundTrip(LicenseRoundTrip* license_messages)
: RoundTrip(license_messages->session()),
license_messages_(license_messages),
refresh_object_(),
is_release_(false) {}
void CreateDefaultResponse() override;
void EncryptAndSignResponse() override;
OEMCryptoResult LoadResponse() override { return LoadResponse(session_); }
OEMCryptoResult LoadResponse(Session* session) override;
void set_is_release(bool is_release) { is_release_ = is_release; }
protected:
void VerifyRequestSignature(const vector<uint8_t>& data,
const vector<uint8_t>& generated_signature,
size_t core_message_length) override;
// Verify the values of the core response.
virtual void FillAndVerifyCoreRequest(
const std::string& core_message_string) override;
LicenseRoundTrip* license_messages_;
OEMCrypto_KeyRefreshObject refresh_object_;
bool is_release_; // If this is a license release, and not a real renewal.
};
class EntitledMessage {
public:
EntitledMessage(LicenseRoundTrip* license_messages)
: license_messages_(license_messages), num_keys_() {}
void FillKeyArray();
void MakeOneKey(size_t entitlement_key_index);
void LoadKeys(OEMCryptoResult expected_sts);
void set_num_keys(uint32_t num_keys) { num_keys_ = num_keys; }
uint32_t num_keys() const { return num_keys_; }
void SetEntitlementKeyId(unsigned int index, const std::string& key_id);
// Verify that key control blocks of the loaded keys.
void VerifyEntitlementTestKeys();
private:
// Find the offset of the give pointer, relative to |entitled_key_data_|.
OEMCrypto_Substring FindSubstring(const void* ptr, size_t size);
LicenseRoundTrip* license_messages_;
uint32_t num_keys_;
// Clear Entitlement key data. This is the backing data for
// |entitled_key_array_|.
EntitledContentKeyData entitled_key_data_[kMaxNumKeys];
// Entitled key object. Pointers are backed by |entitled_key_data_|.
OEMCrypto_EntitledContentKeyObject entitled_key_array_[kMaxNumKeys];
};
class Session {
public:
Session();
@@ -141,9 +429,9 @@ class Session {
// Returns the most recently generated nonce.
// Valid after call to GenerateNonce.
uint32_t get_nonce() { return nonce_; }
uint32_t nonce() const { return nonce_; }
// Valid after call to open().
uint32_t session_id() { return (uint32_t)session_id_; }
uint32_t session_id() const { return (uint32_t)session_id_; }
// Call OEMCrypto_OpenSession, with GTest ASSERTs.
void open();
// Call OEMCrypto_CloseSession, with GTest ASSERTs.
@@ -155,7 +443,7 @@ class Session {
// Generates one nonce. If error_counter is null, this will sleep 1 second
// and try again if a nonce flood has been detected. If error_counter is
// not null, it will be incremented when a nonce flood is detected.
void GenerateNonce(int* error_counter = NULL);
void GenerateNonce(int* error_counter = nullptr);
// Fill the vectors with test context which generate known mac and enc keys.
void FillDefaultContext(vector<uint8_t>* mac_context,
vector<uint8_t>* enc_context);
@@ -165,87 +453,6 @@ class Session {
// Generate known mac and enc keys using OEMCrypto_DeriveKeysFromSessionKey
// and also fill out enc_key_, mac_key_server_, and mac_key_client_.
void GenerateDerivedKeysFromSessionKey();
// Loads and verifies the keys in the message pointed to by message_ptr()
// using OEMCrypto_LoadKeys. This message should have already been created
// by FillSimpleMessage, modified if needed, and then encrypted and signed by
// the server's mac key in EncryptAndSign.
void LoadTestKeys(const std::string& pst = "", bool new_mac_keys = true);
// Loads the entitlement keys in the message pointed to by message_ptr()
// using OEMCrypto_LoadKeys. This message should have already been created
// by FillSimpleEntitlementMessage, modified if needed, and then encrypted
// and signed by the server's mac key in EncryptAndSign.
void LoadEntitlementTestKeys(const std::string& pst = "",
bool new_mac_keys = true,
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
// Fills an OEMCrypto_EntitledContentKeyObject using the information from
// the license_ and randomly generated content keys. This method should be
// called after LoadEntitlementTestKeys.
void FillEntitledKeyArray();
// Encrypts and loads the entitled content keys via
// OEMCrypto_LoadEntitledContentKeys.
void LoadEntitledContentKeys(
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
// This uses OEMCrypto_QueryKeyControl to check that the keys in OEMCrypto
// have the correct key control data.
void VerifyTestKeys();
// This uses OEMCrypto_QueryKeyControl to check that the keys in OEMCrypto
// have the correct key control data.
void VerifyEntitlementTestKeys();
// This creates a refresh key or license renewal message, signs it with the
// server's mac key, and calls OEMCrypto_RefreshKeys.
void RefreshTestKeys(const size_t key_count, uint32_t control_bits,
uint32_t nonce, OEMCryptoResult expected_result);
// This sets the key id in the current message data to the specified string.
// This is used to test with different key id lengths.
void SetKeyId(int index, const string& key_id);
// This fills the data structure license_ with key information. This data
// can be modified, and then should be encrypted and signed in EncryptAndSign
// before being loaded in LoadTestKeys.
void FillSimpleMessage(uint32_t duration, uint32_t control, uint32_t nonce,
const std::string& pst = "");
// This fills the data structure license_ with entitlement key information.
// This data can be modified, and then should be encrypted and signed in
// EncryptAndSign before being loaded in LoadEntitlementTestKeys.
void FillSimpleEntitlementMessage(
uint32_t duration, uint32_t control,
uint32_t nonce, const std::string& pst = "");
// Like FillSimpleMessage, this fills encrypted_license_ with data. The name
// is a little misleading: the license renewal message is not encrypted, it
// is just signed. The signature is computed in RefreshTestKeys, above.
void FillRefreshMessage(size_t key_count, uint32_t control_bits,
uint32_t nonce);
// Sets the OEMCrypto_Substring parameters of the LoadKeys method.
// Specifically, it sets the |enc_mac_keys_iv|, |enc_mac_keys|, |pst|, and
// |srm_restriction_data| in that order. For testing purposes,
// |srm_restriction_data| will always be NULL.
void SetLoadKeysSubstringParams();
// This copies data from license_ to encrypted_license_, and then encrypts
// each field in the key array appropriately. It then signes the buffer with
// the server mac keys. It then fills out the key_array_ so that pointers in
// that array point to the locations in the encrypted message.
void EncryptAndSign();
// This encrypts an RSAPrivateKeyMessage with encryption_key so that it may be
// loaded with OEMCrypto_RewrapDeviceRSAKey.
void EncryptProvisioningMessage(RSAPrivateKeyMessage* data,
RSAPrivateKeyMessage* encrypted,
const vector<uint8_t>& encryption_key);
// Sign the buffer with server's mac key.
void ServerSignBuffer(const uint8_t* data, size_t data_length,
std::vector<uint8_t>* signature);
// Sign the buffer with client's known mac key. Known test keys must be
// installed first.
void ClientSignMessage(const vector<uint8_t>& data,
std::vector<uint8_t>* signature);
// This checks the signature generated by OEMCrypto_GenerateSignature against
// that generaged by ClientSignMessage.
void VerifyClientSignature(size_t data_length = 400);
// Set the pointers in key_array[*] to point values inside data. This is
// needed to satisfy range checks in OEMCrypto_LoadKeys.
void FillKeyArray(const MessageData& data, OEMCrypto_KeyObject* key_array);
// As in FillKeyArray but for the license renewal message passed to
// OEMCrypto_RefreshKeys.
void FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
size_t key_count);
// Encrypt a block of data using CTR mode.
void EncryptCTR(const vector<uint8_t>& in_buffer, const uint8_t* key,
const uint8_t* starting_iv, vector<uint8_t>* out_buffer);
@@ -253,24 +460,12 @@ class Session {
void TestDecryptCTR(bool select_key_first = true,
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
int key_index = 0);
// This compares the actual result with the expected result. If OEMCrypto is
// an older version, we allow it to report an equivalent error code.
void TestDecryptResult(OEMCryptoResult expected_result,
OEMCryptoResult actual_result);
// Verify that an attempt to select an expired key either succeeds, or gives
// an actionable error code.
void TestSelectExpired(unsigned int key_index);
// Calls OEMCrypto_GetOEMPublicCertificate and loads the OEM cert's public
// rsa key into public_rsa_.
// Calls OEMCrypto_GetOEMPublicCertificate and OEMCrypto_LoadOEMPrivateKey and
// loads the OEM cert's public rsa key into public_rsa_.
void LoadOEMCert(bool verify_cert = false);
// Creates RSAPrivateKeyMessage for the specified rsa_key, encrypts it with
// the specified encryption key, and then signs it with the server's mac key.
// If encryption_key is null, use the session's enc_key_.
void MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted,
size_t message_size, std::vector<uint8_t>* signature,
uint32_t allowed_schemes,
const vector<uint8_t>& rsa_key,
const vector<uint8_t>* encryption_key = NULL);
// Calls OEMCrypto_RewrapDeviceRSAKey with the given provisioning response
// message. If force is true, we assert that the key loads successfully.
void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
@@ -278,7 +473,7 @@ class Session {
vector<uint8_t>* wrapped_key, bool force);
// Loads the specified RSA public key into public_rsa_. If rsa_key is null,
// the default test key is loaded.
void PreparePublicKey(const uint8_t* rsa_key = NULL,
void PreparePublicKey(const uint8_t* rsa_key = nullptr,
size_t rsa_key_length = 0);
// Verifies the given signature is from the given message and RSA key, pkey.
static bool VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
@@ -306,7 +501,7 @@ class Session {
// Creates a new usage entry, and keeps track of the index.
// If status is null, we expect success, otherwise status is set to the
// return value.
void CreateNewUsageEntry(OEMCryptoResult *status = NULL);
void CreateNewUsageEntry(OEMCryptoResult* status = nullptr);
// Copy encrypted usage entry from other session, and then load it.
// This session must already be open.
void LoadUsageEntry(uint32_t index, const vector<uint8_t>& buffer);
@@ -330,7 +525,7 @@ class Session {
}
// Generates a usage report for the specified pst. If there is success,
// the report's signature is verified, and several fields are given sanity
// checks. If other is not null, then the mac keys are copied from other in
// checks. If |other| is not null, then the mac keys are copied from other in
// order to verify signatures.
void GenerateReport(const std::string& pst,
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
@@ -355,12 +550,6 @@ class Session {
int64_t time_license_received = 0,
int64_t time_first_decrypt = 0,
int64_t time_last_decrypt = 0);
// Same as above, but generates the report with the given status.
void GenerateVerifyReport(const std::string& pst,
OEMCrypto_Usage_Entry_Status status,
int64_t time_license_received = 0,
int64_t time_first_decrypt = 0,
int64_t time_last_decrypt = 0);
// Create an entry in the old usage table based on the given report.
void CreateOldEntry(const Test_PST_Report &report);
// Create a new entry and copy the old entry into it. Then very the report
@@ -370,88 +559,33 @@ class Session {
// The unencrypted license response or license renewal response.
MessageData& license() { return license_; }
// The encrypted license response or license renewal response.
MessageData& encrypted_license() { return padded_message_; }
// A pointer to the buffer holding encrypted_license.
const uint8_t* message_ptr();
void set_license(const MessageData& license) { license_ = license; }
// An array of key objects for use in LoadKeys.
OEMCrypto_KeyObject* key_array() { return key_array_; }
// An array of key objects for LoadEntitledContentKeys.
OEMCrypto_EntitledContentKeyObject* entitled_key_array() {
return entitled_key_array_;
const KeyDeriver& key_deriver() const { return key_deriver_; }
void set_mac_keys(const uint8_t* mac_keys) {
key_deriver_.set_mac_keys(mac_keys);
}
// The last signature generated with the server's mac key.
std::vector<uint8_t>& signature() { return signature_; }
// Set the number of keys to use in the license(), encrypted_license()
// and key_array().
void set_num_keys(int num_keys) { num_keys_ = num_keys; }
// The current number of keys to use in the license(), encrypted_license()
// and key_array().
unsigned int num_keys() const { return num_keys_; }
// Set the size of the buffer used the encrypted license.
// Must be between sizeof(MessageData) and kMaxMessageSize.
void set_message_size(size_t size);
// The size of the encrypted message.
size_t message_size() { return message_size_; }
// The OEMCrypto_Substrings associated with the encrypted license that are
// passed to LoadKeys.
vector<OEMCrypto_Substring> load_keys_params() { return load_keys_params_; }
OEMCrypto_Substring enc_mac_keys_iv_substr() { return load_keys_params_[0]; }
OEMCrypto_Substring enc_mac_keys_substr() { return load_keys_params_[1]; }
OEMCrypto_Substring pst_substr() { return load_keys_params_[2]; }
OEMCrypto_Substring srm_restriction_data_substr() {
return load_keys_params_[3];
}
// Pointer to buffer holding |encrypted_entitled_message_|
const uint8_t* encrypted_entitled_message_ptr();
private:
// Generate mac and enc keys give the master key.
void DeriveKeys(const uint8_t* master_key,
const vector<uint8_t>& mac_key_context,
const vector<uint8_t>& enc_key_context);
// Internal utility function to derive key using CMAC-128
void DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
int counter, vector<uint8_t>* out);
// This compares the actual result with the expected result. If OEMCrypto is
// an older version, we allow it to report an equivalent error code.
void TestDecryptResult(OEMCryptoResult expected_result,
OEMCryptoResult actual_select_result,
OEMCryptoResult actual_decryt_result);
bool open_;
bool forced_session_id_;
OEMCrypto_SESSION session_id_;
vector<uint8_t> mac_key_server_;
vector<uint8_t> mac_key_client_;
vector<uint8_t> enc_key_;
KeyDeriver key_deriver_;
uint32_t nonce_;
RSA* public_rsa_;
vector<uint8_t> pst_report_buffer_;
MessageData license_;
struct PaddedMessageData : public MessageData {
uint8_t padding[kMaxMessageSize - sizeof(MessageData)];
} padded_message_;
size_t message_size_; // How much of the padded message to use.
OEMCrypto_KeyObject key_array_[kMaxNumKeys];
vector<OEMCrypto_Substring> load_keys_params_;
std::vector<uint8_t> signature_;
unsigned int num_keys_;
vector<uint8_t> encrypted_usage_entry_;
uint32_t usage_entry_number_;
string pst_;
// Clear Entitlement key data. This is the backing data for
// |entitled_key_array_|.
EntitledContentKeyData entitled_key_data_[kMaxNumKeys];
// Message containing data from |key_array| and |entitled_key_data_|.
std::string entitled_message_;
// Entitled key object. Pointers are backed by |entitled_key_data_|.
OEMCrypto_EntitledContentKeyObject entitled_key_array_[kMaxNumKeys];
std::string encrypted_entitled_message_;
};
} // namespace wvoec