Full decrypt path testing
Merge from master branch of Widevine repo of http://go/wvgerrit/66080 Merge from oemcrypto-v15 branch of Widevine repo of http://go/wvgerrit/64002 This CL updates OEMCrypto reference code and unit tests to support full decrypt path testing. Test: unit tests Test: tested as part of http://go/ag/5501993 Bug: 34078913 Change-Id: Ia67374599d6619698a336f41513068ad04294e7f
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include "oemcrypto_types.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wvcrc32.h"
|
||||
|
||||
static const int kPssSaltLength = 20;
|
||||
|
||||
@@ -1167,6 +1168,7 @@ OEMCryptoResult SessionContext::SelectContentKey(
|
||||
LOGE("No key matches key id");
|
||||
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||
}
|
||||
compute_hash_ = false;
|
||||
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
|
||||
current_content_key_ = content_key;
|
||||
const KeyControlBlock& control = current_content_key()->control();
|
||||
@@ -1284,6 +1286,29 @@ OEMCryptoResult SessionContext::DecryptCENC(
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
||||
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
||||
OEMCryptoBufferType buffer_type) {
|
||||
OEMCryptoResult result =
|
||||
ChooseDecrypt(iv, block_offset, pattern, cipher_data, cipher_data_length,
|
||||
is_encrypted, clear_data, buffer_type);
|
||||
if (compute_hash_) {
|
||||
if (current_content_key() == NULL ||
|
||||
(current_content_key()->control().control_bits() &
|
||||
wvoec::kControlAllowHashVerification) == 0) {
|
||||
// This should not happen: this check should already have occured in
|
||||
// InitializeDecryptHash or the hash should have been discarded in
|
||||
// SelectContentKey. But it doesn't hurt to double check.
|
||||
LOGE("[DecryptCENC(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
current_hash_ = wvcrc32Cont(clear_data, cipher_data_length, current_hash_);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::ChooseDecrypt(
|
||||
const uint8_t* iv, size_t block_offset,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
||||
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
||||
OEMCryptoBufferType buffer_type) {
|
||||
// If the data is clear, we do not need a current key selected.
|
||||
if (!is_encrypted) {
|
||||
if (buffer_type != OEMCrypto_BufferType_Direct) {
|
||||
@@ -1501,4 +1526,62 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::InitializeDecryptHash() {
|
||||
// Check there is a content key, and it is allowed.
|
||||
if (current_content_key() == NULL ||
|
||||
(current_content_key()->control().control_bits() &
|
||||
wvoec::kControlAllowHashVerification) == 0) {
|
||||
LOGE("[InitializeDecryptHash(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||
compute_hash_ = false;
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
compute_hash_ = true;
|
||||
current_hash_ = wvcrc32Init();
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::SetDecryptHash(uint32_t frame_number,
|
||||
const uint8_t* hash,
|
||||
size_t hash_length) {
|
||||
// Check there is a content key, and it is allowed.
|
||||
if (current_content_key() == NULL ||
|
||||
(current_content_key()->control().control_bits() &
|
||||
wvoec::kControlAllowHashVerification) == 0) {
|
||||
LOGE("[SetDecryptHash(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!compute_hash_) {
|
||||
// This would happen if somebody computes the hash, and then changes keys.
|
||||
LOGE("[SetDecryptHash(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
compute_hash_ = false;
|
||||
if (hash_length < sizeof(uint32_t)) {
|
||||
LOGE("[SetDecryptHash(): short buffer]");
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
if (hash_length > sizeof(uint32_t)) {
|
||||
LOGE("[SetDecryptHash(): long buffer]");
|
||||
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
|
||||
}
|
||||
uint32_t given_hash = *reinterpret_cast<const uint32_t*>(hash);
|
||||
if (current_hash_ != given_hash) {
|
||||
LOGE("CRC for frame %d is %08x, should be %08x\n", frame_number,
|
||||
current_hash_, given_hash);
|
||||
// Update bad_frame_number_ only if this is the first bad frame.
|
||||
if (hash_error_ == OEMCrypto_SUCCESS) bad_frame_number_ = frame_number;
|
||||
hash_error_ = OEMCrypto_ERROR_BAD_HASH;
|
||||
}
|
||||
// Return success if the hash was compared, even if there was an error.
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SessionContext::GetHashErrorCode(
|
||||
uint32_t* failed_frame_number) {
|
||||
if (failed_frame_number == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (hash_error_ != OEMCrypto_SUCCESS)
|
||||
*failed_frame_number = bad_frame_number_;
|
||||
return hash_error_;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
Reference in New Issue
Block a user