diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.cpp index f3bc963b..1b07045e 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.cpp @@ -7,12 +7,10 @@ #include "log.h" #include "platform.h" +#include "test_sleep.h" namespace wvoec { -/// @addtogroup provision -/// @{ - // This test is used to print the device ID to stdout. TEST_F(OEMCryptoKeyboxTest, NormalGetDeviceId) { OEMCryptoResult sts; @@ -1103,5 +1101,134 @@ TEST_F(OEMCryptoLoadsCertificate, SupportsCertificatesAPI13) { << "Supported certificates is only " << OEMCrypto_SupportedCertificates(); } -/// @} +// This test is not run by default, because it takes a long time and +// is used to measure RSA performance, not test functionality. +TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) { + const std::chrono::milliseconds kTestDuration(5000); + OEMCryptoResult sts; + std::chrono::steady_clock clock; + wvutil::TestSleep::Sleep(kShortSleep); // Make sure we are not nonce limited. + + auto start_time = clock.now(); + int count = 15; + for (int i = 0; i < count; i++) { // Only 20 nonce available. + ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey()); + } + auto delta_time = clock.now() - start_time; + const double provision_time = + delta_time / std::chrono::milliseconds(1) / count; + + Session session; + ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey()); + start_time = clock.now(); + count = 0; + while (clock.now() - start_time < kTestDuration) { + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_)); + const size_t size = 50; + vector licenseRequest(size); + GetRandBytes(licenseRequest.data(), licenseRequest.size()); + size_t signature_length = 0; + sts = OEMCrypto_GenerateRSASignature(s.session_id(), licenseRequest.data(), + licenseRequest.size(), nullptr, + &signature_length, kSign_RSASSA_PSS); + ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); + ASSERT_NE(static_cast(0), signature_length); + + if (ShouldGenerateCorpus()) { + const std::string file_name = + GetFileName("oemcrypto_generate_rsa_signature_fuzz_seed_corpus"); + OEMCrypto_Generate_RSA_Signature_Fuzz fuzzed_structure; + fuzzed_structure.padding_scheme = kSign_RSASSA_PSS; + fuzzed_structure.signature_length = signature_length; + // Cipher mode and algorithm. + AppendToFile(file_name, reinterpret_cast(&fuzzed_structure), + sizeof(fuzzed_structure)); + AppendToFile(file_name, + reinterpret_cast(licenseRequest.data()), + licenseRequest.size()); + } + + std::vector signature(signature_length, 0); + sts = OEMCrypto_GenerateRSASignature( + s.session_id(), licenseRequest.data(), licenseRequest.size(), + signature.data(), &signature_length, kSign_RSASSA_PSS); + ASSERT_EQ(OEMCrypto_SUCCESS, sts); + count++; + } + delta_time = clock.now() - start_time; + const double license_request_time = + delta_time / std::chrono::milliseconds(1) / count; + + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_)); + vector session_key; + vector enc_session_key; + ASSERT_NO_FATAL_FAILURE(s.SetRsaPublicKeyFromPrivateKeyInfo( + encoded_rsa_key_.data(), encoded_rsa_key_.size())); + ASSERT_TRUE(s.GenerateRsaSessionKey(&session_key, &enc_session_key)); + vector mac_context; + vector enc_context; + s.FillDefaultContext(&mac_context, &enc_context); + + enc_session_key = wvutil::a2b_hex( + "7789c619aa3b9fa3c0a53f57a4abc6" + "02157c8aa57e3c6fb450b0bea22667fb" + "0c3200f9d9d618e397837c720dc2dadf" + "486f33590744b2a4e54ca134ae7dbf74" + "434c2fcf6b525f3e132262f05ea3b3c1" + "198595c0e52b573335b2e8a3debd0d0d" + "d0306f8fcdde4e76476be71342957251" + "e1688c9ca6c1c34ed056d3b989394160" + "cf6937e5ce4d39cc73d11a2e93da21a2" + "fa019d246c852fe960095b32f120c3c2" + "7085f7b64aac344a68d607c0768676ce" + "d4c5b2d057f7601921b453a451e1dea0" + "843ebfef628d9af2784d68e86b730476" + "e136dfe19989de4be30a4e7878efcde5" + "ad2b1254f80c0c5dd3cf111b56572217" + "b9f58fc1dacbf74b59d354a1e62cfa0e" + "bf"); + start_time = clock.now(); + while (clock.now() - start_time < kTestDuration) { + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_DeriveKeysFromSessionKey( + s.session_id(), enc_session_key.data(), + enc_session_key.size(), mac_context.data(), + mac_context.size(), enc_context.data(), enc_context.size())); + count++; + } + delta_time = clock.now() - start_time; + const double derive_keys_time = + delta_time / std::chrono::milliseconds(1) / count; + + OEMCrypto_Security_Level level = OEMCrypto_SecurityLevel(); + printf("PERF:head, security, provision (ms), lic req(ms), derive keys(ms)\n"); + printf("PERF:stat, %u, %8.3f, %8.3f, %8.3f\n", + static_cast(level), provision_time, license_request_time, + derive_keys_time); +} + +// Test DeriveKeysFromSessionKey using the maximum size for the HMAC context. +TEST_F(OEMCryptoUsesCertificate, GenerateDerivedKeysLargeBuffer) { + vector session_key; + vector enc_session_key; + ASSERT_TRUE(session_.GenerateSessionKey(&session_key, &enc_session_key)); + const size_t max_size = GetResourceValue(kLargeMessageSize); + vector mac_context(max_size); + vector enc_context(max_size); + // Stripe the data so the two vectors are not identical, and not all zeroes. + for (size_t i = 0; i < max_size; i++) { + mac_context[i] = i % 0x100; + enc_context[i] = (3 * i) % 0x100; + } + ASSERT_EQ(OEMCrypto_SUCCESS, + OEMCrypto_DeriveKeysFromSessionKey( + session_.session_id(), enc_session_key.data(), + enc_session_key.size(), mac_context.data(), mac_context.size(), + enc_context.data(), enc_context.size())); +} + } // namespace wvoec \ No newline at end of file diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.h b/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.h index 3053c2bc..18634036 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.h +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_provisioning_test.h @@ -142,6 +142,31 @@ class OEMCryptoLoadsCertificate : public OEMCryptoSessionTestKeyboxTest { } }; +// These tests are run by all L1 devices that load and use certificates. It is +// also run by a few L3 devices that use a baked in certificate, but cannot load +// a certificate. +class OEMCryptoUsesCertificate : public OEMCryptoLoadsCertificate { + protected: + void SetUp() override { + OEMCryptoLoadsCertificate::SetUp(); + ASSERT_NO_FATAL_FAILURE(session_.open()); + if (global_features.derive_key_method == + DeviceFeatures::LOAD_TEST_RSA_KEY) { + ASSERT_NO_FATAL_FAILURE(session_.SetRsaPublicKeyFromPrivateKeyInfo( + encoded_rsa_key_.data(), encoded_rsa_key_.size())); + } else { + InstallTestDrmKey(&session_); + } + } + + void TearDown() override { + ASSERT_NO_FATAL_FAILURE(session_.close()); + OEMCryptoLoadsCertificate::TearDown(); + } + + Session session_; +}; + } // namespace wvoec #endif // CDM_OEMCRYPTO_PROVISIONING_TEST_ \ No newline at end of file diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index d3b70aea..af1ae58e 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -1669,166 +1669,6 @@ TEST_F(OEMCryptoLoadsCertificate, /// @} -/// @addtogroup provision -/// @{ - -// These tests are run by all L1 devices that load and use certificates. It is -// also run by a few L3 devices that use a baked in certificate, but cannot load -// a certificate. -class OEMCryptoUsesCertificate : public OEMCryptoLoadsCertificate { - protected: - void SetUp() override { - OEMCryptoLoadsCertificate::SetUp(); - ASSERT_NO_FATAL_FAILURE(session_.open()); - if (global_features.derive_key_method == - DeviceFeatures::LOAD_TEST_RSA_KEY) { - ASSERT_NO_FATAL_FAILURE(session_.SetRsaPublicKeyFromPrivateKeyInfo( - encoded_rsa_key_.data(), encoded_rsa_key_.size())); - } else { - InstallTestDrmKey(&session_); - } - } - - void TearDown() override { - ASSERT_NO_FATAL_FAILURE(session_.close()); - OEMCryptoLoadsCertificate::TearDown(); - } - - Session session_; -}; - -// This test is not run by default, because it takes a long time and -// is used to measure RSA performance, not test functionality. -TEST_F(OEMCryptoLoadsCertificate, RSAPerformance) { - const std::chrono::milliseconds kTestDuration(5000); - OEMCryptoResult sts; - std::chrono::steady_clock clock; - wvutil::TestSleep::Sleep(kShortSleep); // Make sure we are not nonce limited. - - auto start_time = clock.now(); - int count = 15; - for (int i = 0; i < count; i++) { // Only 20 nonce available. - ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey()); - } - auto delta_time = clock.now() - start_time; - const double provision_time = - delta_time / std::chrono::milliseconds(1) / count; - - Session session; - ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey()); - start_time = clock.now(); - count = 0; - while (clock.now() - start_time < kTestDuration) { - Session s; - ASSERT_NO_FATAL_FAILURE(s.open()); - ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_)); - const size_t size = 50; - vector licenseRequest(size); - GetRandBytes(licenseRequest.data(), licenseRequest.size()); - size_t signature_length = 0; - sts = OEMCrypto_GenerateRSASignature(s.session_id(), licenseRequest.data(), - licenseRequest.size(), nullptr, - &signature_length, kSign_RSASSA_PSS); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); - ASSERT_NE(static_cast(0), signature_length); - - if (ShouldGenerateCorpus()) { - const std::string file_name = - GetFileName("oemcrypto_generate_rsa_signature_fuzz_seed_corpus"); - OEMCrypto_Generate_RSA_Signature_Fuzz fuzzed_structure; - fuzzed_structure.padding_scheme = kSign_RSASSA_PSS; - fuzzed_structure.signature_length = signature_length; - // Cipher mode and algorithm. - AppendToFile(file_name, reinterpret_cast(&fuzzed_structure), - sizeof(fuzzed_structure)); - AppendToFile(file_name, - reinterpret_cast(licenseRequest.data()), - licenseRequest.size()); - } - - std::vector signature(signature_length, 0); - sts = OEMCrypto_GenerateRSASignature( - s.session_id(), licenseRequest.data(), licenseRequest.size(), - signature.data(), &signature_length, kSign_RSASSA_PSS); - ASSERT_EQ(OEMCrypto_SUCCESS, sts); - count++; - } - delta_time = clock.now() - start_time; - const double license_request_time = - delta_time / std::chrono::milliseconds(1) / count; - - Session s; - ASSERT_NO_FATAL_FAILURE(s.open()); - ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_)); - vector session_key; - vector enc_session_key; - ASSERT_NO_FATAL_FAILURE(s.SetRsaPublicKeyFromPrivateKeyInfo( - encoded_rsa_key_.data(), encoded_rsa_key_.size())); - ASSERT_TRUE(s.GenerateRsaSessionKey(&session_key, &enc_session_key)); - vector mac_context; - vector enc_context; - s.FillDefaultContext(&mac_context, &enc_context); - - enc_session_key = wvutil::a2b_hex( - "7789c619aa3b9fa3c0a53f57a4abc6" - "02157c8aa57e3c6fb450b0bea22667fb" - "0c3200f9d9d618e397837c720dc2dadf" - "486f33590744b2a4e54ca134ae7dbf74" - "434c2fcf6b525f3e132262f05ea3b3c1" - "198595c0e52b573335b2e8a3debd0d0d" - "d0306f8fcdde4e76476be71342957251" - "e1688c9ca6c1c34ed056d3b989394160" - "cf6937e5ce4d39cc73d11a2e93da21a2" - "fa019d246c852fe960095b32f120c3c2" - "7085f7b64aac344a68d607c0768676ce" - "d4c5b2d057f7601921b453a451e1dea0" - "843ebfef628d9af2784d68e86b730476" - "e136dfe19989de4be30a4e7878efcde5" - "ad2b1254f80c0c5dd3cf111b56572217" - "b9f58fc1dacbf74b59d354a1e62cfa0e" - "bf"); - start_time = clock.now(); - while (clock.now() - start_time < kTestDuration) { - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_DeriveKeysFromSessionKey( - s.session_id(), enc_session_key.data(), - enc_session_key.size(), mac_context.data(), - mac_context.size(), enc_context.data(), enc_context.size())); - count++; - } - delta_time = clock.now() - start_time; - const double derive_keys_time = - delta_time / std::chrono::milliseconds(1) / count; - - OEMCrypto_Security_Level level = OEMCrypto_SecurityLevel(); - printf("PERF:head, security, provision (ms), lic req(ms), derive keys(ms)\n"); - printf("PERF:stat, %u, %8.3f, %8.3f, %8.3f\n", - static_cast(level), provision_time, license_request_time, - derive_keys_time); -} - -// Test DeriveKeysFromSessionKey using the maximum size for the HMAC context. -TEST_F(OEMCryptoUsesCertificate, GenerateDerivedKeysLargeBuffer) { - vector session_key; - vector enc_session_key; - ASSERT_TRUE(session_.GenerateSessionKey(&session_key, &enc_session_key)); - const size_t max_size = GetResourceValue(kLargeMessageSize); - vector mac_context(max_size); - vector enc_context(max_size); - // Stripe the data so the two vectors are not identical, and not all zeroes. - for (size_t i = 0; i < max_size; i++) { - mac_context[i] = i % 0x100; - enc_context[i] = (3 * i) % 0x100; - } - ASSERT_EQ(OEMCrypto_SUCCESS, - OEMCrypto_DeriveKeysFromSessionKey( - session_.session_id(), enc_session_key.data(), - enc_session_key.size(), mac_context.data(), mac_context.size(), - enc_context.data(), enc_context.size())); -} - -/// @} - /// @addtogroup cast /// @{ diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_usage_table_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_usage_table_test.cpp index 8b78b14a..d2ac143f 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_usage_table_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_usage_table_test.cpp @@ -10,9 +10,6 @@ using ::testing::Values; namespace wvoec { -/// @addtogroup usage_table -/// @{ - // Test that successive calls to PrepAndSignProvisioningRequest only increase // the provisioning count in the ODK message TEST_F(OEMCryptoSessionTests, Provisioning_IncrementCounterAPI18) { @@ -1703,5 +1700,4 @@ INSTANTIATE_TEST_SUITE_P(TestAPI16, OEMCryptoUsageTableDefragTest, INSTANTIATE_TEST_SUITE_P(TestAPI16, OEMCryptoUsageTableTestWallClock, Values(kCurrentAPI)); -/// @} } // namespace wvoec \ No newline at end of file