Merge "Unit Test for OEMCrypto_ERROR_KEY_EXPIRED"

This commit is contained in:
Fred Gylys-Colwell
2014-03-26 19:50:33 +00:00
committed by Android (Google) Code Review
4 changed files with 110 additions and 133 deletions

View File

@@ -570,194 +570,198 @@ bool SessionContext::LoadRSAKey(uint8_t* pkcs8_rsa_key,
}
}
bool SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
size_t buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer) {
OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
size_t buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer) {
// Check there is a content key
if (current_content_key() == NULL) {
LOGE("[Generic_Encrypt(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
return false;
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 false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowEncrypt)) {
LOGE("[Generic_Encrypt(): control bit says not allowed.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Encrypt(): key expired.");
return false;
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if( algorithm != OEMCrypto_AES_CBC_128_NO_PADDING ) {
LOGE("[Generic_Encrypt(): algorithm bad.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if( buffer_length % AES_BLOCK_SIZE != 0 ) {
LOGE("[Generic_Encrypt(): buffers size bad.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
const uint8_t* key_u8 = &key[0];
AES_KEY aes_key;
if (AES_set_encrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) {
LOGE("[Generic_Encrypt(): FAILURE]");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, iv, wvcdm::KEY_IV_SIZE);
AES_cbc_encrypt(in_buffer, out_buffer, buffer_length,
&aes_key, iv_buffer, AES_ENCRYPT);
return true;
return OEMCrypto_SUCCESS;
}
bool SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
size_t buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer) {
OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
size_t buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer) {
// Check there is a content key
if (current_content_key() == NULL) {
LOGE("[Generic_Decrypt(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
return false;
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 false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowDecrypt)) {
LOGE("[Generic_Decrypt(): control bit says not allowed.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.control_bits() & kControlDataPathSecure) {
LOGE("[Generic_Decrypt(): control bit says secure path only.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Decrypt(): key expired.");
return false;
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if( algorithm != OEMCrypto_AES_CBC_128_NO_PADDING ) {
LOGE("[Generic_Decrypt(): bad algorithm.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if( buffer_length % AES_BLOCK_SIZE != 0 ) {
LOGE("[Generic_Decrypt(): bad buffer size.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
const uint8_t* key_u8 = &key[0];
AES_KEY aes_key;
if (AES_set_decrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) {
LOGE("[Generic_Decrypt(): FAILURE]");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, iv, wvcdm::KEY_IV_SIZE);
AES_cbc_encrypt(in_buffer, out_buffer, buffer_length,
&aes_key, iv_buffer, AES_DECRYPT);
return true;
return OEMCrypto_SUCCESS;
}
bool SessionContext::Generic_Sign(const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
uint8_t* signature,
size_t* signature_length) {
OEMCryptoResult SessionContext::Generic_Sign(const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
uint8_t* signature,
size_t* signature_length) {
// Check there is a content key
if (current_content_key() == NULL) {
LOGE("[Generic_Sign(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
return false;
return OEMCrypto_ERROR_NO_CONTENT_KEY;
}
if (*signature_length < SHA256_DIGEST_LENGTH) {
*signature_length = SHA256_DIGEST_LENGTH;
LOGE("[Generic_Sign(): bad signature length.");
return false;
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 false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowSign)) {
LOGE("[Generic_Sign(): control bit says not allowed.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Sign(): key expired.");
return false;
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if( algorithm != OEMCrypto_HMAC_SHA256 ) {
LOGE("[Generic_Sign(): bad algorithm.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
unsigned int md_len = *signature_length;
if (HMAC(EVP_sha256(), &key[0], SHA256_DIGEST_LENGTH,
in_buffer, buffer_length, signature, &md_len)) {
*signature_length = md_len;
return true;
return OEMCrypto_SUCCESS;
}
LOGE("[Generic_Sign(): hmac failed.");
dump_openssl_error();
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
bool SessionContext::Generic_Verify(const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const uint8_t* signature,
size_t signature_length) {
OEMCryptoResult SessionContext::Generic_Verify(const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const uint8_t* signature,
size_t signature_length) {
// Check there is a content key
if (current_content_key() == NULL) {
LOGE("[Decrypt_Verify(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (signature_length < SHA256_DIGEST_LENGTH) {
return false;
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 false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!(control.control_bits() & kControlAllowVerify)) {
LOGE("[Generic_Verify(): control bit says not allowed.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.duration() > 0) {
if (control.duration() < CurrentTimer()) {
LOGE("[Generic_Verify(): key expired.");
return false;
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
if( algorithm != OEMCrypto_HMAC_SHA256 ) {
LOGE("[Generic_Verify(): bad algorithm.");
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
unsigned int md_len = signature_length;
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
if (HMAC(EVP_sha256(), &key[0], SHA256_DIGEST_LENGTH,
in_buffer, buffer_length, computed_signature, &md_len)) {
return (0 == memcmp( signature, computed_signature, SHA256_DIGEST_LENGTH));
if (0 == memcmp(signature, computed_signature, SHA256_DIGEST_LENGTH)) {
return OEMCrypto_SUCCESS;
} else {
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
}
}
LOGE("[Generic_Verify(): HMAC failed.");
dump_openssl_error();
return false;
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
bool SessionContext::RefreshKey(const KeyId& key_id,
@@ -928,41 +932,41 @@ bool CryptoEngine::DecryptMessage(SessionContext* session,
return true;
}
bool CryptoEngine::DecryptCTR(SessionContext* session,
const uint8_t* iv,
size_t block_offset,
const uint8_t* cipher_data,
size_t cipher_data_length,
bool is_encrypted,
uint8_t* clear_data,
BufferType buffer_type) {
OEMCryptoResult CryptoEngine::DecryptCTR(SessionContext* session,
const uint8_t* iv, size_t block_offset,
const uint8_t* cipher_data,
size_t cipher_data_length,
bool is_encrypted, uint8_t* clear_data,
BufferType buffer_type) {
// If the data is clear, we do not need a current key selected.
if (!is_encrypted && buffer_type != kBufferTypeDirect) {
memcpy(reinterpret_cast<uint8_t*>(clear_data),
cipher_data, cipher_data_length);
return true;
return OEMCrypto_SUCCESS;
}
// Check there is a content key
if (session->current_content_key() == NULL) {
LOGE("[DecryptCTR(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
return false;
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
const KeyControlBlock& control = session->current_content_key()->control();
if (control.control_bits() & kControlDataPathSecure) {
if (buffer_type == kBufferTypeClear) {
LOGE("[DecryptCTR(): Secure key with insecure buffer]");
return false;
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
}
if (control.control_bits() & kControlHDCPRequired) {
// For reference implementation, we do not implement any HDCP.
return false;
LOGE("[DecryptCTR(): DECRYPT FAILED: HDCP Required]");
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
if (control.duration() > 0) {
if (control.duration() < session->CurrentTimer()) {
return false;
LOGE("[DecryptCTR(): KEY_EXPIRED]");
return OEMCrypto_ERROR_KEY_EXPIRED;
}
}
@@ -971,23 +975,23 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
// Set the AES key.
if (static_cast<int>(content_key.size()) != AES_BLOCK_SIZE) {
LOGE("[DecryptCTR(): CONTENT_KEY has wrong size: %d", content_key.size());
return false;
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
const uint8_t* key_u8 = &content_key[0];
AES_KEY aes_key;
if (AES_set_encrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) {
LOGE("[DecryptCTR(): FAILURE]");
return false;
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
if (buffer_type == kBufferTypeDirect) {
// For reference implementation, we quietly drop direct video.
return true;
return OEMCrypto_SUCCESS;
}
if (buffer_type == kBufferTypeSecure) {
// For reference implementation, we also quietly drop secure data.
return true;
return OEMCrypto_SUCCESS;
}
// Local copy (will be modified).
@@ -1011,7 +1015,7 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
ctr128_inc64(aes_iv);
block_offset = 0;
}
return true;
return OEMCrypto_SUCCESS;
}
void NonceTable::AddNonce(uint32_t nonce) {

View File

@@ -116,26 +116,21 @@ class SessionContext {
size_t message_length,
const uint8_t* signature,
size_t signature_length);
bool Generic_Encrypt(const uint8_t* in_buffer,
size_t buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer);
bool Generic_Decrypt(const uint8_t* in_buffer,
size_t buffer_length,
const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer);
bool Generic_Sign(const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
uint8_t* signature,
size_t* signature_length);
bool Generic_Verify(const uint8_t* in_buffer,
size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const uint8_t* signature,
size_t signature_length);
OEMCryptoResult Generic_Encrypt(const uint8_t* in_buffer,
size_t buffer_length, const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer);
OEMCryptoResult Generic_Decrypt(const uint8_t* in_buffer,
size_t buffer_length, const uint8_t* iv,
OEMCrypto_Algorithm algorithm,
uint8_t* out_buffer);
OEMCryptoResult Generic_Sign(const uint8_t* in_buffer, size_t buffer_length,
OEMCrypto_Algorithm algorithm,
uint8_t* signature, size_t* signature_length);
OEMCryptoResult Generic_Verify(const uint8_t* in_buffer, size_t buffer_length,
OEMCrypto_Algorithm algorithm,
const uint8_t* signature,
size_t signature_length);
void StartTimer();
uint32_t CurrentTimer(); // (seconds).
bool InstallKey(const KeyId& key_id,
@@ -248,14 +243,10 @@ class CryptoEngine {
const std::vector<uint8_t>& message,
std::vector<uint8_t>* decrypted);
bool DecryptCTR(SessionContext* session,
const uint8_t* iv,
size_t block_offset,
const uint8_t* cipher_data,
size_t cipher_data_length,
bool is_encrypted,
uint8_t* clear_data,
BufferType buffer_type);
OEMCryptoResult DecryptCTR(SessionContext* session, const uint8_t* iv,
size_t block_offset, const uint8_t* cipher_data,
size_t cipher_data_length, bool is_encrypted,
uint8_t* clear_data, BufferType buffer_type);
private:

View File

@@ -582,14 +582,9 @@ OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session,
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (!crypto_engine->DecryptCTR(session_ctx, iv, block_offset,
data_addr, data_length, is_encrypted,
destination, buffer_type)) {
LOGE("[OEMCrypto_DecryptCTR(): OEMCrypto_ERROR_DECRYPT_FAILED]");
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
return OEMCrypto_SUCCESS;
return crypto_engine->DecryptCTR(session_ctx, iv, block_offset, data_addr,
data_length, is_encrypted, destination,
buffer_type);
}
extern "C"
@@ -1053,12 +1048,8 @@ OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session,
LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (!session_ctx->Generic_Encrypt(in_buffer, buffer_length, iv, algorithm,
out_buffer)) {
LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
return OEMCrypto_SUCCESS;
return session_ctx->Generic_Encrypt(in_buffer, buffer_length, iv, algorithm,
out_buffer);
}
extern "C"
@@ -1077,16 +1068,13 @@ OEMCryptoResult OEMCrypto_Generic_Decrypt(OEMCrypto_SESSION session,
LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_INVALID_SESSION]");
return OEMCrypto_ERROR_INVALID_SESSION;
}
if (!session_ctx->Generic_Decrypt(in_buffer, buffer_length, iv, algorithm,
out_buffer)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (in_buffer == NULL || buffer_length == 0 ||
iv == NULL || out_buffer == NULL) {
LOGE("[OEMCrypto_Generic_Decrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
return OEMCrypto_SUCCESS;
return session_ctx->Generic_Decrypt(in_buffer, buffer_length, iv, algorithm,
out_buffer);
}
extern "C"
@@ -1113,11 +1101,8 @@ OEMCryptoResult OEMCrypto_Generic_Sign(OEMCrypto_SESSION session,
LOGE("[OEMCrypto_Generic_Sign(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (!session_ctx->Generic_Sign(in_buffer, buffer_length, algorithm,
signature, signature_length)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
return OEMCrypto_SUCCESS;
return session_ctx->Generic_Sign(in_buffer, buffer_length, algorithm,
signature, signature_length);
}
extern "C"
@@ -1143,11 +1128,8 @@ OEMCryptoResult OEMCrypto_Generic_Verify(OEMCrypto_SESSION session,
LOGE("[OEMCrypto_Generic_Verify(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (!session_ctx->Generic_Verify(in_buffer, buffer_length, algorithm,
signature, signature_length)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
return OEMCrypto_SUCCESS;
return session_ctx->Generic_Verify(in_buffer, buffer_length, algorithm,
signature, signature_length);
}
extern "C"

View File

@@ -3014,7 +3014,7 @@ TEST_F(DISABLED_TestKeybox, KeyDuration) {
encryptedData.size(), true, &encryptionIv[0], 0,
&destBuffer,
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, sts);
ASSERT_NE(0, memcmp(&unencryptedData[0], outputBuffer,
unencryptedData.size()));
@@ -4975,7 +4975,7 @@ TEST_F(DISABLED_GenericDRMTest, KeyDurationEncrypt) {
memset(encrypted, 0, kBufferSize);
sts = OEMCrypto_Generic_Encrypt(s.session_id(), clear_buffer_, kBufferSize, iv_,
OEMCrypto_AES_CBC_128_NO_PADDING, encrypted);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, sts);
ASSERT_NE(0, memcmp(encrypted, expected_encrypted, kBufferSize));
s.close();
testTearDown();
@@ -5016,7 +5016,7 @@ TEST_F(DISABLED_GenericDRMTest, KeyDurationDecrypt) {
memset(resultant, 0, kBufferSize);
sts = OEMCrypto_Generic_Decrypt(s.session_id(), encrypted, kBufferSize, iv_,
OEMCrypto_AES_CBC_128_NO_PADDING, resultant);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, sts);
ASSERT_NE(0, memcmp(clear_buffer_, resultant, kBufferSize));
s.close();
testTearDown();
@@ -5063,7 +5063,7 @@ TEST_F(DISABLED_GenericDRMTest, KeyDurationSign) {
sts = OEMCrypto_Generic_Sign(s.session_id(), clear_buffer_, kBufferSize,
OEMCrypto_HMAC_SHA256,signature,
&signature_length);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, sts);
ASSERT_NE(0, memcmp(signature, expected_signature, SHA256_DIGEST_LENGTH));
s.close();
@@ -5104,7 +5104,7 @@ TEST_F(DISABLED_GenericDRMTest, KeyDurationVerify) {
sts = OEMCrypto_Generic_Verify(s.session_id(), clear_buffer_, kBufferSize,
OEMCrypto_HMAC_SHA256,signature,
SHA256_DIGEST_LENGTH);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, sts);
s.close();
testTearDown();