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