From 67b06a70e4f053ebf80ca080cacb8122db89eeb9 Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Mon, 28 Nov 2016 21:44:36 -0800 Subject: [PATCH] Buffer Size Unit Tests Merge from widevine repo of http://go/wvgerrit/21260 This CL adds some oemcrypto unit tests for various buffer sizes, as described in b/28887904 and the OEMCrypto v12 specification. Encryption and Decryption buffers can be 100k large. License request and response messages can be 8k. A provider session token (pst) can be at most 255 bytes long. I also passed the code through clang-format. b/28887904 Change-Id: Ia3e317c0f6466e663461e66b610c9a98a90efb0a --- .../oemcrypto/test/oec_session_util.cpp | 216 +++---- .../oemcrypto/test/oec_session_util.h | 48 +- .../oemcrypto/test/oemcrypto_test.cpp | 541 +++++++++++++----- 3 files changed, 546 insertions(+), 259 deletions(-) diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index 100e6fb0..a6df4336 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -76,8 +76,14 @@ Session::Session() mac_key_client_(wvcdm::MAC_KEY_SIZE), enc_key_(wvcdm::KEY_SIZE), public_rsa_(0), - num_keys_(4) {} // Most tests only use 4 keys. - // Other tests will explicitly call set_num_keys. + message_size_(sizeof(MessageData)), + num_keys_(4) { // Most tests only use 4 keys. + // Other tests will explicitly call set_num_keys. + // Stripe the padded message. + for (int i = 0; i < sizeof(padded_message_.padding); i++) { + padded_message_.padding[i] = i % 0x100; + } +} Session::~Session() { if (!forced_session_id_ && open_) close(); @@ -194,25 +200,24 @@ void Session::GenerateTestSessionKeys() { void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) { uint8_t* pst_ptr = NULL; if (pst.length() > 0) { - pst_ptr = encrypted_license_.pst; + pst_ptr = encrypted_license().pst; } if (new_mac_keys) { ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys( - session_id(), message_ptr(), sizeof(MessageData), - &signature_[0], signature_.size(), - encrypted_license_.mac_key_iv, encrypted_license_.mac_keys, - num_keys_, key_array_, pst_ptr, pst.length())); + OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_, + &signature_[0], signature_.size(), + encrypted_license().mac_key_iv, + encrypted_license().mac_keys, num_keys_, + key_array_, pst_ptr, pst.length())); // Update new generated keys. memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE); memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE, wvcdm::MAC_KEY_SIZE); } else { - ASSERT_EQ( - OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(session_id(), message_ptr(), sizeof(MessageData), - &signature_[0], signature_.size(), NULL, NULL, - num_keys_, key_array_, pst_ptr, pst.length())); + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_, + &signature_[0], signature_.size(), NULL, NULL, + num_keys_, key_array_, pst_ptr, pst.length())); } VerifyTestKeys(); } @@ -222,8 +227,8 @@ void Session::VerifyTestKeys() { KeyControlBlock block; size_t size = sizeof(block); OEMCryptoResult sts = OEMCrypto_QueryKeyControl( - session_id(), license_.keys[i].key_id, license_.keys[i].key_id_length, - reinterpret_cast(&block), &size); + session_id(), license_.keys[i].key_id, license_.keys[i].key_id_length, + reinterpret_cast(&block), &size); if (sts != OEMCrypto_ERROR_NOT_IMPLEMENTED) { ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(sizeof(block), size); @@ -237,17 +242,17 @@ void Session::VerifyTestKeys() { } } -void Session::RefreshTestKeys(const size_t key_count, - uint32_t control_bits, uint32_t nonce, - OEMCryptoResult expected_result) { +void Session::RefreshTestKeys(const size_t key_count, uint32_t control_bits, + uint32_t nonce, OEMCryptoResult expected_result) { // Note: we store the message in encrypted_license_, but the refresh key // message is not actually encrypted. It is, however, signed. FillRefreshMessage(key_count, control_bits, nonce); - ServerSignMessage(encrypted_license_, &signature_); + ServerSignBuffer(reinterpret_cast(&padded_message_), + message_size_, &signature_); OEMCrypto_KeyRefreshObject key_array[key_count]; FillRefreshArray(key_array, key_count); OEMCryptoResult sts = OEMCrypto_RefreshKeys( - session_id(), message_ptr(), sizeof(MessageData), &signature_[0], + session_id(), message_ptr(), message_size_, &signature_[0], signature_.size(), key_count, key_array); ASSERT_EQ(expected_result, sts); @@ -272,9 +277,9 @@ void Session::SetKeyId(int index, const string& key_id) { void Session::FillSimpleMessage(uint32_t duration, uint32_t control, uint32_t nonce, const std::string& pst) { - EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(license_.mac_key_iv, - sizeof(license_.mac_key_iv))); + EXPECT_EQ( + OEMCrypto_SUCCESS, + OEMCrypto_GetRandom(license_.mac_key_iv, sizeof(license_.mac_key_iv))); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(license_.mac_keys, sizeof(license_.mac_keys))); for (unsigned int i = 0; i < num_keys_; i++) { @@ -312,24 +317,24 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control, void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits, uint32_t nonce) { for (unsigned int i = 0; i < key_count; i++) { - encrypted_license_.keys[i].key_id_length = license_.keys[i].key_id_length; - memcpy(encrypted_license_.keys[i].key_id, license_.keys[i].key_id, - encrypted_license_.keys[i].key_id_length); - memcpy(encrypted_license_.keys[i].control.verification, "kctl", 4); - encrypted_license_.keys[i].control.duration = htonl(kLongDuration); - encrypted_license_.keys[i].control.nonce = htonl(nonce); - encrypted_license_.keys[i].control.control_bits = htonl(control_bits); + encrypted_license().keys[i].key_id_length = license_.keys[i].key_id_length; + memcpy(encrypted_license().keys[i].key_id, license_.keys[i].key_id, + encrypted_license().keys[i].key_id_length); + memcpy(encrypted_license().keys[i].control.verification, "kctl", 4); + encrypted_license().keys[i].control.duration = htonl(kLongDuration); + encrypted_license().keys[i].control.nonce = htonl(nonce); + encrypted_license().keys[i].control.control_bits = htonl(control_bits); } } void Session::EncryptAndSign() { - encrypted_license_ = license_; + encrypted_license() = license_; uint8_t iv_buffer[16]; memcpy(iv_buffer, &license_.mac_key_iv[0], wvcdm::KEY_IV_SIZE); AES_KEY aes_key; AES_set_encrypt_key(&enc_key_[0], 128, &aes_key); - AES_cbc_encrypt(&license_.mac_keys[0], &encrypted_license_.mac_keys[0], + AES_cbc_encrypt(&license_.mac_keys[0], &encrypted_license().mac_keys[0], 2 * wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT); for (unsigned int i = 0; i < num_keys_; i++) { @@ -337,19 +342,19 @@ void Session::EncryptAndSign() { AES_set_encrypt_key(&license_.keys[i].key_data[0], 128, &aes_key); AES_cbc_encrypt( reinterpret_cast(&license_.keys[i].control), - reinterpret_cast(&encrypted_license_.keys[i].control), + reinterpret_cast(&encrypted_license().keys[i].control), wvcdm::KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT); memcpy(iv_buffer, &license_.keys[i].key_iv[0], wvcdm::KEY_IV_SIZE); AES_set_encrypt_key(&enc_key_[0], 128, &aes_key); - AES_cbc_encrypt(&license_.keys[i].key_data[0], - &encrypted_license_.keys[i].key_data[0], - license_.keys[i].key_data_length, &aes_key, iv_buffer, - AES_ENCRYPT); + AES_cbc_encrypt( + &license_.keys[i].key_data[0], &encrypted_license().keys[i].key_data[0], + license_.keys[i].key_data_length, &aes_key, iv_buffer, AES_ENCRYPT); } - memcpy(encrypted_license_.pst, license_.pst, sizeof(license_.pst)); - ServerSignMessage(encrypted_license_, &signature_); - FillKeyArray(encrypted_license_, key_array_); + memcpy(encrypted_license().pst, license_.pst, sizeof(license_.pst)); + ServerSignBuffer(reinterpret_cast(&padded_message_), + message_size_, &signature_); + FillKeyArray(encrypted_license(), key_array_); } void Session::EncryptMessage(RSAPrivateKeyMessage* data, @@ -364,30 +369,18 @@ void Session::EncryptMessage(RSAPrivateKeyMessage* data, AES_KEY aes_key; AES_set_encrypt_key(&enc_key_[0], 128, &aes_key); AES_cbc_encrypt(&data->rsa_key[0], &encrypted->rsa_key[0], - encrypted->rsa_key_length, &aes_key, iv_buffer, - AES_ENCRYPT); + encrypted->rsa_key_length, &aes_key, iv_buffer, AES_ENCRYPT); } -template -void Session::ServerSignMessage(const T& data, - std::vector* signature) { +void Session::ServerSignBuffer(const uint8_t* data, size_t data_length, + std::vector* signature) { + ASSERT_LE(data_length, kMaxMessageSize); signature->assign(SHA256_DIGEST_LENGTH, 0); unsigned int md_len = SHA256_DIGEST_LENGTH; - HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(), - reinterpret_cast(&data), sizeof(data), - &(signature->front()), &md_len); + HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(), data, + data_length, &(signature->front()), &md_len); } -template -void Session::ServerSignMessage( - const MessageData& data, - std::vector* signature); - -template -void Session::ServerSignMessage( - const RSAPrivateKeyMessage& data, - std::vector* signature); - void Session::ClientSignMessage(const vector& data, std::vector* signature) { signature->assign(SHA256_DIGEST_LENGTH, 0); @@ -415,21 +408,21 @@ void Session::FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array, size_t key_count) { for (size_t i = 0; i < key_count; i++) { if (key_count > 1) { - key_array[i].key_id = encrypted_license_.keys[i].key_id; - key_array[i].key_id_length = encrypted_license_.keys[i].key_id_length; + key_array[i].key_id = encrypted_license().keys[i].key_id; + key_array[i].key_id_length = encrypted_license().keys[i].key_id_length; } else { key_array[i].key_id = NULL; key_array[i].key_id_length = 0; } key_array[i].key_control_iv = NULL; key_array[i].key_control = - reinterpret_cast(&encrypted_license_.keys[i].control); + reinterpret_cast(&encrypted_license().keys[i].control); } } -void Session::EncryptCTR( - const vector& in_buffer, const uint8_t *key, - const uint8_t* starting_iv, vector* out_buffer) { +void Session::EncryptCTR(const vector& in_buffer, const uint8_t* key, + const uint8_t* starting_iv, + vector* out_buffer) { ASSERT_NE(static_cast(NULL), key); ASSERT_NE(static_cast(NULL), starting_iv); ASSERT_NE(static_cast(NULL), out_buffer); @@ -452,8 +445,7 @@ void Session::EncryptCTR( } void Session::TestDecryptCTR(bool select_key_first, - OEMCryptoResult expected_result, - int key_index) { + OEMCryptoResult expected_result, int key_index) { OEMCryptoResult sts; if (select_key_first) { // Select the key (from FillSimpleMessage) @@ -463,15 +455,16 @@ void Session::TestDecryptCTR(bool select_key_first, } vector unencryptedData(256); - for(size_t i=0; i < unencryptedData.size(); i++) unencryptedData[i] = i % 256; + for (size_t i = 0; i < unencryptedData.size(); i++) + unencryptedData[i] = i % 256; EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&unencryptedData[0], unencryptedData.size())); vector encryptionIv(wvcdm::KEY_IV_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], wvcdm::KEY_IV_SIZE)); vector encryptedData(unencryptedData.size()); - EncryptCTR(unencryptedData, license_.keys[key_index].key_data, &encryptionIv[0], - &encryptedData); + EncryptCTR(unencryptedData, license_.keys[key_index].key_data, + &encryptionIv[0], &encryptedData); // Describe the output vector outputBuffer(256); @@ -507,9 +500,11 @@ void Session::TestDecryptCTR(bool select_key_first, } } -void Session::MakeRSACertificate( - struct RSAPrivateKeyMessage* encrypted, std::vector* signature, - uint32_t allowed_schemes, const vector& rsa_key) { +void Session::MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted, + size_t message_size, + std::vector* signature, + uint32_t allowed_schemes, + const vector& rsa_key) { // Dummy context for testing signature generation. vector context = wvcdm::a2b_hex( "0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840" @@ -555,28 +550,28 @@ void Session::MakeRSACertificate( message.nonce = nonce_; EncryptMessage(&message, encrypted); - ServerSignMessage(*encrypted, signature); + ServerSignBuffer(reinterpret_cast(encrypted), message_size, + signature); } void Session::RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted, + size_t message_size, const std::vector& signature, vector* wrapped_key, bool force) { size_t wrapped_key_length = 0; const uint8_t* message_ptr = reinterpret_cast(&encrypted); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, OEMCrypto_RewrapDeviceRSAKey( - session_id(), message_ptr, sizeof(encrypted), &signature[0], + session_id(), message_ptr, message_size, &signature[0], signature.size(), &encrypted.nonce, encrypted.rsa_key, encrypted.rsa_key_length, encrypted.rsa_key_iv, NULL, &wrapped_key_length)); wrapped_key->clear(); wrapped_key->assign(wrapped_key_length, 0); OEMCryptoResult sts = OEMCrypto_RewrapDeviceRSAKey( - session_id(), message_ptr, sizeof(encrypted), &signature[0], - signature.size(), &encrypted.nonce, encrypted.rsa_key, - encrypted.rsa_key_length, encrypted.rsa_key_iv, &(wrapped_key->front()), - &wrapped_key_length); + session_id(), message_ptr, message_size, &signature[0], signature.size(), + &encrypted.nonce, encrypted.rsa_key, encrypted.rsa_key_length, + encrypted.rsa_key_iv, &(wrapped_key->front()), &wrapped_key_length); if (force) { ASSERT_EQ(OEMCrypto_SUCCESS, sts); } @@ -585,8 +580,7 @@ void Session::RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted, } } -void Session::PreparePublicKey(const uint8_t* rsa_key, - size_t rsa_key_length) { +void Session::PreparePublicKey(const uint8_t* rsa_key, size_t rsa_key_length) { if (rsa_key == NULL) { rsa_key = kTestRSAPKCS8PrivateKeyInfo2_2048; rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048); @@ -610,23 +604,24 @@ void Session::PreparePublicKey(const uint8_t* rsa_key, ASSERT_TRUE(false); } switch (RSA_check_key(public_rsa_)) { - case 1: // valid. - ASSERT_TRUE(true); - return; - case 0: // not valid. - cout << "[rsa key not valid] "; - dump_openssl_error(); - ASSERT_TRUE(false); - default: // -1 == check failed. - cout << "[error checking rsa key] "; - dump_openssl_error(); - ASSERT_TRUE(false); + case 1: // valid. + ASSERT_TRUE(true); + return; + case 0: // not valid. + cout << "[rsa key not valid] "; + dump_openssl_error(); + ASSERT_TRUE(false); + default: // -1 == check failed. + cout << "[error checking rsa key] "; + dump_openssl_error(); + ASSERT_TRUE(false); } } -bool Session::VerifyPSSSignature( - EVP_PKEY* pkey, const uint8_t* message, size_t message_length, - const uint8_t* signature, size_t signature_length) { +bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message, + size_t message_length, + const uint8_t* signature, + size_t signature_length) { EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); EVP_PKEY_CTX* pctx = NULL; @@ -668,15 +663,16 @@ bool Session::VerifyPSSSignature( EVP_MD_CTX_cleanup(&ctx); return true; - err: +err: dump_openssl_error(); EVP_MD_CTX_cleanup(&ctx); return false; } -void Session::VerifyRSASignature( - const vector& message, const uint8_t* signature, - size_t signature_length, RSA_Padding_Scheme padding_scheme) { +void Session::VerifyRSASignature(const vector& message, + const uint8_t* signature, + size_t signature_length, + RSA_Padding_Scheme padding_scheme) { EXPECT_TRUE(NULL != public_rsa_) << "No public RSA key loaded in test code.\n"; EXPECT_EQ(static_cast(RSA_size(public_rsa_)), signature_length) @@ -726,8 +722,7 @@ bool Session::GenerateRSASessionKey(vector* enc_session_key) { return true; } -void Session::InstallRSASessionTestKey( - const vector& wrapped_rsa_key) { +void Session::InstallRSASessionTestKey(const vector& wrapped_rsa_key) { ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadDeviceRSAKey(session_id(), &wrapped_rsa_key[0], wrapped_rsa_key.size())); @@ -749,8 +744,8 @@ void Session::DisallowDeriveKeys() { enc_context.size())); } -void Session::GenerateReport( - const std::string& pst, bool expect_success, Session* other) { +void Session::GenerateReport(const std::string& pst, bool expect_success, + Session* other) { if (other) { // If other is specified, copy mac keys. mac_key_server_ = other->mac_key_server_; mac_key_client_ = other->mac_key_client_; @@ -792,12 +787,13 @@ OEMCrypto_PST_Report* Session::pst_report() { } void Session::DeleteEntry(const std::string& pst) { - uint8_t* pst_ptr = encrypted_license_.pst; + uint8_t* pst_ptr = encrypted_license().pst; memcpy(pst_ptr, pst.c_str(), min(sizeof(license_.pst), pst.length())); - ServerSignMessage(encrypted_license_, &signature_); + ServerSignBuffer(reinterpret_cast(&padded_message_), + message_size_, &signature_); ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_DeleteUsageEntry(session_id(), pst_ptr, pst.length(), - message_ptr(), sizeof(MessageData), + message_ptr(), message_size_, &signature_[0], signature_.size())); } @@ -808,7 +804,13 @@ void Session::ForceDeleteEntry(const std::string& pst) { } const uint8_t* Session::message_ptr() { - return reinterpret_cast(&encrypted_license_); + return reinterpret_cast(&encrypted_license()); +} + +void Session::set_message_size(size_t size) { + message_size_ = size; + ASSERT_GE(message_size_, sizeof(MessageData)); + ASSERT_LE(message_size_, kMaxMessageSize); } } // namespace wvoec diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 29967dd5..9fabdca3 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -67,6 +67,9 @@ const size_t kTestKeyIdMaxLength = 16; 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. +const size_t kMaxDecryptSize = 100 * 1024; // In specification. typedef struct { uint8_t key_id[kTestKeyIdMaxLength]; @@ -86,7 +89,7 @@ struct MessageData { 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]; }; struct RSAPrivateKeyMessage { @@ -141,35 +144,34 @@ class Session { void EncryptAndSign(); void EncryptMessage(RSAPrivateKeyMessage* data, RSAPrivateKeyMessage* encrypted); - - template - void ServerSignMessage(const T& data, std::vector* signature); - + void ServerSignBuffer(const uint8_t* data, size_t data_length, + std::vector* signature); void ClientSignMessage(const vector& data, std::vector* signature); void FillKeyArray(const MessageData& data, OEMCrypto_KeyObject* key_array); void FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array, size_t key_count); - void EncryptCTR( - const vector& in_buffer, const uint8_t *key, - const uint8_t* starting_iv, vector* out_buffer); + void EncryptCTR(const vector& in_buffer, const uint8_t* key, + const uint8_t* starting_iv, vector* out_buffer); void TestDecryptCTR(bool select_key_first = true, OEMCryptoResult expected_result = OEMCrypto_SUCCESS, int key_index = 0); - void MakeRSACertificate( - struct RSAPrivateKeyMessage* encrypted, std::vector* signature, - uint32_t allowed_schemes, const vector& rsa_key); + void MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted, + size_t message_size, std::vector* signature, + uint32_t allowed_schemes, + const vector& rsa_key); void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted, - const std::vector& signature, + size_t message_size, const std::vector& signature, vector* wrapped_key, bool force); 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& message, const uint8_t* signature, - size_t signature_length, RSA_Padding_Scheme padding_scheme); + 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& message, + const uint8_t* signature, size_t signature_length, + RSA_Padding_Scheme padding_scheme); bool GenerateRSASessionKey(vector* enc_session_key); void InstallRSASessionTestKey(const vector& wrapped_rsa_key); void DisallowDeriveKeys(); @@ -180,7 +182,7 @@ class Session { void ForceDeleteEntry(const std::string& pst); MessageData& license() { return license_; } - MessageData& encrypted_license() { return encrypted_license_; } + MessageData& encrypted_license() { return padded_message_; } const uint8_t* message_ptr(); @@ -190,6 +192,9 @@ class Session { void set_num_keys(int num_keys) { num_keys_ = num_keys; } int num_keys() const { return num_keys_; } + void set_message_size(size_t size); + size_t message_size() { return message_size_; } + private: bool open_; bool forced_session_id_; @@ -201,7 +206,10 @@ class Session { RSA* public_rsa_; vector pst_report_buffer_; MessageData license_; - MessageData encrypted_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]; std::vector signature_; int num_keys_; diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 2f635e73..c99381e6 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -17,20 +17,20 @@ #include #include -#include #include +#include #include #include #include #include #include +#include "OEMCryptoCENC.h" #include "log.h" +#include "oec_device_features.h" #include "oec_session_util.h" #include "oec_test_data.h" #include "oemcrypto_key_mock.h" -#include "oec_device_features.h" -#include "OEMCryptoCENC.h" #include "properties.h" #include "string_conversions.h" #include "wv_cdm_constants.h" @@ -254,6 +254,24 @@ TEST_F(OEMCryptoClientTest, MaxSessionsOpenCloseAPI10) { } } +TEST_F(OEMCryptoClientTest, GetRandomLargeBuffer) { + // 32 bytes. Not very large, but that's all we really need in one call. + const size_t size = 32; + uint8_t data1[size]; + uint8_t data2[size]; + memset(data1, 0, size); + memset(data2, 0, size); + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(data1, size)); + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(data2, size)); + // We don't have enough data to see that the data is really random, + // so we'll just do a spot check that two calls don't return the same values. + int count = 0; + for (int i = 0; i < size; i++) { + if (data1[i] == data2[i]) count++; + } + ASSERT_LE(count, 3); // P(count > 3) = 1/256^3 = 6e-8. +} + TEST_F(OEMCryptoClientTest, GenerateNonce) { Session s; ASSERT_NO_FATAL_FAILURE(s.open()); @@ -391,6 +409,21 @@ TEST_F(OEMCryptoClientTest, ClearCopyTestAPI10) { OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample)); } +TEST_F(OEMCryptoClientTest, ClearCopyTestLargeBuffer) { + vector input_buffer(kMaxDecryptSize); + OEMCrypto_GetRandom(&input_buffer[0], input_buffer.size()); + vector output_buffer(kMaxDecryptSize); + OEMCrypto_DestBufferDesc dest_buffer; + dest_buffer.type = OEMCrypto_BufferType_Clear; + dest_buffer.buffer.clear.address = &output_buffer[0]; + dest_buffer.buffer.clear.max_length = output_buffer.size(); + ASSERT_EQ( + OEMCrypto_SUCCESS, + OEMCrypto_CopyBuffer(&input_buffer[0], input_buffer.size(), &dest_buffer, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample)); + ASSERT_EQ(input_buffer, output_buffer); +} + TEST_F(OEMCryptoClientTest, CanLoadTestKeys) { ASSERT_NE(DeviceFeatures::NO_METHOD, global_features.derive_key_method) << "Session tests cannot run with out a test keybox or RSA cert."; @@ -427,6 +460,23 @@ TEST_F(OEMCryptoKeyboxTest, GenerateDerivedKeysFromKeybox) { s.GenerateDerivedKeysFromKeybox(); } +// This tests GenerateDerivedKeys with an 8k context. +TEST_F(OEMCryptoKeyboxTest, GenerateDerivedKeysFromKeyboxLargeBuffer) { + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + vector mac_context(kMaxMessageSize); + vector enc_context(kMaxMessageSize); + // Stripe the data so the two vectors are not identical, and not all zeroes. + for(int i=0; i < kMaxMessageSize; i++) { + mac_context[i] = i % 0x100; + enc_context[i] = (3 * i) % 0x100; + } + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_GenerateDerivedKeys(s.session_id(), &mac_context[0], + mac_context.size(), &enc_context[0], + enc_context.size())); +} + // // AddKey Tests // @@ -626,6 +676,48 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithNoMAC) { ASSERT_EQ(expected_signature, signature); } +// This tests GenerateSignature with an 8k licnese request. +TEST_F(OEMCryptoSessionTests, ClientSignatureLargeBuffer) { + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(s.GenerateTestSessionKeys()); + ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys("", false)); + + vector context(kMaxMessageSize); + for (int i = 0; i < kMaxMessageSize; i++) { + context[i] = i % 0x100; + } + static const uint32_t SignatureBufferMaxLength = 256; + vector signature(SignatureBufferMaxLength); + size_t signature_length = signature.size(); + + OEMCryptoResult sts; + sts = OEMCrypto_GenerateSignature(s.session_id(), &context[0], context.size(), + &signature[0], &signature_length); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + + static const uint32_t SignatureExpectedLength = 32; + ASSERT_EQ(SignatureExpectedLength, signature_length); + signature.resize(signature_length); + + std::vector expected_signature; + s.ClientSignMessage(context, &expected_signature); + ASSERT_EQ(expected_signature, signature); +} + +// This tests LoadKeys with an 8k license response. +TEST_F(OEMCryptoSessionTests, LoadKeyLargeBuffer) { + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + s.set_message_size(kMaxMessageSize); + ASSERT_NO_FATAL_FAILURE(s.GenerateTestSessionKeys()); + ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys()); +} + /* The Bad Range tests verify that OEMCrypto_LoadKeys checks the range of all the pointers. It should reject a message if the pointer does not point into the message buffer */ @@ -640,7 +732,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange1) { s.encrypted_license().mac_keys + sizeof(s.encrypted_license().mac_keys)); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, &mac_keys[0], // Not pointing into buffer. s.num_keys(), s.key_array(), NULL, 0); @@ -658,7 +750,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange2) { sizeof(s.encrypted_license().mac_key_iv)); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), &mac_key_iv[0], // bad. s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); @@ -677,7 +769,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange3) { s.key_array()[0].key_id = &bad_buffer[0]; OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -696,7 +788,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange4) { s.key_array()[1].key_data = &bad_buffer[0]; OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -713,7 +805,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange5) { sizeof(s.encrypted_license().keys[1].key_iv)); s.key_array()[1].key_data_iv = &bad_buffer[0]; OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -733,7 +825,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange6) { s.key_array()[2].key_control = &bad_buffer[0]; OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -753,7 +845,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange7) { s.key_array()[2].key_control_iv = &bad_buffer[0]; OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -768,7 +860,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadNonce) { 42)); // bad nonce. ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); @@ -793,7 +885,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithRepeatNonce) { nonce)); // same old nonce. ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); @@ -809,7 +901,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadVerification) { s.license().keys[1].control.verification[2] = 'Z'; ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); @@ -826,7 +918,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithFutureVerification) { memcpy(s.license().keys[1].control.verification, "kc12", 4); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -840,7 +932,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeysBadSignature) { ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); s.signature()[0] ^= 42; // Bad signature. OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -853,7 +945,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeysWithNoDerivedKeys) { ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(0, 0, 0)); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -870,7 +962,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyNoKeys) { int kNoKeys = 0; ASSERT_NE( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), NULL, NULL, kNoKeys, s.key_array(), NULL, 0)); } @@ -885,7 +977,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyNoKeyWithNonce) { int kNoKeys = 0; ASSERT_NE( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), NULL, NULL, kNoKeys, s.key_array(), NULL, 0)); } @@ -925,7 +1017,7 @@ TEST_F(OEMCryptoSessionTests, AntiRollbackHardwareRequired) { 0, wvoec_mock::kControlRequireAntiRollbackHardware, 0)); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); if (OEMCrypto_IsAntiRollbackHwPresent()) { @@ -946,7 +1038,7 @@ TEST_F(OEMCryptoSessionTests, CheckMinimumPatchLevel) { ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); ASSERT_EQ( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), @@ -961,7 +1053,7 @@ TEST_F(OEMCryptoSessionTests, CheckMinimumPatchLevel) { ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); ASSERT_EQ( OEMCrypto_ERROR_UNKNOWN_FAILURE, - OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), @@ -977,7 +1069,7 @@ TEST_F(OEMCryptoSessionTests, CheckMinimumPatchLevel) { ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); ASSERT_EQ( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), @@ -993,10 +1085,10 @@ TEST_F(OEMCryptoSessionTests, Minimum20Keys) { ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(0, 0, 0)); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys()); - for (int key_index=0; key_index < kMaxNumKeys; key_index++) { + for (int key_index = 0; key_index < kMaxNumKeys; key_index++) { bool kSelectKeyFirst = true; - ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR(kSelectKeyFirst, OEMCrypto_SUCCESS, - key_index)); + ASSERT_NO_FATAL_FAILURE( + s.TestDecryptCTR(kSelectKeyFirst, OEMCrypto_SUCCESS, key_index)); } } @@ -1110,6 +1202,21 @@ TEST_P(SessionTestRefreshKeyTest, RefreshBadNonce) { OEMCrypto_ERROR_INVALID_NONCE)); } +TEST_P(SessionTestRefreshKeyTest, RefreshLargeBuffer) { + Session s; + s.set_message_size(kMaxMessageSize); + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(s.GenerateTestSessionKeys()); + ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage( + kDuration, wvoec_mock::kControlNonceEnabled, s.get_nonce())); + ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys("", new_mac_keys_)); + uint32_t nonce; + s.GenerateNonce(&nonce); + ASSERT_NO_FATAL_FAILURE(s.RefreshTestKeys( + num_keys_, wvoec_mock::kControlNonceEnabled, nonce, OEMCrypto_SUCCESS)); +} + // Of only one key control block in the refesh, we update all the keys. INSTANTIATE_TEST_CASE_P(TestRefreshAllKeys, SessionTestRefreshKeyTest, Values(std::make_pair(true, 1), @@ -1150,8 +1257,8 @@ TEST_F(OEMCryptoSessionTests, SimultaneousDecrypt) { } for (int i = 0; i < 8; i++) { ASSERT_NO_FATAL_FAILURE(s[i].GenerateTestSessionKeys()); - ASSERT_NO_FATAL_FAILURE(s[i].FillSimpleMessage(kLongDuration, 0, - s[i].get_nonce())); + ASSERT_NO_FATAL_FAILURE( + s[i].FillSimpleMessage(kLongDuration, 0, s[i].get_nonce())); ASSERT_NO_FATAL_FAILURE(s[i].EncryptAndSign()); } for (int i = 0; i < 8; i++) { @@ -1173,15 +1280,15 @@ TEST_F(OEMCryptoSessionTests, SimultaneousDecryptWithLostMessage) { } for (int i = 0; i < 8; i++) { ASSERT_NO_FATAL_FAILURE(s[i].GenerateTestSessionKeys()); - ASSERT_NO_FATAL_FAILURE(s[i].FillSimpleMessage(kLongDuration, 0, - s[i].get_nonce())); + ASSERT_NO_FATAL_FAILURE( + s[i].FillSimpleMessage(kLongDuration, 0, s[i].get_nonce())); ASSERT_NO_FATAL_FAILURE(s[i].EncryptAndSign()); } // First set of messages are lost. Generate second set. for (int i = 0; i < 8; i++) { ASSERT_NO_FATAL_FAILURE(s[i].GenerateTestSessionKeys()); - ASSERT_NO_FATAL_FAILURE(s[i].FillSimpleMessage(kLongDuration, 0, - s[i].get_nonce())); + ASSERT_NO_FATAL_FAILURE( + s[i].FillSimpleMessage(kLongDuration, 0, s[i].get_nonce())); ASSERT_NO_FATAL_FAILURE(s[i].EncryptAndSign()); } for (int i = 0; i < 8; i++) { @@ -1260,8 +1367,8 @@ class OEMCryptoSessionTestsDecryptTests size_t size = min(subsample_end - buffer_index, AES_BLOCK_SIZE - block_offset); size_t pattern_length = pattern_.encrypt + pattern_.skip; - bool skip_block = (pattern_offset >= pattern_.encrypt) - && (pattern_length>0); + bool skip_block = + (pattern_offset >= pattern_.encrypt) && (pattern_length > 0); if (pattern_length > 0) { pattern_offset = (pattern_offset + 1) % pattern_length; } @@ -1270,8 +1377,7 @@ class OEMCryptoSessionTestsDecryptTests // can put whatever we want in the output buffer. if (skip_block || ((cipher_mode_ == OEMCrypto_CipherMode_CBC) && (size < AES_BLOCK_SIZE))) { - memcpy(&(*out_buffer)[buffer_index], &in_buffer[buffer_index], - size); + memcpy(&(*out_buffer)[buffer_index], &in_buffer[buffer_index], size); block_offset = 0; // Next block should be complete. } else { if (cipher_mode_ == OEMCrypto_CipherMode_CTR) { @@ -1279,8 +1385,7 @@ class OEMCryptoSessionTestsDecryptTests AES_encrypt(iv, aes_output, &aes_key); for (size_t n = 0; n < size; n++) { (*out_buffer)[buffer_index + n] = - aes_output[n + block_offset] ^ - in_buffer[buffer_index + n]; + aes_output[n + block_offset] ^ in_buffer[buffer_index + n]; } if (size + block_offset < AES_BLOCK_SIZE) { // Partial block. Don't increment iv. Compute next block offset. @@ -1393,8 +1498,8 @@ class OEMCryptoSessionTestsDecryptTests // Tests that generate partial ending blocks. These tests should not be used // with CTR mode and pattern encrypt. -class OEMCryptoSessionTestsPartialBlockTests : - public OEMCryptoSessionTestsDecryptTests {}; +class OEMCryptoSessionTestsPartialBlockTests + : public OEMCryptoSessionTestsDecryptTests {}; TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) { // This subsample size should be larger a few encrypt/skip patterns. Most @@ -1408,8 +1513,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) { vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); - EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; EncryptData(key, encryptionIv, unencryptedData, &encryptedData); TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); @@ -1420,7 +1524,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) { // HLS and the CENC standards for samples of size 160*N+16, for N = 1, 2, 3 ... // We require the CENC standard for OEMCrypto, and let a layer above us break // samples into pieces if they wish to use the HLS standard. - subsample_size_.push_back(SampleSize(0, 160+16)); + subsample_size_.push_back(SampleSize(0, 160 + 16)); FindTotalSize(); vector unencryptedData(total_size_); vector encryptedData(total_size_); @@ -1428,8 +1532,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) { vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); - EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; EncryptData(key, encryptionIv, unencryptedData, &encryptedData); TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); @@ -1444,8 +1547,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, OneBlock) { vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); - EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; EncryptData(key, encryptionIv, unencryptedData, &encryptedData); TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); @@ -1465,8 +1567,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, NoOffset) { vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); - EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; EncryptData(key, encryptionIv, unencryptedData, &encryptedData); TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); @@ -1516,8 +1617,7 @@ TEST_P(OEMCryptoSessionTestsPartialBlockTests, OddOffset) { vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); - EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; EncryptData(key, encryptionIv, unencryptedData, &encryptedData); TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); @@ -1562,8 +1662,29 @@ TEST_P(OEMCryptoSessionTestsPartialBlockTests, PartialBlock) { vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; + EncryptData(key, encryptionIv, unencryptedData, &encryptedData); + TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); +} + +TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptLargeBuffer) { + subsample_size_.push_back(SampleSize(kMaxDecryptSize, 0)); + subsample_size_.push_back(SampleSize(kMaxDecryptSize, 0)); + subsample_size_.push_back(SampleSize(0, kMaxDecryptSize)); + subsample_size_.push_back(SampleSize(0, kMaxDecryptSize)); + subsample_size_.push_back(SampleSize(kMaxDecryptSize, 0)); + subsample_size_.push_back(SampleSize(kMaxDecryptSize, 0)); + subsample_size_.push_back(SampleSize(0, kMaxDecryptSize)); + subsample_size_.push_back(SampleSize(0, kMaxDecryptSize)); + FindTotalSize(); + vector unencryptedData(total_size_); + vector encryptedData(total_size_); + vector encryptionIv(AES_BLOCK_SIZE); + vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; EncryptData(key, encryptionIv, unencryptedData, &encryptedData); TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); @@ -1578,8 +1699,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencrypted) { vector key(AES_BLOCK_SIZE); EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&encryptionIv[0], AES_BLOCK_SIZE)); - EXPECT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); + EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetRandom(&key[0], AES_BLOCK_SIZE)); for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256; EncryptData(key, encryptionIv, unencryptedData, &encryptedData); TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData); @@ -1609,10 +1729,10 @@ TEST_F(OEMCryptoSessionTests, DecryptUnencryptedNoKey) { pattern.offset = 0; // Decrypt the data - sts = OEMCrypto_DecryptCENC( - s.session_id(), &in_buffer[0], in_buffer.size(), false, - &encryptionIv[0], 0, &destBuffer, &pattern, - OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); + sts = + OEMCrypto_DecryptCENC(s.session_id(), &in_buffer[0], in_buffer.size(), + false, &encryptionIv[0], 0, &destBuffer, &pattern, + OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); ASSERT_EQ(OEMCrypto_SUCCESS, sts); ASSERT_EQ(in_buffer, out_buffer); } @@ -1635,11 +1755,10 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptCENCPerformance) { ASSERT_EQ(OEMCrypto_SUCCESS, sts); vector encryptionIv = wvcdm::a2b_hex("719dbcb253b2ec702bb8c1b1bc2f3bc6"); - const size_t max_length = 250 * 1024; - vector input(max_length); + vector input(kMaxDecryptSize); printf("Size of input is %zd\n", input.size()); - for (unsigned int i = 0; i < max_length; i++) input[i] = i % 256; - vector output(max_length); + for (unsigned int i = 0; i < kMaxDecryptSize; i++) input[i] = i % 256; + vector output(kMaxDecryptSize); OEMCrypto_DestBufferDesc destBuffer; destBuffer.type = OEMCrypto_BufferType_Clear; destBuffer.buffer.clear.address = &output[0]; @@ -1690,10 +1809,9 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptCENCPerformance) { } } -INSTANTIATE_TEST_CASE_P( - CTRTests, OEMCryptoSessionTestsPartialBlockTests, - Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CTR) - )); +INSTANTIATE_TEST_CASE_P(CTRTests, OEMCryptoSessionTestsPartialBlockTests, + Values(PatternTestVariant(0, 0, + OEMCrypto_CipherMode_CTR))); INSTANTIATE_TEST_CASE_P( CBCTests, OEMCryptoSessionTestsPartialBlockTests, Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CBC), @@ -1702,16 +1820,14 @@ INSTANTIATE_TEST_CASE_P( PatternTestVariant(9, 1, OEMCrypto_CipherMode_CBC), PatternTestVariant(1, 9, OEMCrypto_CipherMode_CBC), PatternTestVariant(1, 3, OEMCrypto_CipherMode_CBC), - PatternTestVariant(2, 1, OEMCrypto_CipherMode_CBC) - )); + PatternTestVariant(2, 1, OEMCrypto_CipherMode_CBC))); INSTANTIATE_TEST_CASE_P( CTRTests, OEMCryptoSessionTestsDecryptTests, Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CTR), PatternTestVariant(3, 7, OEMCrypto_CipherMode_CTR), // Pattern length should be 10, but that is not guaranteed. PatternTestVariant(1, 3, OEMCrypto_CipherMode_CTR), - PatternTestVariant(2, 1, OEMCrypto_CipherMode_CTR) - )); + PatternTestVariant(2, 1, OEMCrypto_CipherMode_CTR))); INSTANTIATE_TEST_CASE_P( CBCTests, OEMCryptoSessionTestsDecryptTests, Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CBC), @@ -1721,8 +1837,7 @@ INSTANTIATE_TEST_CASE_P( PatternTestVariant(1, 9, OEMCrypto_CipherMode_CBC), // Pattern length should be 10, but that is not guaranteed. PatternTestVariant(1, 3, OEMCrypto_CipherMode_CBC), - PatternTestVariant(2, 1, OEMCrypto_CipherMode_CBC) - )); + PatternTestVariant(2, 1, OEMCrypto_CipherMode_CBC))); TEST_F(OEMCryptoSessionTests, DecryptSecureToClear) { Session s; @@ -1770,10 +1885,11 @@ class OEMCryptoLoadsCertificate : public OEMCryptoSessionTestKeyboxTest { s.GenerateDerivedKeysFromKeybox(); struct RSAPrivateKeyMessage encrypted; std::vector signature; - ASSERT_NO_FATAL_FAILURE(s.MakeRSACertificate( - &encrypted, &signature, allowed_schemes, encoded_rsa_key_)); - ASSERT_NO_FATAL_FAILURE( - s.RewrapRSAKey(encrypted, signature, wrapped_key, force)); + ASSERT_NO_FATAL_FAILURE(s.MakeRSACertificate(&encrypted, sizeof(encrypted), + &signature, allowed_schemes, + encoded_rsa_key_)); + ASSERT_NO_FATAL_FAILURE(s.RewrapRSAKey(encrypted, sizeof(encrypted), + signature, wrapped_key, force)); // Verify that the clear key is not contained in the wrapped key. // It should be encrypted. ASSERT_EQ(NULL, find(*wrapped_key, encoded_rsa_key_)); @@ -1804,8 +1920,9 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionBadRange1) { s.GenerateDerivedKeysFromKeybox(); struct RSAPrivateKeyMessage encrypted; std::vector signature; - ASSERT_NO_FATAL_FAILURE(s.MakeRSACertificate( - &encrypted, &signature, kSign_RSASSA_PSS, encoded_rsa_key_)); + ASSERT_NO_FATAL_FAILURE(s.MakeRSACertificate(&encrypted, sizeof(encrypted), + &signature, kSign_RSASSA_PSS, + encoded_rsa_key_)); vector wrapped_key; const uint8_t* message_ptr = reinterpret_cast(&encrypted); size_t wrapped_key_length = 0; @@ -1832,8 +1949,8 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionBadRange2) { s.GenerateDerivedKeysFromKeybox(); struct RSAPrivateKeyMessage encrypted; std::vector signature; - s.MakeRSACertificate(&encrypted, &signature, kSign_RSASSA_PSS, - encoded_rsa_key_); + s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature, + kSign_RSASSA_PSS, encoded_rsa_key_); vector wrapped_key; const uint8_t* message_ptr = reinterpret_cast(&encrypted); size_t wrapped_key_length = 0; @@ -1862,8 +1979,8 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionBadRange3) { s.GenerateDerivedKeysFromKeybox(); struct RSAPrivateKeyMessage encrypted; std::vector signature; - s.MakeRSACertificate(&encrypted, &signature, kSign_RSASSA_PSS, - encoded_rsa_key_); + s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature, + kSign_RSASSA_PSS, encoded_rsa_key_); const uint8_t* message_ptr = reinterpret_cast(&encrypted); vector wrapped_key; @@ -1893,8 +2010,8 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionBadSignature) { s.GenerateDerivedKeysFromKeybox(); struct RSAPrivateKeyMessage encrypted; std::vector signature; - s.MakeRSACertificate(&encrypted, &signature, kSign_RSASSA_PSS, - encoded_rsa_key_); + s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature, + kSign_RSASSA_PSS, encoded_rsa_key_); vector wrapped_key; const uint8_t* message_ptr = reinterpret_cast(&encrypted); @@ -1922,8 +2039,8 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionBadNonce) { s.GenerateDerivedKeysFromKeybox(); struct RSAPrivateKeyMessage encrypted; std::vector signature; - s.MakeRSACertificate(&encrypted, &signature, kSign_RSASSA_PSS, - encoded_rsa_key_); + s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature, + kSign_RSASSA_PSS, encoded_rsa_key_); vector wrapped_key; const uint8_t* message_ptr = reinterpret_cast(&encrypted); @@ -1951,8 +2068,8 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionBadRSAKey) { s.GenerateDerivedKeysFromKeybox(); struct RSAPrivateKeyMessage encrypted; std::vector signature; - s.MakeRSACertificate(&encrypted, &signature, kSign_RSASSA_PSS, - encoded_rsa_key_); + s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature, + kSign_RSASSA_PSS, encoded_rsa_key_); vector wrapped_key; const uint8_t* message_ptr = reinterpret_cast(&encrypted); @@ -1974,6 +2091,24 @@ TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionBadRSAKey) { &(wrapped_key.front()), &wrapped_key_length)); } +TEST_F(OEMCryptoLoadsCertificate, CertificateProvisionLargeBuffer) { + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + s.GenerateDerivedKeysFromKeybox(); + struct LargeRSAPrivateKeyMessage : public RSAPrivateKeyMessage { + uint8_t padding[kMaxMessageSize - sizeof(RSAPrivateKeyMessage)]; + } encrypted; + std::vector signature; + s.MakeRSACertificate(&encrypted, sizeof(encrypted), &signature, + kSign_RSASSA_PSS, encoded_rsa_key_); + vector wrapped_key; + ASSERT_NO_FATAL_FAILURE(s.RewrapRSAKey(encrypted, sizeof(encrypted), + signature, &wrapped_key, true)); + // Verify that the clear key is not contained in the wrapped key. + // It should be encrypted. + ASSERT_EQ(NULL, find(wrapped_key, encoded_rsa_key_)); +} + TEST_F(OEMCryptoLoadsCertificate, LoadWrappedRSAKey) { OEMCryptoResult sts; std::vector wrapped_rsa_key; @@ -2164,6 +2299,52 @@ TEST_F(OEMCryptoUsesCertificate, RSASignature) { licenseRequest, signature, signature_length, kSign_RSASSA_PSS)); } +TEST_F(OEMCryptoUsesCertificate, RSASignatureLargeBuffer) { + OEMCryptoResult sts; + // Sign a Message + vector licenseRequest(kMaxMessageSize); + OEMCrypto_GetRandom(&licenseRequest[0], licenseRequest.size()); + size_t signature_length = 0; + uint8_t signature[500]; + + sts = OEMCrypto_GenerateRSASignature( + session_.session_id(), &licenseRequest[0], licenseRequest.size(), + signature, &signature_length, kSign_RSASSA_PSS); + + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); + ASSERT_NE(static_cast(0), signature_length); + ASSERT_GE(sizeof(signature), signature_length); + + sts = OEMCrypto_GenerateRSASignature( + session_.session_id(), &licenseRequest[0], licenseRequest.size(), + signature, &signature_length, kSign_RSASSA_PSS); + + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + // In the real world, the signature above would just have been used to contact + // the license server to get this response. + session_.PreparePublicKey(); + ASSERT_NO_FATAL_FAILURE(session_.VerifyRSASignature( + licenseRequest, signature, signature_length, kSign_RSASSA_PSS)); +} + +TEST_F(OEMCryptoUsesCertificate, GenerateDerivedKeysLargeBuffer) { + vector enc_session_key; + session_.PreparePublicKey(); + ASSERT_TRUE(session_.GenerateRSASessionKey(&enc_session_key)); + vector mac_context(kMaxMessageSize); + vector enc_context(kMaxMessageSize); + // Stripe the data so the two vectors are not identical, and not all zeroes. + for (int i = 0; i < kMaxMessageSize; i++) { + mac_context[i] = i % 0x100; + enc_context[i] = (3 * i) % 0x100; + } + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_DeriveKeysFromSessionKey( + session_.session_id(), &enc_session_key[0], + enc_session_key.size(), &mac_context[0], mac_context.size(), + &enc_context[0], enc_context.size())); +} + // This test attempts to use alternate algorithms for loaded device certs. class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate { protected: @@ -3496,10 +3677,8 @@ TEST_F(GenericCryptoTest, GenericKeyBadVerify) { BadVerify(3, OEMCrypto_AES_CBC_128_NO_PADDING, SHA256_DIGEST_LENGTH, false); } -TEST_F(GenericCryptoTest, GenericKeyEncryptLargeBufferAPI11) { - // Some applications are known to pass in a block that is almost 400k, but - // the layer above oemcrypto can break it into 100k chunks. - buffer_size_ = 100 * 1024; +TEST_F(GenericCryptoTest, GenericKeyEncryptLargeBuffer) { + buffer_size_ = kMaxDecryptSize; EncryptAndLoadKeys(); unsigned int key_index = 0; vector expected_encrypted; @@ -3517,9 +3696,9 @@ TEST_F(GenericCryptoTest, GenericKeyEncryptLargeBufferAPI11) { ASSERT_EQ(expected_encrypted, encrypted); } -TEST_F(GenericCryptoTest, GenericKeyDecryptLargeBufferAPI11) { +TEST_F(GenericCryptoTest, GenericKeyDecryptLargeBuffer) { // Some applications are known to pass in a block that is almost 400k. - buffer_size_ = 400 * 1024; + buffer_size_ = kMaxDecryptSize; EncryptAndLoadKeys(); unsigned int key_index = 1; vector encrypted; @@ -3537,8 +3716,8 @@ TEST_F(GenericCryptoTest, GenericKeyDecryptLargeBufferAPI11) { ASSERT_EQ(clear_buffer_, resultant); } -TEST_F(GenericCryptoTest, GenericKeySignLargeBufferAPI11) { - buffer_size_ = 100 * 1024; +TEST_F(GenericCryptoTest, GenericKeySignLargeBuffer) { + buffer_size_ = kMaxDecryptSize; EncryptAndLoadKeys(); unsigned int key_index = 2; vector expected_signature; @@ -3563,8 +3742,8 @@ TEST_F(GenericCryptoTest, GenericKeySignLargeBufferAPI11) { ASSERT_EQ(expected_signature, signature); } -TEST_F(GenericCryptoTest, GenericKeyVerifyLargeBufferAPI11) { - buffer_size_ = 100 * 1024; +TEST_F(GenericCryptoTest, GenericKeyVerifyLargeBuffer) { + buffer_size_ = kMaxDecryptSize; EncryptAndLoadKeys(); unsigned int key_index = 3; vector signature; @@ -3898,8 +4077,8 @@ TEST_P(UsageTableTestWithMAC, OnlineLicense) { kTimeTolerance); EXPECT_NEAR(0, wvcdm::htonll64(s.pst_report()->seconds_since_last_decrypt), kTimeTolerance); - DeactivatePST(pst); - s.GenerateReport(pst); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); + ASSERT_NO_FATAL_FAILURE(s.GenerateReport(pst)); EXPECT_EQ(kInactive, s.pst_report()->status); EXPECT_NEAR(0, wvcdm::htonll64(s.pst_report()->seconds_since_license_received), @@ -3929,7 +4108,7 @@ TEST_F(UsageTableTest, RepeatOnlineLicense) { // reused from s. ASSERT_NE( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s2.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s2.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), @@ -3948,7 +4127,7 @@ TEST_F(UsageTableTest, OnlineEmptyPST) { s.get_nonce())); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -4068,7 +4247,7 @@ TEST_P(UsageTableTestWithMAC, DeleteUnusedEntry) { ASSERT_NO_FATAL_FAILURE(s2.open()); s2.GenerateReport(pst, true, &s); EXPECT_EQ(kUnused, s2.pst_report()->status); - s2.DeleteEntry(pst); + ASSERT_NO_FATAL_FAILURE(s2.DeleteEntry(pst)); ASSERT_NO_FATAL_FAILURE(s2.close()); // Now that session is deleted, we can't generate a report for it. @@ -4096,15 +4275,15 @@ TEST_P(UsageTableTestWithMAC, DeleteActiveEntry) { // New session should be able to generate report and copy mac keys. Session s2; ASSERT_NO_FATAL_FAILURE(s2.open()); - s2.GenerateReport(pst, true, &s); + ASSERT_NO_FATAL_FAILURE(s2.GenerateReport(pst, true, &s)); EXPECT_EQ(kActive, s2.pst_report()->status); - s2.DeleteEntry(pst); + ASSERT_NO_FATAL_FAILURE(s2.DeleteEntry(pst)); ASSERT_NO_FATAL_FAILURE(s2.close()); // Now that session is deleted, we can't generate a report for it. Session s3; ASSERT_NO_FATAL_FAILURE(s3.open()); - s3.GenerateReport(pst, false); + ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, false)); ASSERT_NO_FATAL_FAILURE(s3.close()); } @@ -4120,15 +4299,15 @@ TEST_P(UsageTableTestWithMAC, ForceDeleteActiveEntry) { ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_)); ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR()); - s.GenerateReport(pst); + ASSERT_NO_FATAL_FAILURE(s.GenerateReport(pst)); ASSERT_NO_FATAL_FAILURE(s.close()); - s.ForceDeleteEntry(pst); + ASSERT_NO_FATAL_FAILURE(s.ForceDeleteEntry(pst)); // Now that session is deleted, we can't generate a report for it. Session s3; ASSERT_NO_FATAL_FAILURE(s3.open()); - s3.GenerateReport(pst, false); + ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, false)); ASSERT_NO_FATAL_FAILURE(s3.close()); } @@ -4145,7 +4324,7 @@ TEST_P(UsageTableTestWithMAC, DeleteInactiveEntry) { ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_)); s.GenerateReport(pst); ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR()); - DeactivatePST(pst); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); ASSERT_NO_FATAL_FAILURE(s.close()); // New session should be able to generate report and copy mac keys. @@ -4153,7 +4332,7 @@ TEST_P(UsageTableTestWithMAC, DeleteInactiveEntry) { ASSERT_NO_FATAL_FAILURE(s2.open()); s2.GenerateReport(pst, true, &s); EXPECT_EQ(kInactive, s2.pst_report()->status); - s2.DeleteEntry(pst); + ASSERT_NO_FATAL_FAILURE(s2.DeleteEntry(pst)); ASSERT_NO_FATAL_FAILURE(s2.close()); // Now that session is deleted, we can't generate a report for it. @@ -4188,7 +4367,7 @@ TEST_P(UsageTableTestWithMAC, DeleteEntryBadSignature) { // ServerSignMessage(s2.encrypted_license(), &signature); ASSERT_NE(OEMCrypto_SUCCESS, OEMCrypto_DeleteUsageEntry(s2.session_id(), pst_ptr, pst.length(), - s2.message_ptr(), sizeof(MessageData), + s2.message_ptr(), s2.message_size(), &signature[0], signature.size())); ASSERT_NO_FATAL_FAILURE(s2.close()); @@ -4222,10 +4401,11 @@ TEST_P(UsageTableTestWithMAC, DeleteEntryWrongSession) { uint8_t* pst_ptr = s2.encrypted_license().pst; memcpy(pst_ptr, pst.c_str(), min(sizeof(s2.license().pst), pst.length())); std::vector signature(SHA256_DIGEST_LENGTH); - s2.ServerSignMessage(s2.encrypted_license(), &signature); + s2.ServerSignBuffer(reinterpret_cast(&s2.encrypted_license()), + sizeof(s2.encrypted_license()), &signature); ASSERT_NE(OEMCrypto_SUCCESS, OEMCrypto_DeleteUsageEntry(s2.session_id(), pst_ptr, pst.length(), - s2.message_ptr(), sizeof(MessageData), + s2.message_ptr(), s2.message_size(), &signature[0], signature.size())); ASSERT_NO_FATAL_FAILURE(s2.close()); @@ -4259,10 +4439,11 @@ TEST_P(UsageTableTestWithMAC, DeleteEntryBadRange) { uint8_t* pst_ptr = s2.license().pst; memcpy(pst_ptr, pst.c_str(), min(sizeof(s2.license().pst), pst.length())); std::vector signature(SHA256_DIGEST_LENGTH); - s2.ServerSignMessage(s2.encrypted_license(), &signature); + s2.ServerSignBuffer(reinterpret_cast(&s2.encrypted_license()), + sizeof(s2.encrypted_license()), &signature); ASSERT_NE(OEMCrypto_SUCCESS, OEMCrypto_DeleteUsageEntry(s2.session_id(), pst_ptr, pst.length(), - s2.message_ptr(), sizeof(MessageData), + s2.message_ptr(), s2.message_size(), &signature[0], signature.size())); ASSERT_NO_FATAL_FAILURE(s2.close()); @@ -4320,8 +4501,8 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoEncrypt) { EXPECT_NEAR( 0, wvcdm::htonll64(session_.pst_report()->seconds_since_last_decrypt), kTimeTolerance); - DeactivatePST(pst); - session_.GenerateReport(pst); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); + ASSERT_NO_FATAL_FAILURE(session_.GenerateReport(pst)); EXPECT_EQ(kInactive, session_.pst_report()->status); EXPECT_NEAR( 0, wvcdm::htonll64(session_.pst_report()->seconds_since_license_received), @@ -4368,7 +4549,7 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoDecrypt) { EXPECT_NEAR( 0, wvcdm::htonll64(session_.pst_report()->seconds_since_last_decrypt), kTimeTolerance); - DeactivatePST(pst); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); session_.GenerateReport(pst); EXPECT_EQ(kInactive, session_.pst_report()->status); EXPECT_NEAR( @@ -4425,8 +4606,8 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoSign) { EXPECT_NEAR( 0, wvcdm::htonll64(session_.pst_report()->seconds_since_last_decrypt), kTimeTolerance); - DeactivatePST(pst); - session_.GenerateReport(pst); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); + ASSERT_NO_FATAL_FAILURE(session_.GenerateReport(pst)); EXPECT_EQ(kInactive, session_.pst_report()->status); EXPECT_NEAR( 0, wvcdm::htonll64(session_.pst_report()->seconds_since_license_received), @@ -4476,8 +4657,8 @@ TEST_P(UsageTableTestWithMAC, GenericCryptoVerify) { EXPECT_NEAR( 0, wvcdm::htonll64(session_.pst_report()->seconds_since_last_decrypt), kTimeTolerance); - DeactivatePST(pst); - session_.GenerateReport(pst); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); + ASSERT_NO_FATAL_FAILURE(session_.GenerateReport(pst)); EXPECT_EQ(kInactive, session_.pst_report()->status); EXPECT_NEAR( 0, wvcdm::htonll64(session_.pst_report()->seconds_since_license_received), @@ -4542,7 +4723,7 @@ TEST_P(UsageTableTestWithMAC, BadReloadOfflineLicense) { uint8_t* pst_ptr = s2.encrypted_license().pst; ASSERT_NE( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s2.session_id(), s2.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s2.session_id(), s2.message_ptr(), s2.message_size(), &s2.signature()[0], s2.signature().size(), s2.encrypted_license().mac_key_iv, s2.encrypted_license().mac_keys, s.num_keys(), @@ -4569,7 +4750,7 @@ TEST_P(UsageTableTestWithMAC, OfflineBadNonce) { ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); uint8_t* pst_ptr = s.encrypted_license().pst; OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), pst_ptr, pst.length()); @@ -4587,7 +4768,7 @@ TEST_P(UsageTableTestWithMAC, OfflineEmptyPST) { s.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry, s.get_nonce())); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); OEMCryptoResult sts = OEMCrypto_LoadKeys( - s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], + s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), s.key_array(), NULL, 0); ASSERT_NE(OEMCrypto_SUCCESS, sts); @@ -4605,7 +4786,7 @@ TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) { ASSERT_NO_FATAL_FAILURE( s.LoadTestKeys(pst, new_mac_keys_)); // Reload the license ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR()); // Should be able to decrypt. - DeactivatePST(pst); // Then deactivate. + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); // Then deactivate. // After deactivate, should not be able to decrypt. ASSERT_NO_FATAL_FAILURE( s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE)); @@ -4623,7 +4804,7 @@ TEST_P(UsageTableTestWithMAC, DeactivateOfflineLicense) { uint8_t* pst_ptr = s.encrypted_license().pst; EXPECT_NE( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s2.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s2.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), @@ -4647,7 +4828,7 @@ TEST_P(UsageTableTestWithMAC, BadRange) { uint8_t* pst_ptr = s.license().pst; // Bad: not in encrypted_license. ASSERT_NE( OEMCrypto_SUCCESS, - OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), sizeof(MessageData), + OEMCrypto_LoadKeys(s.session_id(), s.message_ptr(), s.message_size(), &s.signature()[0], s.signature().size(), s.encrypted_license().mac_key_iv, s.encrypted_license().mac_keys, s.num_keys(), @@ -4688,13 +4869,14 @@ TEST_F(UsageTableTest, TimingTest) { ASSERT_NO_FATAL_FAILURE(s2.TestDecryptCTR()); sleep(kLongSleep); - DeactivatePST(pst1); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst1)); ASSERT_NO_FATAL_FAILURE(s1.close()); ASSERT_NO_FATAL_FAILURE(s2.close()); sleep(kLongSleep); // This is as close to reboot as we can simulate in code. - ASSERT_NO_FATAL_FAILURE(session_.close()); // Close sessions before terminate. + ASSERT_NO_FATAL_FAILURE( + session_.close()); // Close sessions before terminate. OEMCrypto_Terminate(); sleep(kShortSleep); OEMCrypto_Initialize(); @@ -4843,8 +5025,8 @@ TEST_F(UsageTableTest, VerifyUsageTimes) { EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_last_decrypt), kIdleInSeconds, kUsageTableTimeTolerance); - DeactivatePST(pst); - s.GenerateReport(pst); + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); + ASSERT_NO_FATAL_FAILURE(s.GenerateReport(pst)); EXPECT_EQ(kInactive, s.pst_report()->status); ASSERT_NO_FATAL_FAILURE( s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE)); @@ -4882,6 +5064,101 @@ TEST_F(UsageTableTest, LoadSharedLicense) { ASSERT_NO_FATAL_FAILURE(s.close()); } +TEST_F(UsageTableTest, PSTLargeBuffer) { + std::string pst(kMaxPSTLength, 'a'); // A large PST. + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + Session s; + ASSERT_NO_FATAL_FAILURE(LoadOfflineLicense(s, pst)); + + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(s.GenerateTestSessionKeys()); + ASSERT_NO_FATAL_FAILURE( + s.LoadTestKeys(pst, new_mac_keys_)); // Reload the license + ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR()); // Should be able to decrypt. + ASSERT_NO_FATAL_FAILURE(DeactivatePST(pst)); // Then deactivate. + // After deactivate, should not be able to decrypt. + ASSERT_NO_FATAL_FAILURE( + s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE)); + ASSERT_NO_FATAL_FAILURE(s.GenerateReport(pst)); + EXPECT_EQ(kInactive, s.pst_report()->status); + EXPECT_NEAR(0, + wvcdm::htonll64(s.pst_report()->seconds_since_license_received), + kTimeTolerance); + ASSERT_NO_FATAL_FAILURE(s.close()); + + Session s2; + ASSERT_NO_FATAL_FAILURE(s2.open()); + ASSERT_NO_FATAL_FAILURE(s2.GenerateTestSessionKeys()); + // Offile license can not be reused if it has been deactivated. + uint8_t* pst_ptr = s.encrypted_license().pst; + EXPECT_NE( + OEMCrypto_SUCCESS, + OEMCrypto_LoadKeys(s2.session_id(), s.message_ptr(), s.message_size(), + &s.signature()[0], s.signature().size(), + s.encrypted_license().mac_key_iv, + s.encrypted_license().mac_keys, s.num_keys(), + s.key_array(), pst_ptr, pst.length())); + // But we can still generate a report. + Session s3; + ASSERT_NO_FATAL_FAILURE(s3.open()); + ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, true, &s)); + EXPECT_EQ(kInactive, s3.pst_report()->status); +} + +TEST_F(UsageTableTest, DeleteEntryLargeBuffer) { + std::string pst(kMaxPSTLength, 'a'); // A large PST. + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(s.GenerateTestSessionKeys()); + ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage( + 0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceRequired, + s.get_nonce(), pst)); + ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_)); + ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR()); + s.GenerateReport(pst); + ASSERT_NO_FATAL_FAILURE(s.close()); + + // New session should be able to generate report and copy mac keys. + Session s2; + ASSERT_NO_FATAL_FAILURE(s2.open()); + ASSERT_NO_FATAL_FAILURE(s2.GenerateReport(pst, true, &s)); + EXPECT_EQ(kActive, s2.pst_report()->status); + ASSERT_NO_FATAL_FAILURE(s2.DeleteEntry(pst)); + ASSERT_NO_FATAL_FAILURE(s2.close()); + + // Now that session is deleted, we can't generate a report for it. + Session s3; + ASSERT_NO_FATAL_FAILURE(s3.open()); + ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, false)); + ASSERT_NO_FATAL_FAILURE(s3.close()); +} + +TEST_F(UsageTableTest, ForceDeleteLargeBuffer) { + std::string pst(kMaxPSTLength, 'a'); // A large PST. + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(s.GenerateTestSessionKeys()); + ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage( + 0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceRequired, + s.get_nonce(), pst)); + ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_)); + ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR()); + ASSERT_NO_FATAL_FAILURE(s.GenerateReport(pst)); + ASSERT_NO_FATAL_FAILURE(s.close()); + + ASSERT_NO_FATAL_FAILURE(s.ForceDeleteEntry(pst)); + + // Now that session is deleted, we can't generate a report for it. + Session s3; + ASSERT_NO_FATAL_FAILURE(s3.open()); + ASSERT_NO_FATAL_FAILURE(s3.GenerateReport(pst, false)); + ASSERT_NO_FATAL_FAILURE(s3.close()); +} + INSTANTIATE_TEST_CASE_P(TestUsageTables, UsageTableTestWithMAC, Values(true, false)); // With and without new_mac_keys. } // namespace wvoec