aes_decryptor.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 3// found in the LICENSE file. 4 5#include "media/cdm/aes_decryptor.h" 6 7#include <vector> 8 9#include "base/logging.h" 10#include "base/stl_util.h" 11#include "base/strings/string_number_conversions.h" 12#include "crypto/encryptor.h" 13#include "crypto/symmetric_key.h" 14#include "media/base/audio_decoder_config.h" 15#include "media/base/decoder_buffer.h" 16#include "media/base/decrypt_config.h" 17#include "media/base/video_decoder_config.h" 18#include "media/base/video_frame.h" 19#include "media/cdm/json_web_key.h" 20 21namespace media { 22 23uint32 AesDecryptor::next_session_id_ = 1; 24 25enum ClearBytesBufferSel { 26 kSrcContainsClearBytes, 27 kDstContainsClearBytes 28}; 29 30static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, 31 const ClearBytesBufferSel sel, 32 const uint8* src, 33 uint8* dst) { 34 for (size_t i = 0; i < subsamples.size(); i++) { 35 const SubsampleEntry& subsample = subsamples[i]; 36 if (sel == kSrcContainsClearBytes) { 37 src += subsample.clear_bytes; 38 } else { 39 dst += subsample.clear_bytes; 40 } 41 memcpy(dst, src, subsample.cypher_bytes); 42 src += subsample.cypher_bytes; 43 dst += subsample.cypher_bytes; 44 } 45} 46 47// Decrypts |input| using |key|. Returns a DecoderBuffer with the decrypted 48// data if decryption succeeded or NULL if decryption failed. 49static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, 50 crypto::SymmetricKey* key) { 51 CHECK(input.data_size()); 52 CHECK(input.decrypt_config()); 53 CHECK(key); 54 55 crypto::Encryptor encryptor; 56 if (!encryptor.Init(key, crypto::Encryptor::CTR, "")) { 57 DVLOG(1) << "Could not initialize decryptor."; 58 return NULL; 59 } 60 61 DCHECK_EQ(input.decrypt_config()->iv().size(), 62 static_cast<size_t>(DecryptConfig::kDecryptionKeySize)); 63 if (!encryptor.SetCounter(input.decrypt_config()->iv())) { 64 DVLOG(1) << "Could not set counter block."; 65 return NULL; 66 } 67 68 const int data_offset = input.decrypt_config()->data_offset(); 69 const char* sample = 70 reinterpret_cast<const char*>(input.data() + data_offset); 71 DCHECK_GT(input.data_size(), data_offset); 72 size_t sample_size = static_cast<size_t>(input.data_size() - data_offset); 73 74 DCHECK_GT(sample_size, 0U) << "No sample data to be decrypted."; 75 if (sample_size == 0) 76 return NULL; 77 78 if (input.decrypt_config()->subsamples().empty()) { 79 std::string decrypted_text; 80 base::StringPiece encrypted_text(sample, sample_size); 81 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { 82 DVLOG(1) << "Could not decrypt data."; 83 return NULL; 84 } 85 86 // TODO(xhwang): Find a way to avoid this data copy. 87 return DecoderBuffer::CopyFrom( 88 reinterpret_cast<const uint8*>(decrypted_text.data()), 89 decrypted_text.size()); 90 } 91 92 const std::vector<SubsampleEntry>& subsamples = 93 input.decrypt_config()->subsamples(); 94 95 size_t total_clear_size = 0; 96 size_t total_encrypted_size = 0; 97 for (size_t i = 0; i < subsamples.size(); i++) { 98 total_clear_size += subsamples[i].clear_bytes; 99 total_encrypted_size += subsamples[i].cypher_bytes; 100 // Check for overflow. This check is valid because *_size is unsigned. 101 DCHECK(total_clear_size >= subsamples[i].clear_bytes); 102 if (total_encrypted_size < subsamples[i].cypher_bytes) 103 return NULL; 104 } 105 size_t total_size = total_clear_size + total_encrypted_size; 106 if (total_size < total_clear_size || total_size != sample_size) { 107 DVLOG(1) << "Subsample sizes do not equal input size"; 108 return NULL; 109 } 110 111 // No need to decrypt if there is no encrypted data. 112 if (total_encrypted_size <= 0) { 113 return DecoderBuffer::CopyFrom(reinterpret_cast<const uint8*>(sample), 114 sample_size); 115 } 116 117 // The encrypted portions of all subsamples must form a contiguous block, 118 // such that an encrypted subsample that ends away from a block boundary is 119 // immediately followed by the start of the next encrypted subsample. We 120 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then 121 // copy the decrypted bytes over the encrypted bytes in the output. 122 // TODO(strobe): attempt to reduce number of memory copies 123 scoped_ptr<uint8[]> encrypted_bytes(new uint8[total_encrypted_size]); 124 CopySubsamples(subsamples, kSrcContainsClearBytes, 125 reinterpret_cast<const uint8*>(sample), encrypted_bytes.get()); 126 127 base::StringPiece encrypted_text( 128 reinterpret_cast<const char*>(encrypted_bytes.get()), 129 total_encrypted_size); 130 std::string decrypted_text; 131 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { 132 DVLOG(1) << "Could not decrypt data."; 133 return NULL; 134 } 135 DCHECK_EQ(decrypted_text.size(), encrypted_text.size()); 136 137 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( 138 reinterpret_cast<const uint8*>(sample), sample_size); 139 CopySubsamples(subsamples, kDstContainsClearBytes, 140 reinterpret_cast<const uint8*>(decrypted_text.data()), 141 output->writable_data()); 142 return output; 143} 144 145AesDecryptor::AesDecryptor(const KeyAddedCB& key_added_cb, 146 const KeyErrorCB& key_error_cb, 147 const KeyMessageCB& key_message_cb, 148 const SetSessionIdCB& set_session_id_cb) 149 : key_added_cb_(key_added_cb), 150 key_error_cb_(key_error_cb), 151 key_message_cb_(key_message_cb), 152 set_session_id_cb_(set_session_id_cb) {} 153 154AesDecryptor::~AesDecryptor() { 155 STLDeleteValues(&key_map_); 156} 157 158bool AesDecryptor::GenerateKeyRequest(uint32 reference_id, 159 const std::string& type, 160 const uint8* init_data, 161 int init_data_length) { 162 std::string session_id_string(base::UintToString(next_session_id_++)); 163 164 // For now, the AesDecryptor does not care about |type|; 165 // just fire the event with the |init_data| as the request. 166 std::vector<uint8> message; 167 if (init_data && init_data_length) 168 message.assign(init_data, init_data + init_data_length); 169 170 set_session_id_cb_.Run(reference_id, session_id_string); 171 key_message_cb_.Run(reference_id, message, std::string()); 172 return true; 173} 174 175void AesDecryptor::AddKey(uint32 reference_id, 176 const uint8* key, 177 int key_length, 178 const uint8* init_data, 179 int init_data_length) { 180 CHECK(key); 181 CHECK_GT(key_length, 0); 182 DCHECK(!init_data); 183 DCHECK_EQ(init_data_length, 0); 184 185 // AddKey() is called from update(), where the key(s) are passed as a JSON 186 // Web Key (JWK) set. Each JWK needs to be a symmetric key ('kty' = "oct"), 187 // with 'kid' being the base64-encoded key id, and 'k' being the 188 // base64-encoded key. 189 std::string key_string(reinterpret_cast<const char*>(key), key_length); 190 KeyIdAndKeyPairs keys; 191 if (!ExtractKeysFromJWKSet(key_string, &keys)) { 192 key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0); 193 return; 194 } 195 196 // Make sure that at least one key was extracted. 197 if (keys.empty()) { 198 key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0); 199 return; 200 } 201 202 for (KeyIdAndKeyPairs::iterator it = keys.begin(); it != keys.end(); ++it) { 203 if (it->second.length() != 204 static_cast<size_t>(DecryptConfig::kDecryptionKeySize)) { 205 DVLOG(1) << "Invalid key length: " << key_string.length(); 206 key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0); 207 return; 208 } 209 if (!AddDecryptionKey(it->first, it->second)) { 210 key_error_cb_.Run(reference_id, MediaKeys::kUnknownError, 0); 211 return; 212 } 213 } 214 215 if (!new_audio_key_cb_.is_null()) 216 new_audio_key_cb_.Run(); 217 218 if (!new_video_key_cb_.is_null()) 219 new_video_key_cb_.Run(); 220 221 key_added_cb_.Run(reference_id); 222} 223 224void AesDecryptor::CancelKeyRequest(uint32 reference_id) { 225} 226 227Decryptor* AesDecryptor::GetDecryptor() { 228 return this; 229} 230 231void AesDecryptor::RegisterNewKeyCB(StreamType stream_type, 232 const NewKeyCB& new_key_cb) { 233 switch (stream_type) { 234 case kAudio: 235 new_audio_key_cb_ = new_key_cb; 236 break; 237 case kVideo: 238 new_video_key_cb_ = new_key_cb; 239 break; 240 default: 241 NOTREACHED(); 242 } 243} 244 245void AesDecryptor::Decrypt(StreamType stream_type, 246 const scoped_refptr<DecoderBuffer>& encrypted, 247 const DecryptCB& decrypt_cb) { 248 CHECK(encrypted->decrypt_config()); 249 250 scoped_refptr<DecoderBuffer> decrypted; 251 // An empty iv string signals that the frame is unencrypted. 252 if (encrypted->decrypt_config()->iv().empty()) { 253 int data_offset = encrypted->decrypt_config()->data_offset(); 254 decrypted = DecoderBuffer::CopyFrom(encrypted->data() + data_offset, 255 encrypted->data_size() - data_offset); 256 } else { 257 const std::string& key_id = encrypted->decrypt_config()->key_id(); 258 DecryptionKey* key = GetKey(key_id); 259 if (!key) { 260 DVLOG(1) << "Could not find a matching key for the given key ID."; 261 decrypt_cb.Run(kNoKey, NULL); 262 return; 263 } 264 265 crypto::SymmetricKey* decryption_key = key->decryption_key(); 266 decrypted = DecryptData(*encrypted.get(), decryption_key); 267 if (!decrypted.get()) { 268 DVLOG(1) << "Decryption failed."; 269 decrypt_cb.Run(kError, NULL); 270 return; 271 } 272 } 273 274 decrypted->set_timestamp(encrypted->timestamp()); 275 decrypted->set_duration(encrypted->duration()); 276 decrypt_cb.Run(kSuccess, decrypted); 277} 278 279void AesDecryptor::CancelDecrypt(StreamType stream_type) { 280 // Decrypt() calls the DecryptCB synchronously so there's nothing to cancel. 281} 282 283void AesDecryptor::InitializeAudioDecoder(const AudioDecoderConfig& config, 284 const DecoderInitCB& init_cb) { 285 // AesDecryptor does not support audio decoding. 286 init_cb.Run(false); 287} 288 289void AesDecryptor::InitializeVideoDecoder(const VideoDecoderConfig& config, 290 const DecoderInitCB& init_cb) { 291 // AesDecryptor does not support video decoding. 292 init_cb.Run(false); 293} 294 295void AesDecryptor::DecryptAndDecodeAudio( 296 const scoped_refptr<DecoderBuffer>& encrypted, 297 const AudioDecodeCB& audio_decode_cb) { 298 NOTREACHED() << "AesDecryptor does not support audio decoding"; 299} 300 301void AesDecryptor::DecryptAndDecodeVideo( 302 const scoped_refptr<DecoderBuffer>& encrypted, 303 const VideoDecodeCB& video_decode_cb) { 304 NOTREACHED() << "AesDecryptor does not support video decoding"; 305} 306 307void AesDecryptor::ResetDecoder(StreamType stream_type) { 308 NOTREACHED() << "AesDecryptor does not support audio/video decoding"; 309} 310 311void AesDecryptor::DeinitializeDecoder(StreamType stream_type) { 312 NOTREACHED() << "AesDecryptor does not support audio/video decoding"; 313} 314 315bool AesDecryptor::AddDecryptionKey(const std::string& key_id, 316 const std::string& key_string) { 317 scoped_ptr<DecryptionKey> decryption_key(new DecryptionKey(key_string)); 318 if (!decryption_key) { 319 DVLOG(1) << "Could not create key."; 320 return false; 321 } 322 323 if (!decryption_key->Init()) { 324 DVLOG(1) << "Could not initialize decryption key."; 325 return false; 326 } 327 328 base::AutoLock auto_lock(key_map_lock_); 329 KeyMap::iterator found = key_map_.find(key_id); 330 if (found != key_map_.end()) { 331 delete found->second; 332 key_map_.erase(found); 333 } 334 key_map_[key_id] = decryption_key.release(); 335 return true; 336} 337 338AesDecryptor::DecryptionKey* AesDecryptor::GetKey( 339 const std::string& key_id) const { 340 base::AutoLock auto_lock(key_map_lock_); 341 KeyMap::const_iterator found = key_map_.find(key_id); 342 if (found == key_map_.end()) 343 return NULL; 344 345 return found->second; 346} 347 348AesDecryptor::DecryptionKey::DecryptionKey(const std::string& secret) 349 : secret_(secret) { 350} 351 352AesDecryptor::DecryptionKey::~DecryptionKey() {} 353 354bool AesDecryptor::DecryptionKey::Init() { 355 CHECK(!secret_.empty()); 356 decryption_key_.reset(crypto::SymmetricKey::Import( 357 crypto::SymmetricKey::AES, secret_)); 358 if (!decryption_key_) 359 return false; 360 return true; 361} 362 363} // namespace media 364