2023-12-01 17:32:19 +00:00
|
|
|
// Copyright 2016 Google LLC. All rights reserved.
|
2016-01-13 01:32:48 +00:00
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <packager/media/base/decryptor_source.h>
|
2016-01-13 01:32:48 +00:00
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <absl/log/check.h>
|
|
|
|
#include <absl/log/log.h>
|
|
|
|
|
|
|
|
#include <packager/media/base/aes_decryptor.h>
|
|
|
|
#include <packager/media/base/aes_pattern_cryptor.h>
|
2016-01-13 01:32:48 +00:00
|
|
|
|
2017-09-18 23:31:00 +00:00
|
|
|
namespace {
|
|
|
|
// Return true if [encrypted_buffer, encrypted_buffer + buffer_size) overlaps
|
|
|
|
// with [decrypted_buffer, decrypted_buffer + buffer_size).
|
|
|
|
bool CheckMemoryOverlap(const uint8_t* encrypted_buffer,
|
|
|
|
size_t buffer_size,
|
|
|
|
uint8_t* decrypted_buffer) {
|
|
|
|
return (decrypted_buffer < encrypted_buffer)
|
|
|
|
? (encrypted_buffer < decrypted_buffer + buffer_size)
|
|
|
|
: (decrypted_buffer < encrypted_buffer + buffer_size);
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
namespace shaka {
|
2016-01-13 01:32:48 +00:00
|
|
|
namespace media {
|
|
|
|
|
|
|
|
DecryptorSource::DecryptorSource(KeySource* key_source)
|
|
|
|
: key_source_(key_source) {
|
|
|
|
CHECK(key_source);
|
|
|
|
}
|
2016-08-30 23:01:19 +00:00
|
|
|
DecryptorSource::~DecryptorSource() {}
|
2016-01-13 01:32:48 +00:00
|
|
|
|
|
|
|
bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
|
2017-09-18 23:31:00 +00:00
|
|
|
const uint8_t* encrypted_buffer,
|
|
|
|
size_t buffer_size,
|
|
|
|
uint8_t* decrypted_buffer) {
|
2016-01-13 01:32:48 +00:00
|
|
|
DCHECK(decrypt_config);
|
2017-09-18 23:31:00 +00:00
|
|
|
DCHECK(encrypted_buffer);
|
|
|
|
DCHECK(decrypted_buffer);
|
|
|
|
|
|
|
|
if (CheckMemoryOverlap(encrypted_buffer, buffer_size, decrypted_buffer)) {
|
|
|
|
LOG(ERROR) << "Encrypted buffer and decrypted buffer cannot overlap.";
|
|
|
|
return false;
|
|
|
|
}
|
2016-01-13 01:32:48 +00:00
|
|
|
|
|
|
|
// Get the decryptor object.
|
2016-08-30 23:01:19 +00:00
|
|
|
AesCryptor* decryptor = nullptr;
|
2016-01-13 01:32:48 +00:00
|
|
|
auto found = decryptor_map_.find(decrypt_config->key_id());
|
|
|
|
if (found == decryptor_map_.end()) {
|
2016-03-17 17:03:19 +00:00
|
|
|
// Create new AesDecryptor based on decryption mode.
|
2016-01-13 01:32:48 +00:00
|
|
|
EncryptionKey key;
|
|
|
|
Status status(key_source_->GetKey(decrypt_config->key_id(), &key));
|
|
|
|
if (!status.ok()) {
|
|
|
|
LOG(ERROR) << "Error retrieving decryption key: " << status;
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-17 17:03:19 +00:00
|
|
|
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<AesCryptor> aes_decryptor;
|
2016-04-08 18:41:17 +00:00
|
|
|
switch (decrypt_config->protection_scheme()) {
|
|
|
|
case FOURCC_cenc:
|
2016-03-17 17:03:19 +00:00
|
|
|
aes_decryptor.reset(new AesCtrDecryptor);
|
|
|
|
break;
|
2016-04-08 18:41:17 +00:00
|
|
|
case FOURCC_cbc1:
|
2016-04-13 17:52:41 +00:00
|
|
|
aes_decryptor.reset(new AesCbcDecryptor(kNoPadding));
|
2016-03-17 17:03:19 +00:00
|
|
|
break;
|
2016-04-06 00:28:09 +00:00
|
|
|
case FOURCC_cens:
|
2016-04-13 17:52:41 +00:00
|
|
|
aes_decryptor.reset(new AesPatternCryptor(
|
|
|
|
decrypt_config->crypt_byte_block(),
|
2016-04-27 07:51:51 +00:00
|
|
|
decrypt_config->skip_byte_block(),
|
|
|
|
AesPatternCryptor::kEncryptIfCryptByteBlockRemaining,
|
|
|
|
AesCryptor::kDontUseConstantIv,
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<AesCryptor>(new AesCtrDecryptor())));
|
2016-04-06 00:28:09 +00:00
|
|
|
break;
|
|
|
|
case FOURCC_cbcs:
|
2016-04-13 17:52:41 +00:00
|
|
|
aes_decryptor.reset(new AesPatternCryptor(
|
|
|
|
decrypt_config->crypt_byte_block(),
|
2016-04-27 07:51:51 +00:00
|
|
|
decrypt_config->skip_byte_block(),
|
|
|
|
AesPatternCryptor::kEncryptIfCryptByteBlockRemaining,
|
|
|
|
AesCryptor::kUseConstantIv,
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<AesCryptor>(new AesCbcDecryptor(kNoPadding))));
|
2016-04-06 00:28:09 +00:00
|
|
|
break;
|
2016-03-17 17:03:19 +00:00
|
|
|
default:
|
2016-04-08 18:41:17 +00:00
|
|
|
LOG(ERROR) << "Unsupported protection scheme: "
|
|
|
|
<< decrypt_config->protection_scheme();
|
2016-03-17 17:03:19 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!aes_decryptor->InitializeWithIv(key.key, decrypt_config->iv())) {
|
|
|
|
LOG(ERROR) << "Failed to initialize AesDecryptor for decryption.";
|
2016-01-13 01:32:48 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-08-30 23:01:19 +00:00
|
|
|
decryptor = aes_decryptor.get();
|
|
|
|
decryptor_map_[decrypt_config->key_id()] = std::move(aes_decryptor);
|
2016-01-13 01:32:48 +00:00
|
|
|
} else {
|
2016-08-30 23:01:19 +00:00
|
|
|
decryptor = found->second.get();
|
2016-01-13 01:32:48 +00:00
|
|
|
}
|
|
|
|
if (!decryptor->SetIv(decrypt_config->iv())) {
|
|
|
|
LOG(ERROR) << "Invalid initialization vector.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (decrypt_config->subsamples().empty()) {
|
|
|
|
// Sample not encrypted using subsample encryption. Decrypt whole.
|
2017-09-18 23:31:00 +00:00
|
|
|
if (!decryptor->Crypt(encrypted_buffer, buffer_size, decrypted_buffer)) {
|
2016-01-13 01:32:48 +00:00
|
|
|
LOG(ERROR) << "Error during bulk sample decryption.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Subsample decryption.
|
|
|
|
const std::vector<SubsampleEntry>& subsamples = decrypt_config->subsamples();
|
2017-09-18 23:31:00 +00:00
|
|
|
const uint8_t* current_ptr = encrypted_buffer;
|
|
|
|
const uint8_t* const buffer_end = encrypted_buffer + buffer_size;
|
2016-01-13 01:32:48 +00:00
|
|
|
for (const auto& subsample : subsamples) {
|
|
|
|
if ((current_ptr + subsample.clear_bytes + subsample.cipher_bytes) >
|
|
|
|
buffer_end) {
|
|
|
|
LOG(ERROR) << "Subsamples overflow sample buffer.";
|
|
|
|
return false;
|
|
|
|
}
|
2017-09-18 23:31:00 +00:00
|
|
|
memcpy(decrypted_buffer, current_ptr, subsample.clear_bytes);
|
2016-01-13 01:32:48 +00:00
|
|
|
current_ptr += subsample.clear_bytes;
|
2017-09-18 23:31:00 +00:00
|
|
|
decrypted_buffer += subsample.clear_bytes;
|
|
|
|
if (!decryptor->Crypt(current_ptr, subsample.cipher_bytes,
|
|
|
|
decrypted_buffer)) {
|
2016-01-13 01:32:48 +00:00
|
|
|
LOG(ERROR) << "Error decrypting subsample buffer.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
current_ptr += subsample.cipher_bytes;
|
2017-09-18 23:31:00 +00:00
|
|
|
decrypted_buffer += subsample.cipher_bytes;
|
2016-01-13 01:32:48 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace media
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|