Part of Qualcomm L1 OEMCrypto integration
Upgrade to version 2.1 of license protocol in OEMCrypto. related-to-bug: 8621521 Merge of https://widevine-internal-review.googlesource.com/#/c/4952/ from Widevine CDM repository to android repository. Change-Id: I0d85dae1981b7525ab17aec5f21cf668d078bf47
This commit is contained in:
committed by
Jeff Tinker
parent
bb0c62768a
commit
39ea1df671
@@ -15,6 +15,7 @@
|
||||
#include "log.h"
|
||||
#include "oemcrypto_key_mock.h"
|
||||
#include "openssl/aes.h"
|
||||
#include "openssl/bio.h"
|
||||
#include "openssl/cmac.h"
|
||||
#include "openssl/err.h"
|
||||
#include "openssl/evp.h"
|
||||
@@ -22,6 +23,7 @@
|
||||
#include "openssl/rand.h"
|
||||
#include <openssl/rsa.h>
|
||||
#include "openssl/sha.h"
|
||||
#include "openssl/x509.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
@@ -75,6 +77,15 @@ void SessionKeyTable::Remove(const KeyId key_id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool SessionKeyTable::UpdateDuration(const KeyControlBlock& control) {
|
||||
for(KeyMap::iterator it = keys_.begin(); it != keys_.end(); ++it) {
|
||||
if (!it->second->UpdateDuration(control)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionContext::Open() {
|
||||
}
|
||||
|
||||
@@ -86,7 +97,7 @@ bool SessionContext::DeriveKey(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& context,
|
||||
int counter,
|
||||
std::vector<uint8_t>* out) {
|
||||
if (key.empty() || counter > 2 || context.empty() || out == NULL) {
|
||||
if (key.empty() || counter > 4 || context.empty() || out == NULL) {
|
||||
LOGE("[DeriveKey(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||
return false;
|
||||
}
|
||||
@@ -122,34 +133,45 @@ bool SessionContext::DeriveKey(const std::vector<uint8_t>& key,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionContext::DeriveKeys(const std::vector<uint8_t>& mac_key_context,
|
||||
bool SessionContext::DeriveKeys(const std::vector<uint8_t>& master_key,
|
||||
const std::vector<uint8_t>& mac_key_context,
|
||||
const std::vector<uint8_t>& enc_key_context) {
|
||||
// Generate derived key for mac key
|
||||
std::vector<uint8_t> device_key = ce_->keybox().device_key().value();
|
||||
std::vector<uint8_t> mac_key;
|
||||
std::vector<uint8_t> mac_key_server;
|
||||
std::vector<uint8_t> mac_key_client;
|
||||
std::vector<uint8_t> mac_key_part2;
|
||||
if (!DeriveKey(device_key, mac_key_context, 1, &mac_key)) {
|
||||
if (!DeriveKey(master_key, mac_key_context, 1, &mac_key_server)) {
|
||||
return false;
|
||||
}
|
||||
if (!DeriveKey(device_key, mac_key_context, 2, &mac_key_part2)) {
|
||||
if (!DeriveKey(master_key, mac_key_context, 2, &mac_key_part2)) {
|
||||
return false;
|
||||
}
|
||||
mac_key.insert(mac_key.end(), mac_key_part2.begin(), mac_key_part2.end());
|
||||
mac_key_server.insert(mac_key_server.end(), mac_key_part2.begin(), mac_key_part2.end());
|
||||
|
||||
if (!DeriveKey(master_key, mac_key_context, 3, &mac_key_client)) {
|
||||
return false;
|
||||
}
|
||||
if (!DeriveKey(master_key, mac_key_context, 4, &mac_key_part2)) {
|
||||
return false;
|
||||
}
|
||||
mac_key_client.insert(mac_key_client.end(), mac_key_part2.begin(), mac_key_part2.end());
|
||||
|
||||
// Generate derived key for encryption key
|
||||
std::vector<uint8_t> enc_key;
|
||||
if (!DeriveKey(device_key, enc_key_context, 1, &enc_key)) {
|
||||
if (!DeriveKey(master_key, enc_key_context, 1, &enc_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0 // Print Derived Keys to stdout.
|
||||
std::cout << " mac_key_context = " << wvcdm::b2a_hex(mac_key_context) << std::endl;
|
||||
std::cout << " enc_key_context = " << wvcdm::b2a_hex(enc_key_context) << std::endl;
|
||||
std::cout << " mac_key = " << wvcdm::b2a_hex(mac_key) << std::endl;
|
||||
std::cout << " mac_key_server = " << wvcdm::b2a_hex(mac_key_server) << std::endl;
|
||||
std::cout << " mac_key_client = " << wvcdm::b2a_hex(mac_key_client) << std::endl;
|
||||
std::cout << " enc_key = " << wvcdm::b2a_hex(enc_key) << std::endl;
|
||||
#endif
|
||||
|
||||
set_mac_key(mac_key);
|
||||
set_mac_key_server(mac_key_server);
|
||||
set_mac_key_client(mac_key_client);
|
||||
set_encryption_key(enc_key);
|
||||
return true;
|
||||
}
|
||||
@@ -185,38 +207,7 @@ bool SessionContext::RSADeriveKeys(const std::vector<uint8_t>& enc_session_key,
|
||||
session_key_.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate derived key for mac key
|
||||
std::vector<uint8_t> mac_key;
|
||||
std::vector<uint8_t> mac_key_part2;
|
||||
if (!DeriveKey(session_key_, mac_key_context, 1, &mac_key)) {
|
||||
session_key_.clear();
|
||||
return false;
|
||||
}
|
||||
if (!DeriveKey(session_key_, mac_key_context, 2, &mac_key_part2)) {
|
||||
session_key_.clear();
|
||||
return false;
|
||||
}
|
||||
mac_key.insert(mac_key.end(), mac_key_part2.begin(), mac_key_part2.end());
|
||||
|
||||
// Generate derived key for encryption key
|
||||
std::vector<uint8_t> enc_key;
|
||||
if (!DeriveKey(session_key_, enc_key_context, 1, &enc_key)) {
|
||||
session_key_.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0 // Print Derived Keys to stdout.
|
||||
std::cout << " mac_key_context = " << wvcdm::b2a_hex(mac_key_context) << std::endl;
|
||||
std::cout << " enc_key_context = " << wvcdm::b2a_hex(enc_key_context) << std::endl;
|
||||
std::cout << " session_key = " << wvcdm::b2a_hex(session_key_) << std::endl;
|
||||
std::cout << " mac_key = " << wvcdm::b2a_hex(mac_key) << std::endl;
|
||||
std::cout << " enc_key = " << wvcdm::b2a_hex(enc_key) << std::endl;
|
||||
#endif
|
||||
|
||||
set_mac_key(mac_key);
|
||||
set_encryption_key(enc_key);
|
||||
return true;
|
||||
return DeriveKeys(session_key_, mac_key_context, enc_key_context);
|
||||
}
|
||||
|
||||
// Utility function to generate a message signature
|
||||
@@ -231,7 +222,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mac_key_.empty() || mac_key_.size() != wvcdm::MAC_KEY_SIZE) {
|
||||
if (mac_key_client_.empty() || mac_key_client_.size() != wvcdm::MAC_KEY_SIZE) {
|
||||
LOGE("[GenerateSignature(): No MAC Key]");
|
||||
return false;
|
||||
}
|
||||
@@ -242,7 +233,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
|
||||
}
|
||||
|
||||
unsigned int md_len = *signature_length;
|
||||
if (HMAC(EVP_sha256(), &mac_key_[0], SHA256_DIGEST_LENGTH,
|
||||
if (HMAC(EVP_sha256(), &mac_key_client_[0], SHA256_DIGEST_LENGTH,
|
||||
message, message_length, signature, &md_len)) {
|
||||
*signature_length = md_len;
|
||||
return true;
|
||||
@@ -315,8 +306,10 @@ bool SessionContext::ValidateMessage(const uint8_t* given_message,
|
||||
return false;
|
||||
}
|
||||
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
|
||||
if (! GenerateSignature(given_message, message_length,
|
||||
computed_signature, &signature_length)) {
|
||||
unsigned int md_len = SHA256_DIGEST_LENGTH;
|
||||
if (!HMAC(EVP_sha256(), &mac_key_server_[0], SHA256_DIGEST_LENGTH,
|
||||
given_message, message_length, computed_signature, &md_len)) {
|
||||
LOGE("ValidateMessage: Could not compute signature.");
|
||||
return false;
|
||||
}
|
||||
if (memcmp(given_signature, computed_signature, signature_length)) {
|
||||
@@ -336,6 +329,7 @@ bool SessionContext::ParseKeyControl(
|
||||
key_control_block.Invalidate();
|
||||
|
||||
if (key_control_string.size() < wvcdm::KEY_CONTROL_SIZE) {
|
||||
LOGD("ParseKeyControl: wrong size.");
|
||||
return false;
|
||||
}
|
||||
if (!key_control_block.SetFromString(key_control_string)) {
|
||||
@@ -357,6 +351,14 @@ bool SessionContext::ParseKeyControl(
|
||||
LOGD(" duration: %d", key_control_block.duration());
|
||||
LOGD(" nonce: %08X", key_control_block.nonce());
|
||||
LOGD(" bits: %08X", key_control_block.control_bits());
|
||||
LOGD(" bit kControlAllowEncrypt %s.",
|
||||
(key_control_block.control_bits() & kControlAllowEncrypt) ? "set" : "unset");
|
||||
LOGD(" bit kControlAllowDecrypt %s.",
|
||||
(key_control_block.control_bits() & kControlAllowDecrypt) ? "set" : "unset");
|
||||
LOGD(" bit kControlAllowSign %s.",
|
||||
(key_control_block.control_bits() & kControlAllowSign) ? "set" : "unset");
|
||||
LOGD(" bit kControlAllowVerify %s.",
|
||||
(key_control_block.control_bits() & kControlAllowVerify) ? "set" : "unset");
|
||||
LOGD(" bit kControlObserveDataPath %s.",
|
||||
(key_control_block.control_bits() & kControlObserveDataPath) ? "set" : "unset");
|
||||
LOGD(" bit kControlObserveHDCP %s.",
|
||||
@@ -428,6 +430,7 @@ bool SessionContext::InstallKey(const KeyId& key_id,
|
||||
}
|
||||
|
||||
if (!ParseKeyControl(key_control_str, key_control_block)) {
|
||||
LOGE("Error parsing key control.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -437,38 +440,36 @@ bool SessionContext::InstallKey(const KeyId& key_id,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionContext::EncryptRSAKey(uint8_t* wrapped_rsa_key,
|
||||
size_t wrapped_rsa_key_length,
|
||||
uint8_t* wrapped_rsa_key_iv) {
|
||||
std::vector<uint8_t> buffer(wrapped_rsa_key_length);
|
||||
uint8_t* p = &buffer[0];
|
||||
int len = i2d_RSAPrivateKey(rsa_key_, &p);
|
||||
if (len < 0) {
|
||||
LOGE("[EncryptRSAKey(): Could not decode rsa key]");
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
}
|
||||
if (static_cast<size_t>(len) >= wrapped_rsa_key_length) {
|
||||
LOGE("[EncryptRSAKey(): padding is wrong size: len=%d, size=%zu",
|
||||
len, wrapped_rsa_key_length);
|
||||
return false;
|
||||
}
|
||||
size_t padding = wrapped_rsa_key_length - len;
|
||||
memset(&buffer[len], static_cast<uint8_t>(padding), padding);
|
||||
bool SessionContext::DecryptRSAKey(const uint8_t* enc_rsa_key,
|
||||
size_t enc_rsa_key_length,
|
||||
const uint8_t* enc_rsa_key_iv,
|
||||
uint8_t* pkcs8_rsa_key) {
|
||||
// Decrypt rsa key with keybox.
|
||||
uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE];
|
||||
memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(&encryption_key_[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(enc_rsa_key, pkcs8_rsa_key, enc_rsa_key_length,
|
||||
&aes_key, iv_buffer, AES_DECRYPT);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionContext::EncryptRSAKey(const uint8_t* pkcs8_rsa_key,
|
||||
size_t enc_rsa_key_length,
|
||||
const uint8_t* enc_rsa_key_iv,
|
||||
uint8_t* enc_rsa_key) {
|
||||
// Encrypt rsa key with keybox.
|
||||
uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE];
|
||||
memcpy(iv_buffer, wrapped_rsa_key_iv, wvcdm::KEY_IV_SIZE);
|
||||
memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&encryption_key_[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(&buffer[0], wrapped_rsa_key, wrapped_rsa_key_length,
|
||||
AES_cbc_encrypt(pkcs8_rsa_key, enc_rsa_key, enc_rsa_key_length,
|
||||
&aes_key, iv_buffer, AES_ENCRYPT);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionContext::LoadRSAKey(const uint8_t* enc_rsa_key,
|
||||
size_t enc_rsa_key_length,
|
||||
const uint8_t* enc_rsa_key_iv,
|
||||
bool SessionContext::LoadRSAKey(uint8_t* pkcs8_rsa_key,
|
||||
size_t rsa_key_length,
|
||||
const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
@@ -479,32 +480,44 @@ bool SessionContext::LoadRSAKey(const uint8_t* enc_rsa_key,
|
||||
LOGE("[LoadRSAKey(): Could not verify signature]");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t iv[wvcdm::KEY_IV_SIZE];
|
||||
uint8_t* clear = new uint8_t[enc_rsa_key_length];
|
||||
memcpy(iv, enc_rsa_key_iv, 16);
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(&encryption_key_[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(enc_rsa_key, clear, enc_rsa_key_length, &aes_key,
|
||||
iv, AES_DECRYPT);
|
||||
size_t padding = clear[enc_rsa_key_length - 1];
|
||||
if (padding > 16) {
|
||||
LOGE("[LoadRSAKey(): Encrypted RSA has bad padding]");
|
||||
return false;
|
||||
}
|
||||
size_t rsa_key_length = enc_rsa_key_length - padding;
|
||||
|
||||
if (rsa_key_) {
|
||||
RSA_free(rsa_key_);
|
||||
rsa_key_ = NULL;
|
||||
}
|
||||
uint8_t const* p = clear;
|
||||
rsa_key_ = d2i_RSAPrivateKey(0, &p, rsa_key_length);
|
||||
delete[] clear;
|
||||
|
||||
if (! rsa_key_) {
|
||||
LOGE("[LoadRSAKey(): Could decode unencrypted rsa key]");
|
||||
dump_openssl_error();
|
||||
BIO *bio = BIO_new_mem_buf(pkcs8_rsa_key, rsa_key_length);
|
||||
if( bio == NULL ) {
|
||||
LOGE("[LoadRSAKey(): Could not allocate bio buffer]");
|
||||
return false;
|
||||
}
|
||||
bool success = true;
|
||||
PKCS8_PRIV_KEY_INFO *pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL);
|
||||
if (pkcs8_pki == NULL) {
|
||||
LOGE("d2i_PKCS8_PRIV_KEY_INFO_bio returned NULL.");
|
||||
success = false;
|
||||
}
|
||||
EVP_PKEY *evp = NULL;
|
||||
if (success) {
|
||||
evp = EVP_PKCS82PKEY(pkcs8_pki);
|
||||
if (evp == NULL) {
|
||||
LOGE("EVP_PKCS82PKEY returned NULL.");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
rsa_key_ = EVP_PKEY_get1_RSA(evp);
|
||||
if (rsa_key_ == NULL) {
|
||||
LOGE("PrivateKeyInfo did not contain an RSA key.");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (evp != NULL) {
|
||||
EVP_PKEY_free(evp);
|
||||
}
|
||||
if (pkcs8_pki != NULL) {
|
||||
PKCS8_PRIV_KEY_INFO_free(pkcs8_pki);
|
||||
}
|
||||
BIO_free(bio);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
switch (RSA_check_key(rsa_key_)) {
|
||||
@@ -535,7 +548,7 @@ bool SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
|
||||
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.");
|
||||
LOGE("[Generic_Encrypt(): CONTENT_KEY has wrong size: %d",key.size());
|
||||
return false;
|
||||
}
|
||||
if (!(control.control_bits() & kControlAllowEncrypt)) {
|
||||
@@ -590,6 +603,10 @@ bool SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
|
||||
LOGE("[Generic_Decrypt(): control bit says not allowed.");
|
||||
return false;
|
||||
}
|
||||
if (control.control_bits() & kControlDataPathSecure) {
|
||||
LOGE("[Generic_Decrypt(): control bit says secure path only.");
|
||||
return false;
|
||||
}
|
||||
if (control.duration() > 0) {
|
||||
if (control.duration() < CurrentTimer()) {
|
||||
LOGE("[Generic_Decrypt(): key expired.");
|
||||
@@ -635,7 +652,7 @@ bool SessionContext::Generic_Sign(const uint8_t* in_buffer,
|
||||
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.");
|
||||
LOGE("[Generic_Sign(): CONTENT_KEY has wrong size; %d", key.size());
|
||||
return false;
|
||||
}
|
||||
if (!(control.control_bits() & kControlAllowSign)) {
|
||||
@@ -679,7 +696,7 @@ bool SessionContext::Generic_Verify(const uint8_t* in_buffer,
|
||||
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.");
|
||||
LOGE("[Generic_Verify(): CONTENT_KEY has wrong size: %d", key.size());
|
||||
return false;
|
||||
}
|
||||
if (!(control.control_bits() & kControlAllowVerify)) {
|
||||
@@ -711,52 +728,73 @@ bool SessionContext::RefreshKey(const KeyId& key_id,
|
||||
const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv) {
|
||||
if (key_id.empty()) {
|
||||
return false;
|
||||
// Key control is not encrypted if key id is NULL
|
||||
KeyControlBlock key_control_block(true);
|
||||
if (!ParseKeyControl(key_control, key_control_block)) {
|
||||
LOGD("Parse key control error.");
|
||||
return false;
|
||||
}
|
||||
// Apply duration to all keys in this session
|
||||
return session_keys_.UpdateDuration(key_control_block);
|
||||
}
|
||||
|
||||
Key* content_key = session_keys_.Find(key_id);
|
||||
|
||||
if (NULL == content_key) {
|
||||
LOGD("Error: no matching content key.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!key_control.empty()) {
|
||||
const std::vector<uint8_t> content_key_value = content_key->value();
|
||||
if (key_control.empty()) {
|
||||
LOGD("Error: no key_control.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decrypt encrypted key control block
|
||||
// We don't actually make use of it in Oemcrypto mock, just to verify its
|
||||
// validity
|
||||
std::vector<uint8_t> control;
|
||||
if (key_control_iv.empty()) {
|
||||
control = key_control;
|
||||
} else if (!ce_->DecryptMessage(this, content_key_value, key_control_iv,
|
||||
key_control, &control)) {
|
||||
const std::vector<uint8_t> content_key_value = content_key->value();
|
||||
|
||||
// Decrypt encrypted key control block
|
||||
std::vector<uint8_t> control;
|
||||
if (key_control_iv.empty()) {
|
||||
// TODO(fredg): get confirmation from server team this is valid.
|
||||
LOGD("Key control block is NOT encrypted.");
|
||||
control = key_control;
|
||||
} else {
|
||||
// TODO(fredg): get confirmation from server team this is valid, too.
|
||||
LOGD("Key control block is encrypted.");
|
||||
if (!ce_->DecryptMessage(this, content_key_value, key_control_iv,
|
||||
key_control, &control)) {
|
||||
LOGD("Error decrypting key control block.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
KeyControlBlock key_control_block;
|
||||
if (!ParseKeyControl(control, key_control_block)) {
|
||||
return false;
|
||||
}
|
||||
KeyControlBlock key_control_block(true);
|
||||
if (!ParseKeyControl(control, key_control_block)) {
|
||||
LOGD("Error parsing key control.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!content_key->UpdateControl(key_control_block)) {
|
||||
return false;
|
||||
}
|
||||
if (!content_key->UpdateDuration(key_control_block)) {
|
||||
LOGD("Error updating duration.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionContext::UpdateMacKey(const std::vector<uint8_t>& enc_mac_key,
|
||||
const std::vector<uint8_t>& iv) {
|
||||
bool SessionContext::UpdateMacKeys(const std::vector<uint8_t>& enc_mac_keys,
|
||||
const std::vector<uint8_t>& iv) {
|
||||
|
||||
// Decrypt mac key from enc_mac_key using device_key
|
||||
std::vector<uint8_t> mac_key;
|
||||
// Decrypt mac key from enc_mac_key using device_keya
|
||||
std::vector<uint8_t> mac_keys;
|
||||
if (!ce_->DecryptMessage(this, encryption_key_, iv,
|
||||
enc_mac_key, &mac_key)) {
|
||||
enc_mac_keys, &mac_keys)) {
|
||||
return false;
|
||||
}
|
||||
mac_key_ = mac_key;
|
||||
mac_key_server_ = std::vector<uint8_t>(mac_keys.begin(),
|
||||
mac_keys.begin()+wvcdm::MAC_KEY_SIZE);
|
||||
mac_key_client_ = std::vector<uint8_t>(mac_keys.begin()+wvcdm::MAC_KEY_SIZE,
|
||||
mac_keys.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -896,7 +934,7 @@ 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.");
|
||||
LOGE("[DecryptCTR(): CONTENT_KEY has wrong size: %d", content_key.size());
|
||||
return false;
|
||||
}
|
||||
const uint8_t* key_u8 = &content_key[0];
|
||||
|
||||
Reference in New Issue
Block a user