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

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

Issue 1100763002: Inject CanAddURLToHistory into TopSitesImpl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@prefs
Patch Set: Fix error introduced during rebase Created 5 years, 7 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
« no previous file with comments | « media/cdm/aes_decryptor.h ('k') | media/cdm/aes_decryptor_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/cdm/aes_decryptor.h" 5 #include "media/cdm/aes_decryptor.h"
6 6
7 #include <list> 7 #include <list>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 return key_list_.end(); 98 return key_list_.end();
99 } 99 }
100 100
101 void AesDecryptor::SessionIdDecryptionKeyMap::Erase( 101 void AesDecryptor::SessionIdDecryptionKeyMap::Erase(
102 KeyList::iterator position) { 102 KeyList::iterator position) {
103 DCHECK(position->second); 103 DCHECK(position->second);
104 delete position->second; 104 delete position->second;
105 key_list_.erase(position); 105 key_list_.erase(position);
106 } 106 }
107 107
108 uint32 AesDecryptor::next_session_id_ = 1; 108 uint32_t AesDecryptor::next_session_id_ = 1;
109 109
110 enum ClearBytesBufferSel { 110 enum ClearBytesBufferSel {
111 kSrcContainsClearBytes, 111 kSrcContainsClearBytes,
112 kDstContainsClearBytes 112 kDstContainsClearBytes
113 }; 113 };
114 114
115 static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, 115 static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples,
116 const ClearBytesBufferSel sel, 116 const ClearBytesBufferSel sel,
117 const uint8* src, 117 const uint8_t* src,
118 uint8* dst) { 118 uint8_t* dst) {
119 for (size_t i = 0; i < subsamples.size(); i++) { 119 for (size_t i = 0; i < subsamples.size(); i++) {
120 const SubsampleEntry& subsample = subsamples[i]; 120 const SubsampleEntry& subsample = subsamples[i];
121 if (sel == kSrcContainsClearBytes) { 121 if (sel == kSrcContainsClearBytes) {
122 src += subsample.clear_bytes; 122 src += subsample.clear_bytes;
123 } else { 123 } else {
124 dst += subsample.clear_bytes; 124 dst += subsample.clear_bytes;
125 } 125 }
126 memcpy(dst, src, subsample.cypher_bytes); 126 memcpy(dst, src, subsample.cypher_bytes);
127 src += subsample.cypher_bytes; 127 src += subsample.cypher_bytes;
128 dst += subsample.cypher_bytes; 128 dst += subsample.cypher_bytes;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 if (input.decrypt_config()->subsamples().empty()) { 160 if (input.decrypt_config()->subsamples().empty()) {
161 std::string decrypted_text; 161 std::string decrypted_text;
162 base::StringPiece encrypted_text(sample, sample_size); 162 base::StringPiece encrypted_text(sample, sample_size);
163 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { 163 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
164 DVLOG(1) << "Could not decrypt data."; 164 DVLOG(1) << "Could not decrypt data.";
165 return NULL; 165 return NULL;
166 } 166 }
167 167
168 // TODO(xhwang): Find a way to avoid this data copy. 168 // TODO(xhwang): Find a way to avoid this data copy.
169 return DecoderBuffer::CopyFrom( 169 return DecoderBuffer::CopyFrom(
170 reinterpret_cast<const uint8*>(decrypted_text.data()), 170 reinterpret_cast<const uint8_t*>(decrypted_text.data()),
171 decrypted_text.size()); 171 decrypted_text.size());
172 } 172 }
173 173
174 const std::vector<SubsampleEntry>& subsamples = 174 const std::vector<SubsampleEntry>& subsamples =
175 input.decrypt_config()->subsamples(); 175 input.decrypt_config()->subsamples();
176 176
177 size_t total_clear_size = 0; 177 size_t total_clear_size = 0;
178 size_t total_encrypted_size = 0; 178 size_t total_encrypted_size = 0;
179 for (size_t i = 0; i < subsamples.size(); i++) { 179 for (size_t i = 0; i < subsamples.size(); i++) {
180 total_clear_size += subsamples[i].clear_bytes; 180 total_clear_size += subsamples[i].clear_bytes;
181 total_encrypted_size += subsamples[i].cypher_bytes; 181 total_encrypted_size += subsamples[i].cypher_bytes;
182 // Check for overflow. This check is valid because *_size is unsigned. 182 // Check for overflow. This check is valid because *_size is unsigned.
183 DCHECK(total_clear_size >= subsamples[i].clear_bytes); 183 DCHECK(total_clear_size >= subsamples[i].clear_bytes);
184 if (total_encrypted_size < subsamples[i].cypher_bytes) 184 if (total_encrypted_size < subsamples[i].cypher_bytes)
185 return NULL; 185 return NULL;
186 } 186 }
187 size_t total_size = total_clear_size + total_encrypted_size; 187 size_t total_size = total_clear_size + total_encrypted_size;
188 if (total_size < total_clear_size || total_size != sample_size) { 188 if (total_size < total_clear_size || total_size != sample_size) {
189 DVLOG(1) << "Subsample sizes do not equal input size"; 189 DVLOG(1) << "Subsample sizes do not equal input size";
190 return NULL; 190 return NULL;
191 } 191 }
192 192
193 // No need to decrypt if there is no encrypted data. 193 // No need to decrypt if there is no encrypted data.
194 if (total_encrypted_size <= 0) { 194 if (total_encrypted_size <= 0) {
195 return DecoderBuffer::CopyFrom(reinterpret_cast<const uint8*>(sample), 195 return DecoderBuffer::CopyFrom(reinterpret_cast<const uint8_t*>(sample),
196 sample_size); 196 sample_size);
197 } 197 }
198 198
199 // The encrypted portions of all subsamples must form a contiguous block, 199 // The encrypted portions of all subsamples must form a contiguous block,
200 // such that an encrypted subsample that ends away from a block boundary is 200 // such that an encrypted subsample that ends away from a block boundary is
201 // immediately followed by the start of the next encrypted subsample. We 201 // immediately followed by the start of the next encrypted subsample. We
202 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then 202 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then
203 // copy the decrypted bytes over the encrypted bytes in the output. 203 // copy the decrypted bytes over the encrypted bytes in the output.
204 // TODO(strobe): attempt to reduce number of memory copies 204 // TODO(strobe): attempt to reduce number of memory copies
205 scoped_ptr<uint8[]> encrypted_bytes(new uint8[total_encrypted_size]); 205 scoped_ptr<uint8_t[]> encrypted_bytes(new uint8_t[total_encrypted_size]);
206 CopySubsamples(subsamples, kSrcContainsClearBytes, 206 CopySubsamples(subsamples, kSrcContainsClearBytes,
207 reinterpret_cast<const uint8*>(sample), encrypted_bytes.get()); 207 reinterpret_cast<const uint8_t*>(sample),
208 encrypted_bytes.get());
208 209
209 base::StringPiece encrypted_text( 210 base::StringPiece encrypted_text(
210 reinterpret_cast<const char*>(encrypted_bytes.get()), 211 reinterpret_cast<const char*>(encrypted_bytes.get()),
211 total_encrypted_size); 212 total_encrypted_size);
212 std::string decrypted_text; 213 std::string decrypted_text;
213 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { 214 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
214 DVLOG(1) << "Could not decrypt data."; 215 DVLOG(1) << "Could not decrypt data.";
215 return NULL; 216 return NULL;
216 } 217 }
217 DCHECK_EQ(decrypted_text.size(), encrypted_text.size()); 218 DCHECK_EQ(decrypted_text.size(), encrypted_text.size());
218 219
219 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( 220 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom(
220 reinterpret_cast<const uint8*>(sample), sample_size); 221 reinterpret_cast<const uint8_t*>(sample), sample_size);
221 CopySubsamples(subsamples, kDstContainsClearBytes, 222 CopySubsamples(subsamples, kDstContainsClearBytes,
222 reinterpret_cast<const uint8*>(decrypted_text.data()), 223 reinterpret_cast<const uint8_t*>(decrypted_text.data()),
223 output->writable_data()); 224 output->writable_data());
224 return output; 225 return output;
225 } 226 }
226 227
227 AesDecryptor::AesDecryptor(const GURL& /* security_origin */, 228 AesDecryptor::AesDecryptor(const GURL& /* security_origin */,
228 const SessionMessageCB& session_message_cb, 229 const SessionMessageCB& session_message_cb,
229 const SessionClosedCB& session_closed_cb, 230 const SessionClosedCB& session_closed_cb,
230 const SessionKeysChangeCB& session_keys_change_cb) 231 const SessionKeysChangeCB& session_keys_change_cb)
231 : session_message_cb_(session_message_cb), 232 : session_message_cb_(session_message_cb),
232 session_closed_cb_(session_closed_cb), 233 session_closed_cb_(session_closed_cb),
233 session_keys_change_cb_(session_keys_change_cb) { 234 session_keys_change_cb_(session_keys_change_cb) {
234 // AesDecryptor doesn't keep any persistent data, so no need to do anything 235 // AesDecryptor doesn't keep any persistent data, so no need to do anything
235 // with |security_origin|. 236 // with |security_origin|.
236 DCHECK(!session_message_cb_.is_null()); 237 DCHECK(!session_message_cb_.is_null());
237 DCHECK(!session_closed_cb_.is_null()); 238 DCHECK(!session_closed_cb_.is_null());
238 DCHECK(!session_keys_change_cb_.is_null()); 239 DCHECK(!session_keys_change_cb_.is_null());
239 } 240 }
240 241
241 AesDecryptor::~AesDecryptor() { 242 AesDecryptor::~AesDecryptor() {
242 key_map_.clear(); 243 key_map_.clear();
243 } 244 }
244 245
245 void AesDecryptor::SetServerCertificate(const uint8* certificate_data, 246 void AesDecryptor::SetServerCertificate(const std::vector<uint8_t>& certificate,
246 int certificate_data_length,
247 scoped_ptr<SimpleCdmPromise> promise) { 247 scoped_ptr<SimpleCdmPromise> promise) {
248 promise->reject( 248 promise->reject(
249 NOT_SUPPORTED_ERROR, 0, "SetServerCertificate() is not supported."); 249 NOT_SUPPORTED_ERROR, 0, "SetServerCertificate() is not supported.");
250 } 250 }
251 251
252 void AesDecryptor::CreateSessionAndGenerateRequest( 252 void AesDecryptor::CreateSessionAndGenerateRequest(
253 SessionType session_type, 253 SessionType session_type,
254 EmeInitDataType init_data_type, 254 EmeInitDataType init_data_type,
255 const uint8* init_data, 255 const std::vector<uint8_t>& init_data,
256 int init_data_length,
257 scoped_ptr<NewSessionCdmPromise> promise) { 256 scoped_ptr<NewSessionCdmPromise> promise) {
258 std::string session_id(base::UintToString(next_session_id_++)); 257 std::string session_id(base::UintToString(next_session_id_++));
259 valid_sessions_.insert(session_id); 258 valid_sessions_.insert(session_id);
260 259
261 // For now, the AesDecryptor does not care about |session_type|. 260 // For now, the AesDecryptor does not care about |session_type|.
262 // TODO(jrummell): Validate |session_type|. 261 // TODO(jrummell): Validate |session_type|.
263 262
264 std::vector<uint8> message; 263 std::vector<uint8_t> message;
265 // TODO(jrummell): Since unprefixed will never send NULL, remove this check 264 // TODO(jrummell): Since unprefixed will never send NULL, remove this check
266 // when prefixed EME is removed (http://crbug.com/249976). 265 // when prefixed EME is removed (http://crbug.com/249976).
267 if (init_data && init_data_length) { 266 if (!init_data.empty()) {
268 std::vector<std::vector<uint8>> keys; 267 std::vector<std::vector<uint8_t>> keys;
269 switch (init_data_type) { 268 switch (init_data_type) {
270 case EmeInitDataType::WEBM: 269 case EmeInitDataType::WEBM:
271 // |init_data| is simply the key needed. 270 // |init_data| is simply the key needed.
272 keys.push_back( 271 keys.push_back(init_data);
273 std::vector<uint8>(init_data, init_data + init_data_length));
274 break; 272 break;
275 case EmeInitDataType::CENC: 273 case EmeInitDataType::CENC:
276 // |init_data| is a set of 0 or more concatenated 'pssh' boxes. 274 // |init_data| is a set of 0 or more concatenated 'pssh' boxes.
277 if (!GetKeyIdsForCommonSystemId(init_data, init_data_length, &keys)) { 275 if (!GetKeyIdsForCommonSystemId(init_data, &keys)) {
278 promise->reject(NOT_SUPPORTED_ERROR, 0, 276 promise->reject(NOT_SUPPORTED_ERROR, 0,
279 "No supported PSSH box found."); 277 "No supported PSSH box found.");
280 return; 278 return;
281 } 279 }
282 break; 280 break;
283 case EmeInitDataType::KEYIDS: { 281 case EmeInitDataType::KEYIDS: {
284 std::string init_data_string(init_data, init_data + init_data_length); 282 std::string init_data_string(init_data.begin(), init_data.end());
285 std::string error_message; 283 std::string error_message;
286 if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys, 284 if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys,
287 &error_message)) { 285 &error_message)) {
288 promise->reject(NOT_SUPPORTED_ERROR, 0, error_message); 286 promise->reject(NOT_SUPPORTED_ERROR, 0, error_message);
289 return; 287 return;
290 } 288 }
291 break; 289 break;
292 } 290 }
293 default: 291 default:
294 NOTREACHED(); 292 NOTREACHED();
(...skipping 13 matching lines...) Expand all
308 306
309 void AesDecryptor::LoadSession(SessionType session_type, 307 void AesDecryptor::LoadSession(SessionType session_type,
310 const std::string& session_id, 308 const std::string& session_id,
311 scoped_ptr<NewSessionCdmPromise> promise) { 309 scoped_ptr<NewSessionCdmPromise> promise) {
312 // TODO(xhwang): Change this to NOTREACHED() when blink checks for key systems 310 // TODO(xhwang): Change this to NOTREACHED() when blink checks for key systems
313 // that do not support loadSession. See http://crbug.com/342481 311 // that do not support loadSession. See http://crbug.com/342481
314 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); 312 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported.");
315 } 313 }
316 314
317 void AesDecryptor::UpdateSession(const std::string& session_id, 315 void AesDecryptor::UpdateSession(const std::string& session_id,
318 const uint8* response, 316 const std::vector<uint8_t>& response,
319 int response_length,
320 scoped_ptr<SimpleCdmPromise> promise) { 317 scoped_ptr<SimpleCdmPromise> promise) {
321 CHECK(response); 318 CHECK(!response.empty());
322 CHECK_GT(response_length, 0);
323 319
324 // TODO(jrummell): Convert back to a DCHECK once prefixed EME is removed. 320 // TODO(jrummell): Convert back to a DCHECK once prefixed EME is removed.
325 if (valid_sessions_.find(session_id) == valid_sessions_.end()) { 321 if (valid_sessions_.find(session_id) == valid_sessions_.end()) {
326 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); 322 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist.");
327 return; 323 return;
328 } 324 }
329 325
330 std::string key_string(reinterpret_cast<const char*>(response), 326 std::string key_string(response.begin(), response.end());
331 response_length);
332 327
333 KeyIdAndKeyPairs keys; 328 KeyIdAndKeyPairs keys;
334 SessionType session_type = MediaKeys::TEMPORARY_SESSION; 329 SessionType session_type = MediaKeys::TEMPORARY_SESSION;
335 if (!ExtractKeysFromJWKSet(key_string, &keys, &session_type)) { 330 if (!ExtractKeysFromJWKSet(key_string, &keys, &session_type)) {
336 promise->reject( 331 promise->reject(
337 INVALID_ACCESS_ERROR, 0, "Response is not a valid JSON Web Key Set."); 332 INVALID_ACCESS_ERROR, 0, "Response is not a valid JSON Web Key Set.");
338 return; 333 return;
339 } 334 }
340 335
341 // Make sure that at least one key was extracted. 336 // Make sure that at least one key was extracted.
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 bool AesDecryptor::DecryptionKey::Init() { 595 bool AesDecryptor::DecryptionKey::Init() {
601 CHECK(!secret_.empty()); 596 CHECK(!secret_.empty());
602 decryption_key_.reset(crypto::SymmetricKey::Import( 597 decryption_key_.reset(crypto::SymmetricKey::Import(
603 crypto::SymmetricKey::AES, secret_)); 598 crypto::SymmetricKey::AES, secret_));
604 if (!decryption_key_) 599 if (!decryption_key_)
605 return false; 600 return false;
606 return true; 601 return true;
607 } 602 }
608 603
609 } // namespace media 604 } // namespace media
OLDNEW
« no previous file with comments | « media/cdm/aes_decryptor.h ('k') | media/cdm/aes_decryptor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698