From e59b976625fed348dc8e8e2f33384bebca8cedd9 Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Tue, 20 Nov 2018 15:11:15 -0800 Subject: [PATCH] Update comments and unit tests for InstallKeyboxOrCert Merge from Widevine repo of http://go/wvgerrit/66865 This CL updates the comments for the code that uses InstallKeyboxOrCert to install a keybox or oem cert at runtime. There is also a new unit test for the device id. There are not many unit tests because we don't want to accidentally overwrite the production keybox or cert on a device when running tests. bug: 111725154 test: unit tests Change-Id: Ide9b3d4732f3f96a723a128907babe7e59c02ffc --- .../core/src/oemcrypto_adapter_dynamic.cpp | 16 ++++++++++++++-- .../oemcrypto/test/oemcrypto_test.cpp | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp index 251138c1..27f1f2be 100644 --- a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp +++ b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp @@ -785,11 +785,15 @@ class Adapter { LOOKUP_ALL(15, GetHashErrorCode, OEMCrypto_GetHashErrorCode); // clang-format on - // If the keybox or oem certificate is valid, we are done. + // TODO(119830252): make the code below available to a static adapter. + // Check if the keybox or oem certificate is valid, if so, we are finished + // with initialization. OEMCryptoResult root_valid = level1_.IsKeyboxOrOEMCertValid(); OEMCrypto_ProvisioningMethod provisioning_method = level1_.GetProvisioningMethod(); if (root_valid == OEMCrypto_SUCCESS) { + // The keybox or certificate is valid -- that means initialization is done + // and we only have save some metrics and return. metrics->OemCryptoDynamicAdapterMetrics::SetInitializationMode( (provisioning_method == OEMCrypto_Keybox) ? wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX @@ -797,10 +801,12 @@ class Adapter { OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0); return true; } - + // At this point, the keybox or cert is not valid. We look on the file + // system for one. If it is there we try to install it. wvcdm::FileSystem file_system; std::string filename; if (!wvcdm::Properties::GetFactoryKeyboxPath(&filename)) { + // No keybox or cert file found. Give up. LOGW("Bad Level 1 Root of Trust. Falling Back to L3."); level1_.Terminate(); metrics->OemCryptoDynamicAdapterMetrics::SetInitializationMode( @@ -809,6 +815,7 @@ class Adapter { } ssize_t size = file_system.FileSize(filename); if (size <= 0) { + // A keybox or cert file was found, but it has size 0. Give up. LOGW("Could not find %s. Falling Back to L3.", filename.c_str()); level1_.Terminate(); metrics->OemCryptoDynamicAdapterMetrics::SetInitializationMode( @@ -818,6 +825,7 @@ class Adapter { } wvcdm::File* file = file_system.Open(filename, file_system.kReadOnly); if (!file) { + // A keybox or cert file was found, but can't open it. Give up. LOGW("Could not open %s. Falling Back to L3.", filename.c_str()); level1_.Terminate(); metrics->OemCryptoDynamicAdapterMetrics::SetInitializationMode( @@ -830,6 +838,7 @@ class Adapter { file->Close(); if (level1_.InstallKeyboxOrOEMCert(&root_key[0], size_read) != OEMCrypto_SUCCESS) { + // A keybox or cert file was read, but I could not install it. Give up. LOGE("Could NOT install root key from %s. Falling Back to L3.", filename.c_str()); level1_.Terminate(); @@ -839,6 +848,8 @@ class Adapter { return false; } if (level1_.IsKeyboxOrOEMCertValid() != OEMCrypto_SUCCESS) { + // A keybox or cert file was read and installed, but it is still not + // valid. Give up. LOGE("Installed bad key from %s. Falling Back to L3.", filename.c_str()); level1_.Terminate(); @@ -847,6 +858,7 @@ class Adapter { OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX); return false; } + // A valid keybox or cert file was read and installed. Yay! return success. LOGI("Installed root key from %s", filename.c_str()); metrics->OemCryptoDynamicAdapterMetrics::SetInitializationMode( wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX); diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 3cdaeba6..b145a024 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -557,6 +557,8 @@ TEST_F(OEMCryptoKeyboxTest, GetKeyDataNullPointer) { ASSERT_NE(OEMCrypto_SUCCESS, sts); } +// This test makes sure the installed keybox is valid. It doesn't really check +// that it is a production keybox. That must be done by an integration test. TEST_F(OEMCryptoKeyboxTest, ProductionKeyboxValid) { ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid()); } @@ -584,6 +586,23 @@ TEST_F(OEMCryptoProv30Test, DeviceClaimsOEMCertificate) { ASSERT_EQ(OEMCrypto_OEMCertificate, OEMCrypto_GetProvisioningMethod()); } +TEST_F(OEMCryptoProv30Test, GetDeviceId) { + OEMCryptoResult sts; + std::vector dev_id(128, 0); + size_t dev_id_len = dev_id.size(); + sts = OEMCrypto_GetDeviceID(&dev_id[0], &dev_id_len); + if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) return; + if (sts == OEMCrypto_ERROR_SHORT_BUFFER) { + ASSERT_GT(dev_id_len, 0u); + dev_id.resize(dev_id_len); + sts = OEMCrypto_GetDeviceID(&dev_id[0], &dev_id_len); + } + cout << " NormalGetDeviceId: dev_id = " << &dev_id[0] + << " len = " << dev_id_len << endl; + ASSERT_EQ(OEMCrypto_SUCCESS, sts); +} + + // The OEM certificate must be valid. TEST_F(OEMCryptoProv30Test, CertValidAPI15) { ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxOrOEMCertValid());