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#ifndef MEDIA_CRYPTO_AES_DECRYPTOR_H_
6#define MEDIA_CRYPTO_AES_DECRYPTOR_H_
7
8#include <set>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/containers/scoped_ptr_hash_map.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/synchronization/lock.h"
16#include "media/base/decryptor.h"
17#include "media/base/media_export.h"
18#include "media/base/media_keys.h"
19
20namespace crypto {
21class SymmetricKey;
22}
23
24namespace media {
25
26// Decrypts an AES encrypted buffer into an unencrypted buffer. The AES
27// encryption must be CTR with a key size of 128bits.
28class MEDIA_EXPORT AesDecryptor : public MediaKeys, public Decryptor {
29 public:
30  AesDecryptor(const SessionMessageCB& session_message_cb,
31               const SessionClosedCB& session_closed_cb,
32               const SessionKeysChangeCB& session_keys_change_cb);
33  virtual ~AesDecryptor();
34
35  // MediaKeys implementation.
36  virtual void SetServerCertificate(
37      const uint8* certificate_data,
38      int certificate_data_length,
39      scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
40  virtual void CreateSession(const std::string& init_data_type,
41                             const uint8* init_data,
42                             int init_data_length,
43                             SessionType session_type,
44                             scoped_ptr<NewSessionCdmPromise> promise) OVERRIDE;
45  virtual void LoadSession(const std::string& web_session_id,
46                           scoped_ptr<NewSessionCdmPromise> promise) OVERRIDE;
47  virtual void UpdateSession(const std::string& web_session_id,
48                             const uint8* response,
49                             int response_length,
50                             scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
51  virtual void CloseSession(const std::string& web_session_id,
52                            scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
53  virtual void RemoveSession(const std::string& web_session_id,
54                             scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
55  virtual void GetUsableKeyIds(const std::string& web_session_id,
56                               scoped_ptr<KeyIdsPromise> promise) OVERRIDE;
57  virtual Decryptor* GetDecryptor() OVERRIDE;
58
59  // Decryptor implementation.
60  virtual void RegisterNewKeyCB(StreamType stream_type,
61                                const NewKeyCB& key_added_cb) OVERRIDE;
62  virtual void Decrypt(StreamType stream_type,
63                       const scoped_refptr<DecoderBuffer>& encrypted,
64                       const DecryptCB& decrypt_cb) OVERRIDE;
65  virtual void CancelDecrypt(StreamType stream_type) OVERRIDE;
66  virtual void InitializeAudioDecoder(const AudioDecoderConfig& config,
67                                      const DecoderInitCB& init_cb) OVERRIDE;
68  virtual void InitializeVideoDecoder(const VideoDecoderConfig& config,
69                                      const DecoderInitCB& init_cb) OVERRIDE;
70  virtual void DecryptAndDecodeAudio(
71      const scoped_refptr<DecoderBuffer>& encrypted,
72      const AudioDecodeCB& audio_decode_cb) OVERRIDE;
73  virtual void DecryptAndDecodeVideo(
74      const scoped_refptr<DecoderBuffer>& encrypted,
75      const VideoDecodeCB& video_decode_cb) OVERRIDE;
76  virtual void ResetDecoder(StreamType stream_type) OVERRIDE;
77  virtual void DeinitializeDecoder(StreamType stream_type) OVERRIDE;
78
79 private:
80  // TODO(fgalligan): Remove this and change KeyMap to use crypto::SymmetricKey
81  // as there are no decryptors that are performing an integrity check.
82  // Helper class that manages the decryption key.
83  class DecryptionKey {
84   public:
85    explicit DecryptionKey(const std::string& secret);
86    ~DecryptionKey();
87
88    // Creates the encryption key.
89    bool Init();
90
91    crypto::SymmetricKey* decryption_key() { return decryption_key_.get(); }
92
93   private:
94    // The base secret that is used to create the decryption key.
95    const std::string secret_;
96
97    // The key used to decrypt the data.
98    scoped_ptr<crypto::SymmetricKey> decryption_key_;
99
100    DISALLOW_COPY_AND_ASSIGN(DecryptionKey);
101  };
102
103  // Keep track of the keys for a key ID. If multiple sessions specify keys
104  // for the same key ID, then the last key inserted is used. The structure is
105  // optimized so that Decrypt() has fast access, at the cost of slow deletion
106  // of keys when a session is released.
107  class SessionIdDecryptionKeyMap;
108
109  // Key ID <-> SessionIdDecryptionKeyMap map.
110  typedef base::ScopedPtrHashMap<std::string, SessionIdDecryptionKeyMap>
111      KeyIdToSessionKeysMap;
112
113  // Creates a DecryptionKey using |key_string| and associates it with |key_id|.
114  // Returns true if successful.
115  bool AddDecryptionKey(const std::string& web_session_id,
116                        const std::string& key_id,
117                        const std::string& key_string);
118
119  // Gets a DecryptionKey associated with |key_id|. The AesDecryptor still owns
120  // the key. Returns NULL if no key is associated with |key_id|.
121  DecryptionKey* GetKey(const std::string& key_id) const;
122
123  // Deletes all keys associated with |web_session_id|.
124  void DeleteKeysForSession(const std::string& web_session_id);
125
126  // Callbacks for firing session events.
127  SessionMessageCB session_message_cb_;
128  SessionClosedCB session_closed_cb_;
129  SessionKeysChangeCB session_keys_change_cb_;
130
131  // Since only Decrypt() is called off the renderer thread, we only need to
132  // protect |key_map_|, the only member variable that is shared between
133  // Decrypt() and other methods.
134  KeyIdToSessionKeysMap key_map_;  // Protected by |key_map_lock_|.
135  mutable base::Lock key_map_lock_;  // Protects the |key_map_|.
136
137  // Keeps track of current valid sessions.
138  std::set<std::string> valid_sessions_;
139
140  // Make web session ID unique per renderer by making it static. Web session
141  // IDs seen by the app will be "1", "2", etc.
142  static uint32 next_web_session_id_;
143
144  NewKeyCB new_audio_key_cb_;
145  NewKeyCB new_video_key_cb_;
146
147  // Protect |new_audio_key_cb_| and |new_video_key_cb_| as they are set on the
148  // main thread but called on the media thread.
149  mutable base::Lock new_key_cb_lock_;
150
151  DISALLOW_COPY_AND_ASSIGN(AesDecryptor);
152};
153
154}  // namespace media
155
156#endif  // MEDIA_CRYPTO_AES_DECRYPTOR_H_
157