Require Features for Android OEMCrypto

Merge from Widevine repo if http://go/wvgerrit/13781

This CL adds several unit tests that are specifically designed to test
features that are required for Android CDM but not other platforms.

Once this CL has been merged, future CLs will modify the main
oemcrypto test file so that some tests are skipped if their features
are not implemented.

Change-Id: I55b8cbb9c13d2db88bd4f56bba31a4aab3306067
This commit is contained in:
Fred Gylys-Colwell
2015-03-30 11:12:31 -07:00
parent 2f86c447a4
commit 10cc0a5ddb
4 changed files with 120 additions and 12 deletions

View File

@@ -1,6 +1,5 @@
LOCAL_PATH:= $(call my-dir) LOCAL_PATH:= $(call my-dir)
# THIS IS FOR THE MOCK TESTS:
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE:=oemcrypto_test LOCAL_MODULE:=oemcrypto_test

View File

@@ -1,7 +1,8 @@
LOCAL_PATH:= $(call my-dir) LOCAL_PATH:= $(call my-dir)
LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES:= \
oemcrypto_test.cpp oemcrypto_test.cpp \
oemcrypto_test_android.cpp \
LOCAL_C_INCLUDES += \ LOCAL_C_INCLUDES += \
external/gtest/include \ external/gtest/include \

View File

