Add comments to unit tests

Merge from Widevine repo of http://go/wvgerrit/73383

Partners have been requesting more explanation for what each test is
doing.  This is an attempt to clarify some of the tests.

Bug: 119640588
Test: unit tests
Change-Id: I270203b4e8fa7e65abb55297788e4d55856e7dcd
This commit is contained in:
Fred Gylys-Colwell
2019-03-03 21:16:55 -08:00
parent 50e4d67415
commit 5f7803dedd
7 changed files with 306 additions and 21 deletions

View File

@@ -8,8 +8,13 @@
namespace wvoec {
// Keeps track of which features are supported by the version of OEMCrypto being
// tested. See the integration guide for a list of optional features.
class DeviceFeatures {
public:
// There are several possible methods used to derive a set of known session
// keys. For example, the test can install a known test keybox, or it can
// parse the OEM certificate.
enum DeriveMethod { // Method to use derive session keys.
NO_METHOD, // Cannot derive known session keys.
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
@@ -32,15 +37,24 @@ class DeviceFeatures {
uint32_t api_version;
OEMCrypto_ProvisioningMethod provisioning_method;
// This should be called from the test program's main procedure.
void Initialize(bool is_cast_receiver, bool force_load_test_keybox);
// Generate a GTest filter of tests that should not be run. This should be
// called after Initialize. Tests are filtered out based on which features
// are not supported. For example, a device that uses Provisioning 3.0 will
// have all keybox tests filtered out.
std::string RestrictFilter(const std::string& initial_filter);
private:
// Decide which method should be used to derive session keys, based on
// supported featuers.
void PickDerivedKey();
bool IsTestKeyboxInstalled();
// Add a GTest filter restriction to the current filter.
void FilterOut(std::string* current_filter, const std::string& new_filter);
};
// There is one global set of features for the version of OEMCrypto being
// tested. This should be initialized in the test program's main procedure.
extern DeviceFeatures global_features;
const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method);

View File

@@ -80,6 +80,8 @@ void dump_boringssl_error() {
}
}
// A smart pointer for BoringSSL objects. It uses the specified free function
// to release resources and free memory when the pointer is deleted.
template <typename T, void (*func)(T*)>
class boringssl_ptr {
public:
@@ -163,6 +165,7 @@ void Session::close() {
}
void Session::GenerateNonce(int* error_counter) {
// We make one attempt. If it fails, we assume there was a nonce flood.
if (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(session_id(), &nonce_)) {
return;
}
@@ -170,6 +173,8 @@ void Session::GenerateNonce(int* error_counter) {
(*error_counter)++;
} else {
sleep(1); // wait a second, then try again.
// The following is after a 1 second pause, so it cannot be from a nonce
// flood.
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_GenerateNonce(session_id(), &nonce_));
}
@@ -196,6 +201,9 @@ void Session::FillDefaultContext(vector<uint8_t>* mac_context,
"180120002a0c31383836373837343035000000000080");
}
// This generates the truth data for deriving one key. If there are failures in
// this function, then there is something wrong with the test program and its
// dependency on BoringSSL.
void Session::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
int counter, vector<uint8_t>* out) {
ASSERT_FALSE(context.empty());
@@ -222,6 +230,9 @@ void Session::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
CMAC_CTX_free(cmac_ctx);
}
// This generates the truth data for deriving a set of keys. If there are
// failures in this function, then there is something wrong with the test
// program and its dependency on BoringSSL.
void Session::DeriveKeys(const uint8_t* master_key,
const vector<uint8_t>& mac_key_context,
const vector<uint8_t>& enc_key_context) {
@@ -241,6 +252,8 @@ void Session::DeriveKeys(const uint8_t* master_key,
DeriveKey(master_key, enc_key_context, 1, &enc_key_);
}
// This should only be called if the device uses Provisioning 2.0. A failure in
// this function is probably caused by a bad keybox.
void Session::GenerateDerivedKeysFromKeybox(
const wvoec::WidevineKeybox& keybox) {
GenerateNonce();
@@ -261,10 +274,13 @@ void Session::GenerateDerivedKeysFromSessionKey() {
vector<uint8_t> session_key;
vector<uint8_t> enc_session_key;
if (public_rsa_ == NULL) PreparePublicKey();
// A failure here probably indicates that there is something wrong with the
// test program and its dependency on BoringSSL.
ASSERT_TRUE(GenerateRSASessionKey(&session_key, &enc_session_key));
vector<uint8_t> mac_context;
vector<uint8_t> enc_context;
FillDefaultContext(&mac_context, &enc_context);
// A failure here is probably caused by having the wrong RSA key loaded.
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_DeriveKeysFromSessionKey(
session_id(), enc_session_key.data(), enc_session_key.size(),
@@ -424,6 +440,10 @@ void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) {
VerifyEntitlementTestKeys();
}
// This function verifies that the key control block reported by OEMCrypto agree
// with the truth key control block. Failures in this function probably
// indicate the OEMCrypto_LoadKeys did not correctly process the key control
// block.
void Session::VerifyTestKeys() {
for (unsigned int i = 0; i < num_keys_; i++) {
KeyControlBlock block;
@@ -446,6 +466,10 @@ void Session::VerifyTestKeys() {
}
}
// This function verifies that the key control block 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 Session::VerifyEntitlementTestKeys() {
for (unsigned int i = 0; i < num_keys_; i++) {
KeyControlBlock block;

View File

@@ -20,7 +20,8 @@ const uint8_t* find(const vector<uint8_t>& message,
return &(*pos);
}
// If force is true, we assert that the key loads successfully.
// This creates a wrapped RSA key for devices that have the test keybox
// installed. If force is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes,
bool force) {
Session s;
@@ -42,7 +43,8 @@ void SessionUtil::CreateWrappedRSAKeyFromKeybox(uint32_t allowed_schemes,
ASSERT_EQ(NULL, find(wrapped_rsa_key_, encoded_rsa_key_));
}
// If force is true, we assert that the key loads successfully.
// This creates a wrapped RSA key for devices using provisioning 3.0. If force
// is true, we assert that the key loads successfully.
void SessionUtil::CreateWrappedRSAKeyFromOEMCert(
uint32_t allowed_schemes, bool force) {
Session s;

View File

@@ -26,8 +26,12 @@ public:
// If force is true, we assert that the key loads successfully.
void CreateWrappedRSAKey(uint32_t allowed_schemes, bool force);
// This is used to force installation of a keybox. This overwrites the
// production keybox -- it does NOT use OEMCrypto_LoadTestKeybox.
void InstallKeybox(const wvoec::WidevineKeybox& keybox, bool good);
// This loads the test keybox or the test RSA key, using LoadTestKeybox or
// LoadTestRSAKey as needed.
void EnsureTestKeys();
void InstallTestSessionKeys(Session* s);

File diff suppressed because it is too large Load Diff

View File

@@ -43,6 +43,7 @@ TEST_F(OEMCryptoAndroidLMPTest, GetKeyDataImplemented) {
}
}
// Android devices must have a valid keybox.
TEST_F(OEMCryptoAndroidLMPTest, ValidKeybox) {
if (OEMCrypto_GetProvisioningMethod() == OEMCrypto_Keybox) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
@@ -70,12 +71,14 @@ TEST_F(OEMCryptoAndroidLMPTest, RewrapDeviceRSAKeyImplemented) {
}
}
// This verifies that the device can load a DRM Certificate.
TEST_F(OEMCryptoAndroidLMPTest, RSASignatureImplemented) {
ASSERT_NE(
OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GenerateRSASignature(0, NULL, 0, NULL, NULL, kSign_RSASSA_PSS));
}
// The Generic Crypto API functions are required for Android.
TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Encrypt(0, NULL, 0, NULL,
@@ -91,10 +94,13 @@ TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
OEMCrypto_Generic_Verify(0, NULL, 0, OEMCrypto_HMAC_SHA256, NULL, 0));
}
// Android requires support of usage table. The usage table is used for Secure
// Stops and for offline licenses.
TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
ASSERT_TRUE(OEMCrypto_SupportsUsageTable());
}
// Android devices require L1 OEMCrypto.
TEST_F(OEMCryptoAndroidLMPTest, Level1Required) {
const char* char_level = OEMCrypto_SecurityLevel();
std::string security_level(char_level ? char_level : "");
@@ -112,6 +118,8 @@ TEST_F(OEMCryptoAndroidMNCTest, MinVersionNumber10) {
ASSERT_GE(version, 10u);
}
// Android devices using Provisioning 2.0 must be able to load a test keybox.
// If they are not using Provisioning 2.0, then they must use Provisioning 3.0.
TEST_F(OEMCryptoAndroidMNCTest, LoadsTestKeyboxImplemented) {
if (OEMCrypto_Keybox == OEMCrypto_GetProvisioningMethod()) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox(
@@ -123,6 +131,7 @@ TEST_F(OEMCryptoAndroidMNCTest, LoadsTestKeyboxImplemented) {
}
}
// Android requires implementation of these functions.
TEST_F(OEMCryptoAndroidMNCTest, NumberOfSessionsImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GetNumberOfOpenSessions(NULL));
@@ -130,6 +139,7 @@ TEST_F(OEMCryptoAndroidMNCTest, NumberOfSessionsImplemented) {
OEMCrypto_GetMaxNumberOfSessions(NULL));
}
// Android requires implementation of these functions.
TEST_F(OEMCryptoAndroidMNCTest, QueryKeyControlImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_QueryKeyControl(0, NULL, 0, NULL, NULL));

View File

@@ -12,6 +12,9 @@ static void acknowledge_cast() {
<< "==================================================================\n";
}
// This special main procedure is used instead of the standard GTest main,
// because we need to initialize the list of features supported by the device.
// Also, the test filter is updated based on the feature list.
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
wvcdm::g_cutoff = wvcdm::LOG_INFO;