Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: media/crypto/aes_decryptor.cc

Issue 10651006: Add Common Encryption support to BMFF, including subsample decryption. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Address phantom comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/crypto/aes_decryptor.h" 5 #include "media/crypto/aes_decryptor.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "base/string_number_conversions.h" 9 #include "base/string_number_conversions.h"
10 #include "base/string_piece.h" 10 #include "base/string_piece.h"
11 #include "crypto/encryptor.h" 11 #include "crypto/encryptor.h"
12 #include "crypto/symmetric_key.h" 12 #include "crypto/symmetric_key.h"
13 #include "media/base/decoder_buffer.h" 13 #include "media/base/decoder_buffer.h"
14 #include "media/base/decrypt_config.h" 14 #include "media/base/decrypt_config.h"
15 #include "media/base/decryptor_client.h" 15 #include "media/base/decryptor_client.h"
16 16
17 namespace media { 17 namespace media {
18 18
19 // TODO(xhwang): Get real IV from frames. 19 uint32 AesDecryptor::next_session_id_ = 1;
20 static const char kInitialCounter[] = "0000000000000000";
21 20
22 uint32 AesDecryptor::next_session_id_ = 1; 21 enum ClearBytesBufferSel {
22 kSrcContainsClearBytes,
23 kDstContainsClearBytes,
24 };
25
26 static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples,
27 const ClearBytesBufferSel sel,
28 const uint8* src,
29 uint8* 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 }
23 42
24 // Decrypt |input| using |key|. 43 // Decrypt |input| using |key|.
25 // Return a DecoderBuffer with the decrypted data if decryption succeeded. 44 // Return a DecoderBuffer with the decrypted data if decryption succeeded.
26 // Return NULL if decryption failed. 45 // Return NULL if decryption failed.
27 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, 46 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input,
28 crypto::SymmetricKey* key) { 47 crypto::SymmetricKey* key) {
29 CHECK(input.GetDataSize()); 48 CHECK(input.GetDataSize());
30 CHECK(key); 49 CHECK(key);
31 50
32 // Initialize encryption data. 51 // Initialize encryption data.
33 // The IV must be exactly as long as the cipher block size. 52 // The IV must be exactly as long as the cipher block size.
53 const std::string& iv = input.GetDecryptConfig()->iv();
34 crypto::Encryptor encryptor; 54 crypto::Encryptor encryptor;
35 if (!encryptor.Init(key, crypto::Encryptor::CBC, kInitialCounter)) { 55 if (input.GetDecryptConfig()->use_cbc()) {
36 DVLOG(1) << "Could not initialize encryptor."; 56 if (!encryptor.Init(key, crypto::Encryptor::CBC, iv)) {
57 DVLOG(1) << "Could not initialize encryptor.";
58 return NULL;
59 }
60 } else {
61 if (!encryptor.Init(key, crypto::Encryptor::CTR, base::StringPiece()) ||
62 !encryptor.SetCounter(iv)) {
63 DVLOG(1) << "Could not initialize encryptor.";
64 return NULL;
65 }
66 }
67
68 if (input.GetDecryptConfig()->subsamples().empty()) {
69 std::string decrypted_text;
70 base::StringPiece encrypted_text(
71 reinterpret_cast<const char*>(input.GetData()),
72 input.GetDataSize());
73 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
74 DVLOG(1) << "Could not decrypt data.";
75 return NULL;
76 }
77
78 // TODO(xhwang): Find a way to avoid this data copy.
79 return DecoderBuffer::CopyFrom(
80 reinterpret_cast<const uint8*>(decrypted_text.data()),
81 decrypted_text.size());
82 }
83
84 const std::vector<SubsampleEntry>& subsamples =
85 input.GetDecryptConfig()->subsamples();
86
87 int total_clear_size = 0;
88 int total_encrypted_size = 0;
89 for (size_t i = 0; i < subsamples.size(); i++) {
90 total_clear_size += subsamples[i].clear_bytes;
91 total_encrypted_size += subsamples[i].cypher_bytes;
92 }
93 if (total_clear_size + total_encrypted_size != input.GetDataSize()) {
94 DVLOG(1) << "Subsample sizes do not equal input size";
37 return NULL; 95 return NULL;
38 } 96 }
39 97
98 // The encrypted portions of all subsamples must form a contiguous block,
99 // such that an encrypted subsample that ends away from a block boundary is
100 // immediately followed by the start of the next encrypted subsample. We
101 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then
102 // copy the decrypted bytes over the encrypted bytes in the output.
103 // TODO(strobe): attempt to reduce number of memory copies
104 scoped_array<uint8> encrypted_bytes(
105 new uint8[total_encrypted_size]);
106 CopySubsamples(subsamples, kSrcContainsClearBytes,
107 input.GetData(), encrypted_bytes.get());
108
40 std::string decrypted_text; 109 std::string decrypted_text;
41 base::StringPiece encrypted_text( 110 base::StringPiece encrypted_text(
42 reinterpret_cast<const char*>(input.GetData()), 111 reinterpret_cast<const char*>(encrypted_bytes.get()),
43 input.GetDataSize()); 112 total_encrypted_size);
44 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { 113 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
45 DVLOG(1) << "Could not decrypt data."; 114 DVLOG(1) << "Could not decrypt data.";
46 return NULL; 115 return NULL;
47 } 116 }
48 117
49 // TODO(xhwang): Find a way to avoid this data copy. 118 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom(
50 return DecoderBuffer::CopyFrom( 119 input.GetData(), input.GetDataSize());
51 reinterpret_cast<const uint8*>(decrypted_text.data()), 120 CopySubsamples(subsamples, kDstContainsClearBytes,
52 decrypted_text.size()); 121 reinterpret_cast<const uint8*>(decrypted_text.data()),
122 output->GetWritableData());
123 return output;
53 } 124 }
54 125
55 AesDecryptor::AesDecryptor(DecryptorClient* client) 126 AesDecryptor::AesDecryptor(DecryptorClient* client)
56 : client_(client) { 127 : client_(client) {
57 } 128 }
58 129
59 AesDecryptor::~AesDecryptor() { 130 AesDecryptor::~AesDecryptor() {
60 STLDeleteValues(&key_map_); 131 STLDeleteValues(&key_map_);
61 } 132 }
62 133
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 decrypt_cb.Run(kError, NULL); 232 decrypt_cb.Run(kError, NULL);
162 return; 233 return;
163 } 234 }
164 235
165 decrypted->SetTimestamp(encrypted->GetTimestamp()); 236 decrypted->SetTimestamp(encrypted->GetTimestamp());
166 decrypted->SetDuration(encrypted->GetDuration()); 237 decrypted->SetDuration(encrypted->GetDuration());
167 decrypt_cb.Run(kSuccess, decrypted); 238 decrypt_cb.Run(kSuccess, decrypted);
168 } 239 }
169 240
170 } // namespace media 241 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698