cenc_decryptor.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/cdm/cenc_decryptor.h"
  5. #include <stdint.h>
  6. #include <memory>
  7. #include <string>
  8. #include <vector>
  9. #include "base/logging.h"
  10. #include "base/strings/string_piece.h"
  11. #include "crypto/encryptor.h"
  12. #include "crypto/symmetric_key.h"
  13. #include "media/base/decoder_buffer.h"
  14. #include "media/base/decrypt_config.h"
  15. #include "media/base/subsample_entry.h"
  16. namespace media {
  17. namespace {
  18. enum ClearBytesBufferSel { kSrcContainsClearBytes, kDstContainsClearBytes };
  19. // Copy the cypher bytes as specified by |subsamples| from |src| to |dst|.
  20. // If |sel| == kSrcContainsClearBytes, then |src| is expected to contain any
  21. // clear bytes specified by |subsamples| and will be skipped. This is used
  22. // when copying all the protected data out of a sample. If |sel| ==
  23. // kDstContainsClearBytes, then any clear bytes mentioned in |subsamples|
  24. // will be skipped in |dst|. This is used when copying the decrypted bytes
  25. // back into the buffer, replacing the encrypted portions.
  26. void CopySubsamples(const std::vector<SubsampleEntry>& subsamples,
  27. const ClearBytesBufferSel sel,
  28. const uint8_t* src,
  29. uint8_t* dst) {
  30. for (size_t i = 0; i < subsamples.size(); i++) {
  31. const SubsampleEntry& subsample = subsamples[i];
  32. if (sel == kSrcContainsClearBytes) {
  33. src += subsample.clear_bytes;
  34. } else {
  35. dst += subsample.clear_bytes;
  36. }
  37. memcpy(dst, src, subsample.cypher_bytes);
  38. src += subsample.cypher_bytes;
  39. dst += subsample.cypher_bytes;
  40. }
  41. }
  42. // TODO(crbug.com/840983): This should be done in DecoderBuffer so that
  43. // additional fields are more easily handled.
  44. void CopyExtraSettings(const DecoderBuffer& input, DecoderBuffer* output) {
  45. output->set_timestamp(input.timestamp());
  46. output->set_duration(input.duration());
  47. output->set_is_key_frame(input.is_key_frame());
  48. output->CopySideDataFrom(input.side_data(), input.side_data_size());
  49. }
  50. } // namespace
  51. scoped_refptr<DecoderBuffer> DecryptCencBuffer(
  52. const DecoderBuffer& input,
  53. const crypto::SymmetricKey& key) {
  54. const char* sample = reinterpret_cast<const char*>(input.data());
  55. const size_t sample_size = input.data_size();
  56. DCHECK(sample_size) << "No data to decrypt.";
  57. const DecryptConfig* decrypt_config = input.decrypt_config();
  58. DCHECK(decrypt_config) << "No need to call Decrypt() on unencrypted buffer.";
  59. DCHECK_EQ(EncryptionScheme::kCenc, decrypt_config->encryption_scheme());
  60. const std::string& iv = decrypt_config->iv();
  61. DCHECK_EQ(iv.size(), static_cast<size_t>(DecryptConfig::kDecryptionKeySize));
  62. crypto::Encryptor encryptor;
  63. if (!encryptor.Init(&key, crypto::Encryptor::CTR, "")) {
  64. DVLOG(1) << "Could not initialize decryptor.";
  65. return nullptr;
  66. }
  67. if (!encryptor.SetCounter(iv)) {
  68. DVLOG(1) << "Could not set counter block.";
  69. return nullptr;
  70. }
  71. const std::vector<SubsampleEntry>& subsamples = decrypt_config->subsamples();
  72. if (subsamples.empty()) {
  73. std::string decrypted_text;
  74. base::StringPiece encrypted_text(sample, sample_size);
  75. if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
  76. DVLOG(1) << "Could not decrypt data.";
  77. return nullptr;
  78. }
  79. // TODO(xhwang): Find a way to avoid this data copy.
  80. auto output = DecoderBuffer::CopyFrom(
  81. reinterpret_cast<const uint8_t*>(decrypted_text.data()),
  82. decrypted_text.size());
  83. CopyExtraSettings(input, output.get());
  84. return output;
  85. }
  86. if (!VerifySubsamplesMatchSize(subsamples, sample_size)) {
  87. DVLOG(1) << "Subsample sizes do not equal input size";
  88. return nullptr;
  89. }
  90. // Compute the size of the encrypted portion. Overflow, etc. checked by
  91. // the call to VerifySubsamplesMatchSize().
  92. size_t total_encrypted_size = 0;
  93. for (const auto& subsample : subsamples)
  94. total_encrypted_size += subsample.cypher_bytes;
  95. // No need to decrypt if there is no encrypted data.
  96. if (total_encrypted_size == 0) {
  97. auto output = DecoderBuffer::CopyFrom(input.data(), sample_size);
  98. CopyExtraSettings(input, output.get());
  99. return output;
  100. }
  101. // The encrypted portions of all subsamples must form a contiguous block,
  102. // such that an encrypted subsample that ends away from a block boundary is
  103. // immediately followed by the start of the next encrypted subsample. We
  104. // copy all encrypted subsamples to a contiguous buffer, decrypt them, then
  105. // copy the decrypted bytes over the encrypted bytes in the output.
  106. // TODO(strobe): attempt to reduce number of memory copies
  107. std::unique_ptr<uint8_t[]> encrypted_bytes(new uint8_t[total_encrypted_size]);
  108. CopySubsamples(subsamples, kSrcContainsClearBytes,
  109. reinterpret_cast<const uint8_t*>(sample),
  110. encrypted_bytes.get());
  111. base::StringPiece encrypted_text(
  112. reinterpret_cast<const char*>(encrypted_bytes.get()),
  113. total_encrypted_size);
  114. std::string decrypted_text;
  115. if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
  116. DVLOG(1) << "Could not decrypt data.";
  117. return nullptr;
  118. }
  119. DCHECK_EQ(decrypted_text.size(), encrypted_text.size());
  120. scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom(
  121. reinterpret_cast<const uint8_t*>(sample), sample_size);
  122. CopySubsamples(subsamples, kDstContainsClearBytes,
  123. reinterpret_cast<const uint8_t*>(decrypted_text.data()),
  124. output->writable_data());
  125. CopyExtraSettings(input, output.get());
  126. return output;
  127. }
  128. } // namespace media