Test Key Control Block with HDCP Version
This is a copy of the Widevine CL: https://widevine-internal-review.googlesource.com/#/c/9480/ This change is part of OEMCrypto API version 9. This CL adds verification that a key control block which requires a specific version of HDCP can be loaded. Also, if secure data path is not set, it verifies that data is still decrypted. This CL also adds test that verify DecryptCTR fails when the current HDCP version is below that in the key control block. The expected error is OEMCrypto_ERROR_INSUFFICIENT_HDCP. This error code is newly introduced in this CL. This is one attempt to clarify HDCP, as specified in b/13626021, and is a slight modification from previous behavior for the mock and the level 3 haystacked code. This CL also tests the two valid verification codes "kctl" and "kc09". bug: 13626021 Change-Id: If380709d2306a3489470b29fb148a45b609b089d
This commit is contained in:
@@ -317,7 +317,6 @@ bool SessionContext::GenerateRSASignature(const uint8_t* message,
|
||||
} else { // Bad RSA_Padding_Scheme
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -366,7 +365,22 @@ bool SessionContext::ParseKeyControl(
|
||||
LOGD(" valid: %d", key_control_block.valid());
|
||||
LOGD(" duration: %d", key_control_block.duration());
|
||||
LOGD(" nonce: %08X", key_control_block.nonce());
|
||||
LOGD(" magic: %08X", key_control_block.verification());
|
||||
LOGD(" bits: %08X", key_control_block.control_bits());
|
||||
switch(key_control_block.control_bits() & kControlReplayMask) {
|
||||
case kControlNonceRequired:
|
||||
LOGD(" bits kControlReplay kControlNonceRequired.");
|
||||
break;
|
||||
case kControlNonceOrEntry:
|
||||
LOGD(" bits kControlReplay kControlNonceOrEntry.");
|
||||
break;
|
||||
default:
|
||||
LOGD(" bits kControlReplay unset.");
|
||||
break;
|
||||
}
|
||||
LOGD(" bits kControlKDCPVersion 0x%02x.",
|
||||
(key_control_block.control_bits() & kControlHDCPVersionMask)
|
||||
>> kControlHDCPVersionShift);
|
||||
LOGD(" bit kControlAllowEncrypt %s.",
|
||||
(key_control_block.control_bits() & kControlAllowEncrypt) ? "set" : "unset");
|
||||
LOGD(" bit kControlAllowDecrypt %s.",
|
||||
@@ -870,6 +884,12 @@ CryptoEngine::CryptoEngine() :
|
||||
ce_state_(CE_INITIALIZED), current_session_(NULL) {
|
||||
valid_ = true;
|
||||
ERR_load_crypto_strings();
|
||||
// These are made up numbers, just for illustration.
|
||||
current_hdcp_capability_ = 0x1;
|
||||
maximum_hdcp_capability_ = 0x2;
|
||||
// If local_display_ is true, we pretend we are using a built-in display,
|
||||
// instead of HDMI or WiFi output.
|
||||
local_display_ = false;
|
||||
}
|
||||
|
||||
CryptoEngine::~CryptoEngine() {
|
||||
@@ -958,11 +978,20 @@ OEMCryptoResult CryptoEngine::DecryptCTR(SessionContext* session,
|
||||
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||
}
|
||||
}
|
||||
if (control.control_bits() & kControlHDCPRequired) {
|
||||
// For reference implementation, we do not implement any HDCP.
|
||||
LOGE("[DecryptCTR(): DECRYPT FAILED: HDCP Required]");
|
||||
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||
if (!local_display_) { // Only look at HDCP if the display is not 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 > current_hdcp_capability()
|
||||
|| current_hdcp_capability() == 0) {
|
||||
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (control.duration() > 0) {
|
||||
if (control.duration() < session->CurrentTimer()) {
|
||||
LOGE("[DecryptCTR(): KEY_EXPIRED]");
|
||||
|
||||
@@ -248,6 +248,14 @@ class CryptoEngine {
|
||||
size_t cipher_data_length, bool is_encrypted,
|
||||
uint8_t* clear_data, BufferType buffer_type);
|
||||
|
||||
const OEMCrypto_HDCP_Capability current_hdcp_capability() {
|
||||
return local_display_ ? 0xFF : current_hdcp_capability_;
|
||||
}
|
||||
|
||||
const OEMCrypto_HDCP_Capability maximum_hdcp_capability() {
|
||||
return maximum_hdcp_capability_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool valid_;
|
||||
@@ -256,6 +264,9 @@ class CryptoEngine {
|
||||
ActiveSessions sessions_;
|
||||
WvKeybox keybox_;
|
||||
wvcdm::Lock session_table_lock_;
|
||||
OEMCrypto_HDCP_Capability current_hdcp_capability_;
|
||||
OEMCrypto_HDCP_Capability maximum_hdcp_capability_;
|
||||
bool local_display_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
||||
};
|
||||
|
||||
@@ -17,9 +17,10 @@ namespace wvoec_mock {
|
||||
|
||||
bool KeyControlBlock::Validate() {
|
||||
valid_ = false;
|
||||
if (0x6b63746c != verification_) { // kctl.
|
||||
LOGE("KCB: BAD verification string: %08X (not %08X)", verification_,
|
||||
0x6b63746c);
|
||||
if ((0x6b63746c != verification_) && // kctl.
|
||||
(0x6b633039 != verification_)) { // kc09.
|
||||
LOGE("KCB: BAD verification string: %08X (not %08X or %08X)",
|
||||
verification_, 0x6b63746c, 0x6b633039);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ enum KeyType {
|
||||
const uint32_t kControlObserveDataPath = (1<<31);
|
||||
const uint32_t kControlObserveHDCP = (1<<30);
|
||||
const uint32_t kControlObserveCGMS = (1<<29);
|
||||
const uint32_t kControlReplayMask = (0x03<<13);
|
||||
const uint32_t kControlNonceRequired = (0x01<<13);
|
||||
const uint32_t kControlNonceOrEntry = (0x02<<13);
|
||||
const uint32_t kControlHDCPVersionShift = 9;
|
||||
const uint32_t kControlHDCPVersionMask = (0x0F<<kControlHDCPVersionShift);
|
||||
const uint32_t kControlAllowEncrypt = (1<<8);
|
||||
const uint32_t kControlAllowDecrypt = (1<<7);
|
||||
const uint32_t kControlAllowSign = (1<<6);
|
||||
@@ -55,6 +60,7 @@ class KeyControlBlock {
|
||||
uint32_t duration() const { return duration_; }
|
||||
void set_duration(uint32_t duration) { duration_ = duration; }
|
||||
uint32_t nonce() const { return nonce_; }
|
||||
uint32_t verification() const { return verification_; }
|
||||
uint32_t control_bits() const { return control_bits_; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -1021,8 +1021,8 @@ OEMCryptoResult OEMCrypto_GetHDCPCapability(OEMCrypto_HDCP_Capability *current,
|
||||
OEMCrypto_HDCP_Capability *maximum) {
|
||||
if (current == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (maximum == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
*current = 0;
|
||||
*maximum = 0;
|
||||
*current = crypto_engine->current_hdcp_capability();
|
||||
*maximum = crypto_engine->maximum_hdcp_capability();
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user