OEMCrypto v16.2
Merge from Widevine repo of http://go/wvgerrit/93404 This is the unit tests, reference code, and documentation for OEMCrypto v16.2. Backwards compatibility should work for a v15 OEMCrypto. Some review comments will be addressed in future CLs. Bug: 141247171 Test: Unit tests Test: Media GTS tests on bonito Change-Id: I9d427c07580e180c0a4cfdc4a68f538d351c0ddd
This commit is contained in:
@@ -42,11 +42,15 @@ CryptoEngine::~CryptoEngine() {
|
||||
}
|
||||
|
||||
bool CryptoEngine::Initialize() {
|
||||
std::string file_path = GetUsageTimeFileFullPath();
|
||||
LoadOfflineTimeInfo(file_path);
|
||||
usage_table_.reset(MakeUsageTable());
|
||||
return true;
|
||||
}
|
||||
|
||||
void CryptoEngine::Terminate() {
|
||||
std::string file_path = GetUsageTimeFileFullPath();
|
||||
SaveOfflineTimeInfo(file_path);
|
||||
std::unique_lock<std::mutex> lock(session_table_lock_);
|
||||
ActiveSessions::iterator it;
|
||||
for (it = sessions_.begin(); it != sessions_.end(); ++it) {
|
||||
@@ -102,44 +106,53 @@ int64_t CryptoEngine::OnlineTime() {
|
||||
}
|
||||
|
||||
int64_t CryptoEngine::RollbackCorrectedOfflineTime() {
|
||||
struct TimeInfo {
|
||||
// The max time recorded through this function call.
|
||||
int64_t previous_time;
|
||||
// If the wall time is rollbacked to before the previous_time, this member
|
||||
// is updated to reflect the offset.
|
||||
int64_t rollback_offset;
|
||||
// Pad the struct so that TimeInfo is a multiple of 16.
|
||||
uint8_t padding[16 - (2 * sizeof(time_t)) % 16];
|
||||
};
|
||||
// Add any time offsets in the past to the current time.
|
||||
int64_t current_time = OnlineTime() + offline_time_info_.rollback_offset;
|
||||
// Write time info to disk if kTimeInfoUpdateWindowInSeconds has elapsed since
|
||||
// last write.
|
||||
if (current_time - offline_time_info_.previous_time >
|
||||
kTimeInfoUpdateWindowInSeconds) {
|
||||
std::string file_path = GetUsageTimeFileFullPath();
|
||||
SaveOfflineTimeInfo(file_path);
|
||||
}
|
||||
return current_time;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> encrypted_buffer(sizeof(TimeInfo));
|
||||
std::vector<uint8_t> clear_buffer(sizeof(TimeInfo));
|
||||
TimeInfo time_info;
|
||||
memset(&time_info, 0, sizeof(time_info));
|
||||
// Use the device key for encrypt/decrypt.
|
||||
const std::vector<uint8_t>& key = DeviceRootKey();
|
||||
|
||||
std::unique_ptr<wvcdm::File> file;
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
std::string CryptoEngine::GetUsageTimeFileFullPath() const {
|
||||
std::string file_path;
|
||||
// Note: file path is OK for a real implementation, but using security
|
||||
// level 1 would be better.
|
||||
// TODO(fredgc, jfore): Address how this property is presented to the ref.
|
||||
// For now, the path is empty.
|
||||
// For now, the file path is empty.
|
||||
/*if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
|
||||
&path)) {
|
||||
LOGE("RollbackCorrectedOfflineTime: Unable to get base path");
|
||||
&file_path)) {
|
||||
LOGE("RollbackCorrectedOfflineTime: Unable to get base path");
|
||||
}*/
|
||||
std::string filename = path + "StoredUsageTime.dat";
|
||||
return file_path + kStoredUsageTimeFileName;
|
||||
}
|
||||
|
||||
bool CryptoEngine::LoadOfflineTimeInfo(const std::string& file_path) {
|
||||
memset(&offline_time_info_, 0, sizeof(TimeInfo));
|
||||
wvcdm::FileSystem* file_system = file_system_.get();
|
||||
if (file_system->Exists(filename)) {
|
||||
// Load time info from previous call to this function.
|
||||
file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
|
||||
if (file_system->Exists(file_path)) {
|
||||
std::vector<uint8_t> encrypted_buffer(sizeof(TimeInfo));
|
||||
std::vector<uint8_t> clear_buffer(sizeof(TimeInfo));
|
||||
|
||||
KeyboxError error_code = ValidateKeybox();
|
||||
if (error_code != NO_ERROR) {
|
||||
LOGE("Keybox is invalid: %d", error_code);
|
||||
return false;
|
||||
}
|
||||
// Use the device key for encrypt/decrypt.
|
||||
const std::vector<uint8_t>& key = DeviceRootKey();
|
||||
std::unique_ptr<wvcdm::File> file =
|
||||
file_system->Open(file_path, wvcdm::FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
LOGE("RollbackCorrectedOfflineTime: File open failed: %s",
|
||||
filename.c_str());
|
||||
return OnlineTime();
|
||||
file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
// Load time info from previous call.
|
||||
file->Read(reinterpret_cast<char*>(&encrypted_buffer[0]), sizeof(TimeInfo));
|
||||
// Decrypt the encrypted TimeInfo buffer.
|
||||
AES_KEY aes_key;
|
||||
@@ -147,42 +160,65 @@ int64_t CryptoEngine::RollbackCorrectedOfflineTime() {
|
||||
std::vector<uint8_t> iv(wvoec::KEY_IV_SIZE, 0);
|
||||
AES_cbc_encrypt(&encrypted_buffer[0], &clear_buffer[0], sizeof(TimeInfo),
|
||||
&aes_key, iv.data(), AES_DECRYPT);
|
||||
memcpy(&time_info, &clear_buffer[0], sizeof(TimeInfo));
|
||||
}
|
||||
memcpy(&offline_time_info_, &clear_buffer[0], sizeof(TimeInfo));
|
||||
|
||||
int64_t current_time;
|
||||
// Add any time offsets in the past to the current time.
|
||||
current_time = OnlineTime() + time_info.rollback_offset;
|
||||
if (time_info.previous_time > current_time) {
|
||||
// Time has been rolled back.
|
||||
// Update the rollback offset.
|
||||
time_info.rollback_offset += time_info.previous_time - current_time;
|
||||
// Keep current time at previous recorded time.
|
||||
current_time = time_info.previous_time;
|
||||
// Detect offline time rollback after loading from disk.
|
||||
// Add any time offsets in the past to the current time.
|
||||
int64_t current_time = OnlineTime() + offline_time_info_.rollback_offset;
|
||||
if (offline_time_info_.previous_time > current_time) {
|
||||
// Current time is earlier than the previously saved time. Time has been
|
||||
// rolled back. Update the rollback offset.
|
||||
offline_time_info_.rollback_offset +=
|
||||
offline_time_info_.previous_time - current_time;
|
||||
// Keep current time at previous recorded time.
|
||||
current_time = offline_time_info_.previous_time;
|
||||
}
|
||||
// The new previous_time will either stay the same or move forward.
|
||||
offline_time_info_.previous_time = current_time;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoEngine::SaveOfflineTimeInfo(const std::string& file_path) {
|
||||
// Add any time offsets in the past to the current time. If there was an
|
||||
// earlier offline rollback, the rollback offset will be updated in
|
||||
// LoadOfflineTimeInfo(). It guarantees that the current time to be saved
|
||||
// will never go back.
|
||||
int64_t current_time = OnlineTime() + offline_time_info_.rollback_offset;
|
||||
// The new previous_time will either stay the same or move forward.
|
||||
time_info.previous_time = current_time;
|
||||
if (current_time > offline_time_info_.previous_time)
|
||||
offline_time_info_.previous_time = current_time;
|
||||
|
||||
KeyboxError error_code = ValidateKeybox();
|
||||
if (error_code != NO_ERROR) {
|
||||
LOGE("Keybox is invalid: %d", error_code);
|
||||
return false;
|
||||
}
|
||||
// Use the device key for encrypt/decrypt.
|
||||
const std::vector<uint8_t>& key = DeviceRootKey();
|
||||
std::vector<uint8_t> encrypted_buffer(sizeof(TimeInfo));
|
||||
std::vector<uint8_t> clear_buffer(sizeof(TimeInfo));
|
||||
|
||||
// Copy updated data and encrypt the buffer.
|
||||
memcpy(&clear_buffer[0], &time_info, sizeof(TimeInfo));
|
||||
memcpy(&clear_buffer[0], &offline_time_info_, sizeof(TimeInfo));
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&key[0], 128, &aes_key);
|
||||
std::vector<uint8_t> iv(wvoec::KEY_IV_SIZE, 0);
|
||||
AES_cbc_encrypt(&clear_buffer[0], &encrypted_buffer[0], sizeof(TimeInfo),
|
||||
&aes_key, iv.data(), AES_ENCRYPT);
|
||||
|
||||
std::unique_ptr<wvcdm::File> file;
|
||||
wvcdm::FileSystem* file_system = file_system_.get();
|
||||
// Write the encrypted buffer to disk.
|
||||
file = file_system->Open(
|
||||
filename, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate);
|
||||
file_path, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate);
|
||||
if (!file) {
|
||||
LOGE("RollbackCorrectedOfflineTime: File open failed: %s",
|
||||
filename.c_str());
|
||||
return OnlineTime();
|
||||
file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
file->Write(reinterpret_cast<char*>(&encrypted_buffer[0]), sizeof(TimeInfo));
|
||||
|
||||
// Return time with offset.
|
||||
return current_time;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoEngine::NonceCollision(uint32_t nonce) {
|
||||
|
||||
@@ -29,10 +29,23 @@ namespace wvoec_ref {
|
||||
|
||||
typedef std::map<SessionId, SessionContext*> ActiveSessions;
|
||||
|
||||
static const std::string kStoredUsageTimeFileName = "StoredUsageTime.dat";
|
||||
|
||||
typedef struct {
|
||||
// The max time recorded
|
||||
int64_t previous_time;
|
||||
// If the wall time is rollbacked to before the previous_time, this member
|
||||
// is updated to reflect the offset.
|
||||
int64_t rollback_offset;
|
||||
// Pad the struct so that TimeInfo is a multiple of 16.
|
||||
uint8_t padding[16 - (2 * sizeof(time_t)) % 16];
|
||||
} TimeInfo;
|
||||
|
||||
class CryptoEngine {
|
||||
public:
|
||||
static const uint32_t kApiVersion = 16;
|
||||
static const uint32_t kMinorApiVersion = 0;
|
||||
static const int64_t kTimeInfoUpdateWindowInSeconds = 300;
|
||||
|
||||
// This is like a factory method, except we choose which version to use at
|
||||
// compile time. It is defined in several source files. The build system
|
||||
@@ -217,6 +230,10 @@ class CryptoEngine {
|
||||
// System clock with antirollback protection, measuring time in seconds.
|
||||
int64_t RollbackCorrectedOfflineTime();
|
||||
|
||||
bool LoadOfflineTimeInfo(const std::string& file_path);
|
||||
bool SaveOfflineTimeInfo(const std::string& file_path);
|
||||
std::string GetUsageTimeFileFullPath() const;
|
||||
|
||||
explicit CryptoEngine(std::unique_ptr<wvcdm::FileSystem>&& file_system);
|
||||
virtual SessionContext* MakeSession(SessionId sid);
|
||||
virtual UsageTable* MakeUsageTable();
|
||||
@@ -226,6 +243,7 @@ class CryptoEngine {
|
||||
std::mutex session_table_lock_;
|
||||
std::unique_ptr<wvcdm::FileSystem> file_system_;
|
||||
std::unique_ptr<UsageTable> usage_table_;
|
||||
TimeInfo offline_time_info_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <openssl/cmac.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <stddef.h>
|
||||
@@ -356,8 +357,9 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadKeys(
|
||||
"range check iv]");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
} else {
|
||||
if (memcmp(message + enc_mac_keys.offset - wvoec::KEY_IV_SIZE,
|
||||
message + enc_mac_keys_iv.offset, wvoec::KEY_IV_SIZE) == 0) {
|
||||
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]");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
@@ -465,14 +467,17 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
// Range check
|
||||
for (size_t i = 0; i < num_keys; i++) {
|
||||
if (!RangeCheck(message_length, key_array[i].key_id, true) ||
|
||||
!RangeCheck(message_length, key_array[i].key_control, false) ||
|
||||
!RangeCheck(message_length, key_array[i].key_control_iv, true)) {
|
||||
LOGE("Range Check %zu", i);
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
// We only use the first key object to update the entire license. Since we
|
||||
// know num_keys > 0 after the last if statement, we can assume index is not
|
||||
// out of bounds.
|
||||
constexpr size_t kIndex = 0;
|
||||
|
||||
// Range check.
|
||||
if (!RangeCheck(message_length, key_array[kIndex].key_id, true) ||
|
||||
!RangeCheck(message_length, key_array[kIndex].key_control, false) ||
|
||||
!RangeCheck(message_length, key_array[kIndex].key_control_iv, true)) {
|
||||
LOGE("Range Check %zu", kIndex);
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
// Validate message signature
|
||||
@@ -487,37 +492,31 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||
std::vector<uint8_t> key_id;
|
||||
std::vector<uint8_t> key_control;
|
||||
std::vector<uint8_t> key_control_iv;
|
||||
for (size_t i = 0; i < num_keys; i++) {
|
||||
if (key_array[i].key_id.length != 0) {
|
||||
key_id.assign(
|
||||
message + key_array[i].key_id.offset,
|
||||
message + key_array[i].key_id.offset + key_array[i].key_id.length);
|
||||
key_control.assign(
|
||||
message + key_array[i].key_control.offset,
|
||||
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
|
||||
if (key_array[i].key_control_iv.length == 0) {
|
||||
key_control_iv.clear();
|
||||
} else {
|
||||
key_control_iv.assign(
|
||||
message + key_array[i].key_control_iv.offset,
|
||||
message + key_array[i].key_control_iv.offset + wvoec::KEY_IV_SIZE);
|
||||
}
|
||||
} else {
|
||||
// key_id could be null if special control key type
|
||||
// key_control is not encrypted in this case
|
||||
key_id.clear();
|
||||
if (key_array[kIndex].key_id.length != 0) {
|
||||
key_id.assign(message + key_array[kIndex].key_id.offset,
|
||||
message + key_array[kIndex].key_id.offset +
|
||||
key_array[kIndex].key_id.length);
|
||||
key_control.assign(message + key_array[kIndex].key_control.offset,
|
||||
message + key_array[kIndex].key_control.offset +
|
||||
wvoec::KEY_CONTROL_SIZE);
|
||||
if (key_array[kIndex].key_control_iv.length == 0) {
|
||||
key_control_iv.clear();
|
||||
key_control.assign(
|
||||
message + key_array[i].key_control.offset,
|
||||
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
|
||||
}
|
||||
|
||||
status = session_ctx->RefreshKey(key_id, key_control, key_control_iv);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
LOGE("error %d in key %zu", status, i);
|
||||
break;
|
||||
} else {
|
||||
key_control_iv.assign(message + key_array[kIndex].key_control_iv.offset,
|
||||
message + key_array[kIndex].key_control_iv.offset +
|
||||
wvoec::KEY_IV_SIZE);
|
||||
}
|
||||
} else {
|
||||
// key_id could be null if special control key type
|
||||
// key_control is not encrypted in this case
|
||||
key_id.clear();
|
||||
key_control_iv.clear();
|
||||
key_control.assign(message + key_array[kIndex].key_control.offset,
|
||||
message + key_array[kIndex].key_control.offset +
|
||||
wvoec::KEY_CONTROL_SIZE);
|
||||
}
|
||||
|
||||
status = session_ctx->RefreshKey(key_id, key_control, key_control_iv);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
@@ -429,7 +430,7 @@ OEMCryptoResult SessionContext::PrepAndSignRenewalRequest(
|
||||
}
|
||||
// If we are talking to an old license server, then we only sign the message
|
||||
// body.
|
||||
if (nonce_values_.api_version < 16) {
|
||||
if (nonce_values_.api_major_version < 16) {
|
||||
const uint8_t* message_body = message + *core_message_length;
|
||||
const size_t message_body_length = message_length - *core_message_length;
|
||||
return GenerateSignature(message_body, message_body_length, signature,
|
||||
@@ -643,7 +644,7 @@ bool SessionContext::ValidateMessage(const uint8_t* given_message,
|
||||
LOGE("ValidateMessage: Could not compute signature");
|
||||
return false;
|
||||
}
|
||||
if (memcmp(given_signature, computed_signature, signature_length)) {
|
||||
if (CRYPTO_memcmp(given_signature, computed_signature, signature_length)) {
|
||||
LOGE("Invalid signature given: %s",
|
||||
wvcdm::HexEncode(given_signature, signature_length).c_str());
|
||||
LOGE("Invalid signature computed: %s",
|
||||
@@ -1099,10 +1100,40 @@ OEMCryptoResult SessionContext::RefreshKey(
|
||||
if (session_keys_ == nullptr) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (key_control.empty()) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
std::vector<uint8_t> decrypted_key_control;
|
||||
if (key_id.empty()) {
|
||||
// Key control is not encrypted if key id is NULL
|
||||
decrypted_key_control = key_control;
|
||||
} else {
|
||||
Key* content_key = session_keys_->Find(key_id);
|
||||
if (nullptr == content_key) {
|
||||
LOGE("Key ID not found.");
|
||||
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||
}
|
||||
const std::vector<uint8_t> content_key_value = content_key->value();
|
||||
// Decrypt encrypted key control block
|
||||
if (key_control_iv.empty()) {
|
||||
decrypted_key_control = key_control;
|
||||
} else {
|
||||
if (!DecryptMessage(content_key_value, key_control_iv, key_control,
|
||||
&decrypted_key_control, 128 /* key size */)) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
KeyControlBlock key_control_block(decrypted_key_control);
|
||||
if (!key_control_block.valid()) {
|
||||
LOGE("Parse key control error.");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
uint32_t new_key_duration = key_control_block.duration();
|
||||
uint64_t* timer_value = nullptr;
|
||||
const OEMCryptoResult result =
|
||||
ODK_RefreshV15Values(&timer_limits_, &clock_values_, &nonce_values_,
|
||||
ce_->SystemTime(), timer_value);
|
||||
ce_->SystemTime(), new_key_duration, timer_value);
|
||||
if (result == ODK_SET_TIMER || result == ODK_DISABLE_TIMER)
|
||||
return OEMCrypto_SUCCESS;
|
||||
if (result == ODK_TIMER_EXPIRED) return OEMCrypto_ERROR_KEY_EXPIRED;
|
||||
@@ -1375,7 +1406,8 @@ OEMCryptoResult SessionContext::Generic_Verify(const uint8_t* in_buffer,
|
||||
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
|
||||
if (HMAC(EVP_sha256(), &key[0], key.size(), in_buffer, buffer_length,
|
||||
computed_signature, &md_len)) {
|
||||
if (0 == memcmp(signature, computed_signature, SHA256_DIGEST_LENGTH)) {
|
||||
if (0 ==
|
||||
CRYPTO_memcmp(signature, computed_signature, SHA256_DIGEST_LENGTH)) {
|
||||
return OEMCrypto_SUCCESS;
|
||||
} else {
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
@@ -79,15 +80,17 @@ bool UsageTableEntry::VerifyPST(const uint8_t* pst, size_t pst_length) {
|
||||
if (pst_length > kMaxPSTLength) return false;
|
||||
if (data_.pst_length != pst_length) return false;
|
||||
if (!pst || !pst_length) return false;
|
||||
return 0 == memcmp(pst, data_.pst, pst_length);
|
||||
return 0 == CRYPTO_memcmp(pst, data_.pst, pst_length);
|
||||
}
|
||||
|
||||
bool UsageTableEntry::VerifyMacKeys(const std::vector<uint8_t>& server,
|
||||
const std::vector<uint8_t>& client) {
|
||||
return (server.size() == wvoec::MAC_KEY_SIZE) &&
|
||||
(client.size() == wvoec::MAC_KEY_SIZE) &&
|
||||
(0 == memcmp(&server[0], data_.mac_key_server, wvoec::MAC_KEY_SIZE)) &&
|
||||
(0 == memcmp(&client[0], data_.mac_key_client, wvoec::MAC_KEY_SIZE));
|
||||
(0 == CRYPTO_memcmp(&server[0], data_.mac_key_server,
|
||||
wvoec::MAC_KEY_SIZE)) &&
|
||||
(0 ==
|
||||
CRYPTO_memcmp(&client[0], data_.mac_key_client, wvoec::MAC_KEY_SIZE));
|
||||
}
|
||||
|
||||
bool UsageTableEntry::SetMacKeys(const std::vector<uint8_t>& server,
|
||||
@@ -117,7 +120,7 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
|
||||
data_.pst_length);
|
||||
return OEMCrypto_ERROR_WRONG_PST;
|
||||
}
|
||||
if (memcmp(&pst[0], data_.pst, data_.pst_length)) {
|
||||
if (CRYPTO_memcmp(&pst[0], data_.pst, data_.pst_length)) {
|
||||
LOGE("ReportUsage: wrong pst %s, should be %s.", wvcdm::b2a_hex(pst).c_str(),
|
||||
wvcdm::HexEncode(data_.pst, data_.pst_length).c_str());
|
||||
return OEMCrypto_ERROR_WRONG_PST;
|
||||
@@ -254,7 +257,8 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
|
||||
LOGE("LoadUsageEntry: Could not sign entry.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (memcmp(clear->signature, encrypted->signature, SHA256_DIGEST_LENGTH)) {
|
||||
if (CRYPTO_memcmp(clear->signature, encrypted->signature,
|
||||
SHA256_DIGEST_LENGTH)) {
|
||||
LOGE("LoadUsageEntry: Signature did not match.");
|
||||
LOGE("LoadUsageEntry: Invalid signature given: %s",
|
||||
wvcdm::HexEncode(encrypted->signature, sig_length).c_str());
|
||||
@@ -530,7 +534,8 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
|
||||
LOGE("LoadUsageTableHeader: Could not sign entry.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (memcmp(clear->signature, encrypted->signature, SHA256_DIGEST_LENGTH)) {
|
||||
if (CRYPTO_memcmp(clear->signature, encrypted->signature,
|
||||
SHA256_DIGEST_LENGTH)) {
|
||||
LOGE("LoadUsageTableHeader: Signature did not match.");
|
||||
LOGE("LoadUsageTableHeader: Invalid signature given: %s",
|
||||
wvcdm::HexEncode(encrypted->signature, sig_length).c_str());
|
||||
|
||||
Reference in New Issue
Block a user