Source release v3.2.0
This commit is contained in:
@@ -36,7 +36,7 @@ void PrintTo(const PatternTestVariant& param, ostream* os);
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
const size_t kNumKeys = 4;
|
||||
const size_t kMaxNumKeys = 20;
|
||||
|
||||
namespace {
|
||||
#if defined(TEST_SPEED_MULTIPLIER) // Can slow test time limits when
|
||||
@@ -66,7 +66,10 @@ const 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 kMaxTestRSAKeyLength = 2000; // Rough estimate.
|
||||
const size_t kMaxPSTLength = 255; // In specification.
|
||||
const size_t kMaxMessageSize = 8 * 1024; // In specification.
|
||||
const size_t kMaxDecryptSize = 100 * 1024; // In specification.
|
||||
|
||||
typedef struct {
|
||||
uint8_t key_id[kTestKeyIdMaxLength];
|
||||
@@ -83,12 +86,14 @@ typedef struct {
|
||||
|
||||
// This structure will be signed to simulate a message from the server.
|
||||
struct MessageData {
|
||||
MessageKeyData keys[kNumKeys];
|
||||
MessageKeyData keys[kMaxNumKeys];
|
||||
uint8_t mac_key_iv[wvcdm::KEY_IV_SIZE];
|
||||
uint8_t mac_keys[2 * wvcdm::MAC_KEY_SIZE];
|
||||
uint8_t pst[kTestKeyIdMaxLength];
|
||||
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[wvcdm::KEY_IV_SIZE];
|
||||
@@ -113,79 +118,177 @@ class Session {
|
||||
Session();
|
||||
~Session();
|
||||
|
||||
// Returns the most recently generated nonce.
|
||||
// Valid after call to GenerateNonce.
|
||||
uint32_t get_nonce() { return nonce_; }
|
||||
|
||||
// Valid after call to open().
|
||||
uint32_t session_id() { return (uint32_t)session_id_; }
|
||||
|
||||
// Call OEMCrypto_OpenSession, with GTest ASSERTs.
|
||||
void open();
|
||||
// Call OEMCrypto_CloseSession, with GTest ASSERTs.
|
||||
void close();
|
||||
// Artifically set session id without calling OEMCrypto_OpenSession. This is
|
||||
// used in core/test/generic_crypto_unittest.cpp.
|
||||
void SetSessionId(uint32_t session_id);
|
||||
|
||||
uint32_t GetOecSessionId() { return session_id_; }
|
||||
void GenerateNonce(uint32_t* nonce, int* error_counter = NULL);
|
||||
// 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);
|
||||
// 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);
|
||||
// Generate known mac and enc keys using OEMCrypto_GenerateDerivedKeys and
|
||||
// also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||
void GenerateDerivedKeysFromKeybox();
|
||||
// Generate known mac and enc keys using OEMCrypto_DeriveKeysFromSessionKey
|
||||
// and also fill out enc_key_, mac_key_server_, and mac_key_client_.
|
||||
void GenerateDerivedKeysFromSessionKey();
|
||||
void GenerateTestSessionKeys();
|
||||
// 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);
|
||||
// This uses OEMCrypto_QueryKeyControl to check that the keys in OEMCrypto
|
||||
// have the correct key control data.
|
||||
void VerifyTestKeys();
|
||||
// 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 = "");
|
||||
|
||||
// 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);
|
||||
// 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();
|
||||
void EncryptMessage(RSAPrivateKeyMessage* data,
|
||||
RSAPrivateKeyMessage* encrypted);
|
||||
|
||||
template <typename T>
|
||||
void ServerSignMessage(const T& data, std::vector<uint8_t>* signature);
|
||||
|
||||
// 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);
|
||||
void EncryptCTR(
|
||||
const vector<uint8_t>& in_buffer, const uint8_t *key,
|
||||
const uint8_t* starting_iv, vector<uint8_t>* out_buffer);
|
||||
// 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);
|
||||
// Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption.
|
||||
void TestDecryptCTR(bool select_key_first = true,
|
||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS);
|
||||
void MakeRSACertificate(
|
||||
struct RSAPrivateKeyMessage* encrypted, std::vector<uint8_t>* signature,
|
||||
uint32_t allowed_schemes, const vector<uint8_t>& rsa_key);
|
||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
||||
int key_index = 0);
|
||||
// Calls OEMCrypto_GetOEMPublicCertificate 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,
|
||||
const std::vector<uint8_t>& signature,
|
||||
size_t message_size, const std::vector<uint8_t>& signature,
|
||||
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,
|
||||
size_t rsa_key_length = 0);
|
||||
static bool VerifyPSSSignature(
|
||||
EVP_PKEY* pkey, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length);
|
||||
void VerifyRSASignature(
|
||||
const vector<uint8_t>& message, const uint8_t* signature,
|
||||
size_t signature_length, RSA_Padding_Scheme padding_scheme);
|
||||
bool GenerateRSASessionKey(vector<uint8_t>* enc_session_key);
|
||||
// Verifies the given signature is from the given message and RSA key, pkey.
|
||||
static bool VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length);
|
||||
// Verify that the message was signed by the private key associated with
|
||||
// |public_rsa_| using the specified padding scheme.
|
||||
void VerifyRSASignature(const vector<uint8_t>& message,
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
RSA_Padding_Scheme padding_scheme);
|
||||
// Encrypts a known session key with public_rsa_ for use in future calls to
|
||||
// OEMCrypto_DeriveKeysFromSessionKey or OEMCrypto_RewrapDeviceRSAKey30.
|
||||
// The unencrypted session key is stored in session_key.
|
||||
bool GenerateRSASessionKey(vector<uint8_t>* session_key,
|
||||
vector<uint8_t>* enc_session_key);
|
||||
// Calls OEMCrypto_RewrapDeviceRSAKey30 with the given provisioning response
|
||||
// message. If force is true, we assert that the key loads successfully.
|
||||
void RewrapRSAKey30(const struct RSAPrivateKeyMessage& encrypted,
|
||||
size_t message_size,
|
||||
const std::vector<uint8_t>& encrypted_message_key,
|
||||
vector<uint8_t>* wrapped_key, bool force);
|
||||
// Loads the specified wrapped_rsa_key into OEMCrypto, and then runs
|
||||
// GenerateDerivedKeysFromSessionKey to install known encryption and mac keys.
|
||||
void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key);
|
||||
void DisallowDeriveKeys();
|
||||
// Generates a usage report for the specified pst. If expect_success is true,
|
||||
// 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
|
||||
// order to verify signatures.
|
||||
void GenerateReport(const std::string& pst, bool expect_success = true,
|
||||
Session* other = 0);
|
||||
// Returns a pointer to the usage report generated by the previous call to
|
||||
// GenerateReport.
|
||||
OEMCrypto_PST_Report* pst_report();
|
||||
// Creates a signed delete usage table entry message and calls
|
||||
// OEMCrypto_DeleteUsageEntry on it.
|
||||
void DeleteEntry(const std::string& pst);
|
||||
// Calls OEMCrypto_ForceDeleteUsageEntry to delete a usage table entry without
|
||||
// a signed message.
|
||||
void ForceDeleteEntry(const std::string& pst);
|
||||
|
||||
// The unencrypted license response or license renewal response.
|
||||
MessageData& license() { return license_; }
|
||||
MessageData& encrypted_license() { return encrypted_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();
|
||||
|
||||
// An array of key objects for use in LoadKeys.
|
||||
OEMCrypto_KeyObject* key_array() { return key_array_; }
|
||||
// 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().
|
||||
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_; }
|
||||
|
||||
private:
|
||||
bool open_;
|
||||
bool forced_session_id_;
|
||||
@@ -197,9 +300,13 @@ class Session {
|
||||
RSA* public_rsa_;
|
||||
vector<uint8_t> pst_report_buffer_;
|
||||
MessageData license_;
|
||||
MessageData encrypted_license_;
|
||||
OEMCrypto_KeyObject key_array_[kNumKeys];
|
||||
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];
|
||||
std::vector<uint8_t> signature_;
|
||||
int num_keys_;
|
||||
};
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
Reference in New Issue
Block a user