Merge "Unit Test Updates for v13"

This commit is contained in:
Fred Gylys-Colwell
2017-01-26 00:21:50 +00:00
committed by Android (Google) Code Review
7 changed files with 133 additions and 118 deletions

View File

@@ -697,6 +697,63 @@ bool SessionContext::LoadRSAKey(const uint8_t* pkcs8_rsa_key,
return rsa_key_.LoadPkcs8RsaKey(pkcs8_rsa_key, rsa_key_length);
}
OEMCryptoResult SessionContext::AllowKeyUse(const std::string& log_string,
uint32_t use_type,
OEMCryptoBufferType buffer_type) {
const KeyControlBlock& control = current_content_key()->control();
if (use_type && (!(control.control_bits() & use_type))) {
LOGE("[%s(): control bit says not allowed.", log_string.c_str());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.control_bits() & kControlDataPathSecure) {
if (!ce_->config_closed_platform() &&
buffer_type == OEMCrypto_BufferType_Clear) {
LOGE("[%s(): Secure key with insecure buffer]", log_string.c_str());
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
}
if (control.control_bits() & kControlReplayMask) {
if (!IsUsageEntryValid()) {
LOGE("[%s(): usage entry not valid]", log_string.c_str());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[%s(): key expired.", log_string.c_str());
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if (!ce_->config_local_display_only()) {
// Only look at HDCP and Analog restrictions if the display is non-local.
if (control.control_bits() & kControlHDCPRequired) {
uint8_t required_hdcp =
(control.control_bits() & kControlHDCPVersionMask) >>
kControlHDCPVersionShift;
// For reference implementation, we pretend we can handle the current
// HDCP version.
if (required_hdcp > ce_->config_current_hdcp_capability() ||
ce_->config_current_hdcp_capability() == 0) {
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
}
}
if (control.control_bits() & kControlSRMVersionRequired) {
LOGE("[%s(): control bit says SRM version required.",
log_string.c_str());
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
}
}
if (!ce_->config_local_display_only()
|| buffer_type == OEMCrypto_BufferType_Clear) {
if (control.control_bits() & kControlDisableAnalogOutput) {
LOGE("[%s(): control bit says disable analog.",
log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
}
return OEMCrypto_SUCCESS;
}
OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
size_t buffer_length,
const uint8_t* iv,
@@ -708,28 +765,14 @@ OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
return OEMCrypto_ERROR_NO_CONTENT_KEY;
}
const std::vector<uint8_t>& key = current_content_key()->value();
const KeyControlBlock& control = current_content_key()->control();
// Set the AES key.
if (static_cast<int>(key.size()) != AES_BLOCK_SIZE) {
LOGE("[Generic_Encrypt(): CONTENT_KEY has wrong size: %d", key.size());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowEncrypt)) {
LOGE("[Generic_Encrypt(): control bit says not allowed.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Encrypt(): key expired.");
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if (control.control_bits() & kControlReplayMask) {
if (!IsUsageEntryValid()) {
LOGE("[Generic_Encrypt(): usage entry not valid]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
OEMCryptoResult result = AllowKeyUse("Generic_Encrypt", kControlAllowEncrypt,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) {
LOGE("[Generic_Encrypt(): algorithm bad.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -762,34 +805,15 @@ OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
return OEMCrypto_ERROR_NO_CONTENT_KEY;
}
const std::vector<uint8_t>& key = current_content_key()->value();
const KeyControlBlock& control = current_content_key()->control();
// Set the AES key.
if (static_cast<int>(key.size()) != AES_BLOCK_SIZE) {
LOGE("[Generic_Decrypt(): CONTENT_KEY has wrong size.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowDecrypt)) {
LOGE("[Generic_Decrypt(): control bit says not allowed.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.control_bits() & kControlDataPathSecure) {
if (!ce_->config_closed_platform()) {
LOGE("[Generic_Decrypt(): control bit says secure path only.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Decrypt(): key expired.");
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if (control.control_bits() & kControlReplayMask) {
if (!IsUsageEntryValid()) {
LOGE("[Generic_Decrypt(): usage entry not valid]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
OEMCryptoResult result = AllowKeyUse("Generic_Decrypt", kControlAllowDecrypt,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) {
LOGE("[Generic_Decrypt(): bad algorithm.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -827,27 +851,13 @@ OEMCryptoResult SessionContext::Generic_Sign(const uint8_t* in_buffer,
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
const std::vector<uint8_t>& key = current_content_key()->value();
const KeyControlBlock& control = current_content_key()->control();
if (static_cast<int>(key.size()) != SHA256_DIGEST_LENGTH) {
LOGE("[Generic_Sign(): CONTENT_KEY has wrong size; %d", key.size());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowSign)) {
LOGE("[Generic_Sign(): control bit says not allowed.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Sign(): key expired.");
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if (control.control_bits() & kControlReplayMask) {
if (!IsUsageEntryValid()) {
LOGE("[Generic_Sign(): usage entry not valid]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
OEMCryptoResult result = AllowKeyUse("Generic_Sign", kControlAllowSign,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
if (algorithm != OEMCrypto_HMAC_SHA256) {
LOGE("[Generic_Sign(): bad algorithm.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -877,27 +887,13 @@ OEMCryptoResult SessionContext::Generic_Verify(const uint8_t* in_buffer,
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
const std::vector<uint8_t>& key = current_content_key()->value();
const KeyControlBlock& control = current_content_key()->control();
if (static_cast<int>(key.size()) != SHA256_DIGEST_LENGTH) {
LOGE("[Generic_Verify(): CONTENT_KEY has wrong size: %d", key.size());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowVerify)) {
LOGE("[Generic_Verify(): control bit says not allowed.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Verify(): key expired.");
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if (control.control_bits() & kControlReplayMask) {
if (!IsUsageEntryValid()) {
LOGE("[Generic_Verify(): usage entry not valid]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
OEMCryptoResult result = AllowKeyUse("Generic_Verify", kControlAllowVerify,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
if (algorithm != OEMCrypto_HMAC_SHA256) {
LOGE("[Generic_Verify(): bad algorithm.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1083,40 +1079,10 @@ OEMCryptoResult SessionContext::DecryptCENC(
LOGE("[DecryptCTR(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
const KeyControlBlock& control = current_content_key()->control();
if (control.control_bits() & kControlDataPathSecure) {
if (!ce_->config_closed_platform() &&
buffer_type == OEMCrypto_BufferType_Clear) {
LOGE("[DecryptCTR(): Secure key with insecure buffer]");
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[DecryptCTR(): KEY_EXPIRED]");
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if (control.control_bits() & kControlReplayMask) {
if (!IsUsageEntryValid()) {
LOGE("[DecryptCTR(): usage entry not valid]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
if (!ce_->config_local_display_only()) {
// Only look at HDCP if the display is non-local.
if (control.control_bits() & kControlHDCPRequired) {
uint8_t required_hdcp =
(control.control_bits() & kControlHDCPVersionMask) >>
kControlHDCPVersionShift;
// For reference implementation, we pretend we can handle the current
// HDCP version.
if (required_hdcp > ce_->config_current_hdcp_capability() ||
ce_->config_current_hdcp_capability() == 0) {
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
}
}
}
OEMCryptoResult result = AllowKeyUse("DecryptCENC", 0, buffer_type);
if (result != OEMCrypto_SUCCESS) return result;
const std::vector<uint8_t>& content_key = current_content_key()->value();
// Set the AES key.

View File

@@ -212,7 +212,8 @@ class SessionContext {
OEMCryptoResult DecryptCTR(const uint8_t* key_u8, const uint8_t* iv,
size_t block_offset, const uint8_t* cipher_data,
size_t cipher_data_length, uint8_t* clear_data);
OEMCryptoResult AllowKeyUse(const std::string& log_string, uint32_t use_type,
OEMCryptoBufferType buffer_type);
RSA* rsa_key() { return rsa_key_.get(); }
bool valid_;

View File

@@ -59,6 +59,13 @@ KeyControlBlock::KeyControlBlock(
LOGD(" nonce: %08X", nonce());
LOGD(" magic: %08X", verification());
LOGD(" bits: %08X", control_bits());
LOGD(" bit kControlSRMVersionRequired %s.",
(control_bits() & kControlSRMVersionRequired) ? "set" : "unset");
LOGD(" bit kControlDisableAnalogOutput %s.",
(control_bits() & kControlDisableAnalogOutput) ? "set" : "unset");
LOGD(" bits kControlSecurityPatchLevel 0x%02x.",
(control_bits() & kControlSecurityPatchLevelMask)
>> kControlSecurityPatchLevelShift);
switch (control_bits() & kControlReplayMask) {
case kControlNonceRequired:
LOGD(" bits kControlReplay kControlNonceRequired.");
@@ -70,12 +77,9 @@ KeyControlBlock::KeyControlBlock(
LOGD(" bits kControlReplay unset.");
break;
}
LOGD(" bits kControlKDCPVersion 0x%02x.",
LOGD(" bits kControlHDCPVersion 0x%02x.",
(control_bits() & kControlHDCPVersionMask)
>> kControlHDCPVersionShift);
LOGD(" bits kControlSecurityPatchLevel 0x%02x.",
(control_bits() & kControlSecurityPatchLevelMask)
>> kControlSecurityPatchLevelShift);
LOGD(" bit kControlAllowEncrypt %s.",
(control_bits() & kControlAllowEncrypt) ? "set" : "unset");
LOGD(" bit kControlAllowDecrypt %s.",

View File

@@ -15,6 +15,8 @@ const uint32_t kControlObserveDataPath = (1<<31);
const uint32_t kControlObserveHDCP = (1<<30);
const uint32_t kControlObserveCGMS = (1<<29);
const uint32_t kControlRequireAntiRollbackHardware = (1<<28);
const uint32_t kControlSRMVersionRequired = (1<<22);
const uint32_t kControlDisableAnalogOutput = (1<<21);
const uint32_t kControlSecurityPatchLevelShift = 15;
const uint32_t kControlSecurityPatchLevelMask =
(0x3F<<kControlSecurityPatchLevelShift);

View File

@@ -123,6 +123,7 @@ std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
if (api_version < 10) FilterOut(&filter, "*API10*");
if (api_version < 11) FilterOut(&filter, "*API11*");
if (api_version < 12) FilterOut(&filter, "*API12*");
if (api_version < 13) FilterOut(&filter, "*API13*");
// Performance tests take a long time. Filter them out if they are not
// specifically requested.
if (filter.find("Performance") == std::string::npos) {

View File

@@ -309,8 +309,11 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
sizeof(license_.keys[i].key_iv)));
EXPECT_EQ(1, RAND_pseudo_bytes(license_.keys[i].control_iv,
sizeof(license_.keys[i].control_iv)));
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
if (global_features.api_version == 12) {
if (global_features.api_version == 13) {
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
memcpy(license_.keys[i].control.verification, "kc13", 4);
} else if (global_features.api_version == 12) {
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
memcpy(license_.keys[i].control.verification, "kc12", 4);
} else if (control & wvoec_mock::kControlSecurityPatchLevelMask) {
// For versions before 12, we require the special key control block only
@@ -338,7 +341,10 @@ void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
encrypted_license().keys[i].key_id_length = license_.keys[i].key_id_length;
memcpy(encrypted_license().keys[i].key_id, license_.keys[i].key_id,
encrypted_license().keys[i].key_id_length);
if (global_features.api_version == 12) {
if (global_features.api_version == 13) {
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
memcpy(encrypted_license().keys[i].control.verification, "kc13", 4);
} else if (global_features.api_version == 12) {
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
memcpy(encrypted_license().keys[i].control.verification, "kc12", 4);
} else {
@@ -538,6 +544,10 @@ void Session::TestDecryptCTR(bool select_key_first,
// Report HDCP errors.
ASSERT_EQ(OEMCrypto_ERROR_INSUFFICIENT_HDCP, sts);
ASSERT_NE(unencryptedData, outputBuffer);
} else if (expected_result == OEMCrypto_ERROR_ANALOG_OUTPUT) {
// Report analog errors.
ASSERT_EQ(OEMCrypto_ERROR_ANALOG_OUTPUT, sts);
ASSERT_NE(unencryptedData, outputBuffer);
} else {
// OEM's can fine tune other error codes for debugging.
ASSERT_NE(OEMCrypto_SUCCESS, sts);

View File

@@ -131,6 +131,24 @@ TEST_F(OEMCryptoClientTest, CheckHDCPCapability) {
HDCPCapabilityAsString(maximum));
}
TEST_F(OEMCryptoClientTest, CheckSRMCapabilityV13) {
// This just tests some trivial functionality of the SRM update functions.
bool supported = OEMCrypto_IsSRMUpdateSupported();
printf(" Update SRM Supported: %s.\n",
supported ? "true" : "false");
uint16_t version = 0;
OEMCryptoResult current_result = OEMCrypto_GetCurrentSRMVersion(&version);
if (current_result == OEMCrypto_SUCCESS) {
printf(" Current SRM Version: %d.\n", version);
EXPECT_NE(OEMCrypto_SUCCESS, OEMCrypto_GetCurrentSRMVersion(NULL));
} else {
EXPECT_EQ(OEMCrypto_ERROR_NOT_IMPLEMENTED, current_result);
}
vector<uint8_t> bad_srm(42);
RAND_pseudo_bytes(&bad_srm[0], bad_srm.size());
EXPECT_NE(OEMCrypto_SUCCESS, OEMCrypto_LoadSRM(&bad_srm[0], bad_srm.size()));
}
TEST_F(OEMCryptoClientTest, CheckMaxNumberOfSessionsAPI10) {
size_t sessions_count;
ASSERT_EQ(OEMCrypto_SUCCESS,
@@ -1153,7 +1171,8 @@ TEST_P(SessionTestAlternateVerification, LoadKeys) {
ASSERT_NE(OEMCrypto_SUCCESS, sts);
} else {
// Otherwise, LoadKeys should succeed.
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(OEMCrypto_SUCCESS, sts)
<< "LoadKeys failed for key control block kc" << target_api_;
}
}
@@ -1161,7 +1180,7 @@ TEST_P(SessionTestAlternateVerification, LoadKeys) {
// the current API + 2. We use +2 because we want to test at least 1
// future API, and the ::testing::Range is not inclusive.
INSTANTIATE_TEST_CASE_P(TestAll, SessionTestAlternateVerification,
Range(8, 12 + 2));
Range(8, 13 + 2));
TEST_F(OEMCryptoSessionTests, LoadKeysBadSignature) {
Session s;
@@ -2104,6 +2123,18 @@ TEST_F(OEMCryptoSessionTests, DecryptSecureToClear) {
s.TestDecryptCTR(true, OEMCrypto_ERROR_UNKNOWN_FAILURE));
}
TEST_F(OEMCryptoSessionTests, DecryptNoAnalogToClear) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(
kDuration, wvoec_mock::kControlDisableAnalogOutput, 0));
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
ASSERT_NO_FATAL_FAILURE(
s.TestDecryptCTR(true, OEMCrypto_ERROR_ANALOG_OUTPUT));
}
TEST_F(OEMCryptoSessionTests, KeyDuration) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());