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