Fix cens Mode in Android CDM
(This is a merge of go/wvgerrit/20500) This patch removes the logic that calculates the "pattern offset" from the Android glue layer. There is no such thing as a pattern offset, and setting this value to anything other than zero may break cens mode on some devices. To reduce the risk of setting this value to anything other than zero, the offset_blocks parameter has been removed from the pattern descriptor in the CDM Core. It will have to remain part of OEMCrypto v11, unfortunately, but the code to set it to zero is now centralized in CryptoSession. Bug: 28726863 Change-Id: I9c5bfe470fe251c7a57901dc2e998f4dab7fe7d7
This commit is contained in:
@@ -282,11 +282,9 @@ enum CdmCipherMode {
|
|||||||
struct CdmCencPatternEncryptionDescriptor {
|
struct CdmCencPatternEncryptionDescriptor {
|
||||||
size_t encrypt_blocks; // number of 16 byte blocks to decrypt
|
size_t encrypt_blocks; // number of 16 byte blocks to decrypt
|
||||||
size_t skip_blocks; // number of 16 byte blocks to leave in clear
|
size_t skip_blocks; // number of 16 byte blocks to leave in clear
|
||||||
size_t offset_blocks; // offset into the pattern for this call, in blocks
|
|
||||||
CdmCencPatternEncryptionDescriptor()
|
CdmCencPatternEncryptionDescriptor()
|
||||||
: encrypt_blocks(0),
|
: encrypt_blocks(0),
|
||||||
skip_blocks(0),
|
skip_blocks(0) {}
|
||||||
offset_blocks(0) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CdmDecryptionParameters {
|
struct CdmDecryptionParameters {
|
||||||
|
|||||||
@@ -689,7 +689,7 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
|
|||||||
OEMCrypto_CENCEncryptPatternDesc pattern_descriptor;
|
OEMCrypto_CENCEncryptPatternDesc pattern_descriptor;
|
||||||
pattern_descriptor.encrypt = params.pattern_descriptor.encrypt_blocks;
|
pattern_descriptor.encrypt = params.pattern_descriptor.encrypt_blocks;
|
||||||
pattern_descriptor.skip = params.pattern_descriptor.skip_blocks;
|
pattern_descriptor.skip = params.pattern_descriptor.skip_blocks;
|
||||||
pattern_descriptor.offset = params.pattern_descriptor.offset_blocks;
|
pattern_descriptor.offset = 0; // Deprecated field
|
||||||
AutoLock auto_lock(crypto_lock_);
|
AutoLock auto_lock(crypto_lock_);
|
||||||
// Check if key needs to be selected
|
// Check if key needs to be selected
|
||||||
if (params.is_encrypted) {
|
if (params.is_encrypted) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class WVCryptoPlugin : public android::CryptoPlugin {
|
|||||||
wvcdm::CdmSessionId configureTestMode(const void* data, size_t size);
|
wvcdm::CdmSessionId configureTestMode(const void* data, size_t size);
|
||||||
static wvcdm::CdmResponseType countEncryptedBlocksInPatternedRange(
|
static wvcdm::CdmResponseType countEncryptedBlocksInPatternedRange(
|
||||||
size_t range, size_t startingOffset, const Pattern& pattern,
|
size_t range, size_t startingOffset, const Pattern& pattern,
|
||||||
size_t startingPatternOffset, uint64_t* result);
|
uint64_t* result);
|
||||||
static void incrementIV(uint64_t increaseBy, std::vector<uint8_t>* ivPtr);
|
static void incrementIV(uint64_t increaseBy, std::vector<uint8_t>* ivPtr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
size_t blockOffset = 0;
|
size_t blockOffset = 0;
|
||||||
const size_t patternLengthInBytes =
|
const size_t patternLengthInBytes =
|
||||||
(pattern.mEncryptBlocks + pattern.mSkipBlocks) * kAESBlockSize;
|
(pattern.mEncryptBlocks + pattern.mSkipBlocks) * kAESBlockSize;
|
||||||
size_t patternOffsetInBytes = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numSubSamples; ++i) {
|
for (size_t i = 0; i < numSubSamples; ++i) {
|
||||||
const SubSample& subSample = subSamples[i];
|
const SubSample& subSample = subSamples[i];
|
||||||
@@ -187,7 +186,6 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
params.encrypt_buffer = source + offset;
|
params.encrypt_buffer = source + offset;
|
||||||
params.encrypt_length = subSample.mNumBytesOfClearData;
|
params.encrypt_length = subSample.mNumBytesOfClearData;
|
||||||
params.block_offset = 0;
|
params.block_offset = 0;
|
||||||
params.pattern_descriptor.offset_blocks = 0;
|
|
||||||
params.decrypt_buffer_offset = offset;
|
params.decrypt_buffer_offset = offset;
|
||||||
params.subsample_flags = clearFlags;
|
params.subsample_flags = clearFlags;
|
||||||
|
|
||||||
@@ -238,12 +236,6 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
params.encrypt_buffer = source + offset;
|
params.encrypt_buffer = source + offset;
|
||||||
params.encrypt_length = subSample.mNumBytesOfEncryptedData;
|
params.encrypt_length = subSample.mNumBytesOfEncryptedData;
|
||||||
params.block_offset = blockOffset;
|
params.block_offset = blockOffset;
|
||||||
// Note that the pattern offset calculation relies intentionally on
|
|
||||||
// integer division's flooring behavior. If we are partway through a
|
|
||||||
// crypto block, we should return the offset of the pattern block we are
|
|
||||||
// partway through.
|
|
||||||
size_t patternOffsetInBlocks = patternOffsetInBytes / kAESBlockSize;
|
|
||||||
params.pattern_descriptor.offset_blocks = patternOffsetInBlocks;
|
|
||||||
params.decrypt_buffer_offset = offset;
|
params.decrypt_buffer_offset = offset;
|
||||||
params.subsample_flags = encryptedFlags;
|
params.subsample_flags = encryptedFlags;
|
||||||
|
|
||||||
@@ -301,7 +293,7 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
} else {
|
} else {
|
||||||
res = countEncryptedBlocksInPatternedRange(
|
res = countEncryptedBlocksInPatternedRange(
|
||||||
subSample.mNumBytesOfEncryptedData, blockOffset, pattern,
|
subSample.mNumBytesOfEncryptedData, blockOffset, pattern,
|
||||||
patternOffsetInBlocks, &increment);
|
&increment);
|
||||||
if (!isCdmResponseTypeSuccess(res)) {
|
if (!isCdmResponseTypeSuccess(res)) {
|
||||||
// Swallow the specifics of the error to obscure decrypt internals.
|
// Swallow the specifics of the error to obscure decrypt internals.
|
||||||
return kErrorCDMGeneric;
|
return kErrorCDMGeneric;
|
||||||
@@ -312,12 +304,6 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
// Update the block offset
|
// Update the block offset
|
||||||
blockOffset = (blockOffset + subSample.mNumBytesOfEncryptedData) %
|
blockOffset = (blockOffset + subSample.mNumBytesOfEncryptedData) %
|
||||||
kAESBlockSize;
|
kAESBlockSize;
|
||||||
|
|
||||||
if (patternLengthInBytes > 0) {
|
|
||||||
patternOffsetInBytes =
|
|
||||||
(patternOffsetInBytes + subSample.mNumBytesOfEncryptedData) %
|
|
||||||
patternLengthInBytes;
|
|
||||||
}
|
|
||||||
} else if (mode == kMode_AES_CBC && patternLengthInBytes == 0) {
|
} else if (mode == kMode_AES_CBC && patternLengthInBytes == 0) {
|
||||||
// If there is no pattern, assume cbc1 mode and update the IV.
|
// If there is no pattern, assume cbc1 mode and update the IV.
|
||||||
|
|
||||||
@@ -363,14 +349,13 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
|
|
||||||
CdmResponseType WVCryptoPlugin::countEncryptedBlocksInPatternedRange(
|
CdmResponseType WVCryptoPlugin::countEncryptedBlocksInPatternedRange(
|
||||||
size_t range, size_t startingOffset, const Pattern& pattern,
|
size_t range, size_t startingOffset, const Pattern& pattern,
|
||||||
size_t startingPatternOffset, uint64_t* result) {
|
uint64_t* result) {
|
||||||
uint64_t blocksPassed = 0;
|
uint64_t blocksPassed = 0;
|
||||||
size_t bytesRemaining = range;
|
size_t bytesRemaining = range;
|
||||||
size_t patternOffset = startingPatternOffset;
|
size_t patternPosition = 0;
|
||||||
size_t patternLength = pattern.mEncryptBlocks + pattern.mSkipBlocks;
|
size_t patternLength = pattern.mEncryptBlocks + pattern.mSkipBlocks;
|
||||||
|
|
||||||
if (result == NULL || startingOffset >= kAESBlockSize ||
|
if (result == NULL || startingOffset >= kAESBlockSize) {
|
||||||
startingPatternOffset >= patternLength) {
|
|
||||||
return wvcdm::UNKNOWN_ERROR;
|
return wvcdm::UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,10 +364,10 @@ CdmResponseType WVCryptoPlugin::countEncryptedBlocksInPatternedRange(
|
|||||||
size_t bytesNeededToCompleteABlock = kAESBlockSize - startingOffset;
|
size_t bytesNeededToCompleteABlock = kAESBlockSize - startingOffset;
|
||||||
while (bytesRemaining >= bytesNeededToCompleteABlock) {
|
while (bytesRemaining >= bytesNeededToCompleteABlock) {
|
||||||
bytesRemaining -= bytesNeededToCompleteABlock;
|
bytesRemaining -= bytesNeededToCompleteABlock;
|
||||||
if (patternOffset < pattern.mEncryptBlocks) {
|
if (patternPosition < pattern.mEncryptBlocks) {
|
||||||
++blocksPassed;
|
++blocksPassed;
|
||||||
}
|
}
|
||||||
patternOffset = (patternOffset + 1) % patternLength;
|
patternPosition = (patternPosition + 1) % patternLength;
|
||||||
|
|
||||||
// After the first block, we only concern ourselves with complete blocks.
|
// After the first block, we only concern ourselves with complete blocks.
|
||||||
bytesNeededToCompleteABlock = kAESBlockSize;
|
bytesNeededToCompleteABlock = kAESBlockSize;
|
||||||
|
|||||||
Reference in New Issue
Block a user