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