diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp index 5b92ee0a..1473d3ea 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp @@ -177,6 +177,9 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = { 0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03 }; + +// Filler for returning vector references. +const std::vector kEmptyVector; } // namespace bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { @@ -184,12 +187,10 @@ bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { // If provisioning method is something other than ProvisioningError // indicates it has already been initialized before. Must // existing data. - drm_cert_key_.reset(); - test_drm_cert_key_.reset(); + rsa_key_.reset(); + test_rsa_key_.reset(); keybox_.reset(); test_keybox_.reset(); - oem_cert_.reset(); - oem_cert_key_.reset(); } prov_method_ = method; switch (method) { @@ -197,7 +198,7 @@ bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { std::unique_ptr key = RsaPrivateKey::Load(kPrivateKey, kPrivateKeySize); if (key) { - drm_cert_key_ = std::move(key); + rsa_key_ = std::move(key); } else { // This error message is OK in unit tests which use test certificate. LOGE( @@ -229,7 +230,8 @@ bool AuthenticationRoot::IsValid() const { return HasDeviceKey(); } case OEMCrypto_OEMCertificate: { - return HasOemCertKey() && HasDeviceKey(); + // TODO(sigquit): Add OEM Certificate validation. + return true; } default: { LOGE("Root of trust is not properly initialized"); @@ -249,11 +251,8 @@ OEMCryptoResult AuthenticationRoot::IsKeyboxOrOemCertValid() const { return kb->IsKeyboxValid(); } case OEMCrypto_OEMCertificate: { - if (!oem_cert_) { - LOGW("OEM cert is not installed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return oem_cert_->IsCertificateValid(); + LOGW("OEM certificate validation is not implemented"); + return OEMCrypto_ERROR_NOT_IMPLEMENTED; } case OEMCrypto_DrmCertificate: { return OEMCrypto_ERROR_NOT_IMPLEMENTED; @@ -301,7 +300,7 @@ std::vector AuthenticationRoot::DeviceId() const { } if (prov_method_ == OEMCrypto_Keybox) { LOGE("Expected keybox to be set for a device ID"); - return std::vector(); + return kEmptyVector; } return std::vector(kFakeDeviceId.begin(), kFakeDeviceId.end()); } @@ -312,7 +311,7 @@ std::vector AuthenticationRoot::DeviceKey() const { return kb->DeviceKey(); } LOGE("No device key has been set"); - return std::vector(); + return kEmptyVector; } bool AuthenticationRoot::HasDeviceKey() const { return keybox() != nullptr; } @@ -327,7 +326,7 @@ OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() { LOGE("System does not support DRM certificates"); return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - if (test_drm_cert_key_) { + if (test_rsa_key_) { LOGE("Test RSA key is already loaded"); return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; } @@ -338,7 +337,7 @@ OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() { LOGE("Failed to load test RSA key"); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - test_drm_cert_key_ = std::move(key); + test_rsa_key_ = std::move(key); return OEMCrypto_SUCCESS; } @@ -400,48 +399,22 @@ OEMCryptoResult AuthenticationRoot::GetKeyData(uint8_t* key_data, return kb->GetKeyData(key_data, key_data_length); } -OEMCryptoResult AuthenticationRoot::InstallOemCertificate( - const uint8_t* private_key, size_t private_key_size, - const uint8_t* public_cert, size_t public_cert_size) { - if (prov_method_ != OEMCrypto_OEMCertificate) { - LOGE("System does not support OEM certificates"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (oem_cert_ || oem_cert_key_) { - LOGE("OEM certificate is already installed"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - std::unique_ptr oem_cert = OemCertificate::Create( - private_key, private_key_size, public_cert, public_cert_size); - if (!oem_cert) { - LOGE("Failed to install OEM certificate as root of trust"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (oem_cert->key_type() != OemCertificate::kRsa) { - LOGE("Only RSA-based OEM certificates supported"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - std::unique_ptr oem_cert_key = - RsaPrivateKey::Load(oem_cert->GetPrivateKey()); - if (!oem_cert_key) { - LOGE("Failed to parse OEM certificate private key"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - oem_cert_ = std::move(oem_cert); - oem_cert_key_ = std::move(oem_cert_key); - return OEMCrypto_SUCCESS; -} - OEMCryptoResult AuthenticationRoot::GetOemPublicCertificate( uint8_t* public_cert, size_t* public_cert_length) const { if (prov_method_ != OEMCrypto_OEMCertificate) { LOGE("System does not support OEM certificates"); return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - if (!oem_cert_) { - LOGE("OEM certificate is not installed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + LOGE("OEM certificates have not been implemented on auth root"); + return OEMCrypto_ERROR_NOT_IMPLEMENTED; +} + +const std::vector& AuthenticationRoot::GetOemPrivateKey() const { + if (prov_method_ != OEMCrypto_OEMCertificate) { + LOGE("System does not support OEM certificates"); + return kEmptyVector; } - return oem_cert_->GetPublicCertificate(public_cert, public_cert_length); + LOGE("OEM certificates have not been implemented on auth root"); + return kEmptyVector; } } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h index c2a88dcd..aa898886 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h @@ -15,7 +15,6 @@ #include "OEMCryptoCENC.h" // Needed for enums only. #include "disallow_copy_and_assign.h" #include "oemcrypto_keybox_ref.h" -#include "oemcrypto_oem_cert.h" #include "oemcrypto_rsa_key.h" namespace wvoec_ref { @@ -68,12 +67,12 @@ class AuthenticationRoot { // Returns the shared RSA private key from the built-in DRM // Certificate. std::shared_ptr ShareDrmCertKey() { - return test_drm_cert_key_ ? test_drm_cert_key_ : drm_cert_key_; + return test_rsa_key_ ? test_rsa_key_ : rsa_key_; } RsaPrivateKey* DrmCertKey() const { - return test_drm_cert_key_ ? test_drm_cert_key_.get() : drm_cert_key_.get(); + return test_rsa_key_ ? test_rsa_key_.get() : rsa_key_.get(); } - bool HasDrmCertKey() const { return test_drm_cert_key_ || drm_cert_key_; } + bool HasDrmCertKey() const { return test_rsa_key_ || rsa_key_; } // Loads the system's built-in RSA key. Only implemented for // devices that are that pre-provisioned with a built-in DRM @@ -83,7 +82,7 @@ class AuthenticationRoot { OEMCryptoResult LoadTestRsaKey(); // Removes any installed test RSA key. - void RemoveTestRsaKey() { test_drm_cert_key_.reset(); } + void RemoveTestRsaKey() { test_rsa_key_.reset(); } // Keybox-based root of trust API. @@ -125,14 +124,6 @@ class AuthenticationRoot { // OEM Certificate-base root of trust API. - // Installs an OEM certificate as the root of trust. The provided - // private key and public cert are parsed, but not validated. The - // private key will be made available for sessions to load. - OEMCryptoResult InstallOemCertificate(const uint8_t* private_key, - size_t private_key_size, - const uint8_t* public_cert, - size_t public_cert_size); - // For OEM Cert-based devices, returns the OEM Public Certificate // component of the OEM Certificate. // This method implements the expected behavior of @@ -144,9 +135,7 @@ class AuthenticationRoot { // the OEM private key into a session. // Should only be called for devices that use OEM Certificates // for provisioning. - std::shared_ptr ShareOemCertKey() { return oem_cert_key_; } - RsaPrivateKey* OemCertKey() const { return oem_cert_key_.get(); } - bool HasOemCertKey() const { return static_cast(oem_cert_key_); } + const std::vector& GetOemPrivateKey() const; private: OEMCrypto_ProvisioningMethod prov_method_ = OEMCrypto_ProvisioningError; @@ -154,17 +143,13 @@ class AuthenticationRoot { // DRM certificate. // If no keybox, this is the private key of the baked-in DRM // Certificate. - std::shared_ptr drm_cert_key_; - std::shared_ptr test_drm_cert_key_; + std::shared_ptr rsa_key_; + std::shared_ptr test_rsa_key_; // Keybox data. std::unique_ptr keybox_; std::unique_ptr test_keybox_; - // OEM certificate. - std::unique_ptr oem_cert_; - std::shared_ptr oem_cert_key_; - CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot); }; } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp index d2115ca1..0a2fc0dc 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp @@ -24,15 +24,6 @@ class Prov30CryptoEngine : public CryptoEngine { explicit Prov30CryptoEngine(std::unique_ptr&& file_system) : CryptoEngine(std::move(file_system)) {} - bool Initialize() override { - if (!CryptoEngine::Initialize()) { - return false; - } - const OEMCryptoResult result = InstallOemCertificate( - kOEMPrivateKey, kOEMPrivateKeySize, kOEMPublicCert, kOEMPublicCertSize); - return result == OEMCrypto_SUCCESS; - } - bool config_local_display_only() { return true; } // Returns the max HDCP version supported. @@ -56,6 +47,31 @@ class Prov30CryptoEngine : public CryptoEngine { return OEMCrypto_OEMCertificate; } + OEMCryptoResult get_oem_certificate(SessionContext* session, + uint8_t* public_cert, + size_t* public_cert_length) { + if (kOEMPublicCertSize == 0) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + if (public_cert_length == nullptr) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (*public_cert_length < kOEMPublicCertSize) { + *public_cert_length = kOEMPublicCertSize; + return OEMCrypto_ERROR_SHORT_BUFFER; + } + *public_cert_length = kOEMPublicCertSize; + if (public_cert == nullptr) { + return OEMCrypto_ERROR_SHORT_BUFFER; + } + memcpy(public_cert, kOEMPublicCert, kOEMPublicCertSize); + if (!session->LoadRsaDrmKey(kOEMPrivateKey, kOEMPrivateKeySize)) { + LOGE("Private RSA Key did not load correctly."); + return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + return OEMCrypto_SUCCESS; + } + // Returns "L3" for a software only library. L1 is for hardware protected // keys and data paths. L2 is for hardware protected keys but no data path // protection. diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h index f7f92c14..150fdf96 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h @@ -75,8 +75,8 @@ class CryptoEngine { OEMCryptoResult LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); } - OEMCryptoResult IsKeyboxOrOemCertValid() const { - return root_of_trust_.IsKeyboxOrOemCertValid(); + OEMCryptoResult IsKeyboxValid() const { + return root_of_trust_.IsKeyboxValid(); } std::vector DeviceRootKey() const { @@ -97,26 +97,6 @@ class CryptoEngine { return root_of_trust_.GetKeyData(key_data, key_data_length); } - OEMCryptoResult InstallOemCertificate(const uint8_t* private_key, - size_t private_key_size, - const uint8_t* public_cert, - size_t public_cert_size) { - return root_of_trust_.InstallOemCertificate(private_key, private_key_size, - public_cert, public_cert_size); - } - - OEMCryptoResult GetOemPublicCertificate(uint8_t* public_cert, - size_t* public_cert_length) const { - return root_of_trust_.GetOemPublicCertificate(public_cert, - public_cert_length); - } - - std::shared_ptr ShareOemPrivateKey() { - return root_of_trust_.ShareOemCertKey(); - } - - bool HasOemPrivateKey() const { return root_of_trust_.HasOemCertKey(); } - virtual void Terminate(); virtual SessionId OpenSession(); @@ -175,6 +155,15 @@ class CryptoEngine { return OEMCrypto_Keybox; } + virtual OEMCryptoResult get_oem_certificate(uint8_t* public_cert, + size_t* public_cert_length) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + + virtual OEMCryptoResult load_oem_private_key(SessionContext* session) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + // Used for OEMCrypto_IsAntiRollbackHwPresent. virtual bool config_is_anti_rollback_hw_present() { return false; } diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp index 6aa2f19e..b2f3b63c 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp @@ -762,8 +762,10 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) { case OEMCrypto_DrmCertificate: return OEMCrypto_SUCCESS; case OEMCrypto_Keybox: + return crypto_engine->IsKeyboxValid(); case OEMCrypto_OEMCertificate: - return crypto_engine->IsKeyboxOrOemCertValid(); + // TODO(sigquit): verify that the certificate exists and is valid. + return OEMCrypto_SUCCESS; default: LOGE("Invalid provisioning method: %d.", crypto_engine->config_provisioning_method()); @@ -795,7 +797,7 @@ OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session) { LOGE("OEMCrypto_ERROR_INVALID_SESSION"); return OEMCrypto_ERROR_INVALID_SESSION; } - return session_ctx->LoadOemPrivateKey(); + return crypto_engine->load_oem_private_key(session_ctx); } OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate( @@ -809,8 +811,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate( crypto_engine->config_provisioning_method()); return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - return crypto_engine->GetOemPublicCertificate(public_cert, - public_cert_length); + return crypto_engine->get_oem_certificate(public_cert, public_cert_length); } OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* device_id, diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp index 657867aa..4ca614b9 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp @@ -296,15 +296,6 @@ OEMCryptoResult SessionContext::RSADeriveKeys( return DeriveKeys(session_key_, mac_key_context, enc_key_context); } -OEMCryptoResult SessionContext::LoadOemPrivateKey() { - if (!ce_->HasOemPrivateKey()) { - LOGE("No OEM private key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - rsa_key_ = ce_->ShareOemPrivateKey(); - return OEMCrypto_SUCCESS; -} - OEMCryptoResult SessionContext::PrepAndSignLicenseRequest( uint8_t* message, size_t message_length, size_t* core_message_length, uint8_t* signature, size_t* signature_length) { diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h index 8811b9eb..4ed6846e 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h @@ -75,9 +75,6 @@ class SessionContext { const std::vector& enc_session_key, const std::vector& mac_context, const std::vector& enc_context); - - virtual OEMCryptoResult LoadOemPrivateKey(); - virtual OEMCryptoResult PrepAndSignLicenseRequest(uint8_t* message, size_t message_length, size_t* core_message_length, diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index 243c7984..6a3b85cd 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -51,12 +51,67 @@ void PrintTo(const vector& value, ostream* os) { } } // namespace std -namespace { -constexpr size_t kTestSubsampleSectionSize = 256; -} // namespace - namespace wvoec { +namespace { + +constexpr size_t kTestSubsampleSectionSize = 256; + +// Encrypt a block of data using CTR mode. +void EncryptCTR(const vector& in_buffer, const uint8_t* key, + const uint8_t* starting_iv, vector* out_buffer) { + ASSERT_NE(nullptr, key); + ASSERT_NE(nullptr, starting_iv); + ASSERT_NE(nullptr, out_buffer); + AES_KEY aes_key; + AES_set_encrypt_key(key, AES_BLOCK_SIZE * 8, &aes_key); + out_buffer->resize(in_buffer.size()); + + uint8_t iv[AES_BLOCK_SIZE]; // Current iv. + + memcpy(iv, &starting_iv[0], AES_BLOCK_SIZE); + size_t l = 0; // byte index into encrypted subsample. + while (l < in_buffer.size()) { + uint8_t aes_output[AES_BLOCK_SIZE]; + AES_encrypt(iv, aes_output, &aes_key); + for (size_t n = 0; n < AES_BLOCK_SIZE && l < in_buffer.size(); n++, l++) { + (*out_buffer)[l] = aes_output[n] ^ in_buffer[l]; + } + ctr128_inc64(1, iv); + } +} + +// Uses OEMCrypto to decrypt some random data in 'cenc' mode. This function +// assumes that the correct key is already selected in the session. It requires +// the plaintext of that key so that it can encrypt the test data. It resizes +// the provided vectors and fills them with the expected and actual decrypt +// results. Returns the result of OEMCrypto_DecryptCENC(). +OEMCryptoResult DecryptCTR(OEMCrypto_SESSION session_id, const uint8_t* key, + vector* expected_data, + vector* actual_data) { + vector encrypted_data(kTestSubsampleSectionSize); + expected_data->resize(encrypted_data.size()); + actual_data->resize(encrypted_data.size()); + + // Create test sample description + OEMCrypto_SampleDescription sample_description; + OEMCrypto_SubSampleDescription subsample_description; + GenerateSimpleSampleDescription(encrypted_data, *actual_data, + &sample_description, &subsample_description); + + // Generate test data + EXPECT_EQ(GetRandBytes(expected_data->data(), expected_data->size()), 1); + EncryptCTR(*expected_data, key, &sample_description.iv[0], &encrypted_data); + + // Create the pattern description (always 0,0 for 'cenc') + OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; + + // Decrypt the data + return OEMCrypto_DecryptCENC(session_id, &sample_description, 1, &pattern); +} + +} // namespace + int GetRandBytes(unsigned char* buf, int num) { // returns 1 on success, -1 if not supported, or 0 if other failure. return RAND_bytes(buf, num); @@ -70,9 +125,6 @@ void GenerateSimpleSampleDescription( const std::vector& in, std::vector& out, OEMCrypto_SampleDescription* sample, OEMCrypto_SubSampleDescription* subsample) { - ASSERT_NE(sample, nullptr); - ASSERT_NE(subsample, nullptr); - // Generate test data EXPECT_EQ(GetRandBytes(&sample->iv[0], KEY_IV_SIZE), 1); @@ -950,7 +1002,8 @@ void EntitledMessage::LoadKeys(OEMCryptoResult expected_sts) { if (expected_sts != OEMCrypto_SUCCESS) { return; } - VerifyEntitlementTestKeys(); + VerifyKCBs(); + VerifyDecrypt(); } OEMCryptoResult EntitledMessage::LoadKeys(const vector& message) { @@ -997,11 +1050,11 @@ void EntitledMessage::EncryptContentKey() { } } -// This function verifies that the key control block reported by OEMCrypto agree -// with the truth key control block. Failures in this function probably +// This function verifies that the key control blocks reported by OEMCrypto +// agree with the truth key control block. Failures in this function probably // indicate the OEMCrypto_LoadEntitledKeys did not correctly process the key // control block. -void EntitledMessage::VerifyEntitlementTestKeys() { +void EntitledMessage::VerifyKCBs() { for (unsigned int i = 0; i < num_keys_; i++) { EntitledContentKeyData* key_data = &entitled_key_data_[i]; const size_t entitlement_key_index = key_data->key_index; @@ -1028,6 +1081,28 @@ void EntitledMessage::VerifyEntitlementTestKeys() { } } +void EntitledMessage::VerifyDecrypt() { + const OEMCrypto_SESSION session_id = + license_messages_->session()->session_id(); + + // Loop through all the keys and try decrypt with each one. + for (unsigned int i = 0; i < num_keys_; i++) { + const EntitledContentKeyData* const key_data = &entitled_key_data_[i]; + + OEMCryptoResult result = OEMCrypto_SelectKey( + session_id, key_data->content_key_id, key_data->content_key_id_length, + OEMCrypto_CipherMode_CTR); + ASSERT_EQ(result, OEMCrypto_SUCCESS) << "For key " << i; + + vector expected_data; + vector actual_data; + result = DecryptCTR(session_id, key_data->content_key_data, &expected_data, + &actual_data); + EXPECT_EQ(result, OEMCrypto_SUCCESS) << "For key " << i; + EXPECT_EQ(actual_data, expected_data) << "For key " << i; + } +} + void RenewalRoundTrip::VerifyRequestSignature( const vector& data, const vector& generated_signature, size_t core_message_length) { @@ -1297,30 +1372,6 @@ void Session::GenerateDerivedKeysFromSessionKey() { key_deriver_.DeriveKeys(session_key.data(), mac_context, enc_context); } -void Session::EncryptCTR(const vector& in_buffer, const uint8_t* key, - const uint8_t* starting_iv, - vector* out_buffer) { - ASSERT_NE(nullptr, key); - ASSERT_NE(nullptr, starting_iv); - ASSERT_NE(nullptr, out_buffer); - AES_KEY aes_key; - AES_set_encrypt_key(key, AES_BLOCK_SIZE * 8, &aes_key); - out_buffer->resize(in_buffer.size()); - - uint8_t iv[AES_BLOCK_SIZE]; // Current iv. - - memcpy(iv, &starting_iv[0], AES_BLOCK_SIZE); - size_t l = 0; // byte index into encrypted subsample. - while (l < in_buffer.size()) { - uint8_t aes_output[AES_BLOCK_SIZE]; - AES_encrypt(iv, aes_output, &aes_key); - for (size_t n = 0; n < AES_BLOCK_SIZE && l < in_buffer.size(); n++, l++) { - (*out_buffer)[l] = aes_output[n] ^ in_buffer[l]; - } - ctr128_inc64(1, iv); - } -} - void Session::TestDecryptCTR(bool select_key_first, OEMCryptoResult expected_result, int key_index) { OEMCryptoResult select_result = OEMCrypto_SUCCESS; @@ -1331,28 +1382,12 @@ void Session::TestDecryptCTR(bool select_key_first, license_.keys[key_index].key_id_length, OEMCrypto_CipherMode_CTR); } - // Create test sample description - vector unencrypted_data(kTestSubsampleSectionSize); - vector encrypted_data(unencrypted_data.size()); - vector output_buffer(unencrypted_data.size()); - OEMCrypto_SampleDescription sample_description; - OEMCrypto_SubSampleDescription subsample_description; - - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - encrypted_data, output_buffer, &sample_description, - &subsample_description)); - - // Generate test data - EXPECT_EQ(GetRandBytes(unencrypted_data.data(), unencrypted_data.size()), 1); - EncryptCTR(unencrypted_data, license_.keys[key_index].key_data, - &sample_description.iv[0], &encrypted_data); - - // Create the pattern description (always 0,0 for CTR) - OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; - - // Decrypt the data + vector unencrypted_data; + vector output_buffer; const OEMCryptoResult decrypt_result = - OEMCrypto_DecryptCENC(session_id(), &sample_description, 1, &pattern); + DecryptCTR(session_id(), license_.keys[key_index].key_data, + &unencrypted_data, &output_buffer); + // We only have a few errors that we test are reported. ASSERT_NO_FATAL_FAILURE( TestDecryptResult(expected_result, select_result, decrypt_result)) diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 272e85e1..d2bde5e8 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -476,8 +476,6 @@ class EntitledMessage { 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(); OEMCrypto_EntitledContentKeyObject* entitled_key_array(); // Returns entitled_key_data_ which is used as input message buffer to // load entitled content keys API. @@ -487,6 +485,11 @@ class EntitledMessage { private: // Find the offset of the give pointer, relative to |entitled_key_data_|. OEMCrypto_Substring FindSubstring(const void* ptr, size_t size); + // Verify that key control blocks of the loaded keys matches their entitlement + // key. + void VerifyKCBs(); + // Verify that decryption with the entitled keys works. + void VerifyDecrypt(); LicenseRoundTrip* license_messages_; uint32_t num_keys_; @@ -528,9 +531,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(); - // Encrypt a block of data using CTR mode. - void EncryptCTR(const vector& in_buffer, const uint8_t* key, - const uint8_t* starting_iv, vector* 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, diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 07d2a1e7..8612bdae 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -2516,8 +2516,8 @@ TEST_P(OEMCryptoLicenseTest, SelectKeyNotThereAPI16) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); // Generate test data for (size_t i = 0; i < in_buffer.size(); i++) in_buffer[i] = i % 256; @@ -2551,8 +2551,8 @@ TEST_P(OEMCryptoLicenseTest, RejectCensAPI16) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); // Create a non-zero pattern to indicate this is 'cens' OEMCrypto_CENCEncryptPatternDesc pattern = {1, 9}; @@ -2582,8 +2582,8 @@ TEST_P(OEMCryptoLicenseTest, RejectCbc1API16) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); // Create a zero pattern to indicate this is 'cbc1' OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; @@ -2612,8 +2612,8 @@ TEST_P(OEMCryptoLicenseTest, RejectCbcsWithBlockOffset) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); subsample_description.block_offset = 5; // Any value 1-15 will do. // Create a non-zero pattern to indicate this is 'cbcs'. @@ -2643,8 +2643,8 @@ TEST_P(OEMCryptoLicenseTest, RejectOversizedBlockOffset) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); subsample_description.block_offset = 0xFF; // Anything 16+ // Create a zero pattern to indicate this is 'cenc'.