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

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: Fix another case issue 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.
20 static const char kInitialCounter[] = "0000000000000000";
21
22 uint32 AesDecryptor::next_session_id_ = 1; 19 uint32 AesDecryptor::next_session_id_ = 1;
23 20
24 // Decrypt |input| using |key|. 21 // Decrypt |input| using |key|.
25 // Return a DecoderBuffer with the decrypted data if decryption succeeded. 22 // Return a DecoderBuffer with the decrypted data if decryption succeeded.
26 // Return NULL if decryption failed. 23 // Return NULL if decryption failed.
27 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, 24 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input,
28 crypto::SymmetricKey* key) { 25 crypto::SymmetricKey* key) {
29 CHECK(input.GetDataSize()); 26 CHECK(input.GetDataSize());
30 CHECK(key); 27 CHECK(key);
31 28
29 base::StringPiece iv(
30 reinterpret_cast<const char*>(input.GetDecryptConfig()->iv()),
31 input.GetDecryptConfig()->iv_size());
xhwang 2012/06/27 19:37:43 Life will be easier here if we use std::string for
strobe_ 2012/07/13 00:47:07 Done.
32
32 // Initialize encryption data. 33 // Initialize encryption data.
33 // The IV must be exactly as long as the cipher block size. 34 // The IV must be exactly as long as the cipher block size.
34 crypto::Encryptor encryptor; 35 crypto::Encryptor encryptor;
35 if (!encryptor.Init(key, crypto::Encryptor::CBC, kInitialCounter)) { 36 if (input.GetDecryptConfig()->use_cbc()) {
36 DVLOG(1) << "Could not initialize encryptor."; 37 if (!encryptor.Init(key, crypto::Encryptor::CBC, iv)) {
37 return NULL; 38 DVLOG(1) << "Could not initialize encryptor.";
39 return NULL;
40 }
41 } else {
42 if (!encryptor.Init(key, crypto::Encryptor::CTR, base::StringPiece()) ||
43 !encryptor.SetCounter(iv)) {
44 DVLOG(1) << "Could not initialize encryptor.";
45 return NULL;
46 }
38 } 47 }
39 48
40 std::string decrypted_text; 49 if (!input.GetDecryptConfig()->subsamples().empty()) {
41 base::StringPiece encrypted_text( 50 // XXX(strobe): factor out and test before final commit
ddorwin 2012/07/03 21:03:47 XXX? TODO?
strobe_ 2012/07/13 00:47:07 Done.
42 reinterpret_cast<const char*>(input.GetData()), 51 const std::vector<SubsampleEntry> subsamples =
ddorwin 2012/07/03 21:03:47 const ref instead of copying
strobe_ 2012/07/13 00:47:07 Done.
43 input.GetDataSize()); 52 input.GetDecryptConfig()->subsamples();
44 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { 53
45 DVLOG(1) << "Could not decrypt data."; 54 int total_encrypted_subsample_size = 0;
46 return NULL; 55 for (size_t i = 0; i < subsamples.size(); i++)
56 total_encrypted_subsample_size += subsamples[i].cypher_bytes;
57
58 if (total_encrypted_subsample_size > input.GetDataSize()) {
ddorwin 2012/07/03 21:03:47 Should we also check that enc plus unenc are == da
strobe_ 2012/07/13 00:47:07 Done.
59 DVLOG(1) << "Subsample encrypted size larger than input size";
60 return NULL;
61 }
62
63 // The encrypted portion of each subsample must form a contiguous block,
ddorwin 2012/07/03 21:03:47 This line seems to discuss a single subsample rath
strobe_ 2012/07/13 00:47:07 Done.
64 // such that an encrypted subsample that ends away from a block boundary is
65 // immediately followed by the start of the next encrypted subsample. We
66 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then
67 // copy the decrypted bytes over the encrypted bytes in the output.
68 // TODO(strobe): attempt to reduce number of memory copies
69 scoped_array<uint8> encrypted_bytes(
70 new uint8[total_encrypted_subsample_size]);
71 int in_pos = 0, out_pos = 0;
xhwang 2012/06/27 19:37:43 Prefer to declaring variables on separate lines. I
strobe_ 2012/07/13 00:47:07 Done.
72 for (size_t i = 0; i < subsamples.size(); i++) {
73 const SubsampleEntry& subsample = subsamples[i];
74 in_pos += subsample.clear_bytes;
75 if (in_pos + subsample.cypher_bytes > input.GetDataSize()) {
76 DVLOG(1) << "Subsample total size larger than input size";
77 return NULL;
78 }
79 memcpy(encrypted_bytes.get() + out_pos, input.GetData() + in_pos,
80 subsample.cypher_bytes);
81 in_pos += subsample.cypher_bytes;
82 out_pos += subsample.cypher_bytes;
83 }
84
85 std::string decrypted_text;
86 base::StringPiece encrypted_text(
87 reinterpret_cast<const char*>(encrypted_bytes.get()),
88 total_encrypted_subsample_size);
89 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
90 DVLOG(1) << "Could not decrypt data.";
91 return NULL;
92 }
93
94 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom(
95 input.GetData(), input.GetDataSize());
96 in_pos = 0;
97 out_pos = 0;
98 for (size_t i = 0; i < subsamples.size(); i++) {
99 const SubsampleEntry& subsample = subsamples[i];
100 out_pos += subsample.clear_bytes;
101 memcpy(output->GetWritableData() + out_pos,
102 reinterpret_cast<const uint8*>(decrypted_text.data()) + in_pos,
103 subsample.cypher_bytes);
104 in_pos += subsample.cypher_bytes;
105 out_pos += subsample.cypher_bytes;
xhwang 2012/06/27 19:37:43 This part is so similar to the block starting from
strobe_ 2012/07/13 00:47:07 Done.
106 }
107 return output;
108 } else {
xhwang 2012/06/27 19:37:43 nit: we don't need this "else" since "if" will alw
strobe_ 2012/07/13 00:47:07 Done.
109 std::string decrypted_text;
110 base::StringPiece encrypted_text(
111 reinterpret_cast<const char*>(input.GetData()),
112 input.GetDataSize());
113 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
114 DVLOG(1) << "Could not decrypt data.";
115 return NULL;
116 }
117
118 // TODO(xhwang): Find a way to avoid this data copy.
119 return DecoderBuffer::CopyFrom(
120 reinterpret_cast<const uint8*>(decrypted_text.data()),
121 decrypted_text.size());
47 } 122 }
48
49 // TODO(xhwang): Find a way to avoid this data copy.
50 return DecoderBuffer::CopyFrom(
51 reinterpret_cast<const uint8*>(decrypted_text.data()),
52 decrypted_text.size());
53 } 123 }
54 124
55 AesDecryptor::AesDecryptor(DecryptorClient* client) 125 AesDecryptor::AesDecryptor(DecryptorClient* client)
56 : client_(client) { 126 : client_(client) {
57 } 127 }
58 128
59 AesDecryptor::~AesDecryptor() { 129 AesDecryptor::~AesDecryptor() {
60 STLDeleteValues(&key_map_); 130 STLDeleteValues(&key_map_);
61 } 131 }
62 132
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 225
156 if (decrypted) { 226 if (decrypted) {
157 decrypted->SetTimestamp(encrypted->GetTimestamp()); 227 decrypted->SetTimestamp(encrypted->GetTimestamp());
158 decrypted->SetDuration(encrypted->GetDuration()); 228 decrypted->SetDuration(encrypted->GetDuration());
159 } 229 }
160 230
161 return decrypted; 231 return decrypted;
162 } 232 }
163 233
164 } // namespace media 234 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698