@@ -1076,7 +1076,7 @@ class Session {
void FillRefreshMessage(size_t key_count, uint32_t control_bits, void FillRefreshMessage(size_t key_count, uint32_t control_bits,
uint32_t nonce) { uint32_t nonce) {
for (unsigned int i = 0; i < kNumKeys; i++) { for (unsigned int i = 0; i < key_count; i++) {
memset(encrypted_license_.keys[i].key_id, i, kTestKeyIdLength); memset(encrypted_license_.keys[i].key_id, i, kTestKeyIdLength);
memcpy(encrypted_license_.keys[i].control.verification, "kctl", 4); memcpy(encrypted_license_.keys[i].control.verification, "kctl", 4);
encrypted_license_.keys[i].control.duration = htonl(kLongDuration); encrypted_license_.keys[i].control.duration = htonl(kLongDuration);
@@ -1605,8 +1605,8 @@ TEST_F(OEMCryptoClientTest, VersionNumber) {
cout << " OEMCrypto Security Level is " << level << endl; cout << " OEMCrypto Security Level is " << level << endl;
uint32_t version = OEMCrypto_APIVersion(); uint32_t version = OEMCrypto_APIVersion();
cout << " OEMCrypto API version is " << version << endl; cout << " OEMCrypto API version is " << version << endl;
ASSERT_LE(8, version); ASSERT_LE(8u, version);
ASSERT_GE(10, version); ASSERT_GE(10u, version);
} }
TEST_F(OEMCryptoClientTest, NormalGetKeyData) { TEST_F(OEMCryptoClientTest, NormalGetKeyData) {
@@ -1752,7 +1752,7 @@ TEST_F(OEMCryptoClientTest, MaxSessionsOpenClose) {
size_t sessions_count; size_t sessions_count;
ASSERT_EQ(OEMCrypto_SUCCESS, ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_GetNumberOfOpenSessions(&sessions_count)); OEMCrypto_GetNumberOfOpenSessions(&sessions_count));
ASSERT_EQ(0, sessions_count); ASSERT_EQ(0u, sessions_count);
size_t max_sessions; size_t max_sessions;
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetMaxNumberOfSessions(&max_sessions)); ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetMaxNumberOfSessions(&max_sessions));
// We expect OEMCrypto implementations support at least 8 sessions. // We expect OEMCrypto implementations support at least 8 sessions.
@@ -1762,7 +1762,7 @@ TEST_F(OEMCryptoClientTest, MaxSessionsOpenClose) {
vector<OEMCrypto_SESSION> sessions; vector<OEMCrypto_SESSION> sessions;
// Limit the number of sessions for testing. // Limit the number of sessions for testing.
const size_t kMaxNumberOfSessionsForTesting = 0x100u; const size_t kMaxNumberOfSessionsForTesting = 0x100u;
for (int i = 0; i < kMaxNumberOfSessionsForTesting; i++) { for (size_t i = 0; i < kMaxNumberOfSessionsForTesting; i++) {
OEMCrypto_SESSION session_id; OEMCrypto_SESSION session_id;
OEMCryptoResult sts = OEMCrypto_OpenSession(&session_id); OEMCryptoResult sts = OEMCrypto_OpenSession(&session_id);
// GetMaxNumberOfSessions might be an estimate. We allow OEMCrypto to report // GetMaxNumberOfSessions might be an estimate. We allow OEMCrypto to report
@@ -1780,7 +1780,7 @@ TEST_F(OEMCryptoClientTest, MaxSessionsOpenClose) {
ASSERT_EQ(i + 1, sessions_count); ASSERT_EQ(i + 1, sessions_count);
sessions.push_back(session_id); sessions.push_back(session_id);
} }
for (int i = 0; i < sessions.size(); i++) { for (size_t i = 0; i < sessions.size(); i++) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(sessions[i])); ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(sessions[i]));
ASSERT_EQ(OEMCrypto_SUCCESS, ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_GetNumberOfOpenSessions(&sessions_count)); OEMCrypto_GetNumberOfOpenSessions(&sessions_count));
@@ -4581,7 +4581,7 @@ TEST_F(OEMCryptoClientTest, PSTReportSizes) {
if (OEMCrypto_SupportsUsageTable()) { if (OEMCrypto_SupportsUsageTable()) {
OEMCrypto_PST_Report report; OEMCrypto_PST_Report report;
uint8_t* location = reinterpret_cast<uint8_t*>(&report); uint8_t* location = reinterpret_cast<uint8_t*>(&report);
EXPECT_EQ(48, sizeof(report)); EXPECT_EQ(48u, sizeof(report));
uint8_t *field; uint8_t *field;
field = reinterpret_cast<uint8_t *>(&report.status); field = reinterpret_cast<uint8_t *>(&report.status);
EXPECT_EQ(20, field - location); EXPECT_EQ(20, field - location);
@@ -4762,7 +4762,7 @@ TEST_P(DISABLED_UsageTableTest, FiftyEntries) {
const size_t ENTRY_COUNT = 49;// API says should hold at least 50 entries. const size_t ENTRY_COUNT = 49;// API says should hold at least 50 entries.
Session sessions[ENTRY_COUNT]; Session sessions[ENTRY_COUNT];
for (int i=0; i<ENTRY_COUNT; i++) { for (size_t i=0; i < ENTRY_COUNT; i++) {
sessions[i].open(); sessions[i].open();
sessions[i].GenerateDerivedKeys(); sessions[i].GenerateDerivedKeys();
std::string pst = "pst "; std::string pst = "pst ";
@@ -4776,7 +4776,7 @@ TEST_P(DISABLED_UsageTableTest, FiftyEntries) {
sessions[i].GenerateReport(pst); sessions[i].GenerateReport(pst);
sessions[i].close(); sessions[i].close();
} }
for (int i=0; i<ENTRY_COUNT; i++) { for (size_t i=0; i<ENTRY_COUNT; i++) {
Session s; Session s;
s.open(); s.open();
std::string pst = "pst "; std::string pst = "pst ";
@@ -4789,7 +4789,7 @@ TEST_P(DISABLED_UsageTableTest, FiftyEntries) {
sleep(kShortSleep); sleep(kShortSleep);
// If I add too many entries, it can delete the older ones first, except // If I add too many entries, it can delete the older ones first, except
// it shouldn't delete the one attached to an open session. (s1) // it shouldn't delete the one attached to an open session. (s1)
for (int i=0; i<ENTRY_COUNT; i++) { for (size_t i=0; i < ENTRY_COUNT; i++) {
sessions[i].open(); sessions[i].open();
sessions[i].GenerateDerivedKeys(); sessions[i].GenerateDerivedKeys();
std::string pst = "newer pst "; std::string pst = "newer pst ";

View File

@@ -0,0 +1,108 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// OEMCrypto unit tests - extra tests required for Android platform.
//
// The Widevine CDM system can be built on many platforms, with different
// capabilities. For example, some platforms do not require usage tables,
// and some can have a pre-installed certificate and do not need a keybox.
// On Android, these features are not optional. This set of unit tests
// verify that these features are implemented.
//
// In the file oemcrypto_test.cpp, the unit tests only verify correct
// functionality for functions that are implemented. Android devices must pass
// unit tests in both files.
#include <gtest/gtest.h>
#include "OEMCryptoCENC.h"
namespace wvoec {
// These tests are required for LollyPop Android devices.
class OEMCryptoAndroidLMPTest : public ::testing::Test {
protected:
virtual void SetUp() {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize());
}
virtual void TearDown() {
OEMCrypto_Terminate();
}
};
// Android devices must have a keybox.
TEST_F(OEMCryptoAndroidLMPTest, GetKeyDataImplemented) {
uint8_t key_data[256];
size_t key_data_len = sizeof(key_data);
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GetKeyData(key_data, &key_data_len));
}
TEST_F(OEMCryptoAndroidLMPTest, MinVersionNumber9) {
uint32_t version = OEMCrypto_APIVersion();
ASSERT_LE(9u, version);
}
TEST_F(OEMCryptoAndroidLMPTest, ValidKeyboxTest) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
}
TEST_F(OEMCryptoAndroidLMPTest, RewrapDeviceRSAKeyImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_RewrapDeviceRSAKey(0, NULL, 0, NULL, 0, NULL,
NULL, 0, NULL, NULL, NULL));
}
TEST_F(OEMCryptoAndroidLMPTest, RSASignatureImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GenerateRSASignature(0, NULL, 0, NULL, NULL,
kSign_RSASSA_PSS));
}
TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Encrypt(0, NULL, 0, NULL,
OEMCrypto_AES_CBC_128_NO_PADDING, NULL));
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Decrypt(0, NULL, 0, NULL,
OEMCrypto_AES_CBC_128_NO_PADDING, NULL));
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Sign(0, NULL, 0,
OEMCrypto_HMAC_SHA256, NULL, NULL));
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_Generic_Verify(0, NULL, 0,
OEMCrypto_HMAC_SHA256, NULL, 0));
}
TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
// TODO(fredgc): maybe remove Properties::oem_crypto_require_usage_tables?
ASSERT_TRUE(OEMCrypto_SupportsUsageTable());
}
// These tests are required for M Android devices.
class OEMCryptoAndroidMNCTest : public OEMCryptoAndroidLMPTest {};
TEST_F(OEMCryptoAndroidMNCTest, MinVersionNumber10) {
uint32_t version = OEMCrypto_APIVersion();
ASSERT_GE(version, 10u);
}
// TODO(fredgc): b/18962381
// TEST_F(OEMCryptoAndroidMNCTest, LoadsTestKeyboxImplemented) {
// ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox());
// }
TEST_F(OEMCryptoAndroidMNCTest, NumberOfSessionsImplemented) {
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GetNumberOfOpenSessions(NULL));
ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
OEMCrypto_GetMaxNumberOfSessions(NULL));
}
// TODO(fredgc): b/18503541
// TEST_F(OEMCryptoAndroidMNCTest, QueryKeyControlImplemented) {
// ASSERT_NE(OEMCrypto_ERROR_NOT_IMPLEMENTED,
// OEMCrypto_QueryKeyControl(0, NULL, 0, NULL, NULL));
// }
} // namespace wvoec