From ed17d09c1b7ad9b5ecfac008d4523a65c8b18fec Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Tue, 11 May 2021 12:49:22 -0700 Subject: [PATCH 1/3] Remove asserts from GenerateSimpleSampleDescription() (This change is merged from http://go/wvgerrit/124824) GenerateSimpleSampleDescription() only had asserts to check parameters that only came from other test code, so they weren't testing anything of use. With the asserts removed, it's no longer necessary to wrap calls to GenerateSimpleSampleDescription() with ASSERT_NO_FATAL_FAILURE(), which a lot of callers were already forgetting to do anyway. This also simplifies a future patch that will generalize the decryption test code to work with entitlement licenses. Bug: 186782279 Test: x86-64 platform Test: build_and_run_all_unit_tests Change-Id: I987427fdfee4826d77ab95344f9aca8c374b2001 --- .../oemcrypto/test/oec_session_util.cpp | 8 ++------ .../oemcrypto/test/oemcrypto_test.cpp | 20 +++++++++---------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index 243c7984..88c67879 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -70,9 +70,6 @@ void GenerateSimpleSampleDescription( const std::vector& in, std::vector& out, OEMCrypto_SampleDescription* sample, OEMCrypto_SubSampleDescription* subsample) { - ASSERT_NE(sample, nullptr); - ASSERT_NE(subsample, nullptr); - // Generate test data EXPECT_EQ(GetRandBytes(&sample->iv[0], KEY_IV_SIZE), 1); @@ -1338,9 +1335,8 @@ void Session::TestDecryptCTR(bool select_key_first, OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - encrypted_data, output_buffer, &sample_description, - &subsample_description)); + GenerateSimpleSampleDescription(encrypted_data, output_buffer, + &sample_description, &subsample_description); // Generate test data EXPECT_EQ(GetRandBytes(unencrypted_data.data(), unencrypted_data.size()), 1); diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 07d2a1e7..8612bdae 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -2516,8 +2516,8 @@ TEST_P(OEMCryptoLicenseTest, SelectKeyNotThereAPI16) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); // Generate test data for (size_t i = 0; i < in_buffer.size(); i++) in_buffer[i] = i % 256; @@ -2551,8 +2551,8 @@ TEST_P(OEMCryptoLicenseTest, RejectCensAPI16) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); // Create a non-zero pattern to indicate this is 'cens' OEMCrypto_CENCEncryptPatternDesc pattern = {1, 9}; @@ -2582,8 +2582,8 @@ TEST_P(OEMCryptoLicenseTest, RejectCbc1API16) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); // Create a zero pattern to indicate this is 'cbc1' OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; @@ -2612,8 +2612,8 @@ TEST_P(OEMCryptoLicenseTest, RejectCbcsWithBlockOffset) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); subsample_description.block_offset = 5; // Any value 1-15 will do. // Create a non-zero pattern to indicate this is 'cbcs'. @@ -2643,8 +2643,8 @@ TEST_P(OEMCryptoLicenseTest, RejectOversizedBlockOffset) { OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; - ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( - in_buffer, out_buffer, &sample_description, &subsample_description)); + GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description, + &subsample_description); subsample_description.block_offset = 0xFF; // Anything 16+ // Create a zero pattern to indicate this is 'cenc'. From d742daf9c79f92754b576fa3683fb216ecb0e8a4 Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Tue, 11 May 2021 12:52:24 -0700 Subject: [PATCH 2/3] Validate decryption with entitled keys in OEC tests (This change is merged from http://go/wvgerrit/124825) The OEMCrypto tests have tests that verify that entitled keys can be loaded but not that they can be successfully used for decrypt. This patch adds a decrypt portion to the existing tests. As part of this, the existing Session::EncryptCTR() method and portions of Session::TestDecryptCTR() are lifted to be static functions so they can be shared across unrelated classes in oec_session_util.cpp. EncryptCTR() had no dependence on its enclosing class and is unchanged other than being moved outside the class. To reduce ambiguity with the new decrypt verification, this patch also renames EntitledMessage::VerifyEntitlementTestKeys() to the more-specific EntitledMessage::VerifyKCBs(). Its behavior is unchanged. Bug: 186782279 Test: x86-64 platform Test: opk_ta platform Test: build_and_run_all_unit_tests Change-Id: I15156882907b0987215087aaf43b4666fedc171a --- .../oemcrypto/test/oec_session_util.cpp | 143 +++++++++++------- .../oemcrypto/test/oec_session_util.h | 10 +- 2 files changed, 96 insertions(+), 57 deletions(-) diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index 88c67879..6a3b85cd 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -51,12 +51,67 @@ void PrintTo(const vector& value, ostream* os) { } } // namespace std -namespace { -constexpr size_t kTestSubsampleSectionSize = 256; -} // namespace - namespace wvoec { +namespace { + +constexpr size_t kTestSubsampleSectionSize = 256; + +// Encrypt a block of data using CTR mode. +void EncryptCTR(const vector& in_buffer, const uint8_t* key, + const uint8_t* starting_iv, vector* out_buffer) { + ASSERT_NE(nullptr, key); + ASSERT_NE(nullptr, starting_iv); + ASSERT_NE(nullptr, out_buffer); + AES_KEY aes_key; + AES_set_encrypt_key(key, AES_BLOCK_SIZE * 8, &aes_key); + out_buffer->resize(in_buffer.size()); + + uint8_t iv[AES_BLOCK_SIZE]; // Current iv. + + memcpy(iv, &starting_iv[0], AES_BLOCK_SIZE); + size_t l = 0; // byte index into encrypted subsample. + while (l < in_buffer.size()) { + uint8_t aes_output[AES_BLOCK_SIZE]; + AES_encrypt(iv, aes_output, &aes_key); + for (size_t n = 0; n < AES_BLOCK_SIZE && l < in_buffer.size(); n++, l++) { + (*out_buffer)[l] = aes_output[n] ^ in_buffer[l]; + } + ctr128_inc64(1, iv); + } +} + +// Uses OEMCrypto to decrypt some random data in 'cenc' mode. This function +// assumes that the correct key is already selected in the session. It requires +// the plaintext of that key so that it can encrypt the test data. It resizes +// the provided vectors and fills them with the expected and actual decrypt +// results. Returns the result of OEMCrypto_DecryptCENC(). +OEMCryptoResult DecryptCTR(OEMCrypto_SESSION session_id, const uint8_t* key, + vector* expected_data, + vector* actual_data) { + vector encrypted_data(kTestSubsampleSectionSize); + expected_data->resize(encrypted_data.size()); + actual_data->resize(encrypted_data.size()); + + // Create test sample description + OEMCrypto_SampleDescription sample_description; + OEMCrypto_SubSampleDescription subsample_description; + GenerateSimpleSampleDescription(encrypted_data, *actual_data, + &sample_description, &subsample_description); + + // Generate test data + EXPECT_EQ(GetRandBytes(expected_data->data(), expected_data->size()), 1); + EncryptCTR(*expected_data, key, &sample_description.iv[0], &encrypted_data); + + // Create the pattern description (always 0,0 for 'cenc') + OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; + + // Decrypt the data + return OEMCrypto_DecryptCENC(session_id, &sample_description, 1, &pattern); +} + +} // namespace + int GetRandBytes(unsigned char* buf, int num) { // returns 1 on success, -1 if not supported, or 0 if other failure. return RAND_bytes(buf, num); @@ -947,7 +1002,8 @@ void EntitledMessage::LoadKeys(OEMCryptoResult expected_sts) { if (expected_sts != OEMCrypto_SUCCESS) { return; } - VerifyEntitlementTestKeys(); + VerifyKCBs(); + VerifyDecrypt(); } OEMCryptoResult EntitledMessage::LoadKeys(const vector& message) { @@ -994,11 +1050,11 @@ void EntitledMessage::EncryptContentKey() { } } -// This function verifies that the key control block reported by OEMCrypto agree -// with the truth key control block. Failures in this function probably +// This function verifies that the key control blocks reported by OEMCrypto +// agree with the truth key control block. Failures in this function probably // indicate the OEMCrypto_LoadEntitledKeys did not correctly process the key // control block. -void EntitledMessage::VerifyEntitlementTestKeys() { +void EntitledMessage::VerifyKCBs() { for (unsigned int i = 0; i < num_keys_; i++) { EntitledContentKeyData* key_data = &entitled_key_data_[i]; const size_t entitlement_key_index = key_data->key_index; @@ -1025,6 +1081,28 @@ void EntitledMessage::VerifyEntitlementTestKeys() { } } +void EntitledMessage::VerifyDecrypt() { + const OEMCrypto_SESSION session_id = + license_messages_->session()->session_id(); + + // Loop through all the keys and try decrypt with each one. + for (unsigned int i = 0; i < num_keys_; i++) { + const EntitledContentKeyData* const key_data = &entitled_key_data_[i]; + + OEMCryptoResult result = OEMCrypto_SelectKey( + session_id, key_data->content_key_id, key_data->content_key_id_length, + OEMCrypto_CipherMode_CTR); + ASSERT_EQ(result, OEMCrypto_SUCCESS) << "For key " << i; + + vector expected_data; + vector actual_data; + result = DecryptCTR(session_id, key_data->content_key_data, &expected_data, + &actual_data); + EXPECT_EQ(result, OEMCrypto_SUCCESS) << "For key " << i; + EXPECT_EQ(actual_data, expected_data) << "For key " << i; + } +} + void RenewalRoundTrip::VerifyRequestSignature( const vector& data, const vector& generated_signature, size_t core_message_length) { @@ -1294,30 +1372,6 @@ void Session::GenerateDerivedKeysFromSessionKey() { key_deriver_.DeriveKeys(session_key.data(), mac_context, enc_context); } -void Session::EncryptCTR(const vector& in_buffer, const uint8_t* key, - const uint8_t* starting_iv, - vector* out_buffer) { - ASSERT_NE(nullptr, key); - ASSERT_NE(nullptr, starting_iv); - ASSERT_NE(nullptr, out_buffer); - AES_KEY aes_key; - AES_set_encrypt_key(key, AES_BLOCK_SIZE * 8, &aes_key); - out_buffer->resize(in_buffer.size()); - - uint8_t iv[AES_BLOCK_SIZE]; // Current iv. - - memcpy(iv, &starting_iv[0], AES_BLOCK_SIZE); - size_t l = 0; // byte index into encrypted subsample. - while (l < in_buffer.size()) { - uint8_t aes_output[AES_BLOCK_SIZE]; - AES_encrypt(iv, aes_output, &aes_key); - for (size_t n = 0; n < AES_BLOCK_SIZE && l < in_buffer.size(); n++, l++) { - (*out_buffer)[l] = aes_output[n] ^ in_buffer[l]; - } - ctr128_inc64(1, iv); - } -} - void Session::TestDecryptCTR(bool select_key_first, OEMCryptoResult expected_result, int key_index) { OEMCryptoResult select_result = OEMCrypto_SUCCESS; @@ -1328,27 +1382,12 @@ void Session::TestDecryptCTR(bool select_key_first, license_.keys[key_index].key_id_length, OEMCrypto_CipherMode_CTR); } - // Create test sample description - vector unencrypted_data(kTestSubsampleSectionSize); - vector encrypted_data(unencrypted_data.size()); - vector output_buffer(unencrypted_data.size()); - OEMCrypto_SampleDescription sample_description; - OEMCrypto_SubSampleDescription subsample_description; - - GenerateSimpleSampleDescription(encrypted_data, output_buffer, - &sample_description, &subsample_description); - - // Generate test data - EXPECT_EQ(GetRandBytes(unencrypted_data.data(), unencrypted_data.size()), 1); - EncryptCTR(unencrypted_data, license_.keys[key_index].key_data, - &sample_description.iv[0], &encrypted_data); - - // Create the pattern description (always 0,0 for CTR) - OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; - - // Decrypt the data + vector unencrypted_data; + vector output_buffer; const OEMCryptoResult decrypt_result = - OEMCrypto_DecryptCENC(session_id(), &sample_description, 1, &pattern); + DecryptCTR(session_id(), license_.keys[key_index].key_data, + &unencrypted_data, &output_buffer); + // We only have a few errors that we test are reported. ASSERT_NO_FATAL_FAILURE( TestDecryptResult(expected_result, select_result, decrypt_result)) diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 272e85e1..d2bde5e8 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -476,8 +476,6 @@ class EntitledMessage { void set_num_keys(uint32_t num_keys) { num_keys_ = num_keys; } uint32_t num_keys() const { return num_keys_; } void SetEntitlementKeyId(unsigned int index, const std::string& key_id); - // Verify that key control blocks of the loaded keys. - void VerifyEntitlementTestKeys(); OEMCrypto_EntitledContentKeyObject* entitled_key_array(); // Returns entitled_key_data_ which is used as input message buffer to // load entitled content keys API. @@ -487,6 +485,11 @@ class EntitledMessage { private: // Find the offset of the give pointer, relative to |entitled_key_data_|. OEMCrypto_Substring FindSubstring(const void* ptr, size_t size); + // Verify that key control blocks of the loaded keys matches their entitlement + // key. + void VerifyKCBs(); + // Verify that decryption with the entitled keys works. + void VerifyDecrypt(); LicenseRoundTrip* license_messages_; uint32_t num_keys_; @@ -528,9 +531,6 @@ class Session { // Generate known mac and enc keys using OEMCrypto_DeriveKeysFromSessionKey // and also fill out enc_key_, mac_key_server_, and mac_key_client_. void GenerateDerivedKeysFromSessionKey(); - // Encrypt a block of data using CTR mode. - void EncryptCTR(const vector& in_buffer, const uint8_t* key, - const uint8_t* starting_iv, vector* out_buffer); // Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption. void TestDecryptCTR(bool select_key_first = true, OEMCryptoResult expected_result = OEMCrypto_SUCCESS, From fe28d4cafcd8c5213c4c321fb3ed6ac645ffc544 Mon Sep 17 00:00:00 2001 From: Alex Dale Date: Sat, 8 May 2021 01:14:08 +0000 Subject: [PATCH 3/3] [DO NOT MERGE] Revert "Restructed reference root of trust (3/3 OEM Cert)" This reverts commit 9f7e2c4413f150ff30541bbc20c347ea58c40101. Reason for revert: Feature missed deadline Bug: 135283522 Change-Id: I63eb0431762fd13c64bef926fb1e64b6edacb156 --- .../oemcrypto/ref/src/oemcrypto_auth_ref.cpp | 75 ++++++------------- .../oemcrypto/ref/src/oemcrypto_auth_ref.h | 29 ++----- ...crypto_engine_device_properties_prov30.cpp | 34 ++++++--- .../oemcrypto/ref/src/oemcrypto_engine_ref.h | 33 +++----- .../oemcrypto/ref/src/oemcrypto_ref.cpp | 9 ++- .../oemcrypto/ref/src/oemcrypto_session.cpp | 9 --- .../oemcrypto/ref/src/oemcrypto_session.h | 3 - 7 files changed, 72 insertions(+), 120 deletions(-) diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp index b62cd39f..984de937 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp @@ -177,6 +177,9 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = { 0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03 }; + +// Filler for returning vector references. +const std::vector kEmptyVector; } // namespace bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { @@ -184,12 +187,10 @@ bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { // If provisioning method is something other than ProvisioningError // indicates it has already been initialized before. Must // existing data. - drm_cert_key_.reset(); - test_drm_cert_key_.reset(); + rsa_key_.reset(); + test_rsa_key_.reset(); keybox_.reset(); test_keybox_.reset(); - oem_cert_.reset(); - oem_cert_key_.reset(); } prov_method_ = method; switch (method) { @@ -197,7 +198,7 @@ bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { std::unique_ptr key = RsaPrivateKey::Load(kPrivateKey, kPrivateKeySize); if (key) { - drm_cert_key_ = std::move(key); + rsa_key_ = std::move(key); } else { // This error message is OK in unit tests which use test certificate. LOGE( @@ -229,7 +230,8 @@ bool AuthenticationRoot::IsValid() const { return HasDeviceKey(); } case OEMCrypto_OEMCertificate: { - return HasOemCertKey() && HasDeviceKey(); + // TODO(sigquit): Add OEM Certificate validation. + return true; } default: { LOGE("Root of trust is not properly initialized"); @@ -249,11 +251,8 @@ OEMCryptoResult AuthenticationRoot::IsKeyboxOrOemCertValid() const { return kb->IsKeyboxValid(); } case OEMCrypto_OEMCertificate: { - if (!oem_cert_) { - LOGW("OEM cert is not installed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return oem_cert_->IsCertificateValid(); + LOGW("OEM certificate validation is not implemented"); + return OEMCrypto_ERROR_NOT_IMPLEMENTED; } case OEMCrypto_DrmCertificate: { return OEMCrypto_ERROR_NOT_IMPLEMENTED; @@ -301,7 +300,7 @@ std::vector AuthenticationRoot::DeviceId() const { } if (prov_method_ == OEMCrypto_Keybox) { LOGE("Expected keybox to be set for a device ID"); - return std::vector(); + return kEmptyVector; } return std::vector(kFakeDeviceId.begin(), kFakeDeviceId.end()); } @@ -312,7 +311,7 @@ std::vector AuthenticationRoot::DeviceKey() const { return kb->DeviceKey(); } LOGE("No device key has been set"); - return std::vector(); + return kEmptyVector; } bool AuthenticationRoot::HasDeviceKey() const { return keybox() != nullptr; } @@ -327,7 +326,7 @@ OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() { LOGE("System does not support DRM certificates"); return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - if (test_drm_cert_key_) { + if (test_rsa_key_) { LOGE("Test RSA key is already loaded"); return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; } @@ -338,7 +337,7 @@ OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() { LOGE("Failed to load test RSA key"); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - test_drm_cert_key_ = std::move(key); + test_rsa_key_ = std::move(key); return OEMCrypto_SUCCESS; } @@ -400,48 +399,22 @@ OEMCryptoResult AuthenticationRoot::GetKeyData(uint8_t* key_data, return kb->GetKeyData(key_data, key_data_length); } -OEMCryptoResult AuthenticationRoot::InstallOemCertificate( - const uint8_t* private_key, size_t private_key_size, - const uint8_t* public_cert, size_t public_cert_size) { - if (prov_method_ != OEMCrypto_OEMCertificate) { - LOGE("System does not support OEM certificates"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (oem_cert_ || oem_cert_key_) { - LOGE("OEM certificate is already installed"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - std::unique_ptr oem_cert = OemCertificate::Create( - private_key, private_key_size, public_cert, public_cert_size); - if (!oem_cert) { - LOGE("Failed to install OEM certificate as root of trust"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (oem_cert->key_type() != OemCertificate::kRsa) { - LOGE("Only RSA-based OEM certificates supported"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - std::unique_ptr oem_cert_key = - RsaPrivateKey::Load(oem_cert->GetPrivateKey()); - if (!oem_cert_key) { - LOGE("Failed to parse OEM certificate private key"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - oem_cert_ = std::move(oem_cert); - oem_cert_key_ = std::move(oem_cert_key); - return OEMCrypto_SUCCESS; -} - OEMCryptoResult AuthenticationRoot::GetOemPublicCertificate( uint8_t* public_cert, size_t* public_cert_length) const { if (prov_method_ != OEMCrypto_OEMCertificate) { LOGE("System does not support OEM certificates"); return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - if (!oem_cert_) { - LOGE("OEM certificate is not installed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + LOGE("OEM certificates have not been implemented on auth root"); + return OEMCrypto_ERROR_NOT_IMPLEMENTED; +} + +const std::vector& AuthenticationRoot::GetOemPrivateKey() const { + if (prov_method_ != OEMCrypto_OEMCertificate) { + LOGE("System does not support OEM certificates"); + return kEmptyVector; } - return oem_cert_->GetPublicCertificate(public_cert, public_cert_length); + LOGE("OEM certificates have not been implemented on auth root"); + return kEmptyVector; } } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h index c1ae01db..9050b983 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h @@ -15,7 +15,6 @@ #include "OEMCryptoCENC.h" // Needed for enums only. #include "disallow_copy_and_assign.h" #include "oemcrypto_keybox_ref.h" -#include "oemcrypto_oem_cert.h" #include "oemcrypto_rsa_key.h" namespace wvoec_ref { @@ -68,12 +67,12 @@ class AuthenticationRoot { // Returns the shared RSA private key from the built-in DRM // Certificate. std::shared_ptr ShareDrmCertKey() { - return test_drm_cert_key_ ? test_drm_cert_key_ : drm_cert_key_; + return test_rsa_key_ ? test_rsa_key_ : rsa_key_; } RsaPrivateKey* DrmCertKey() const { - return test_drm_cert_key_ ? test_drm_cert_key_.get() : drm_cert_key_.get(); + return test_rsa_key_ ? test_rsa_key_.get() : rsa_key_.get(); } - bool HasDrmCertKey() const { return test_drm_cert_key_ || drm_cert_key_; } + bool HasDrmCertKey() const { return test_rsa_key_ || rsa_key_; } // Loads the system's built-in RSA key. Only implemented for // devices that are that pre-provisioned with a built-in DRM @@ -83,7 +82,7 @@ class AuthenticationRoot { OEMCryptoResult LoadTestRsaKey(); // Removes any installed test RSA key. - void RemoveTestRsaKey() { test_drm_cert_key_.reset(); } + void RemoveTestRsaKey() { test_rsa_key_.reset(); } // Keybox-based root of trust API. @@ -125,14 +124,6 @@ class AuthenticationRoot { // OEM Certificate-base root of trust API. - // Installs an OEM certificate as the root of trust. The provided - // private key and public cert are parsed, but not validated. The - // private key will be made available for sessions to load. - OEMCryptoResult InstallOemCertificate(const uint8_t* private_key, - size_t private_key_size, - const uint8_t* public_cert, - size_t public_cert_size); - // For OEM Cert-based devices, returns the OEM Public Certificate // component of the OEM Certificate. // This method implements the expected behavior of @@ -144,9 +135,7 @@ class AuthenticationRoot { // the OEM private key into a session. // Should only be called for devices that use OEM Certificates // for provisioning. - std::shared_ptr ShareOemCertKey() { return oem_cert_key_; } - RsaPrivateKey* OemCertKey() const { return oem_cert_key_.get(); } - bool HasOemCertKey() const { return static_cast(oem_cert_key_); } + const std::vector& GetOemPrivateKey() const; private: OEMCrypto_ProvisioningMethod prov_method_ = OEMCrypto_ProvisioningError; @@ -154,17 +143,13 @@ class AuthenticationRoot { // DRM certificate. // If no keybox, this is the private key of the baked-in DRM // Certificate. - std::shared_ptr drm_cert_key_; - std::shared_ptr test_drm_cert_key_; + std::shared_ptr rsa_key_; + std::shared_ptr test_rsa_key_; // Keybox data. std::unique_ptr keybox_; std::unique_ptr test_keybox_; - // OEM certificate. - std::unique_ptr oem_cert_; - std::shared_ptr oem_cert_key_; - CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot); }; } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp index 96134b99..3b17bb63 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp @@ -24,15 +24,6 @@ class Prov30CryptoEngine : public CryptoEngine { explicit Prov30CryptoEngine(std::unique_ptr&& file_system) : CryptoEngine(std::move(file_system)) {} - bool Initialize() override { - if (!CryptoEngine::Initialize()) { - return false; - } - const OEMCryptoResult result = InstallOemCertificate( - kOEMPrivateKey, kOEMPrivateKeySize, kOEMPublicCert, kOEMPublicCertSize); - return result == OEMCrypto_SUCCESS; - } - bool config_local_display_only() { return true; } // Returns the max HDCP version supported. @@ -56,6 +47,31 @@ class Prov30CryptoEngine : public CryptoEngine { return OEMCrypto_OEMCertificate; } + OEMCryptoResult get_oem_certificate(SessionContext* session, + uint8_t* public_cert, + size_t* public_cert_length) { + if (kOEMPublicCertSize == 0) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + if (public_cert_length == nullptr) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (*public_cert_length < kOEMPublicCertSize) { + *public_cert_length = kOEMPublicCertSize; + return OEMCrypto_ERROR_SHORT_BUFFER; + } + *public_cert_length = kOEMPublicCertSize; + if (public_cert == nullptr) { + return OEMCrypto_ERROR_SHORT_BUFFER; + } + memcpy(public_cert, kOEMPublicCert, kOEMPublicCertSize); + if (!session->LoadRsaDrmKey(kOEMPrivateKey, kOEMPrivateKeySize)) { + LOGE("Private RSA Key did not load correctly."); + return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + return OEMCrypto_SUCCESS; + } + // Returns "L3" for a software only library. L1 is for hardware protected // keys and data paths. L2 is for hardware protected keys but no data path // protection. diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h index 0fddd30f..70613aff 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h @@ -75,8 +75,8 @@ class CryptoEngine { OEMCryptoResult LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); } - OEMCryptoResult IsKeyboxOrOemCertValid() const { - return root_of_trust_.IsKeyboxOrOemCertValid(); + OEMCryptoResult IsKeyboxValid() const { + return root_of_trust_.IsKeyboxValid(); } std::vector DeviceRootKey() const { @@ -97,26 +97,6 @@ class CryptoEngine { return root_of_trust_.GetKeyData(key_data, key_data_length); } - OEMCryptoResult InstallOemCertificate(const uint8_t* private_key, - size_t private_key_size, - const uint8_t* public_cert, - size_t public_cert_size) { - return root_of_trust_.InstallOemCertificate(private_key, private_key_size, - public_cert, public_cert_size); - } - - OEMCryptoResult GetOemPublicCertificate(uint8_t* public_cert, - size_t* public_cert_length) const { - return root_of_trust_.GetOemPublicCertificate(public_cert, - public_cert_length); - } - - std::shared_ptr ShareOemPrivateKey() { - return root_of_trust_.ShareOemCertKey(); - } - - bool HasOemPrivateKey() const { return root_of_trust_.HasOemCertKey(); } - virtual void Terminate(); virtual SessionId OpenSession(); @@ -175,6 +155,15 @@ class CryptoEngine { return OEMCrypto_Keybox; } + virtual OEMCryptoResult get_oem_certificate(uint8_t* public_cert, + size_t* public_cert_length) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + + virtual OEMCryptoResult load_oem_private_key(SessionContext* session) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + // Used for OEMCrypto_IsAntiRollbackHwPresent. virtual bool config_is_anti_rollback_hw_present() { return false; } diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp index 0f65f489..09b78315 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp @@ -762,8 +762,10 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) { case OEMCrypto_DrmCertificate: return OEMCrypto_SUCCESS; case OEMCrypto_Keybox: + return crypto_engine->IsKeyboxValid(); case OEMCrypto_OEMCertificate: - return crypto_engine->IsKeyboxOrOemCertValid(); + // TODO(sigquit): verify that the certificate exists and is valid. + return OEMCrypto_SUCCESS; default: LOGE("Invalid provisioning method: %d.", crypto_engine->config_provisioning_method()); @@ -795,7 +797,7 @@ OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session) { LOGE("OEMCrypto_ERROR_INVALID_SESSION"); return OEMCrypto_ERROR_INVALID_SESSION; } - return session_ctx->LoadOemPrivateKey(); + return crypto_engine->load_oem_private_key(session_ctx); } OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate( @@ -809,8 +811,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate( crypto_engine->config_provisioning_method()); return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - return crypto_engine->GetOemPublicCertificate(public_cert, - public_cert_length); + return crypto_engine->get_oem_certificate(public_cert, public_cert_length); } OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* device_id, diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp index 96f0b8ea..69e219f6 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp @@ -296,15 +296,6 @@ OEMCryptoResult SessionContext::RSADeriveKeys( return DeriveKeys(session_key_, mac_key_context, enc_key_context); } -OEMCryptoResult SessionContext::LoadOemPrivateKey() { - if (!ce_->HasOemPrivateKey()) { - LOGE("No OEM private key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - rsa_key_ = ce_->ShareOemPrivateKey(); - return OEMCrypto_SUCCESS; -} - OEMCryptoResult SessionContext::PrepAndSignLicenseRequest( uint8_t* message, size_t message_length, size_t* core_message_length, uint8_t* signature, size_t* signature_length) { diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h index e01054eb..fe942ad6 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h @@ -75,9 +75,6 @@ class SessionContext { const std::vector& enc_session_key, const std::vector& mac_context, const std::vector& enc_context); - - virtual OEMCryptoResult LoadOemPrivateKey(); - virtual OEMCryptoResult PrepAndSignLicenseRequest(uint8_t* message, size_t message_length, size_t* core_message_length,