Status ClearKeyDecryptor::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, const CryptoMetaData& aMetadata) {
CK_LOGD("ClearKeyDecryptor::Decrypt"); if (aBufferSize == 0) { // Nothing to decrypt. return Status::kSuccess;
}
// If the sample is split up into multiple encrypted subsamples, we need to // stitch them into one continuous buffer for decryption.
std::vector<uint8_t> tmp(aBufferSize);
static_assert(sizeof(uintptr_t) == sizeof(uint8_t*), "We need uintptr_t to be exactly the same size as a pointer");
// Decrypt CBCS case: if (aMetadata.mEncryptionScheme == EncryptionScheme::kCbcs) {
mozilla::CheckedInt<uintptr_t> data = reinterpret_cast<uintptr_t>(aBuffer); if (!data.isValid()) { return Status::kDecryptError;
} const uintptr_t endBuffer =
reinterpret_cast<uintptr_t>(aBuffer + aBufferSize);
for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) {
data += aMetadata.mClearBytes[i]; if (!data.isValid() || data.value() > endBuffer) { return Status::kDecryptError;
}
mozilla::CheckedInt<uintptr_t> dataAfterCipher =
data + aMetadata.mCipherBytes[i]; if (!dataAfterCipher.isValid() || dataAfterCipher.value() > endBuffer) { // Trying to read past the end of the buffer! return Status::kDecryptError;
}
mozilla::Span<uint8_t> encryptedSpan = mozilla::Span(
reinterpret_cast<uint8_t*>(data.value()), aMetadata.mCipherBytes[i]); if (!ClearKeyUtils::DecryptCbcs(mKey, aMetadata.mIV, encryptedSpan,
aMetadata.mCryptByteBlock,
aMetadata.mSkipByteBlock)) { return Status::kDecryptError;
}
data += aMetadata.mCipherBytes[i]; if (!data.isValid()) { return Status::kDecryptError;
}
} return Status::kSuccess;
}
// Decrypt CENC case: if (aMetadata.NumSubsamples()) { // Take all encrypted parts of subsamples and stitch them into one // continuous encrypted buffer.
mozilla::CheckedInt<uintptr_t> data = reinterpret_cast<uintptr_t>(aBuffer); const uintptr_t endBuffer =
reinterpret_cast<uintptr_t>(aBuffer + aBufferSize);
uint8_t* iter = tmp.data(); for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) {
data += aMetadata.mClearBytes[i]; if (!data.isValid() || data.value() > endBuffer) { // Trying to read past the end of the buffer! return Status::kDecryptError;
} const uint32_t& cipherBytes = aMetadata.mCipherBytes[i];
mozilla::CheckedInt<uintptr_t> dataAfterCipher = data + cipherBytes; if (!dataAfterCipher.isValid() || dataAfterCipher.value() > endBuffer) { // Trying to read past the end of the buffer! return Status::kDecryptError;
}
// It is possible that we could be passed an unencrypted sample, if all // encrypted sample lengths are zero, and in this case, a zero length // IV is allowed.
assert(aMetadata.mIV.size() == 8 || aMetadata.mIV.size() == 16 ||
(aMetadata.mIV.empty() && AllZero(aMetadata.mCipherBytes)));
if (aMetadata.mIV.size() > CENC_KEY_LEN) {
CK_LOGD("ClearKeyDecryptor::Decrypt unexpected IV size %zu",
aMetadata.mIV.size()); return Status::kDecryptError;
}
if (!ClearKeyUtils::DecryptAES(mKey, tmp, iv)) { return Status::kDecryptError;
}
if (aMetadata.NumSubsamples()) { // Take the decrypted buffer, split up into subsamples, and insert those // subsamples back into their original position in the original buffer.
uint8_t* data = aBuffer;
uint8_t* iter = tmp.data(); for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) {
data += aMetadata.mClearBytes[i];
uint32_t cipherBytes = aMetadata.mCipherBytes[i];
memcpy(data, iter, cipherBytes);
data += cipherBytes;
iter += cipherBytes;
}
} else {
memcpy(aBuffer, tmp.data(), aBufferSize);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.