Sync Android reference with CDM reference.

The sc-dev branch on Android is out of sync with several important
changes on the CDM master branch.  This changes copies several CLs.

[ Merge of http://go/wvgerrit/104524 ]

OEMCrypto unittest: generic crypto APIs

Add unit tests to verify that generic crypto APIs do not crash for large
input buffer lengths and signature lengths.

[ Merge of http://go/wvgerrit/106583 ]

Fix secure buffer tests in OEMCrypto testbed

The secure buffers were not being used correctly in the testbed, and
were failing OEMCryptoMemoryCopyBufferForHugeBufferLengths.

[ Merge of http://go/wvgerrit/109603 ]

Reject block_offsets of 16 or greater in OEC Ref

This is a potential security hole. We will be enforcing that OEMCrypto
rejects this in an upcoming test, so the Ref must be updated to reject
it.

[ Merge of http://go/wvgerrit/110165 ]

Fix Format String Signedness

See above for full description.

[ Merge of http://go/wvgerrit/111784 ]

Fix heap overflow test in L3 and OEMCrypto ref

Check the length of wrapped_rsa_key_length before casting to
WrappedRSAKey struct.

[ Merge of http://go/wvgerrit/113563 ]

Reword "blacklisted" to "forbidden"

[ Merge of http://go/wvgerrit/113583 ]

Use error code from RAND_bytes

The return code from RAND_bytes was not used correctly.

[ Merge of http://go/wvgerrit/113644 ]

Check for buffer overflow when computing subsample size

The test DecryptCENCForNumBytesClearPlusEncryptedOverflowsSize
cleverly picks num_bytes_clear + num_bytes_encrypted = 1 after integer
overflow. This is in the refernce code, level 3, and odkitee.

[ Merge of http://go/wvgerrit/113683 ]

OEMCrypto reference code: respect analog flags for clear buffers

The reference code should honor the analog_display_active flag for
both clear and secure buffers.

[ Merge of http://go/wvgerrit/114883 ]

Add size check for IV in OEMCrypto APIs

IV is supposed to be 16 bytes but the size is never checked before iv
gets used in LoadProvisioning.

Bug: 145026457
Bug: 147569428
Bug: 159847851
Bug: 162372059
Bug: 169278035
Bug: 169980065
Bug: 173460694
Bug: 173994023
Bug: 174523584
Bug: 175001473
Bug: 175041667
Test: No compiled files changed
Change-Id: If0ccd1cd3a56f72eedd2a6cb202a34bc7b43ca0d
This commit is contained in:
Alex Dale
2021-02-19 17:16:32 -08:00
parent eb56801fdb
commit 23f7cd60a7
5 changed files with 167 additions and 110 deletions

View File

@@ -230,6 +230,13 @@ OEMCryptoResult CryptoEngine::SetDestination(
max_length = out_description.buffer.clear.address_length;
break;
case OEMCrypto_BufferType_Secure:
if (out_description.buffer.secure.handle_length <
out_description.buffer.secure.offset) {
LOGE("Secure buffer offset too large: %zu < %zu",
out_description.buffer.secure.handle_length,
out_description.buffer.secure.offset);
return OEMCrypto_ERROR_SHORT_BUFFER;
}
destination_ =
reinterpret_cast<uint8_t*>(out_description.buffer.secure.handle) +
out_description.buffer.secure.offset;

View File

@@ -171,12 +171,12 @@ class CryptoEngine {
// If 0 no restriction, otherwise it's the max subsample size for
// DecryptCENC. This is not the same as the max sample or buffer size.
virtual size_t max_subsample_size() { return 1024 * 100; } // 100 KiB
virtual size_t max_subsample_size() { return 4 * 1024 * 1024; } // 4 MiB
// If 0 no restriction, otherwise it's the max sample size for DecryptCENC.
// This is the same as the max input and output buffer size for DecryptCENC
// and CopyBuffer. It is not the same as the max subsample size.
virtual size_t max_sample_size() { return 1024 * 1024; } // 1 MiB
virtual size_t max_sample_size() { return 16 * 1024 * 1024; } // 16 MiB
virtual bool srm_update_supported() { return false; }
@@ -193,7 +193,7 @@ class CryptoEngine {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
virtual bool srm_blacklisted_device_attached() { return false; }
virtual bool srm_forbidden_device_attached() { return false; }
// Rate limit for nonce generation. Default to 200 nonce/second.
virtual int nonce_flood_count() { return 200; }

View File

@@ -32,9 +32,9 @@
#include "string_conversions.h"
#if defined(_WIN32)
# define OEMCRYPTO_API extern "C" __declspec(dllexport)
# define OEMCRYPTO_API extern "C" __declspec(dllexport)
#else // defined(_WIN32)
# define OEMCRYPTO_API extern "C" __attribute__((visibility("default")))
# define OEMCRYPTO_API extern "C" __attribute__((visibility("default")))
#endif // defined(_WIN32)
namespace {
@@ -42,6 +42,12 @@ const uint8_t kBakedInCertificateMagicBytes[] = {0xDE, 0xAD, 0xBE, 0xEF};
// Maximum context key length used for performance reasons, not mandated by
// specification.
const size_t kMaxContextKeyLength = 1024 * 1024;
// Maximum buffer length used by reference implementation for performance
// reasons. This is not mandated by specification.
const size_t kMaxInputMessageBuferLength = 1024 * 1024;
// Maximum signature length used by reference implementation for performance
// reasons. This is not mandated by specification.
const size_t kMaxInputSignatureLength = 10 * 1024;
// Return uint32 referenced through a potentially unaligned pointer.
// If the pointer is nullptr, return 0.
@@ -100,8 +106,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Terminate(void) {
return OEMCrypto_SUCCESS;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_OpenSession(
OEMCrypto_SESSION* session) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_OpenSession(OEMCrypto_SESSION* session) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_OpenSession: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -120,8 +126,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_OpenSession(
return OEMCrypto_SUCCESS;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_CloseSession(
OEMCrypto_SESSION session) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_CloseSession(OEMCrypto_SESSION session) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_CloseSession: OEMCrypto not initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -209,7 +215,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
while (nonce_value == 0 || crypto_engine->NonceCollision(nonce_value)) {
// Generate 4 bytes of random data
if (!RAND_bytes(nonce_string, 4)) {
if (RAND_bytes(nonce_string, 4) != 1) {
LOGE("[OEMCrypto_GenerateNonce(): Random bytes failure]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -309,7 +315,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadLicense(OEMCrypto_SESSION session,
}
SessionContext* session_ctx = crypto_engine->FindSession(session);
if (session_ctx == nullptr || !session_ctx->isValid()) {
LOGE("ERROR_INVALID_SESSION sid=%d", session);
LOGE("ERROR_INVALID_SESSION sid=%u", session);
return OEMCrypto_ERROR_INVALID_SESSION;
}
return session_ctx->LoadLicense(message, message_length, core_message_length,
@@ -333,7 +339,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadKeys(
}
SessionContext* session_ctx = crypto_engine->FindSession(session);
if (session_ctx == nullptr || !session_ctx->isValid()) {
LOGE("ERROR_INVALID_SESSION sid=%d", session);
LOGE("ERROR_INVALID_SESSION sid=%u", session);
return OEMCrypto_ERROR_INVALID_SESSION;
}
if (message == nullptr || message_length == 0 || signature == nullptr ||
@@ -347,33 +353,38 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadKeys(
!RangeCheck(message_length, enc_mac_keys, true) ||
!RangeCheck(message_length, pst, true) ||
!RangeCheck(message_length, srm_restriction_data, true)) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - "
"range check.]");
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - "
"range check.]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
for (unsigned int i = 0; i < num_keys; i++) {
for (size_t i = 0; i < num_keys; i++) {
if (!RangeCheck(message_length, key_array[i].key_id, false) ||
!RangeCheck(message_length, key_array[i].key_data, false) ||
!RangeCheck(message_length, key_array[i].key_data_iv, false) ||
!RangeCheck(message_length, key_array[i].key_control, false) ||
!RangeCheck(message_length, key_array[i].key_control_iv, false)) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - "
"range check %d]", i);
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range "
"check %zu]",
i);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
}
if (enc_mac_keys.offset >= wvoec::KEY_IV_SIZE && enc_mac_keys.length > 0) {
if (enc_mac_keys_iv.offset + wvoec::KEY_IV_SIZE == enc_mac_keys.offset) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - "
"range check iv]");
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - "
"range check iv]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
} else {
if (CRYPTO_memcmp(message + enc_mac_keys.offset - wvoec::KEY_IV_SIZE,
message + enc_mac_keys_iv.offset,
wvoec::KEY_IV_SIZE) == 0) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - "
"suspicious iv]");
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - "
"suspicious iv]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
}
@@ -570,9 +581,9 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_QueryKeyControl(
return OEMCrypto_SUCCESS;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_SelectKey(
const OEMCrypto_SESSION session, const uint8_t* key_id,
size_t key_id_length, OEMCryptoCipherMode cipher_mode) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_SelectKey(const OEMCrypto_SESSION session, const uint8_t* key_id,
size_t key_id_length, OEMCryptoCipherMode cipher_mode) {
#ifndef NDEBUG
if (!crypto_engine->ValidRootOfTrust()) {
LOGE("[OEMCrypto_SelectKey(): ERROR_KEYBOX_INVALID]");
@@ -619,7 +630,14 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_DecryptCENC(
return OEMCrypto_ERROR_KEYBOX_INVALID;
}
#endif
// The maximum subsample and sample sizes we use -- if 0, we just pick a
// very large size for a validity check.
const size_t max_subsample_size = crypto_engine->max_subsample_size() > 0
? crypto_engine->max_subsample_size()
: 100 * 1024 * 1024;
const size_t max_sample_size = crypto_engine->max_subsample_size() > 0
? crypto_engine->max_subsample_size()
: 1000 * 1024 * 1024;
// Iterate through all the samples and validate them before doing any decrypt
for (size_t sample_index = 0; sample_index < samples_length; ++sample_index) {
const OEMCrypto_SampleDescription& sample = samples[sample_index];
@@ -636,17 +654,20 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_DecryptCENC(
LOGE("[OEMCrypto_DecryptCENC(): Sample too large]");
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
}
// Iterate through all the subsamples and sum their lengths
size_t subsample_length_tally = 0;
for (size_t subsample_index = 0; subsample_index < sample.subsamples_length;
++subsample_index) {
const OEMCrypto_SubSampleDescription& subsample =
sample.subsamples[subsample_index];
// Compute the length now, but we check for possible overflow in the next
// if statement.
const size_t length =
subsample.num_bytes_clear + subsample.num_bytes_encrypted;
if (crypto_engine->max_subsample_size() > 0 &&
length > crypto_engine->max_subsample_size()) {
if (subsample.num_bytes_clear > max_subsample_size ||
subsample.num_bytes_encrypted > max_subsample_size ||
length > max_subsample_size ||
subsample_length_tally > max_sample_size) {
// For testing reasons only, pretend that this integration only supports
// the given buffer size.
LOGE("[OEMCrypto_DecryptCENC(): Subsample too large]");
@@ -711,8 +732,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert(
return OEMCrypto_SUCCESS;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_InstallKeyboxOrOEMCert(
const uint8_t* keybox, size_t keyBoxLength) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_InstallKeyboxOrOEMCert(const uint8_t* keybox, size_t keyBoxLength) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_InstallKeyboxOrOEMCert: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -876,7 +897,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
if (!randomData) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (RAND_bytes(randomData, dataLength)) {
if (RAND_bytes(randomData, dataLength) == 1) {
return OEMCrypto_SUCCESS;
}
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -944,11 +965,11 @@ static OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
// Now we generate a wrapped keybox.
WrappedRSAKey* wrapped = reinterpret_cast<WrappedRSAKey*>(wrapped_rsa_key);
// Pick a random context and IV for generating keys.
if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) {
if (RAND_bytes(wrapped->context, sizeof(wrapped->context)) != 1) {
LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) {
if (RAND_bytes(wrapped->iv, sizeof(wrapped->iv)) != 1) {
LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -1045,10 +1066,10 @@ static OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
// Now we generate a wrapped keybox.
WrappedRSAKey* wrapped = reinterpret_cast<WrappedRSAKey*>(wrapped_rsa_key);
// Pick a random context and IV for generating keys.
if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) {
if (RAND_bytes(wrapped->context, sizeof(wrapped->context)) != 1) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) {
if (RAND_bytes(wrapped->iv, sizeof(wrapped->iv)) != 1) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
const std::vector<uint8_t> context(
@@ -1111,6 +1132,11 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadProvisioning(
LOGE("ODK Error %d", result);
return result;
}
if (parsed_response.enc_private_key_iv.length != wvoec::KEY_IV_SIZE) {
LOGE("Encrypted private key iv has invalid length: %zu",
parsed_response.enc_private_key_iv.length);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
// For the reference implementation, the wrapped key and the encrypted
// key are the same size -- just encrypted with different keys.
@@ -1178,6 +1204,10 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadDRMPrivateKey(
return OEMCrypto_SUCCESS;
}
}
if (wrapped_rsa_key_length < sizeof(WrappedRSAKey)) {
LOGE("RSA Key has wrong size.");
return OEMCrypto_ERROR_INVALID_RSA_KEY;
}
const WrappedRSAKey* wrapped =
reinterpret_cast<const WrappedRSAKey*>(wrapped_rsa_key);
if (!crypto_engine->ValidRootOfTrust()) {
@@ -1393,8 +1423,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) {
return OEMCrypto_SUCCESS;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetMaxNumberOfSessions(
size_t* maximum) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_GetMaxNumberOfSessions(size_t* maximum) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_GetMaxNumberOfSessions: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1444,6 +1474,11 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Encrypt(
LOGE("[OEMCrypto_Generic_Encrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (buffer_length > kMaxInputMessageBuferLength) {
LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_BUFFER_TOO_LARGE]");
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
}
OEMCryptoResult sts = session_ctx->Generic_Encrypt(in_buffer, buffer_length,
iv, algorithm, out_buffer);
return sts;
@@ -1470,15 +1505,19 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Decrypt(
LOGE("[OEMCrypto_Generic_Decrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (buffer_length > kMaxInputMessageBuferLength) {
LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_BUFFER_TOO_LARGE]");
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
}
OEMCryptoResult sts = session_ctx->Generic_Decrypt(in_buffer, buffer_length,
iv, algorithm, out_buffer);
return sts;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Sign(
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
OEMCrypto_Algorithm algorithm, uint8_t* signature,
size_t* signature_length) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, const uint8_t* in_buffer,
size_t buffer_length, OEMCrypto_Algorithm algorithm,
uint8_t* signature, size_t* signature_length) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_Generic_Sign: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1500,15 +1539,19 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Sign(
LOGE("[OEMCrypto_Generic_Sign(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (buffer_length > kMaxInputMessageBuferLength) {
LOGE("[OEMCrypto_Generic_Sign(): ERROR_BUFFER_TOO_LARGE]");
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
}
OEMCryptoResult sts = session_ctx->Generic_Sign(
in_buffer, buffer_length, algorithm, signature, signature_length);
return sts;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Verify(
OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length,
OEMCrypto_Algorithm algorithm, const uint8_t* signature,
size_t signature_length) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_Generic_Verify(OEMCrypto_SESSION session, const uint8_t* in_buffer,
size_t buffer_length, OEMCrypto_Algorithm algorithm,
const uint8_t* signature, size_t signature_length) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_Generic_Verify: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1525,10 +1568,15 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Verify(
if (signature_length != SHA256_DIGEST_LENGTH) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (in_buffer == nullptr || buffer_length == 0 || signature == nullptr) {
if (in_buffer == nullptr || buffer_length == 0 || signature == nullptr ||
signature_length > kMaxInputSignatureLength) {
LOGE("[OEMCrypto_Generic_Verify(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (buffer_length > kMaxInputMessageBuferLength) {
LOGE("[OEMCrypto_Generic_Verify(): ERROR_BUFFER_TOO_LARGE]");
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
}
return session_ctx->Generic_Verify(in_buffer, buffer_length, algorithm,
signature, signature_length);
}
@@ -1585,8 +1633,8 @@ OEMCRYPTO_API bool OEMCrypto_IsSRMUpdateSupported() {
return result;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetCurrentSRMVersion(
uint16_t* version) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_GetCurrentSRMVersion(uint16_t* version) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_GetCurrentSRMVersion: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1629,8 +1677,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
header_buffer, header_buffer_length);
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
const uint8_t* buffer, size_t buffer_length) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_LoadUsageTableHeader(const uint8_t* buffer, size_t buffer_length) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_LoadUsageTableHeader: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1667,9 +1715,9 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateNewUsageEntry(
return sts;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadUsageEntry(
OEMCrypto_SESSION session, uint32_t index, const uint8_t* buffer,
size_t buffer_size) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_LoadUsageEntry(OEMCrypto_SESSION session, uint32_t index,
const uint8_t* buffer, size_t buffer_size) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_LoadUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1690,10 +1738,10 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadUsageEntry(
return session_ctx->LoadUsageEntry(index, bufferv);
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_UpdateUsageEntry(
OEMCrypto_SESSION session, uint8_t* header_buffer,
size_t* header_buffer_length, uint8_t* entry_buffer,
size_t* entry_buffer_length) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_UpdateUsageEntry(OEMCrypto_SESSION session, uint8_t* header_buffer,
size_t* header_buffer_length, uint8_t* entry_buffer,
size_t* entry_buffer_length) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_UpdateUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -1748,9 +1796,9 @@ OEMCRYPTO_API uint32_t OEMCrypto_SupportsDecryptHash() {
return OEMCrypto_CRC_Clear_Buffer;
}
OEMCRYPTO_API OEMCryptoResult OEMCrypto_SetDecryptHash(
OEMCrypto_SESSION session, uint32_t frame_number, const uint8_t* hash,
size_t hash_length) {
OEMCRYPTO_API OEMCryptoResult
OEMCrypto_SetDecryptHash(OEMCrypto_SESSION session, uint32_t frame_number,
const uint8_t* hash, size_t hash_length) {
if (crypto_engine == nullptr) {
LOGE("OEMCrypto_SetDecryptHash: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;

View File

@@ -303,9 +303,12 @@ bool SessionContext::RSADeriveKeys(
LOGE("[RSADeriveKeys(): no RSA key set]");
return false;
}
if (enc_session_key.size() != static_cast<size_t>(RSA_size(rsa_key()))) {
LOGE("[RSADeriveKeys(): encrypted session key wrong size:%zu, expected %d]",
enc_session_key.size(), RSA_size(rsa_key()));
const size_t actual_key_size = static_cast<size_t>(RSA_size(rsa_key()));
if (enc_session_key.size() != actual_key_size) {
LOGE(
"[RSADeriveKeys(): encrypted session key wrong size: %zu, expected "
"%zu]",
enc_session_key.size(), actual_key_size);
dump_boringssl_error();
return false;
}
@@ -806,8 +809,8 @@ OEMCryptoResult SessionContext::LoadKeysNoSignature(
LOGW("[LoadKeys: SRM Version is too small %u, required: %u",
current_version, minimum_version);
srm_requirements_status_ = InvalidSRMVersion;
} else if (ce_->srm_blacklisted_device_attached()) {
LOGW("[LoadKeys: SRM blacklisted device attached]");
} else if (ce_->srm_forbidden_device_attached()) {
LOGW("[LoadKeys: SRM forbidden device attached]");
srm_requirements_status_ = InvalidSRMVersion;
} else {
LOGI("[LoadKeys: SRM Versions is %u, required: %u]", current_version,
@@ -1193,6 +1196,36 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
}
if (!ce_->config_local_display_only()) {
// Only look at HDCP restrictions if the display can be non-local.
if (control.control_bits() & wvoec::kControlHDCPRequired) {
uint8_t required_hdcp =
(control.control_bits() & wvoec::kControlHDCPVersionMask) >>
wvoec::kControlHDCPVersionShift;
if (ce_->srm_forbidden_device_attached()) {
required_hdcp = HDCP_NO_DIGITAL_OUTPUT;
}
// For reference implementation, we pretend we can handle the current
// HDCP version.
if (required_hdcp > ce_->config_current_hdcp_capability() ||
ce_->config_current_hdcp_capability() == 0) {
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
}
}
}
// Return an error if analog displays should be disabled.
if ((control.control_bits() & wvoec::kControlDisableAnalogOutput) &&
ce_->analog_display_active()) {
LOGE("[%s(): control bit says disable analog", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
// Check if CGMS is required.
if (control.control_bits() & wvoec::kControlCGMSMask) {
if (ce_->analog_display_active() && !ce_->cgms_a_active()) {
LOGE("[%s(): control bit says CGMS required", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
}
if (!decrypt_started_) {
// The reference implementation does not have a hardware timer.
uint64_t* timer_expiration = nullptr;
@@ -1207,44 +1240,6 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
if (result == ODK_TIMER_EXPIRED) return OEMCrypto_ERROR_KEY_EXPIRED;
if (usage_entry_ != nullptr) usage_entry_->set_recent_decrypt(true);
}
if (!ce_->config_local_display_only()) {
// Only look at HDCP restrictions if the display can be non-local.
if (control.control_bits() & wvoec::kControlHDCPRequired) {
uint8_t required_hdcp =
(control.control_bits() & wvoec::kControlHDCPVersionMask) >>
wvoec::kControlHDCPVersionShift;
if (ce_->srm_blacklisted_device_attached()) {
required_hdcp = HDCP_NO_DIGITAL_OUTPUT;
}
// For reference implementation, we pretend we can handle the current
// HDCP version.
if (required_hdcp > ce_->config_current_hdcp_capability() ||
ce_->config_current_hdcp_capability() == 0) {
return OEMCrypto_ERROR_INSUFFICIENT_HDCP;
}
}
}
// If the output buffer is clear, then we cannot control whether the output is
// an active analog display. In that case, return an error if analog displays
// should be disabled.
if ((control.control_bits() & wvoec::kControlDisableAnalogOutput) &&
(ce_->analog_display_active() ||
(buffer_type == OEMCrypto_BufferType_Clear))) {
LOGE("[%s(): control bit says disable analog", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
// Check if CGMS is required.
if (control.control_bits() & wvoec::kControlCGMSMask) {
// We can't control CGMS for a clear buffer.
if (buffer_type == OEMCrypto_BufferType_Clear) {
LOGE("[%s(): CGMS required, but buffer is clear", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
if (ce_->analog_display_active() && !ce_->cgms_a_active()) {
LOGE("[%s(): control bit says CGMS required", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
}
decrypt_started_ = true; // First playback for session.
return OEMCrypto_SUCCESS;
}
@@ -1761,6 +1756,8 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
const uint8_t* cipher_data,
size_t cipher_data_length,
uint8_t* clear_data) {
if (block_offset >= AES_BLOCK_SIZE) return OEMCrypto_ERROR_INVALID_CONTEXT;
// Local copy (will be modified).
// Allocated as 64-bit ints to enforce 64-bit alignment for later access as a
// 64-bit value.

View File

@@ -209,7 +209,10 @@ OEMCryptoResult UsageTableEntry::SaveData(CryptoEngine* ce,
}
// Encrypt the entry.
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
if (RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE) != 1) {
LOGE("SaveUsageEntry: Could not generate iv.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; // working iv buffer.
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
@@ -292,7 +295,7 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
// Check that the index is correct.
if (index != clear->data.index) {
LOGE("LoadUsageEntry: entry says index is %d, not %d", clear->data.index,
LOGE("LoadUsageEntry: entry says index is %u, not %u", clear->data.index,
index);
return OEMCrypto_ERROR_INVALID_SESSION;
}
@@ -386,7 +389,7 @@ OEMCryptoResult UsageTable::LoadUsageEntry(
if (index >= generation_numbers_.size())
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (sessions_[index]) {
LOGE("LoadUsageEntry: index %d used by other session.", index);
LOGE("LoadUsageEntry: index %u used by other session.", index);
return OEMCrypto_ERROR_INVALID_SESSION;
}
const size_t max = ce_->max_usage_table_size();
@@ -479,7 +482,10 @@ OEMCryptoResult UsageTable::SaveUsageTableHeader(uint8_t* signed_buffer,
}
// Encrypt the entry.
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
if (RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE) != 1) {
LOGE("SaveUsageHeader: Could not generate iv entry.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; // working iv buffer.
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
@@ -667,9 +673,8 @@ bool UsageTable::LoadGenerationNumber(bool or_make_new_one) {
auto file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
if (!file) {
if (or_make_new_one) {
RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
sizeof(int64_t));
return true;
return RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
sizeof(int64_t)) == 1;
}
LOGE("UsageTable: File open failed: %s (clearing table)", path.c_str());
master_generation_number_ = 0;