// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine // License Agreement. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // TODO(b/253779846) Change it to include a header instead #include "oemcrypto_test.cpp" using ::testing::Bool; using ::testing::Combine; using ::testing::Range; using ::testing::tuple; using ::testing::Values; using ::testing::WithParamInterface; using namespace std; namespace wvoec { /// @addtogroup security /// @{ /** Test that OEMCrypto_FreeSecureBuffer fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemoryAllocateSecureBufferForHugeBufferSize) { Session s; s.open(); auto oemcrypto_function = [&s](size_t buffer_size) { OEMCrypto_DestBufferDesc output_descriptor; int secure_fd; OEMCryptoResult sts = OEMCrypto_AllocateSecureBuffer( s.session_id(), buffer_size, &output_descriptor, &secure_fd); if (sts == OEMCrypto_SUCCESS) { OEMCrypto_FreeSecureBuffer(s.session_id(), &output_descriptor, secure_fd); } return sts; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); s.close(); } /** Test that OEMCrypto_WrapKeyboxOrOEMCert fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemoryWrapKeyboxOrOEMCertForHugeKeyboxLength) { auto oemcrypto_function = [](size_t keybox_length) { vector keybox_buffer(keybox_length); size_t wrapped_keybox_length = keybox_length + 50; vector wrapped_keybox_buffer(wrapped_keybox_length); vector transport_key_buffer(20); memcpy(keybox_buffer.data(), &kTestKeybox, sizeof(kTestKeybox)); return OEMCrypto_WrapKeyboxOrOEMCert( keybox_buffer.data(), keybox_length, wrapped_keybox_buffer.data(), &wrapped_keybox_length, transport_key_buffer.data(), transport_key_buffer.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, sizeof(kTestKeybox), kHugeInputBufferLength, kCheckStatus); } /** Test that OEMCrypto_WrapKeyboxOrOEMCert fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemoryWrapKeyboxOrOEMCertForHugeWrappedKeyboxLength) { auto oemcrypto_function = [](size_t buffer_length) { size_t wrapped_keybox_length = buffer_length; vector wrapped_keybox_buffer(wrapped_keybox_length); vector transport_key_buffer(20); return OEMCrypto_WrapKeyboxOrOEMCert( reinterpret_cast(&kTestKeybox), sizeof(kTestKeybox), wrapped_keybox_buffer.data(), &wrapped_keybox_length, transport_key_buffer.data(), transport_key_buffer.size()); }; // API expects keybox length and wrapped keybox length to be equal. We would // like to test for various values of wrapped keybox lengths, hence skipping // status check. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_WrapKeyboxOrOEMCert fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemoryWrapKeyboxOrOEMCertForHugeTransportKey) { auto oemcrypto_function = [](size_t transport_key_length) { size_t wrapped_keybox_length = sizeof(&kTestKeybox) + 50; vector wrapped_keybox_buffer(wrapped_keybox_length); vector transport_key_buffer(transport_key_length); return OEMCrypto_WrapKeyboxOrOEMCert( reinterpret_cast(&kTestKeybox), sizeof(kTestKeybox), wrapped_keybox_buffer.data(), &wrapped_keybox_length, transport_key_buffer.data(), transport_key_buffer.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_WrapKeyboxOrOEMCert fails gracefully on a huge buffer. */ TEST_F( OEMCryptoClientTest, OEMCryptoMemoryWrapKeyboxOrOEMCertForHugeKeyboxLengthStartingFromLength1) { auto oemcrypto_function = [](size_t keybox_length) { vector keybox_buffer(keybox_length); size_t wrapped_keybox_length = keybox_length + 50; vector wrapped_keybox_buffer(wrapped_keybox_length); vector transport_key_buffer(20); return OEMCrypto_WrapKeyboxOrOEMCert( keybox_buffer.data(), keybox_length, wrapped_keybox_buffer.data(), &wrapped_keybox_length, transport_key_buffer.data(), transport_key_buffer.size()); }; // Cannot check status as keybox will not be valid for this test. // We still want to test what happens if buffer lengths is less that keybox // length. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_SetSandbox fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemorySetSandboxForHugeSandboxIdLength) { auto oemcrypto_function = [](size_t buffer_length) { vector buffer(buffer_length); return OEMCrypto_SetSandbox(buffer.data(), buffer.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_CopyBuffer fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemoryCopyBufferForHugeBufferLengths) { Session s; ASSERT_NO_FATAL_FAILURE(s.open()); vector input_buffer; OEMCrypto_DestBufferDesc dest_buffer_descriptor; dest_buffer_descriptor.type = OEMCrypto_BufferType_Secure; auto oemcrypto_function = [&s, &dest_buffer_descriptor, &input_buffer](size_t buffer_length) { input_buffer.resize(buffer_length); int secure_fd; OEMCryptoResult sts = OEMCrypto_AllocateSecureBuffer( s.session_id(), buffer_length, &dest_buffer_descriptor, &secure_fd); if (sts != OEMCrypto_SUCCESS) { LOGI("Secure buffers are not supported."); return sts; } dest_buffer_descriptor.buffer.secure.secure_buffer_length = buffer_length; OEMCryptoResult status = OEMCrypto_CopyBuffer( s.session_id(), input_buffer.data(), buffer_length, &dest_buffer_descriptor, OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); OEMCrypto_FreeSecureBuffer(s.session_id(), &dest_buffer_descriptor, secure_fd); return status; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** @ingroup security * Test that OEMCrypto_CopyBuffer fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemoryCopyBufferDirectForHugeBufferLengths) { Session s; ASSERT_NO_FATAL_FAILURE(s.open()); vector input_buffer; OEMCrypto_DestBufferDesc dest_buffer_descriptor; dest_buffer_descriptor.type = OEMCrypto_BufferType_Direct; dest_buffer_descriptor.buffer.direct.is_video = false; auto oemcrypto_function = [&s, &dest_buffer_descriptor, &input_buffer](size_t buffer_length) { input_buffer.resize(buffer_length); OEMCryptoResult status = OEMCrypto_CopyBuffer( s.session_id(), input_buffer.data(), buffer_length, &dest_buffer_descriptor, OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); return status; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** @ingroup security * Test that OEMCrypto_CopyBuffer fails gracefully on a huge buffer. */ TEST_F(OEMCryptoClientTest, OEMCryptoMemoryCopyBufferForOutOfRangeOffset) { Session s; ASSERT_NO_FATAL_FAILURE(s.open()); vector input_buffer; OEMCrypto_DestBufferDesc dest_buffer_descriptor; dest_buffer_descriptor.type = OEMCrypto_BufferType_Secure; size_t buffer_length = KiB; input_buffer.resize(buffer_length); int secure_fd; if (OEMCrypto_AllocateSecureBuffer(s.session_id(), buffer_length, &dest_buffer_descriptor, &secure_fd) != OEMCrypto_SUCCESS) { LOGI("Secure buffers are not supported."); return; } dest_buffer_descriptor.buffer.secure.secure_buffer_length = buffer_length; auto oemcrypto_function = [&s, &dest_buffer_descriptor, &input_buffer, &buffer_length](size_t offset) { dest_buffer_descriptor.buffer.secure.offset = offset; return OEMCrypto_CopyBuffer( s.session_id(), input_buffer.data(), buffer_length, &dest_buffer_descriptor, OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); OEMCrypto_FreeSecureBuffer(s.session_id(), &dest_buffer_descriptor, secure_fd); } /******** Dangerous Tests - DO NOT RUN ***********/ /*The following tests try to test InstallKeybox API with random buffers of varying length in order to catch any overflow issues. These tests override the actual keybox on the device. Remove the if and endif statement to run these tests on a device ONLY IF YOU ARE ABLE TO RECOVER THE KEYBOX on the device.*/ #if 0 TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryInstallKeyboxForHugeKeyboxBuffer) { auto f = [](size_t keybox_length) { vector keybox(keybox_length); memcpy(keybox.data(), &kTestKeybox, sizeof(kTestKeybox)); return OEMCrypto_InstallKeyboxOrOEMCert(keybox.data(), keybox.size()); }; // Starting at sizeof(kTestKeybox) as we are copying valid keybox // at beginning of generated buffers. TestHugeLengthDoesNotCrashAPI(f, sizeof(kTestKeybox), kHugeInputBufferLength, kCheckStatus); } TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryInstallKeyboxForHugeKeyboxBufferStartingFromLength1) { auto f = [](size_t keybox_length) { vector keybox(keybox_length); return OEMCrypto_InstallKeyboxOrOEMCert(keybox.data(), keybox.size()); }; // We are testing for keybox lengths starting from 1 which would return error, // hence skipping status check. TestHugeLengthDoesNotCrashAPI(f, !kCheckStatus); } #endif /** @ingroup security * Test that OEMCrypto_LoadTestKeybox fails gracefully on a huge buffer. */ TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryLoadTestKeyBoxForHugeKeyboxBuffer) { auto f = [](size_t keybox_length) { vector keybox(keybox_length); memcpy(keybox.data(), &kTestKeybox, sizeof(kTestKeybox)); return OEMCrypto_LoadTestKeybox(keybox.data(), keybox.size()); }; // Starting at sizeof(kTestKeybox) as we are copying valid keybox // at beginning of generated buffers. TestHugeLengthDoesNotCrashAPI(f, sizeof(kTestKeybox), kHugeInputBufferLength, kCheckStatus); } /** @ingroup security * Test that OEMCrypto_LoadTestKeybox fails gracefully on a huge buffer. */ TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryLoadTestKeyBoxForHugeKeyboxBufferStartingFromLength1) { auto f = [](size_t keybox_length) { vector keybox(keybox_length); return OEMCrypto_LoadTestKeybox(keybox.data(), keybox.size()); }; // We are testing for keybox lengths starting from 1 which would return error, // hence skipping status check. TestHugeLengthDoesNotCrashAPI(f, !kCheckStatus); } /** Test that OEMCrypto_GetDeviceID fails gracefully on a huge buffer. */ TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryGetDeviceIdForHugeIdLength) { auto oemcrypto_function = [](size_t input_length) { size_t device_id_length = input_length; vector device_id(device_id_length); return OEMCrypto_GetDeviceID(device_id.data(), &device_id_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_GetKeyData fails gracefully on a huge buffer. */ TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryGetKeyIdForHugeIdLength) { auto oemcrypto_function = [](size_t input_length) { size_t key_data_length = input_length; vector key_data(key_data_length); return OEMCrypto_GetKeyData(key_data.data(), &key_data_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_GenerateDerivedKeys fails gracefully on a huge buffer. */ TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryGenerateDerivedKeysForHugeMacContextLength) { Session s; ASSERT_NO_FATAL_FAILURE(s.open()); vector mac_context; vector enc_context; s.FillDefaultContext(&mac_context, &enc_context); auto oemcrypto_function = [&s, &mac_context, &enc_context](size_t buffer_length) { mac_context.resize(buffer_length); return OEMCrypto_GenerateDerivedKeys(s.session_id(), mac_context.data(), mac_context.size(), enc_context.data(), enc_context.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_GenerateDerivedKeys fails gracefully on a huge buffer. */ TEST_F(OEMCryptoKeyboxTest, OEMCryptoMemoryGenerateDerivedKeysForHugeEncContextLength) { Session s; ASSERT_NO_FATAL_FAILURE(s.open()); vector mac_context; vector enc_context; s.FillDefaultContext(&mac_context, &enc_context); auto oemcrypto_function = [&s, &mac_context, &enc_context](size_t buffer_length) { enc_context.resize(buffer_length); return OEMCrypto_GenerateDerivedKeys(s.session_id(), mac_context.data(), mac_context.size(), enc_context.data(), enc_context.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_GetOEMPublicCertificate fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoProv30Test, OEMCryptoMemoryGetOEMPublicCertForHugeCertLength) { if (wrapped_rsa_key_.size() == 0) { // If we don't have a wrapped key yet, create one. // This wrapped key will be shared by all sessions in the test. ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey()); } Session s; ASSERT_NO_FATAL_FAILURE(s.open()); // Install the DRM Cert's RSA key. ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_rsa_key_)); ASSERT_NO_FATAL_FAILURE(s.SetTestRsaPublicKey()); auto oemcrypto_function = [](size_t input_length) { size_t public_cert_length = input_length; vector public_cert(public_cert_length); return OEMCrypto_GetOEMPublicCertificate(public_cert.data(), &public_cert_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_CreateUsageTableHeader fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoSessionTests, OEMCryptoMemoryCreateUsageTableHeaderForHugeHeaderBufferLength) { auto oemcrypto_function = [](size_t buffer_length) { size_t header_buffer_length = buffer_length; vector usage_table_header(header_buffer_length); return OEMCrypto_CreateUsageTableHeader(usage_table_header.data(), &header_buffer_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_PrepAndSignRenewalRequest fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryPrepareRenewalRequestForHugeBufferLength) { RenewalRoundTrip renewal_messages(&license_messages_); auto oemcrypto_function = [&renewal_messages](size_t buffer_length) { renewal_messages.set_message_size(buffer_length); return renewal_messages.SignAndCreateRequestWithCustomBufferLengths(); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_PrepAndSignRenewalRequest fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryPrepareRenewalRequestForHugeSignatureLength) { RenewalRoundTrip renewal_messages(&license_messages_); auto oemcrypto_function = [&renewal_messages](size_t buffer_length) { renewal_messages.set_request_signature_size(buffer_length); return renewal_messages.SignAndCreateRequestWithCustomBufferLengths(); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_PrepAndSignRenewalRequest fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryPrepareRenewalRequestForHugeCoreMessageLength) { RenewalRoundTrip renewal_messages(&license_messages_); auto oemcrypto_function = [&renewal_messages](size_t buffer_length) { renewal_messages.set_core_message_size(buffer_length); return renewal_messages.SignAndCreateRequestWithCustomBufferLengths(); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that loading entitled content keys fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeBufferLength) { auto oemcrypto_function = [&](size_t buffer_length) { size_t entitled_key_data_length = entitled_message_.entitled_key_data_size(); vector message(entitled_key_data_length); memcpy(message.data(), entitled_message_.entitled_key_data(), entitled_key_data_length); message.resize(buffer_length); return entitled_message_.LoadKeys(message); }; // We are not constructing a valid message for load entitled content keys. // Hence skipping status check. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_LoadLicense fails gracefully on a huge buffer. */ TEST_F(OEMCryptoSessionTests, OEMCryptoMemoryLoadLicenseForHugeSignatureLength) { auto oemcrypto_function = [&](size_t signature_size) { Session s; LicenseRoundTrip license_messages(&s); s.open(); InstallTestDrmKey(&s); license_messages.SignAndVerifyRequest(); license_messages.CreateDefaultResponse(); license_messages.EncryptAndSignResponse(); vector signature(signature_size); OEMCryptoResult result = OEMCrypto_LoadLicense( s.session_id(), license_messages.encrypted_response_buffer().data(), license_messages.encrypted_response_buffer().size(), license_messages.serialized_core_message().size(), signature.data(), signature_size); s.close(); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_LoadRenewal fails gracefully on a huge buffer. */ TEST_F(OEMCryptoSessionTests, OEMCryptoMemoryLoadRenewalForHugeResponseLength) { auto oemcrypto_function = [&](size_t message_size) { Session s; LicenseRoundTrip license_messages(&s); s.open(); LoadLicense(s, license_messages); RenewalRoundTrip renewal_messages(&license_messages); renewal_messages.SignAndVerifyRequest(); renewal_messages.CreateDefaultResponse(); renewal_messages.set_message_size(message_size); renewal_messages.EncryptAndSignResponse(); OEMCryptoResult result = renewal_messages.LoadResponse(); s.close(); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_LoadRenewal fails gracefully on a huge buffer. */ TEST_F(OEMCryptoSessionTests, OEMCryptoMemoryLoadRenewalForHugeSignatureLength) { auto oemcrypto_function = [&](size_t signature_size) { Session s; LicenseRoundTrip license_messages(&s); s.open(); LoadLicense(s, license_messages); RenewalRoundTrip renewal_messages(&license_messages); renewal_messages.SignAndVerifyRequest(); renewal_messages.CreateDefaultResponse(); renewal_messages.EncryptAndSignResponse(); vector signature(signature_size); OEMCryptoResult result = OEMCrypto_LoadRenewal( s.session_id(), renewal_messages.encrypted_response_buffer().data(), renewal_messages.encrypted_response_buffer().size(), renewal_messages.serialized_core_message().size(), signature.data(), signature_size); s.close(); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_QueryKeyControl fails gracefully on a huge buffer. */ TEST_F(OEMCryptoSessionTests, OEMCryptoMemoryLoadRenewalForHugeCoreMessageLength) { auto oemcrypto_function = [&](size_t core_message_size) { Session s; LicenseRoundTrip license_messages(&s); s.open(); LoadLicense(s, license_messages); RenewalRoundTrip renewal_messages(&license_messages); renewal_messages.SignAndVerifyRequest(); renewal_messages.CreateDefaultResponse(); renewal_messages.set_core_message_size(core_message_size); renewal_messages.EncryptAndSignResponse(); OEMCryptoResult result = renewal_messages.LoadResponse(); s.close(); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_QueryKeyControl fails gracefully on a huge buffer. */ TEST_F(OEMCryptoSessionTests, OEMCryptoMemoryQueryKeyControlForHugeKeyIdLength) { Session session; LicenseRoundTrip license_messages(&session); session.open(); LoadLicense(session, license_messages); OEMCrypto_SESSION session_id = session.session_id(); vector valid_key_id( license_messages.response_data().keys[0].key_id, license_messages.response_data().keys[0].key_id + kTestKeyIdMaxLength); auto oemcrypto_function = [&session_id, &valid_key_id](size_t additional_key_id_length) { vector key_id(valid_key_id); key_id.resize(valid_key_id.size() + additional_key_id_length); KeyControlBlock block; size_t size = sizeof(block); return OEMCrypto_QueryKeyControl(session_id, key_id.data(), key_id.size(), reinterpret_cast(&block), &size); }; // We do not want to stop as soon as API results in an error as it would // return error on first iteration as key_id is invalid. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test OEMCrypto_QueryKeyControl doesn't crash for huge key_control_block * length. */ TEST_F(OEMCryptoSessionTests, OEMCryptoMemoryQueryKeyControlForHugeKeyControlBlockLength) { Session session; LicenseRoundTrip license_messages(&session); session.open(); LoadLicense(session, license_messages); OEMCrypto_SESSION session_id = session.session_id(); uint8_t* key_id = license_messages.response_data().keys[0].key_id; size_t key_id_length = license_messages.response_data().keys[0].key_id_length; auto oemcrypto_function = [&session_id, &key_id, &key_id_length](size_t buffer_length) { size_t key_control_block_length = buffer_length; vector key_control_block(key_control_block_length); return OEMCrypto_QueryKeyControl(session_id, key_id, key_id_length, key_control_block.data(), &key_control_block_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** This test verifies that OEMCrypto_SetDecryptHash doesn't crash for a very large hash buffer. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryDecryptHashForHugeHashBuffer) { uint32_t session_id = session_.session_id(); auto f = [session_id]() { const uint32_t frame_number = 1; const uint32_t crc32 = 0; return OEMCrypto_SetDecryptHash(session_id, frame_number, crc32); }; TestHugeLengthDoesNotCrashAPI(f, kCheckStatus); } /** Test Decrypt fails gracefully for huge input. */ TEST_P(OEMCryptoSessionTestsDecryptTests, OEMCryptoMemoryDecryptCENCForHugeNumberOfSubSamples) { auto oemcrypto_function = [&](size_t number_of_subsamples) { std::vector subsample_sizes; while (number_of_subsamples-- > 0) { subsample_sizes.push_back({1, 1}); } SetSubsampleSizes(subsample_sizes); LoadLicense(); MakeBuffers(); EncryptData(); OEMCryptoResult result = DecryptCENC(); FreeSecureBuffers(); // Closing the session and opening it for next iteration. // If it is last iteration, session will be closed in teardown method of // class. session_.close(); session_.open(); InstallTestDrmKey(&session_); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, 1, 2 * MiB, kCheckStatus); // Avoid double free when test teardown calls FreeSecureBuffers() MakeBuffers(); } /** Test Decrypt fails gracefully for huge input. */ TEST_P(OEMCryptoSessionTestsDecryptTests, OEMCryptoMemoryDecryptCENCForHugeNumberOfSamples) { auto oemcrypto_function = [&](size_t number_of_samples) { std::vector> samples; std::vector subsample_sizes; subsample_sizes.push_back({1, 1}); while (number_of_samples-- > 0) { samples.push_back(subsample_sizes); } SetSampleSizes(samples); LoadLicense(); MakeBuffers(); EncryptData(); OEMCryptoResult result = DecryptCENC(); FreeSecureBuffers(); // Closing the session and opening it for next iteration. // If it is last iteration, session will be closed in teardown method of // class. session_.close(); session_.open(); InstallTestDrmKey(&session_); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, 1, 2 * MiB, kCheckStatus); // Avoid double free when test teardown calls FreeSecureBuffers() MakeBuffers(); } /** Test that OEMCrypto_LoadProvisioning fails gracefully on a huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeSignatureLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } auto oemcrypto_function = [&](size_t signature_size) { Session s; ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_); provisioning_messages.PrepareSession(keybox_); provisioning_messages.SignAndVerifyRequest(); provisioning_messages.CreateDefaultResponse(); provisioning_messages.EncryptAndSignResponse(); vector signature(signature_size); size_t wrapped_private_key_length = 0; // Find wrapped_private_key_length. OEMCrypto_LoadProvisioning( s.session_id(), provisioning_messages.encrypted_response_buffer().data(), provisioning_messages.encrypted_response_buffer().size(), provisioning_messages.serialized_core_message().size(), signature.data(), signature_size, nullptr, &wrapped_private_key_length); std::vector wrapped_rsa_key(wrapped_private_key_length); OEMCryptoResult result = OEMCrypto_LoadProvisioning( s.session_id(), provisioning_messages.encrypted_response_buffer().data(), provisioning_messages.encrypted_response_buffer().size(), provisioning_messages.serialized_core_message().size(), signature.data(), signature_size, wrapped_rsa_key.data(), &wrapped_private_key_length); s.close(); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_LoadProvisioning fails gracefully on a huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeWrappedRsaKeyLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } auto oemcrypto_function = [&](size_t buffer_length) { Session s; ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_); provisioning_messages.PrepareSession(keybox_); provisioning_messages.SignAndVerifyRequest(); provisioning_messages.CreateDefaultResponse(); provisioning_messages.EncryptAndSignResponse(); size_t wrapped_private_key_length = buffer_length; vector wrapped_private_key(wrapped_private_key_length); OEMCryptoResult result = OEMCrypto_LoadProvisioning( s.session_id(), provisioning_messages.encrypted_response_buffer().data(), provisioning_messages.encrypted_response_buffer().size(), provisioning_messages.serialized_core_message().size(), provisioning_messages.response_signature().data(), provisioning_messages.response_signature().size(), wrapped_private_key.data(), &wrapped_private_key_length); s.close(); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_LoadDRMPrivateKey fails gracefully on a huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadDrmPrivateKeyForHugeWrappedRsaKeyLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey()); auto oemcrypto_function = [&](size_t wrapped_rsa_key_length) { Session s; s.open(); vector wrapped_rsa_key_buffer = wrapped_rsa_key_; wrapped_rsa_key_buffer.resize(wrapped_rsa_key_length); OEMCryptoResult result = OEMCrypto_LoadDRMPrivateKey( s.session_id(), OEMCrypto_RSA_Private_Key, wrapped_rsa_key_buffer.data(), wrapped_rsa_key_buffer.size()); s.close(); return result; }; // It is hard to generate varying length valid wrapped rsa key with valid // signature. Hence we just call function with random data and do not check // status to test API with varying length wrapped rsa key. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, wrapped_rsa_key_.size(), kHugeInputBufferLength, !kCheckStatus); } /** Test that OEMCrypto_LoadDRMPrivateKey fails gracefully on a huge buffer. */ TEST_F( OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadDrmPrivateKeyForHugeWrappedRsaKeyLengthStartingFromLength1) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey()); auto oemcrypto_function = [&](size_t wrapped_rsa_key_length) { Session s; s.open(); vector wrapped_rsa_key_buffer(wrapped_rsa_key_length); OEMCryptoResult result = OEMCrypto_LoadDRMPrivateKey( s.session_id(), OEMCrypto_RSA_Private_Key, wrapped_rsa_key_buffer.data(), wrapped_rsa_key_buffer.size()); s.close(); return result; }; // It is hard to generate varying length valid wrapped rsa key with valid // signature. Hence we just call function with random data and do not check // status to test API with varying length wrapped rsa key. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_LoadDRMPrivateKey fails gracefully on a huge buffer. */ TEST_F(OEMCryptoUsesCertificate, OEMCryptoMemoryDeriveKeysFromSessionKeyForHugeMacContext) { vector session_key; vector enc_session_key; ASSERT_TRUE(session_.GenerateSessionKey(&session_key, &enc_session_key)); vector mac_context; vector enc_context; session_.FillDefaultContext(&mac_context, &enc_context); OEMCrypto_SESSION session_id = session_.session_id(); auto oemcrypto_function = [&session_id, &enc_context, &mac_context, &enc_session_key](size_t buffer_length) { mac_context.resize(buffer_length); return OEMCrypto_DeriveKeysFromSessionKey( session_id, enc_session_key.data(), enc_session_key.size(), mac_context.data(), mac_context.size(), enc_context.data(), enc_context.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_DeriveKeysFromSessionKey fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoUsesCertificate, OEMCryptoMemoryDeriveKeysFromSessionKeyForHugeEncContext) { vector session_key; vector enc_session_key; ASSERT_TRUE(session_.GenerateSessionKey(&session_key, &enc_session_key)); vector mac_context; vector enc_context; session_.FillDefaultContext(&mac_context, &enc_context); OEMCrypto_SESSION session_id = session_.session_id(); auto oemcrypto_function = [&session_id, &enc_context, &mac_context, &enc_session_key](size_t buffer_length) { enc_context.resize(buffer_length); return OEMCrypto_DeriveKeysFromSessionKey( session_id, enc_session_key.data(), enc_session_key.size(), mac_context.data(), mac_context.size(), enc_context.data(), enc_context.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that OEMCrypto_DeriveKeysFromSessionKey fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoUsesCertificate, OEMCryptoMemoryDeriveKeysFromSessionKeyForHugeEncSessionKey) { vector session_key; vector enc_session_key; ASSERT_TRUE(session_.GenerateSessionKey(&session_key, &enc_session_key)); vector mac_context; vector enc_context; session_.FillDefaultContext(&mac_context, &enc_context); OEMCrypto_SESSION session_id = session_.session_id(); auto oemcrypto_function = [&session_id, &session_key, &enc_context, &mac_context, &enc_session_key](size_t buffer_length) { session_key.resize(buffer_length); return OEMCrypto_DeriveKeysFromSessionKey( session_id, enc_session_key.data(), enc_session_key.size(), mac_context.data(), mac_context.size(), enc_context.data(), enc_context.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that OEMCrypto_GenerateRSASignature fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoLoadsCertificateAlternates, OEMCryptoMemoryGenerateRSASignatureForHugeBuffer) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } OEMCryptoResult sts; LoadCastCertificateKey(false); // If the device is a cast receiver, then this scheme is required. if (global_features.cast_receiver) { ASSERT_TRUE(key_loaded_); } if (key_loaded_) { // If the key did load, then it should be processed correctly. Session s; ASSERT_NO_FATAL_FAILURE(s.open()); ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_rsa_key_)); vector message_buffer(10); size_t signature_length = 0; sts = OEMCrypto_GenerateRSASignature(s.session_id(), message_buffer.data(), message_buffer.size(), nullptr, &signature_length, kSign_PKCS1_Block1); if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) return; ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); ASSERT_NE(static_cast(0), signature_length); vector signature(signature_length); auto oemcrypto_function = [&](size_t buffer_length) { message_buffer.resize(buffer_length); return OEMCrypto_GenerateRSASignature( s.session_id(), message_buffer.data(), message_buffer.size(), signature.data(), &signature_length, kSign_PKCS1_Block1); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); s.close(); } } /** Test that OEMCrypto_GenerateRSASignature fails gracefully on a huge * buffer. */ TEST_F(OEMCryptoLoadsCertificateAlternates, OEMCryptoMemoryGenerateRSASignatureForHugeSignatureLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } LoadCastCertificateKey(false); // If the device is a cast receiver, then this scheme is required. if (global_features.cast_receiver) { ASSERT_TRUE(key_loaded_); } if (key_loaded_) { // If the key did load, then it should be processed correctly. Session s; ASSERT_NO_FATAL_FAILURE(s.open()); ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_rsa_key_)); vector message_buffer(50); vector signature; auto oemcrypto_function = [&](size_t signature_length) { signature.resize(signature_length); return OEMCrypto_GenerateRSASignature( s.session_id(), message_buffer.data(), message_buffer.size(), signature.data(), &signature_length, kSign_PKCS1_Block1); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); s.close(); } } /** Test that GetKeyHandle fails gracefully on a huge buffer. */ TEST_P(OEMCryptoGenericCryptoTest, OEMCryptoMemorySelectKeyForHugeKeyIdLength) { EncryptAndLoadKeys(); OEMCrypto_SESSION session_id = session_.session_id(); auto oemcrypto_function = [session_id](size_t key_id_length) { vector key_id(key_id_length); vector key_handle; return GetKeyHandleIntoVector(session_id, key_id.data(), key_id.size(), OEMCrypto_CipherMode_CENC, key_handle); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoGenericCryptoTest, OEMCryptoMemoryGenericKeyEncryptForHugeBuffer) { 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)); OEMCrypto_SESSION session_id = session_.session_id(); auto& iv = iv_; auto oemcrypto_function = [&session_id, &iv](size_t buffer_length) mutable { vector buffer(buffer_length); return OEMCrypto_Generic_Encrypt( key_handle.data(), key_handle.size(), buffer.data(), buffer.size(), iv, OEMCrypto_AES_CBC_128_NO_PADDING, buffer.data()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, 16, kHugeInputBufferLength, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoGenericCryptoTest, OEMCryptoMemoryGenericKeyDecryptForHugeBuffer) { EncryptAndLoadKeys(); unsigned int key_index = 1; vector key_handle; GetKeyHandleIntoVector(session_.session_id(), session_.license().keys[key_index].key_id, session_.license().keys[key_index].key_id_length, OEMCrypto_CipherMode_CENC, key_handle); OEMCrypto_SESSION session_id = session_.session_id(); auto iv = iv_; auto oemcrypto_function = [&session_id, &iv](size_t buffer_length) { vector encrypted(buffer_length); vector resultant(encrypted.size()); return OEMCrypto_Generic_Decrypt(key_handle.data(), key_handle.size(), encrypted.data(), encrypted.size(), iv, OEMCrypto_AES_CBC_128_NO_PADDING, resultant.data()); }; // API expects length to be multiple of 16. Starting from 16. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, 16, kHugeInputBufferLength, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoGenericCryptoTest, OEMCryptoMemoryGenericKeySignForHugeBuffer) { EncryptAndLoadKeys(); unsigned int key_index = 2; 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 signature(SHA256_DIGEST_LENGTH); size_t signature_length = signature.size(); OEMCrypto_SESSION session_id = session_.session_id(); auto oemcrypto_function = [&session_id, &signature, &signature_length](size_t buffer_length) { vector buffer(buffer_length); return OEMCrypto_Generic_Sign( key_handle.data(), key_handle.size(), buffer.data(), buffer.size(), OEMCrypto_HMAC_SHA256, signature.data(), &signature_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoGenericCryptoTest, OEMCryptoMemoryGenericKeySignForHugeSignatureLength) { EncryptAndLoadKeys(); unsigned int key_index = 2; 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); OEMCrypto_SESSION session_id = session_.session_id(); auto clear_buffer = clear_buffer_; auto oemcrypto_function = [&session_id, &clear_buffer](size_t signature_length) { vector signature(signature_length); size_t gen_signature_length = signature_length; return OEMCrypto_Generic_Sign(key_handle.data(), key_handle.size(), clear_buffer.data(), clear_buffer.size(), OEMCrypto_HMAC_SHA256, signature.data(), &gen_signature_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoGenericCryptoTest, OEMCryptoMemoryGenericKeyVerifyForHugeBuffer) { EncryptAndLoadKeys(); unsigned int key_index = 3; 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)); auto oemcrypto_function = [&](size_t buffer_length) { vector buffer(buffer_length); vector signature; SignBuffer(key_index, buffer, &signature); return GenericVerify(key_handle.data(), key_handle.size(), buffer.data(), buffer.size(), OEMCrypto_HMAC_SHA256, signature.data(), signature.size()); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoGenericCryptoTest, OEMCryptoMemoryGenericKeyVerifyForHugeSignatureLength) { 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)); OEMCrypto_SESSION session_id = session_.session_id(); auto clear_buffer = clear_buffer_; auto oemcrypto_function = [&session_id, &clear_buffer, &signature](size_t signature_length) { return OEMCrypto_Generic_Verify(key_handle.data(), key_handle.size(), clear_buffer.data(), clear_buffer.size(), OEMCrypto_HMAC_SHA256, signature.data(), signature_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryUpdateUsageEntryForHugeHeaderBuffer) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { if (buffer_length < encrypted_usage_header_.size()) { return OEMCrypto_ERROR_SHORT_BUFFER; } LicenseWithUsageEntry entry; entry.license_messages().set_api_version(license_api_version_); entry.MakeAndLoadOnline(this); Session& s = entry.session(); size_t header_buffer_length = 0; size_t entry_buffer_length = 0; // Header buffer length varies as generation_numbers size changes on every // call. Hence, we need to call update usage entry in every loop to get // latest value of header_buffer_length. OEMCrypto_UpdateUsageEntry(s.session_id(), nullptr, &header_buffer_length, nullptr, &entry_buffer_length); vector encrypted_usage_entry(entry_buffer_length); vector header_buffer(encrypted_usage_header_); header_buffer.resize(buffer_length); return OEMCrypto_UpdateUsageEntry( s.session_id(), header_buffer.data(), &buffer_length, encrypted_usage_entry.data(), &entry_buffer_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryUpdateUsageEntryForHugeUsageEntryBuffer) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { LicenseWithUsageEntry entry; entry.license_messages().set_api_version(license_api_version_); entry.MakeAndLoadOnline(this); Session& s = entry.session(); size_t header_buffer_length = 0; size_t entry_buffer_length = 0; // Header buffer length varies as generation_numbers size changes on every // call. Hence, we need to call update usage entry in every loop to get // latest value of header_buffer_length. OEMCrypto_UpdateUsageEntry(s.session_id(), nullptr, &header_buffer_length, nullptr, &entry_buffer_length); vector header_buffer(encrypted_usage_header_); header_buffer.resize(header_buffer_length); vector encrypted_usage_entry(buffer_length); return OEMCrypto_UpdateUsageEntry( s.session_id(), header_buffer.data(), &header_buffer_length, encrypted_usage_entry.data(), &buffer_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryDeactivateUsageEntryForHugePstBuffer) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { LicenseWithUsageEntry entry; std::string pst("pst"); pst.resize(buffer_length); entry.license_messages().set_pst(pst); entry.license_messages().set_api_version(license_api_version_); entry.MakeAndLoadOnline(this); Session& s = entry.session(); return OEMCrypto_DeactivateUsageEntry( s.session_id(), reinterpret_cast(pst.c_str()), pst.length()); }; // The test setup assertions fails if pst length goes beyond kMaxPSTLength. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, 1, kMaxPSTLength, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryLoadUsageTableHeaderForHugeHeader) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { if (buffer_length < encrypted_usage_header_.size()) { return OEMCrypto_ERROR_SHORT_BUFFER; } LicenseWithUsageEntry entry; entry.license_messages().set_api_version(license_api_version_); entry.MakeOfflineAndClose(this); vector header_buffer(encrypted_usage_header_); header_buffer.resize(buffer_length); return OEMCrypto_LoadUsageTableHeader(header_buffer.data(), header_buffer.size()); }; // We cannot generate an encrypted usage header of varying length with // valid signature. Hence irrespective of return status, we call API for // varying buffer lengths. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, encrypted_usage_header_.size(), kHugeInputBufferLength, !kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P( OEMCryptoUsageTableTest, OEMCryptoMemoryLoadUsageTableHeaderForHugeHeaderStartingHeaderLengthFrom1) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { LicenseWithUsageEntry entry; entry.license_messages().set_api_version(license_api_version_); entry.MakeOfflineAndClose(this); vector header_buffer(buffer_length); return OEMCrypto_LoadUsageTableHeader(header_buffer.data(), header_buffer.size()); }; // We cannot generate an encrypted usage header of varying length with // valid signature. Hence irrespective of return status, we call API for // varying buffer lengths. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryLoadUsageEntryForHugeUsageEntryBuffer) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { LicenseWithUsageEntry entry; entry.license_messages().set_api_version(license_api_version_); Session& s = entry.session(); // Make first entry 0. entry.MakeOfflineAndClose(this); if (buffer_length < s.encrypted_usage_entry().size()) { return OEMCrypto_ERROR_SHORT_BUFFER; } Session s2; s2.open(); InstallTestDrmKey(&s2); vector encrypted_usage_entry(buffer_length); memcpy(encrypted_usage_entry.data(), s.encrypted_usage_entry().data(), s.encrypted_usage_entry().size()); const uint32_t usage_entry_number = s.usage_entry_number(); return OEMCrypto_LoadUsageEntry(s2.session_id(), usage_entry_number, encrypted_usage_entry.data(), encrypted_usage_entry.size()); }; // We cannot generate an encrypted usage enctry of varying length with // valid signature. Hence irrespective of return status, we call API for // varying buffer lengths. TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryReportUsageForHugeReportBuffer) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { LicenseWithUsageEntry entry; entry.license_messages().set_api_version(license_api_version_); entry.MakeAndLoadOnline(this); Session& s = entry.session(); s.UpdateUsageEntry(&encrypted_usage_header_); size_t length = 0; OEMCrypto_ReportUsage(s.session_id(), reinterpret_cast(entry.pst().c_str()), entry.pst().length(), nullptr, &length); if (ShouldGenerateCorpus()) { const std::string file_name = GetFileName("oemcrypto_report_usage_fuzz_seed_corpus"); AppendToFile(file_name, reinterpret_cast(&length), sizeof(length)); AppendToFile(file_name, entry.pst().c_str(), entry.pst().length()); } vector pst_report_buffer(buffer_length); return OEMCrypto_ReportUsage( s.session_id(), reinterpret_cast(entry.pst().c_str()), entry.pst().length(), pst_report_buffer.data(), &buffer_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryReportUsageForHugePstBuffer) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } auto oemcrypto_function = [&](size_t buffer_length) { LicenseWithUsageEntry entry; entry.license_messages().set_api_version(license_api_version_); entry.MakeAndLoadOnline(this); Session& s = entry.session(); s.UpdateUsageEntry(&encrypted_usage_header_); size_t length = 0; OEMCrypto_ReportUsage(s.session_id(), reinterpret_cast(entry.pst().c_str()), entry.pst().length(), nullptr, &length); vector pst_report_buffer(length); vector pst(buffer_length); return OEMCrypto_ReportUsage(s.session_id(), pst.data(), pst.size(), pst_report_buffer.data(), &length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, !kCheckStatus); } /** Test that API fails gracefully on a huge buffer. */ TEST_P(OEMCryptoUsageTableTest, OEMCryptoMemoryShrinkUsageTableHeaderForHugeHeaderBufferLength) { if (!wvoec::global_features.usage_table) { GTEST_SKIP() << "Usage tables are not supported."; } LicenseWithUsageEntry entry0; entry0.set_pst("pst 0"); entry0.MakeOfflineAndClose(this); auto oemcrypto_function = [&](size_t buffer_length) { LicenseWithUsageEntry entry1; entry1.set_pst("pst 1"); entry1.MakeOfflineAndClose(this); size_t header_buffer_length = buffer_length; encrypted_usage_header_.resize(header_buffer_length); return OEMCrypto_ShrinkUsageTableHeader(1, encrypted_usage_header_.data(), &header_buffer_length); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, kCheckStatus); } /// @} } // namespace wvoec