Unit Tests for Security Patch Level

Merge of widevine change http://go/wvgerrit/16249

This CL adds unit tests and reference code for the security patch
level, which is a new feature in OEMCrypto v11.  This CL also adjusts
the dynamic and static adapters to still run with devices that have a
v10 OEMCrypto.

The level 3 haystack code will be updated in a future CL.

bug: 26188985

Change-Id: I518ef46b4098cf3718fe0c0390bfb6825db4fb6b
This commit is contained in:
Fred Gylys-Colwell
2015-12-16 13:27:36 -08:00
parent 17faabee44
commit ce6d392041
13 changed files with 134 additions and 36 deletions

View File

@@ -50,4 +50,10 @@ const char* CryptoEngine::security_level() {
return "L3";
}
// This should start at 0, and be incremented only when a security patch has
// been applied to the device that fixes a security bug.
uint8_t CryptoEngine::security_patch_level() {
return 0;
}
} // namespace wvoec_mock

View File

@@ -51,4 +51,10 @@ const char* CryptoEngine::security_level() {
return "L1";
}
// This should start at 0, and be incremented only when a security patch has
// been applied to the device that fixes a security bug.
uint8_t CryptoEngine::security_patch_level() {
return 3;
}
} // namespace wvoec_mock

View File

@@ -53,4 +53,10 @@ const char* CryptoEngine::security_level() {
return "L2";
}
// This should start at 0, and be incremented only when a security patch has
// been applied to the device that fixes a security bug.
uint8_t CryptoEngine::security_patch_level() {
return 0;
}
} // namespace wvoec_mock

View File

@@ -683,6 +683,14 @@ bool SessionContext::InstallKey(const KeyId& key_id,
LOGE("Anti-rollback hardware is required but hardware not present.");
return false;
}
uint8_t minimum_patch_level
= (key_control_block.control_bits() & kControlSecurityPatchLevelMask) >>
kControlSecurityPatchLevelShift;
if (minimum_patch_level > OEMCrypto_Security_Patch_Level()) {
LOGE("[InstallKey(): security patch level: %d. Minimum:%d]",
OEMCrypto_Security_Patch_Level(), minimum_patch_level);
return false;
}
if (!CheckNonceOrEntry(key_control_block, pst)) {
LOGE("Failed Nonce/PST check.");

View File

@@ -259,6 +259,7 @@ class CryptoEngine {
bool supports_keybox();
bool is_anti_rollback_hw_present();
const char* security_level();
uint8_t security_patch_level();
private:
bool LoadPkcs8RsaKey(const uint8_t* buffer, size_t length);

View File

@@ -17,7 +17,8 @@ namespace wvoec_mock {
bool KeyControlBlock::Validate() {
if (memcmp(verification_, "kctl", 4) && // original verification
memcmp(verification_, "kc09", 4) && // add in version 9 api
memcmp(verification_, "kc10", 4)) { // add in version 10 api
memcmp(verification_, "kc10", 4) && // add in version 10 api
memcmp(verification_, "kc11", 4)) { // add in version 11 api
LOGE("KCB: BAD verification string: %4.4s", verification_);
valid_ = false;
} else {
@@ -71,6 +72,9 @@ KeyControlBlock::KeyControlBlock(
LOGD(" bits kControlKDCPVersion 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,9 @@ 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 kControlSecurityPatchLevelShift = 15;
const uint32_t kControlSecurityPatchLevelMask =
(0x3F<<kControlSecurityPatchLevelShift);
const uint32_t kControlReplayMask = (0x03<<13);
const uint32_t kControlNonceRequired = (0x01<<13);
const uint32_t kControlNonceOrEntry = (0x02<<13);

View File

@@ -327,6 +327,8 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE);
dump_array_part("key_array", i, "key_control",
key_array[i].key_control, wvcdm::KEY_IV_SIZE);
LOGV("key_array[%zu].cipher_mode=%s;\n", i,
key_array[i].cipher_mode == OEMCrypto_CipherMode_CTR ? "CTR" : "CBC");
}
}
}
@@ -380,6 +382,10 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT -range check %d]", i);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (key_array[i].cipher_mode != OEMCrypto_CipherMode_CTR) {
LOGE("[OEMCrypto_LoadKeys(): CBC Mode not yet implemented]");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
}
return session_ctx->LoadKeys(message, message_length, signature,
@@ -603,7 +609,7 @@ OEMCryptoResult OEMCrypto_DecryptCENC(OEMCrypto_SESSION session,
const uint8_t* iv,
size_t block_offset,
OEMCrypto_DestBufferDesc* out_buffer,
const OEMCrypto_PatternDesc* pattern,
const OEMCrypto_CENCEncryptPatternDesc* pattern,
uint8_t subsample_flags) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_DecryptCTR"
@@ -1214,14 +1220,19 @@ uint32_t OEMCrypto_APIVersion() {
extern "C"
uint8_t OEMCrypto_Security_Patch_Level() {
return 0;
uint8_t security_patch_level = crypto_engine->security_patch_level();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- uint8_t OEMCrypto_Security_Patch_Level(); // returns %d.\n",
security_patch_level);
}
return security_patch_level;
}
extern "C"
const char* OEMCrypto_SecurityLevel() {
const char* security_level = crypto_engine->security_level();
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- bool OEMCrypto_SecurityLevel(); // returns %s.\n", security_level);
LOGI("-- const char* OEMCrypto_SecurityLevel(); // returns %s.\n", security_level);
}
return security_level;
}