From 5317ce1c63e6eccb56bf43e6221fca82baca39b5 Mon Sep 17 00:00:00 2001 From: Vicky Min Date: Thu, 8 Jun 2023 21:55:51 +0000 Subject: [PATCH] Refactor generic crypto unit tests Refactor the generic crypto oemcrypto unit tests into a separate file. Bug: 253779846 Merged from https://widevine-internal-review.googlesource.com/176730 Change-Id: I343ee19ef979a9bedbc528a4533711a137ffb5e9 --- libwvdrmengine/oemcrypto/test/common.mk | 1 + .../test/oemcrypto_generic_crypto_test.cpp | 577 ++++++++++++++++++ .../oemcrypto/test/oemcrypto_test.cpp | 566 ----------------- 3 files changed, 578 insertions(+), 566 deletions(-) create mode 100644 libwvdrmengine/oemcrypto/test/oemcrypto_generic_crypto_test.cpp diff --git a/libwvdrmengine/oemcrypto/test/common.mk b/libwvdrmengine/oemcrypto/test/common.mk index 8a92ad43..3b57f083 100644 --- a/libwvdrmengine/oemcrypto/test/common.mk +++ b/libwvdrmengine/oemcrypto/test/common.mk @@ -18,6 +18,7 @@ LOCAL_SRC_FILES:= \ oemcrypto_session_tests_helper.cpp \ oemcrypto_basic_test.cpp \ oemcrypto_decrypt_test.cpp \ + oemcrypto_generic_crypto_test.cpp \ oemcrypto_license_test.cpp \ oemcrypto_provisioning_test.cpp \ oemcrypto_usage_table_test.cpp \ diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_generic_crypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_generic_crypto_test.cpp new file mode 100644 index 00000000..867b4f8e --- /dev/null +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_generic_crypto_test.cpp @@ -0,0 +1,577 @@ +// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine +// License Agreement. +// + +#include + +#include "oemcrypto_usage_table_test.h" + +using ::testing::Range; + +namespace wvoec { + +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyLoad) { EncryptAndLoadKeys(); } + +// Test that the Generic_Encrypt function works correctly. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncrypt) { + EncryptAndLoadKeys(); + unsigned int key_index = 0; + vector expected_encrypted; + EncryptBuffer(key_index, clear_buffer_, &expected_encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector encrypted(clear_buffer_.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericEncrypt(key_handle.data(), key_handle.size(), + clear_buffer_.data(), clear_buffer_.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data())); + ASSERT_EQ(expected_encrypted, encrypted); +} + +// Test that the Generic_Encrypt function fails when not allowed. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadEncrypt) { + EncryptAndLoadKeys(); + BadEncrypt(0, OEMCrypto_HMAC_SHA256, buffer_size_); + // The buffer size must be a multiple of 16, so subtracting 10 is bad. + BadEncrypt(0, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_ - 10); + BadEncrypt(1, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); + BadEncrypt(2, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); + BadEncrypt(3, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); +} + +// Test that the Generic_Encrypt works if the input and output buffers are the +// same. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncryptSameBufferAPI12) { + EncryptAndLoadKeys(); + unsigned int key_index = 0; + vector expected_encrypted; + EncryptBuffer(key_index, clear_buffer_, &expected_encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + // Input and output are same buffer: + vector buffer = clear_buffer_; + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericEncrypt(key_handle.data(), key_handle.size(), buffer.data(), + buffer.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING, + buffer.data())); + ASSERT_EQ(expected_encrypted, buffer); +} + +TEST_P( + OEMCryptoGenericCryptoTest, + OEMCryptoMemoryGenericKeyEncryptForHugeBufferWithBufferLengthNotMultipleOf16) { + EncryptAndLoadKeys(); + unsigned int key_index = 0; + vector expected_encrypted; + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector buffer(17); + ASSERT_NO_FATAL_FAILURE(OEMCrypto_Generic_Encrypt( + key_handle.data(), key_handle.size(), buffer.data(), buffer.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, buffer.data())); +} + +// Test Generic_Decrypt works correctly. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyDecrypt) { + EncryptAndLoadKeys(); + unsigned int key_index = 1; + vector encrypted; + EncryptBuffer(key_index, clear_buffer_, &encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector resultant(encrypted.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericDecrypt(key_handle.data(), key_handle.size(), + encrypted.data(), encrypted.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); + ASSERT_EQ(clear_buffer_, resultant); +} + +// Test that Generic_Decrypt works correctly when the input and output buffers +// are the same. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyDecryptSameBufferAPI12) { + EncryptAndLoadKeys(); + unsigned int key_index = 1; + vector encrypted; + EncryptBuffer(key_index, clear_buffer_, &encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector buffer = encrypted; + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericDecrypt(key_handle.data(), key_handle.size(), buffer.data(), + buffer.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING, + buffer.data())); + ASSERT_EQ(clear_buffer_, buffer); +} + +// Test that Generic_Decrypt fails to decrypt to an insecure buffer if the key +// requires a secure data path. +TEST_P(OEMCryptoGenericCryptoTest, GenericSecureToClear) { + license_messages_.set_control(wvoec::kControlObserveDataPath | + wvoec::kControlDataPathSecure); + license_messages_.CreateResponseWithGenericCryptoKeys(); + EncryptAndLoadKeys(); + unsigned int key_index = 1; + vector encrypted; + EncryptBuffer(key_index, clear_buffer_, &encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector resultant(encrypted.size()); + ASSERT_NE(OEMCrypto_SUCCESS, + GenericDecrypt(key_handle.data(), key_handle.size(), + encrypted.data(), encrypted.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); + ASSERT_NE(clear_buffer_, resultant); +} + +// Test that the Generic_Decrypt function fails when not allowed. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadDecrypt) { + EncryptAndLoadKeys(); + BadDecrypt(1, OEMCrypto_HMAC_SHA256, buffer_size_); + // The buffer size must be a multiple of 16, so subtracting 10 is bad. + BadDecrypt(1, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_ - 10); + BadDecrypt(0, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); + BadDecrypt(2, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); + BadDecrypt(3, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); +} + +TEST_P(OEMCryptoGenericCryptoTest, GenericKeySign) { + EncryptAndLoadKeys(); + unsigned int key_index = 2; + vector expected_signature; + SignBuffer(key_index, clear_buffer_, &expected_signature); + + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + size_t gen_signature_length = 0; + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, + GenericSign(key_handle.data(), key_handle.size(), + clear_buffer_.data(), clear_buffer_.size(), + OEMCrypto_HMAC_SHA256, nullptr, &gen_signature_length)); + ASSERT_EQ(static_cast(SHA256_DIGEST_LENGTH), gen_signature_length); + vector signature(SHA256_DIGEST_LENGTH); + ASSERT_EQ( + OEMCrypto_SUCCESS, + GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), + &gen_signature_length)); + ASSERT_EQ(expected_signature, signature); +} + +// Test that the Generic_Sign function fails when not allowed. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadSign) { + EncryptAndLoadKeys(); + BadSign(0, OEMCrypto_HMAC_SHA256); // Can't sign with encrypt key. + BadSign(1, OEMCrypto_HMAC_SHA256); // Can't sign with decrypt key. + BadSign(3, OEMCrypto_HMAC_SHA256); // Can't sign with verify key. + BadSign(2, OEMCrypto_AES_CBC_128_NO_PADDING); // Bad signing algorithm. +} + +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyVerify) { + EncryptAndLoadKeys(); + unsigned int key_index = 3; + vector signature; + SignBuffer(key_index, clear_buffer_, &signature); + + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + ASSERT_EQ( + OEMCrypto_SUCCESS, + GenericVerify(key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, + signature.data(), signature.size())); +} + +// Test that the Generic_Verify function fails when not allowed. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadVerify) { + EncryptAndLoadKeys(); + BadVerify(0, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, false); + BadVerify(1, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, false); + BadVerify(2, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, false); + BadVerify(3, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, true); + BadVerify(3, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH - 1, false); + BadVerify(3, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH + 1, false); + BadVerify(3, OEMCrypto_AES_CBC_128_NO_PADDING, SHA256_DIGEST_LENGTH, false); +} + +// Test Generic_Encrypt with the maximum buffer size. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncryptLargeBuffer) { + ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); + EncryptAndLoadKeys(); + unsigned int key_index = 0; + vector expected_encrypted; + EncryptBuffer(key_index, clear_buffer_, &expected_encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector encrypted(clear_buffer_.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericEncrypt(key_handle.data(), key_handle.size(), + clear_buffer_.data(), clear_buffer_.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data())); + ASSERT_EQ(expected_encrypted, encrypted); +} + +// Test Generic_Decrypt with the maximum buffer size. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyDecryptLargeBuffer) { + // Some applications are known to pass in a block that is almost 400k. + ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); + EncryptAndLoadKeys(); + unsigned int key_index = 1; + vector encrypted; + EncryptBuffer(key_index, clear_buffer_, &encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector resultant(encrypted.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericDecrypt(key_handle.data(), key_handle.size(), + encrypted.data(), encrypted.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); + ASSERT_EQ(clear_buffer_, resultant); +} + +// Test Generic_Sign with the maximum buffer size. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeySignLargeBuffer) { + ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); + EncryptAndLoadKeys(); + unsigned int key_index = 2; + vector expected_signature; + SignBuffer(key_index, clear_buffer_, &expected_signature); + + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + size_t gen_signature_length = 0; + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, + GenericSign(key_handle.data(), key_handle.size(), + clear_buffer_.data(), clear_buffer_.size(), + OEMCrypto_HMAC_SHA256, nullptr, &gen_signature_length)); + ASSERT_EQ(static_cast(SHA256_DIGEST_LENGTH), gen_signature_length); + vector signature(SHA256_DIGEST_LENGTH); + ASSERT_EQ( + OEMCrypto_SUCCESS, + GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), + &gen_signature_length)); + ASSERT_EQ(expected_signature, signature); +} + +// Test Generic_Verify with the maximum buffer size. +TEST_P(OEMCryptoGenericCryptoTest, GenericKeyVerifyLargeBuffer) { + ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); + EncryptAndLoadKeys(); + unsigned int key_index = 3; + vector signature; + SignBuffer(key_index, clear_buffer_, &signature); + + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + ASSERT_EQ( + OEMCrypto_SUCCESS, + GenericVerify(key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, + signature.data(), signature.size())); +} + +// Test Generic_Encrypt when the key duration has expired. +TEST_P(OEMCryptoGenericCryptoTest, KeyDurationEncrypt) { + license_messages_.core_response() + .timer_limits.total_playback_duration_seconds = kDuration; + license_messages_.CreateResponseWithGenericCryptoKeys(); + EncryptAndLoadKeys(); + vector expected_encrypted; + EncryptBuffer(0, clear_buffer_, &expected_encrypted); + unsigned int key_index = 0; + vector encrypted(clear_buffer_.size()); + + vector key_handle; + // Should be valid key at the start. + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericEncrypt(key_handle.data(), key_handle.size(), + clear_buffer_.data(), clear_buffer_.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data())); + ASSERT_EQ(expected_encrypted, encrypted); + + wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. + encrypted.assign(clear_buffer_.size(), 0); + OEMCryptoResult status = OEMCrypto_Generic_Encrypt( + key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING, + encrypted.data()); + ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); + ASSERT_NE(encrypted, expected_encrypted); + ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); +} + +// Test Generic_Decrypt when the key duration has expired. +TEST_P(OEMCryptoGenericCryptoTest, KeyDurationDecrypt) { + license_messages_.core_response() + .timer_limits.total_playback_duration_seconds = kDuration; + license_messages_.CreateResponseWithGenericCryptoKeys(); + EncryptAndLoadKeys(); + + // Should be valid key at the start. + unsigned int key_index = 1; + vector encrypted; + EncryptBuffer(key_index, clear_buffer_, &encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector resultant(encrypted.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, + GenericDecrypt(key_handle.data(), key_handle.size(), + encrypted.data(), encrypted.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); + ASSERT_EQ(clear_buffer_, resultant); + + wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. + resultant.assign(encrypted.size(), 0); + OEMCryptoResult status = GenericDecrypt( + key_handle.data(), key_handle.size(), encrypted.data(), encrypted.size(), + iv_, OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data()); + ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); + ASSERT_NE(clear_buffer_, resultant); + ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); +} + +// Test Generic_Sign when the key duration has expired. +TEST_P(OEMCryptoGenericCryptoTest, KeyDurationSign) { + license_messages_.core_response() + .timer_limits.total_playback_duration_seconds = kDuration; + license_messages_.CreateResponseWithGenericCryptoKeys(); + EncryptAndLoadKeys(); + + unsigned int key_index = 2; + vector expected_signature; + vector signature(SHA256_DIGEST_LENGTH); + size_t signature_length = signature.size(); + SignBuffer(key_index, clear_buffer_, &expected_signature); + + vector key_handle; + // Should be valid key at the start. + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + ASSERT_EQ( + OEMCrypto_SUCCESS, + GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), + &signature_length)); + ASSERT_EQ(expected_signature, signature); + + wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. + signature.assign(SHA256_DIGEST_LENGTH, 0); + OEMCryptoResult status = + GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), + &signature_length); + ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); + ASSERT_NE(expected_signature, signature); + ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); +} + +// Test Generic_Verify when the key duration has expired. +TEST_P(OEMCryptoGenericCryptoTest, KeyDurationVerify) { + license_messages_.core_response() + .timer_limits.total_playback_duration_seconds = kDuration; + license_messages_.CreateResponseWithGenericCryptoKeys(); + EncryptAndLoadKeys(); + + unsigned int key_index = 3; + vector signature; + SignBuffer(key_index, clear_buffer_, &signature); + + vector key_handle; + // Should be valid key at the start. + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), + session_.license().keys[key_index].key_id, + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + ASSERT_EQ( + OEMCrypto_SUCCESS, + GenericVerify(key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, + signature.data(), signature.size())); + + wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. + OEMCryptoResult status = OEMCrypto_Generic_Verify( + key_handle.data(), key_handle.size(), clear_buffer_.data(), + clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), + signature.size()); + ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); + ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); +} + +const unsigned int kLongKeyId = 2; + +// Test that short key ids are allowed. +class OEMCryptoGenericCryptoKeyIdLengthTest + : public OEMCryptoGenericCryptoTest { + protected: + void SetUp() override { + OEMCryptoGenericCryptoTest::SetUp(); + license_messages_.set_num_keys(5); + license_messages_.set_control(wvoec::kControlAllowDecrypt); + license_messages_.core_response() + .timer_limits.total_playback_duration_seconds = kDuration; + ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); + SetUniformKeyIdLength(16); // Start with all key ids being 16 bytes. + // But, we are testing that the key ids do not have to have the same + // length. + // 12 bytes (common key id length). + license_messages_.SetKeyId(0, "123456789012"); + license_messages_.SetKeyId(1, "12345"); // short key id. + // 16 byte key id. (default) + license_messages_.SetKeyId(2, "1234567890123456"); + license_messages_.SetKeyId(3, "12345678901234"); // 14 byte. (uncommon) + license_messages_.SetKeyId(4, "1"); // very short key id. + ASSERT_EQ(2u, kLongKeyId); + ASSERT_NO_FATAL_FAILURE(license_messages_.FillCoreResponseSubstrings()); + } + + // Make all four keys have the same length. + void SetUniformKeyIdLength(size_t key_id_length) { + for (size_t i = 0; i < license_messages_.num_keys(); i++) { + string key_id; + key_id.resize(key_id_length, i + 'a'); + license_messages_.SetKeyId(i, key_id); + } + ASSERT_NO_FATAL_FAILURE(license_messages_.FillCoreResponseSubstrings()); + } + + void TestWithKey(unsigned int key_index) { + ASSERT_LT(key_index, license_messages_.num_keys()); + EncryptAndLoadKeys(); + vector encrypted; + // To make sure OEMCrypto is not expecting the key_id to be zero padded, + // we will create a buffer that is padded with 'Z'. Then, we use fill + // the buffer with the longer of the three keys. If OEMCrypto is paying + // attention to the key id length, it should pick out the correct key. + vector key_id_buffer( + session_.license().keys[kLongKeyId].key_id_length + 5, + 'Z'); // Fill a bigger buffer with letter 'Z'. + memcpy(key_id_buffer.data(), session_.license().keys[kLongKeyId].key_id, + session_.license().keys[kLongKeyId].key_id_length); + EncryptBuffer(key_index, clear_buffer_, &encrypted); + vector key_handle; + ASSERT_EQ( + OEMCrypto_SUCCESS, + GetKeyHandleIntoVector(session_.session_id(), key_id_buffer.data(), + session_.license().keys[key_index].key_id_length, + OEMCrypto_CipherMode_CENC, key_handle)); + vector resultant(encrypted.size()); + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_Generic_Decrypt(key_handle.data(), key_handle.size(), + encrypted.data(), encrypted.size(), iv_, + OEMCrypto_AES_CBC_128_NO_PADDING, + resultant.data())); + ASSERT_EQ(clear_buffer_, resultant); + } +}; + +TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, MediumKeyId) { TestWithKey(0); } + +TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, ShortKeyId) { TestWithKey(1); } + +TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, LongKeyId) { TestWithKey(2); } + +TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, FourteenByteKeyId) { + TestWithKey(3); +} + +TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, VeryShortKeyId) { + TestWithKey(4); +} + +TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, UniformShortKeyId) { + SetUniformKeyIdLength(5); + TestWithKey(2); +} + +TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, UniformLongKeyId) { + SetUniformKeyIdLength(kTestKeyIdMaxLength); + TestWithKey(2); +} + +INSTANTIATE_TEST_SUITE_P(TestAll, OEMCryptoGenericCryptoTest, + Range(kCoreMessagesAPI, kCurrentAPI + 1)); + +INSTANTIATE_TEST_SUITE_P(TestAll, OEMCryptoGenericCryptoKeyIdLengthTest, + Range(kCoreMessagesAPI, kCurrentAPI + 1)); + +/// @} +} // namespace wvoec \ No newline at end of file diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index af1ae58e..b2219cd4 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -2781,570 +2781,4 @@ TEST_F(OEMCryptoCastReceiverTest, TestSignaturePKCS1_15_20) { } /// @} - -/// @addtogroup generic -/// @{ - -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyLoad) { EncryptAndLoadKeys(); } - -// Test that the Generic_Encrypt function works correctly. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncrypt) { - EncryptAndLoadKeys(); - unsigned int key_index = 0; - vector expected_encrypted; - EncryptBuffer(key_index, clear_buffer_, &expected_encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector encrypted(clear_buffer_.size()); - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericEncrypt(key_handle.data(), key_handle.size(), - clear_buffer_.data(), clear_buffer_.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data())); - ASSERT_EQ(expected_encrypted, encrypted); -} - -// Test that the Generic_Encrypt function fails when not allowed. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadEncrypt) { - EncryptAndLoadKeys(); - BadEncrypt(0, OEMCrypto_HMAC_SHA256, buffer_size_); - // The buffer size must be a multiple of 16, so subtracting 10 is bad. - BadEncrypt(0, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_ - 10); - BadEncrypt(1, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); - BadEncrypt(2, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); - BadEncrypt(3, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); -} - -// Test that the Generic_Encrypt works if the input and output buffers are the -// same. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncryptSameBufferAPI12) { - EncryptAndLoadKeys(); - unsigned int key_index = 0; - vector expected_encrypted; - EncryptBuffer(key_index, clear_buffer_, &expected_encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - // Input and output are same buffer: - vector buffer = clear_buffer_; - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericEncrypt(key_handle.data(), key_handle.size(), buffer.data(), - buffer.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING, - buffer.data())); - ASSERT_EQ(expected_encrypted, buffer); -} - -TEST_P( - OEMCryptoGenericCryptoTest, - OEMCryptoMemoryGenericKeyEncryptForHugeBufferWithBufferLengthNotMultipleOf16) { - EncryptAndLoadKeys(); - unsigned int key_index = 0; - vector expected_encrypted; - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector buffer(17); - ASSERT_NO_FATAL_FAILURE(OEMCrypto_Generic_Encrypt( - key_handle.data(), key_handle.size(), buffer.data(), buffer.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, buffer.data())); -} - -// Test Generic_Decrypt works correctly. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyDecrypt) { - EncryptAndLoadKeys(); - unsigned int key_index = 1; - vector encrypted; - EncryptBuffer(key_index, clear_buffer_, &encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector resultant(encrypted.size()); - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericDecrypt(key_handle.data(), key_handle.size(), - encrypted.data(), encrypted.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); - ASSERT_EQ(clear_buffer_, resultant); -} - -// Test that Generic_Decrypt works correctly when the input and output buffers -// are the same. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyDecryptSameBufferAPI12) { - EncryptAndLoadKeys(); - unsigned int key_index = 1; - vector encrypted; - EncryptBuffer(key_index, clear_buffer_, &encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector buffer = encrypted; - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericDecrypt(key_handle.data(), key_handle.size(), buffer.data(), - buffer.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING, - buffer.data())); - ASSERT_EQ(clear_buffer_, buffer); -} - -// Test that Generic_Decrypt fails to decrypt to an insecure buffer if the key -// requires a secure data path. -TEST_P(OEMCryptoGenericCryptoTest, GenericSecureToClear) { - license_messages_.set_control(wvoec::kControlObserveDataPath | - wvoec::kControlDataPathSecure); - license_messages_.CreateResponseWithGenericCryptoKeys(); - EncryptAndLoadKeys(); - unsigned int key_index = 1; - vector encrypted; - EncryptBuffer(key_index, clear_buffer_, &encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector resultant(encrypted.size()); - ASSERT_NE(OEMCrypto_SUCCESS, - GenericDecrypt(key_handle.data(), key_handle.size(), - encrypted.data(), encrypted.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); - ASSERT_NE(clear_buffer_, resultant); -} - -// Test that the Generic_Decrypt function fails when not allowed. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadDecrypt) { - EncryptAndLoadKeys(); - BadDecrypt(1, OEMCrypto_HMAC_SHA256, buffer_size_); - // The buffer size must be a multiple of 16, so subtracting 10 is bad. - BadDecrypt(1, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_ - 10); - BadDecrypt(0, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); - BadDecrypt(2, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); - BadDecrypt(3, OEMCrypto_AES_CBC_128_NO_PADDING, buffer_size_); -} - -TEST_P(OEMCryptoGenericCryptoTest, GenericKeySign) { - EncryptAndLoadKeys(); - unsigned int key_index = 2; - vector expected_signature; - SignBuffer(key_index, clear_buffer_, &expected_signature); - - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - size_t gen_signature_length = 0; - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - GenericSign(key_handle.data(), key_handle.size(), - clear_buffer_.data(), clear_buffer_.size(), - OEMCrypto_HMAC_SHA256, nullptr, &gen_signature_length)); - ASSERT_EQ(static_cast(SHA256_DIGEST_LENGTH), gen_signature_length); - vector signature(SHA256_DIGEST_LENGTH); - ASSERT_EQ( - OEMCrypto_SUCCESS, - GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), - &gen_signature_length)); - ASSERT_EQ(expected_signature, signature); -} - -// Test that the Generic_Sign function fails when not allowed. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadSign) { - EncryptAndLoadKeys(); - BadSign(0, OEMCrypto_HMAC_SHA256); // Can't sign with encrypt key. - BadSign(1, OEMCrypto_HMAC_SHA256); // Can't sign with decrypt key. - BadSign(3, OEMCrypto_HMAC_SHA256); // Can't sign with verify key. - BadSign(2, OEMCrypto_AES_CBC_128_NO_PADDING); // Bad signing algorithm. -} - -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyVerify) { - EncryptAndLoadKeys(); - unsigned int key_index = 3; - vector signature; - SignBuffer(key_index, clear_buffer_, &signature); - - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - ASSERT_EQ( - OEMCrypto_SUCCESS, - GenericVerify(key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, - signature.data(), signature.size())); -} - -// Test that the Generic_Verify function fails when not allowed. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyBadVerify) { - EncryptAndLoadKeys(); - BadVerify(0, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, false); - BadVerify(1, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, false); - BadVerify(2, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, false); - BadVerify(3, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH, true); - BadVerify(3, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH - 1, false); - BadVerify(3, OEMCrypto_HMAC_SHA256, SHA256_DIGEST_LENGTH + 1, false); - BadVerify(3, OEMCrypto_AES_CBC_128_NO_PADDING, SHA256_DIGEST_LENGTH, false); -} - -// Test Generic_Encrypt with the maximum buffer size. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyEncryptLargeBuffer) { - ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); - EncryptAndLoadKeys(); - unsigned int key_index = 0; - vector expected_encrypted; - EncryptBuffer(key_index, clear_buffer_, &expected_encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector encrypted(clear_buffer_.size()); - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericEncrypt(key_handle.data(), key_handle.size(), - clear_buffer_.data(), clear_buffer_.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data())); - ASSERT_EQ(expected_encrypted, encrypted); -} - -// Test Generic_Decrypt with the maximum buffer size. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyDecryptLargeBuffer) { - // Some applications are known to pass in a block that is almost 400k. - ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); - EncryptAndLoadKeys(); - unsigned int key_index = 1; - vector encrypted; - EncryptBuffer(key_index, clear_buffer_, &encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector resultant(encrypted.size()); - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericDecrypt(key_handle.data(), key_handle.size(), - encrypted.data(), encrypted.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); - ASSERT_EQ(clear_buffer_, resultant); -} - -// Test Generic_Sign with the maximum buffer size. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeySignLargeBuffer) { - ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); - EncryptAndLoadKeys(); - unsigned int key_index = 2; - vector expected_signature; - SignBuffer(key_index, clear_buffer_, &expected_signature); - - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - size_t gen_signature_length = 0; - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - GenericSign(key_handle.data(), key_handle.size(), - clear_buffer_.data(), clear_buffer_.size(), - OEMCrypto_HMAC_SHA256, nullptr, &gen_signature_length)); - ASSERT_EQ(static_cast(SHA256_DIGEST_LENGTH), gen_signature_length); - vector signature(SHA256_DIGEST_LENGTH); - ASSERT_EQ( - OEMCrypto_SUCCESS, - GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), - &gen_signature_length)); - ASSERT_EQ(expected_signature, signature); -} - -// Test Generic_Verify with the maximum buffer size. -TEST_P(OEMCryptoGenericCryptoTest, GenericKeyVerifyLargeBuffer) { - ResizeBuffer(GetResourceValue(kMaxGenericBuffer)); - EncryptAndLoadKeys(); - unsigned int key_index = 3; - vector signature; - SignBuffer(key_index, clear_buffer_, &signature); - - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - ASSERT_EQ( - OEMCrypto_SUCCESS, - GenericVerify(key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, - signature.data(), signature.size())); -} - -// Test Generic_Encrypt when the key duration has expired. -TEST_P(OEMCryptoGenericCryptoTest, KeyDurationEncrypt) { - license_messages_.core_response() - .timer_limits.total_playback_duration_seconds = kDuration; - license_messages_.CreateResponseWithGenericCryptoKeys(); - EncryptAndLoadKeys(); - vector expected_encrypted; - EncryptBuffer(0, clear_buffer_, &expected_encrypted); - unsigned int key_index = 0; - vector encrypted(clear_buffer_.size()); - - vector key_handle; - // Should be valid key at the start. - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericEncrypt(key_handle.data(), key_handle.size(), - clear_buffer_.data(), clear_buffer_.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, encrypted.data())); - ASSERT_EQ(expected_encrypted, encrypted); - - wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. - encrypted.assign(clear_buffer_.size(), 0); - OEMCryptoResult status = OEMCrypto_Generic_Encrypt( - key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), iv_, OEMCrypto_AES_CBC_128_NO_PADDING, - encrypted.data()); - ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); - ASSERT_NE(encrypted, expected_encrypted); - ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); -} - -// Test Generic_Decrypt when the key duration has expired. -TEST_P(OEMCryptoGenericCryptoTest, KeyDurationDecrypt) { - license_messages_.core_response() - .timer_limits.total_playback_duration_seconds = kDuration; - license_messages_.CreateResponseWithGenericCryptoKeys(); - EncryptAndLoadKeys(); - - // Should be valid key at the start. - unsigned int key_index = 1; - vector encrypted; - EncryptBuffer(key_index, clear_buffer_, &encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector resultant(encrypted.size()); - ASSERT_EQ(OEMCrypto_SUCCESS, - GenericDecrypt(key_handle.data(), key_handle.size(), - encrypted.data(), encrypted.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data())); - ASSERT_EQ(clear_buffer_, resultant); - - wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. - resultant.assign(encrypted.size(), 0); - OEMCryptoResult status = GenericDecrypt( - key_handle.data(), key_handle.size(), encrypted.data(), encrypted.size(), - iv_, OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data()); - ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); - ASSERT_NE(clear_buffer_, resultant); - ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); -} - -// Test Generic_Sign when the key duration has expired. -TEST_P(OEMCryptoGenericCryptoTest, KeyDurationSign) { - license_messages_.core_response() - .timer_limits.total_playback_duration_seconds = kDuration; - license_messages_.CreateResponseWithGenericCryptoKeys(); - EncryptAndLoadKeys(); - - unsigned int key_index = 2; - vector expected_signature; - vector signature(SHA256_DIGEST_LENGTH); - size_t signature_length = signature.size(); - SignBuffer(key_index, clear_buffer_, &expected_signature); - - vector key_handle; - // Should be valid key at the start. - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - ASSERT_EQ( - OEMCrypto_SUCCESS, - GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), - &signature_length)); - ASSERT_EQ(expected_signature, signature); - - wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. - signature.assign(SHA256_DIGEST_LENGTH, 0); - OEMCryptoResult status = - GenericSign(key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), - &signature_length); - ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); - ASSERT_NE(expected_signature, signature); - ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); -} - -// Test Generic_Verify when the key duration has expired. -TEST_P(OEMCryptoGenericCryptoTest, KeyDurationVerify) { - license_messages_.core_response() - .timer_limits.total_playback_duration_seconds = kDuration; - license_messages_.CreateResponseWithGenericCryptoKeys(); - EncryptAndLoadKeys(); - - unsigned int key_index = 3; - vector signature; - SignBuffer(key_index, clear_buffer_, &signature); - - vector key_handle; - // Should be valid key at the start. - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), - session_.license().keys[key_index].key_id, - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - ASSERT_EQ( - OEMCrypto_SUCCESS, - GenericVerify(key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, - signature.data(), signature.size())); - - wvutil::TestSleep::Sleep(kLongSleep + kShortSleep); // Should be expired key. - OEMCryptoResult status = OEMCrypto_Generic_Verify( - key_handle.data(), key_handle.size(), clear_buffer_.data(), - clear_buffer_.size(), OEMCrypto_HMAC_SHA256, signature.data(), - signature.size()); - ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, status); - ASSERT_NO_FATAL_FAILURE(session_.TestGetKeyHandleExpired(key_index)); -} - -const unsigned int kLongKeyId = 2; - -// Test that short key ids are allowed. -class OEMCryptoGenericCryptoKeyIdLengthTest - : public OEMCryptoGenericCryptoTest { - protected: - void SetUp() override { - OEMCryptoGenericCryptoTest::SetUp(); - license_messages_.set_num_keys(5); - license_messages_.set_control(wvoec::kControlAllowDecrypt); - license_messages_.core_response() - .timer_limits.total_playback_duration_seconds = kDuration; - ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); - SetUniformKeyIdLength(16); // Start with all key ids being 16 bytes. - // But, we are testing that the key ids do not have to have the same - // length. - // 12 bytes (common key id length). - license_messages_.SetKeyId(0, "123456789012"); - license_messages_.SetKeyId(1, "12345"); // short key id. - // 16 byte key id. (default) - license_messages_.SetKeyId(2, "1234567890123456"); - license_messages_.SetKeyId(3, "12345678901234"); // 14 byte. (uncommon) - license_messages_.SetKeyId(4, "1"); // very short key id. - ASSERT_EQ(2u, kLongKeyId); - ASSERT_NO_FATAL_FAILURE(license_messages_.FillCoreResponseSubstrings()); - } - - // Make all four keys have the same length. - void SetUniformKeyIdLength(size_t key_id_length) { - for (size_t i = 0; i < license_messages_.num_keys(); i++) { - string key_id; - key_id.resize(key_id_length, i + 'a'); - license_messages_.SetKeyId(i, key_id); - } - ASSERT_NO_FATAL_FAILURE(license_messages_.FillCoreResponseSubstrings()); - } - - void TestWithKey(unsigned int key_index) { - ASSERT_LT(key_index, license_messages_.num_keys()); - EncryptAndLoadKeys(); - vector encrypted; - // To make sure OEMCrypto is not expecting the key_id to be zero padded, - // we will create a buffer that is padded with 'Z'. Then, we use fill - // the buffer with the longer of the three keys. If OEMCrypto is paying - // attention to the key id length, it should pick out the correct key. - vector key_id_buffer( - session_.license().keys[kLongKeyId].key_id_length + 5, - 'Z'); // Fill a bigger buffer with letter 'Z'. - memcpy(key_id_buffer.data(), session_.license().keys[kLongKeyId].key_id, - session_.license().keys[kLongKeyId].key_id_length); - EncryptBuffer(key_index, clear_buffer_, &encrypted); - vector key_handle; - ASSERT_EQ( - OEMCrypto_SUCCESS, - GetKeyHandleIntoVector(session_.session_id(), key_id_buffer.data(), - session_.license().keys[key_index].key_id_length, - OEMCrypto_CipherMode_CENC, key_handle)); - vector resultant(encrypted.size()); - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_Generic_Decrypt(key_handle.data(), key_handle.size(), - encrypted.data(), encrypted.size(), iv_, - OEMCrypto_AES_CBC_128_NO_PADDING, - resultant.data())); - ASSERT_EQ(clear_buffer_, resultant); - } -}; - -TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, MediumKeyId) { TestWithKey(0); } - -TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, ShortKeyId) { TestWithKey(1); } - -TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, LongKeyId) { TestWithKey(2); } - -TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, FourteenByteKeyId) { - TestWithKey(3); -} - -TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, VeryShortKeyId) { - TestWithKey(4); -} - -TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, UniformShortKeyId) { - SetUniformKeyIdLength(5); - TestWithKey(2); -} - -TEST_P(OEMCryptoGenericCryptoKeyIdLengthTest, UniformLongKeyId) { - SetUniformKeyIdLength(kTestKeyIdMaxLength); - TestWithKey(2); -} - -INSTANTIATE_TEST_SUITE_P(TestAll, OEMCryptoGenericCryptoTest, - Range(kCoreMessagesAPI, kCurrentAPI + 1)); - -INSTANTIATE_TEST_SUITE_P(TestAll, OEMCryptoGenericCryptoKeyIdLengthTest, - Range(kCoreMessagesAPI, kCurrentAPI + 1)); -/// @} } // namespace wvoec