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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user