1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_CRYPTO_AES_DECRYPTOR_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_CRYPTO_AES_DECRYPTOR_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/containers/scoped_ptr_hash_map.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/decryptor.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_export.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "media/base/media_keys.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SymmetricKey;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decrypts an AES encrypted buffer into an unencrypted buffer. The AES
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encryption must be CTR with a key size of 128bits.
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class MEDIA_EXPORT AesDecryptor : public MediaKeys, public Decryptor {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AesDecryptor(const SessionMessageCB& session_message_cb,
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               const SessionClosedCB& session_closed_cb,
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               const SessionKeysChangeCB& session_keys_change_cb);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AesDecryptor();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // MediaKeys implementation.
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void SetServerCertificate(
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const uint8* certificate_data,
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      int certificate_data_length,
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void CreateSession(const std::string& init_data_type,
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             const uint8* init_data,
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             int init_data_length,
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             SessionType session_type,
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             scoped_ptr<NewSessionCdmPromise> promise) OVERRIDE;
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void LoadSession(const std::string& web_session_id,
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                           scoped_ptr<NewSessionCdmPromise> promise) OVERRIDE;
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual void UpdateSession(const std::string& web_session_id,
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             const uint8* response,
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             int response_length,
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void CloseSession(const std::string& web_session_id,
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void RemoveSession(const std::string& web_session_id,
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             scoped_ptr<SimpleCdmPromise> promise) OVERRIDE;
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void GetUsableKeyIds(const std::string& web_session_id,
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               scoped_ptr<KeyIdsPromise> promise) OVERRIDE;
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual Decryptor* GetDecryptor() OVERRIDE;
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Decryptor implementation.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void RegisterNewKeyCB(StreamType stream_type,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const NewKeyCB& key_added_cb) OVERRIDE;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Decrypt(StreamType stream_type,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const scoped_refptr<DecoderBuffer>& encrypted,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const DecryptCB& decrypt_cb) OVERRIDE;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelDecrypt(StreamType stream_type) OVERRIDE;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void InitializeAudioDecoder(const AudioDecoderConfig& config,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const DecoderInitCB& init_cb) OVERRIDE;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void InitializeVideoDecoder(const VideoDecoderConfig& config,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const DecoderInitCB& init_cb) OVERRIDE;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecryptAndDecodeAudio(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<DecoderBuffer>& encrypted,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const AudioDecodeCB& audio_decode_cb) OVERRIDE;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecryptAndDecodeVideo(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<DecoderBuffer>& encrypted,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const VideoDecodeCB& video_decode_cb) OVERRIDE;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ResetDecoder(StreamType stream_type) OVERRIDE;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeinitializeDecoder(StreamType stream_type) OVERRIDE;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(fgalligan): Remove this and change KeyMap to use crypto::SymmetricKey
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as there are no decryptors that are performing an integrity check.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper class that manages the decryption key.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DecryptionKey {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit DecryptionKey(const std::string& secret);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~DecryptionKey();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Creates the encryption key.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool Init();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::SymmetricKey* decryption_key() { return decryption_key_.get(); }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The base secret that is used to create the decryption key.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string secret_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The key used to decrypt the data.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<crypto::SymmetricKey> decryption_key_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(DecryptionKey);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Keep track of the keys for a key ID. If multiple sessions specify keys
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // for the same key ID, then the last key inserted is used. The structure is
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // optimized so that Decrypt() has fast access, at the cost of slow deletion
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // of keys when a session is released.
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  class SessionIdDecryptionKeyMap;
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Key ID <-> SessionIdDecryptionKeyMap map.
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  typedef base::ScopedPtrHashMap<std::string, SessionIdDecryptionKeyMap>
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      KeyIdToSessionKeysMap;
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Creates a DecryptionKey using |key_string| and associates it with |key_id|.
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Returns true if successful.
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool AddDecryptionKey(const std::string& web_session_id,
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        const std::string& key_id,
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        const std::string& key_string);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets a DecryptionKey associated with |key_id|. The AesDecryptor still owns
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the key. Returns NULL if no key is associated with |key_id|.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecryptionKey* GetKey(const std::string& key_id) const;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Deletes all keys associated with |web_session_id|.
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void DeleteKeysForSession(const std::string& web_session_id);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Callbacks for firing session events.
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SessionMessageCB session_message_cb_;
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SessionClosedCB session_closed_cb_;
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SessionKeysChangeCB session_keys_change_cb_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since only Decrypt() is called off the renderer thread, we only need to
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // protect |key_map_|, the only member variable that is shared between
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Decrypt() and other methods.
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  KeyIdToSessionKeysMap key_map_;  // Protected by |key_map_lock_|.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock key_map_lock_;  // Protects the |key_map_|.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Keeps track of current valid sessions.
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::set<std::string> valid_sessions_;
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Make web session ID unique per renderer by making it static. Web session
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // IDs seen by the app will be "1", "2", etc.
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  static uint32 next_web_session_id_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NewKeyCB new_audio_key_cb_;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NewKeyCB new_video_key_cb_;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Protect |new_audio_key_cb_| and |new_video_key_cb_| as they are set on the
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // main thread but called on the media thread.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mutable base::Lock new_key_cb_lock_;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AesDecryptor);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // MEDIA_CRYPTO_AES_DECRYPTOR_H_
157