Remove OEMCrypto_InitializeDecryptHash
Merge from Widevine repo of http://go/wvgerrit/68464 The Full Decrypt Path Testing design has changed to remove OEMCrypto_InitializeDecryptHash. This CL updates the unit tests and reference code. Bug: 120795057 Test: unit tests Change-Id: Iee28fa9034dc21cee81c5b894c192e260375eeee
This commit is contained in:
committed by
Srujan Gaddam
parent
f42038d89a
commit
9c95e4caae
@@ -807,7 +807,6 @@ class Adapter {
|
|||||||
LOOKUP( 9, 12, UpdateUsageTable, OEMCrypto_UpdateUsageTable);
|
LOOKUP( 9, 12, UpdateUsageTable, OEMCrypto_UpdateUsageTable);
|
||||||
LOOKUP_ALL( 8, WrapKeybox, OEMCrypto_WrapKeybox);
|
LOOKUP_ALL( 8, WrapKeybox, OEMCrypto_WrapKeybox);
|
||||||
LOOKUP_ALL(15, SupportsDecryptHash, OEMCrypto_SupportsDecryptHash);
|
LOOKUP_ALL(15, SupportsDecryptHash, OEMCrypto_SupportsDecryptHash);
|
||||||
LOOKUP_ALL(15, InitializeDecryptHash, OEMCrypto_InitializeDecryptHash);
|
|
||||||
LOOKUP_ALL(15, SetDecryptHash, OEMCrypto_SetDecryptHash);
|
LOOKUP_ALL(15, SetDecryptHash, OEMCrypto_SetDecryptHash);
|
||||||
LOOKUP_ALL(15, GetHashErrorCode, OEMCrypto_GetHashErrorCode);
|
LOOKUP_ALL(15, GetHashErrorCode, OEMCrypto_GetHashErrorCode);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
@@ -2376,17 +2375,6 @@ extern "C" uint32_t OEMCrypto_SupportsDecryptHash(){
|
|||||||
return OEMCrypto_SupportsDecryptHash(kLevelDefault);
|
return OEMCrypto_SupportsDecryptHash(kLevelDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_InitializeDecryptHash(
|
|
||||||
OEMCrypto_SESSION session) {
|
|
||||||
if (!gAdapter.get()) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
||||||
LevelSession pair = gAdapter->GetSession(session);
|
|
||||||
if (!pair.fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
|
||||||
if (pair.fcn->InitializeDecryptHash == NULL) {
|
|
||||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
return pair.fcn->InitializeDecryptHash(pair.session);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_SetDecryptHash(OEMCrypto_SESSION session,
|
extern "C" OEMCryptoResult OEMCrypto_SetDecryptHash(OEMCrypto_SESSION session,
|
||||||
uint32_t frame_number,
|
uint32_t frame_number,
|
||||||
const uint8_t* hash,
|
const uint8_t* hash,
|
||||||
|
|||||||
@@ -535,7 +535,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_DecryptCENC(
|
|||||||
|
|
||||||
OEMCryptoResult result = session_ctx->DecryptCENC(
|
OEMCryptoResult result = session_ctx->DecryptCENC(
|
||||||
iv, block_offset, pattern, data_addr, data_length, is_encrypted,
|
iv, block_offset, pattern, data_addr, data_length, is_encrypted,
|
||||||
crypto_engine->destination(), out_buffer->type);
|
crypto_engine->destination(), out_buffer->type, subsample_flags);
|
||||||
if (result != OEMCrypto_SUCCESS) return result;
|
if (result != OEMCrypto_SUCCESS) return result;
|
||||||
return crypto_engine->PushDestination(out_buffer, subsample_flags);
|
return crypto_engine->PushDestination(out_buffer, subsample_flags);
|
||||||
}
|
}
|
||||||
@@ -1621,20 +1621,6 @@ OEMCRYPTO_API uint32_t OEMCrypto_SupportsDecryptHash() {
|
|||||||
return OEMCrypto_CRC_Clear_Buffer;
|
return OEMCrypto_CRC_Clear_Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_InitializeDecryptHash(
|
|
||||||
OEMCrypto_SESSION session) {
|
|
||||||
if (!crypto_engine) {
|
|
||||||
LOGE("OEMCrypto_InitializeDecryptHash: OEMCrypto Not Initialized.");
|
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
|
||||||
}
|
|
||||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
|
||||||
if (!session_ctx || !session_ctx->isValid()) {
|
|
||||||
LOGE("[OEMCrypto_InitializeDecryptHash(): ERROR_INVALID_SESSION]");
|
|
||||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
||||||
}
|
|
||||||
return session_ctx->InitializeDecryptHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_SetDecryptHash(
|
OEMCRYPTO_API OEMCryptoResult OEMCrypto_SetDecryptHash(
|
||||||
OEMCrypto_SESSION session, uint32_t frame_number, const uint8_t* hash,
|
OEMCrypto_SESSION session, uint32_t frame_number, const uint8_t* hash,
|
||||||
size_t hash_length) {
|
size_t hash_length) {
|
||||||
|
|||||||
@@ -1168,7 +1168,6 @@ OEMCryptoResult SessionContext::SelectContentKey(
|
|||||||
LOGE("No key matches key id");
|
LOGE("No key matches key id");
|
||||||
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||||
}
|
}
|
||||||
compute_hash_ = false;
|
|
||||||
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
|
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
|
||||||
current_content_key_ = content_key;
|
current_content_key_ = content_key;
|
||||||
const KeyControlBlock& control = current_content_key()->control();
|
const KeyControlBlock& control = current_content_key()->control();
|
||||||
@@ -1285,7 +1284,7 @@ OEMCryptoResult SessionContext::DecryptCENC(
|
|||||||
const uint8_t* iv, size_t block_offset,
|
const uint8_t* iv, size_t block_offset,
|
||||||
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
||||||
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
||||||
OEMCryptoBufferType buffer_type) {
|
OEMCryptoBufferType buffer_type, uint8_t subsample_flags) {
|
||||||
OEMCryptoResult result =
|
OEMCryptoResult result =
|
||||||
ChooseDecrypt(iv, block_offset, pattern, cipher_data, cipher_data_length,
|
ChooseDecrypt(iv, block_offset, pattern, cipher_data, cipher_data_length,
|
||||||
is_encrypted, clear_data, buffer_type);
|
is_encrypted, clear_data, buffer_type);
|
||||||
@@ -1293,13 +1292,30 @@ OEMCryptoResult SessionContext::DecryptCENC(
|
|||||||
if (current_content_key() == NULL ||
|
if (current_content_key() == NULL ||
|
||||||
(current_content_key()->control().control_bits() &
|
(current_content_key()->control().control_bits() &
|
||||||
wvoec::kControlAllowHashVerification) == 0) {
|
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]");
|
LOGE("[DecryptCENC(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
hash_error_ = OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
compute_hash_ = false;
|
||||||
|
current_hash_ = 0;
|
||||||
|
current_frame_number_ = 0;
|
||||||
|
} else {
|
||||||
|
if (OEMCrypto_FirstSubsample & subsample_flags) {
|
||||||
|
current_hash_ = wvcrc32Init();
|
||||||
|
}
|
||||||
|
current_hash_ =
|
||||||
|
wvcrc32Cont(clear_data, cipher_data_length, current_hash_);
|
||||||
|
if (OEMCrypto_LastSubsample & subsample_flags) {
|
||||||
|
if (current_hash_ != given_hash_) {
|
||||||
|
LOGE("CRC for frame %d is %08x, should be %08x\n",
|
||||||
|
current_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_ = current_frame_number_;
|
||||||
|
hash_error_ = OEMCrypto_ERROR_BAD_HASH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compute_hash_ = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
current_hash_ = wvcrc32Cont(clear_data, cipher_data_length, current_hash_);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1526,36 +1542,9 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
|
|||||||
return OEMCrypto_SUCCESS;
|
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,
|
OEMCryptoResult SessionContext::SetDecryptHash(uint32_t frame_number,
|
||||||
const uint8_t* hash,
|
const uint8_t* hash,
|
||||||
size_t hash_length) {
|
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)) {
|
if (hash_length < sizeof(uint32_t)) {
|
||||||
LOGE("[SetDecryptHash(): short buffer]");
|
LOGE("[SetDecryptHash(): short buffer]");
|
||||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||||
@@ -1564,15 +1553,9 @@ OEMCryptoResult SessionContext::SetDecryptHash(uint32_t frame_number,
|
|||||||
LOGE("[SetDecryptHash(): long buffer]");
|
LOGE("[SetDecryptHash(): long buffer]");
|
||||||
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
|
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
|
||||||
}
|
}
|
||||||
uint32_t given_hash = *reinterpret_cast<const uint32_t*>(hash);
|
compute_hash_ = true;
|
||||||
if (current_hash_ != given_hash) {
|
current_frame_number_ = frame_number;
|
||||||
LOGE("CRC for frame %d is %08x, should be %08x\n", frame_number,
|
given_hash_ = *reinterpret_cast<const uint32_t*>(hash);
|
||||||
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;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ class SessionContext {
|
|||||||
const uint8_t* cipher_data,
|
const uint8_t* cipher_data,
|
||||||
size_t cipher_data_length, bool is_encrypted,
|
size_t cipher_data_length, bool is_encrypted,
|
||||||
uint8_t* clear_data,
|
uint8_t* clear_data,
|
||||||
OEMCryptoBufferType buffer_type);
|
OEMCryptoBufferType buffer_type,
|
||||||
|
uint8_t subsample_flags);
|
||||||
|
|
||||||
OEMCryptoResult Generic_Encrypt(const uint8_t* in_buffer,
|
OEMCryptoResult Generic_Encrypt(const uint8_t* in_buffer,
|
||||||
size_t buffer_length, const uint8_t* iv,
|
size_t buffer_length, const uint8_t* iv,
|
||||||
@@ -152,7 +153,6 @@ class SessionContext {
|
|||||||
virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
|
virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
|
||||||
virtual OEMCryptoResult SelectContentKey(const KeyId& key_id,
|
virtual OEMCryptoResult SelectContentKey(const KeyId& key_id,
|
||||||
OEMCryptoCipherMode cipher_mode);
|
OEMCryptoCipherMode cipher_mode);
|
||||||
virtual OEMCryptoResult InitializeDecryptHash();
|
|
||||||
virtual OEMCryptoResult SetDecryptHash(uint32_t frame_number,
|
virtual OEMCryptoResult SetDecryptHash(uint32_t frame_number,
|
||||||
const uint8_t* hash,
|
const uint8_t* hash,
|
||||||
size_t hash_length);
|
size_t hash_length);
|
||||||
@@ -258,7 +258,9 @@ class SessionContext {
|
|||||||
// These are used when doing full decrypt path testing.
|
// These are used when doing full decrypt path testing.
|
||||||
bool compute_hash_; // True if the current frame needs a hash.
|
bool compute_hash_; // True if the current frame needs a hash.
|
||||||
uint32_t current_hash_; // Running CRC hash of frame.
|
uint32_t current_hash_; // Running CRC hash of frame.
|
||||||
uint32_t bad_frame_number_; // Frame number with bad hash.
|
uint32_t given_hash_; // True CRC hash of frame.
|
||||||
|
uint32_t current_frame_number_; // Current frame for CRC hash.
|
||||||
|
uint32_t bad_frame_number_; // Frame number with bad hash.
|
||||||
OEMCryptoResult hash_error_; // Error code for first bad frame.
|
OEMCryptoResult hash_error_; // Error code for first bad frame.
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);
|
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);
|
||||||
|
|||||||
@@ -1721,21 +1721,27 @@ INSTANTIATE_TEST_CASE_P(TestRefreshEachKeys, SessionTestRefreshKeyTest,
|
|||||||
|
|
||||||
// If the license does not allow a hash, then we should not compute one.
|
// If the license does not allow a hash, then we should not compute one.
|
||||||
TEST_F(OEMCryptoSessionTests, HashForbiddenAPI15) {
|
TEST_F(OEMCryptoSessionTests, HashForbiddenAPI15) {
|
||||||
|
uint32_t hash_type = OEMCrypto_SupportsDecryptHash();
|
||||||
|
// If hash is not supported, or is vendor defined, don't try to test it.
|
||||||
|
if (hash_type != OEMCrypto_CRC_Clear_Buffer) return;
|
||||||
Session s;
|
Session s;
|
||||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(kDuration, 0, 0));
|
ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(kDuration, 0, 0));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
||||||
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
|
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
|
||||||
// Either failure, or not supported is allowed.
|
uint32_t frame_number = 1;
|
||||||
ASSERT_NE(OEMCrypto_SUCCESS, OEMCrypto_InitializeDecryptHash(s.session_id()));
|
uint32_t hash = 42;
|
||||||
ASSERT_EQ(
|
// It is OK to set the hash before loading the keys
|
||||||
OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_SelectKey(s.session_id(), s.license().keys[0].key_id,
|
OEMCrypto_SetDecryptHash(s.session_id(), frame_number,
|
||||||
s.license().keys[0].key_id_length,
|
reinterpret_cast<const uint8_t*>(&hash),
|
||||||
OEMCrypto_CipherMode_CTR));
|
sizeof(hash)));
|
||||||
// Still not allowed.
|
// It is OK to select the key and decrypt.
|
||||||
ASSERT_NE(OEMCrypto_SUCCESS, OEMCrypto_InitializeDecryptHash(s.session_id()));
|
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
|
||||||
|
// But the error code should be bad.
|
||||||
|
ASSERT_EQ(OEMCrypto_ERROR_UNKNOWN_FAILURE,
|
||||||
|
OEMCrypto_GetHashErrorCode(s.session_id(), &frame_number));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -1944,14 +1950,18 @@ class OEMCryptoSessionTestsDecryptTests
|
|||||||
s.license().keys[0].cipher_mode = cipher_mode_;
|
s.license().keys[0].cipher_mode = cipher_mode_;
|
||||||
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
||||||
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
|
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
|
||||||
|
if (global_features.supports_crc) {
|
||||||
|
uint32_t hash =
|
||||||
|
wvcrc32(unencryptedData.data(), unencryptedData.size());
|
||||||
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
|
OEMCrypto_SetDecryptHash(
|
||||||
|
s.session_id(), 1, reinterpret_cast<const uint8_t*>(&hash),
|
||||||
|
sizeof(hash)));
|
||||||
|
}
|
||||||
sts = OEMCrypto_SelectKey(s.session_id(), s.license().keys[0].key_id,
|
sts = OEMCrypto_SelectKey(s.session_id(), s.license().keys[0].key_id,
|
||||||
s.license().keys[0].key_id_length,
|
s.license().keys[0].key_id_length,
|
||||||
cipher_mode_);
|
cipher_mode_);
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||||
if (global_features.supports_crc) {
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
|
||||||
OEMCrypto_InitializeDecryptHash(s.session_id()));
|
|
||||||
}
|
|
||||||
// We decrypt each subsample.
|
// We decrypt each subsample.
|
||||||
vector<uint8_t> output_buffer(total_size_ + 16, 0xaa);
|
vector<uint8_t> output_buffer(total_size_ + 16, 0xaa);
|
||||||
const uint8_t *input_buffer = NULL;
|
const uint8_t *input_buffer = NULL;
|
||||||
@@ -2021,12 +2031,6 @@ class OEMCryptoSessionTestsDecryptTests
|
|||||||
output_buffer.resize(total_size_);
|
output_buffer.resize(total_size_);
|
||||||
EXPECT_EQ(unencryptedData, output_buffer);
|
EXPECT_EQ(unencryptedData, output_buffer);
|
||||||
if (global_features.supports_crc) {
|
if (global_features.supports_crc) {
|
||||||
uint32_t hash =
|
|
||||||
wvoec::wvcrc32(unencryptedData.data(), unencryptedData.size());
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
|
||||||
OEMCrypto_SetDecryptHash(
|
|
||||||
s.session_id(), 1, reinterpret_cast<const uint8_t*>(&hash),
|
|
||||||
sizeof(hash)));
|
|
||||||
uint32_t frame;
|
uint32_t frame;
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_GetHashErrorCode(s.session_id(), &frame));
|
OEMCrypto_GetHashErrorCode(s.session_id(), &frame));
|
||||||
|
|||||||
Reference in New Issue
Block a user