• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2015 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef TALK_APP_WEBRTC_DTLSIDENTITYSTORE_H_
29 #define TALK_APP_WEBRTC_DTLSIDENTITYSTORE_H_
30 
31 #include <queue>
32 #include <string>
33 #include <utility>
34 
35 #include "webrtc/base/messagehandler.h"
36 #include "webrtc/base/messagequeue.h"
37 #include "webrtc/base/refcount.h"
38 #include "webrtc/base/scoped_ptr.h"
39 #include "webrtc/base/scoped_ref_ptr.h"
40 #include "webrtc/base/sslidentity.h"
41 #include "webrtc/base/thread.h"
42 
43 namespace webrtc {
44 
45 // Passed to SSLIdentity::Generate.
46 extern const char kIdentityName[];
47 
48 class SSLIdentity;
49 class Thread;
50 
51 // Used to receive callbacks of DTLS identity requests.
52 class DtlsIdentityRequestObserver : public rtc::RefCountInterface {
53  public:
54   virtual void OnFailure(int error) = 0;
55   // TODO(hbos): Unify the OnSuccess method once Chrome code is updated.
56   virtual void OnSuccess(const std::string& der_cert,
57                          const std::string& der_private_key) = 0;
58   // |identity| is a scoped_ptr because rtc::SSLIdentity is not copyable and the
59   // client has to get the ownership of the object to make use of it.
60   virtual void OnSuccess(rtc::scoped_ptr<rtc::SSLIdentity> identity) = 0;
61 
62  protected:
~DtlsIdentityRequestObserver()63   virtual ~DtlsIdentityRequestObserver() {}
64 };
65 
66 // This interface defines an in-memory DTLS identity store, which generates DTLS
67 // identities.
68 // APIs calls must be made on the signaling thread and the callbacks are also
69 // called on the signaling thread.
70 class DtlsIdentityStoreInterface {
71  public:
~DtlsIdentityStoreInterface()72   virtual ~DtlsIdentityStoreInterface() { }
73 
74   // The |observer| will be called when the requested identity is ready, or when
75   // identity generation fails.
76   // TODO(torbjorng,hbos): The following RequestIdentity is about to be removed,
77   // see below todo.
RequestIdentity(rtc::KeyType key_type,const rtc::scoped_refptr<DtlsIdentityRequestObserver> & observer)78   virtual void RequestIdentity(
79       rtc::KeyType key_type,
80       const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) {
81     // Add default parameterization.
82     RequestIdentity(rtc::KeyParams(key_type), observer);
83   }
84   // TODO(torbjorng,hbos): Parameterized key types! The following
85   // RequestIdentity should replace the old one that takes rtc::KeyType. When
86   // the new one is implemented by Chromium and WebRTC the old one should be
87   // removed. crbug.com/544902, webrtc:5092.
RequestIdentity(rtc::KeyParams key_params,const rtc::scoped_refptr<DtlsIdentityRequestObserver> & observer)88   virtual void RequestIdentity(
89       rtc::KeyParams key_params,
90       const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) {
91     // Drop parameterization.
92     RequestIdentity(key_params.type(), observer);
93   }
94 };
95 
96 // The WebRTC default implementation of DtlsIdentityStoreInterface.
97 // Identity generation is performed on the worker thread.
98 class DtlsIdentityStoreImpl : public DtlsIdentityStoreInterface,
99                               public rtc::MessageHandler {
100  public:
101   // This will start to preemptively generating an RSA identity in the
102   // background if the worker thread is not the same as the signaling thread.
103   DtlsIdentityStoreImpl(rtc::Thread* signaling_thread,
104                         rtc::Thread* worker_thread);
105   ~DtlsIdentityStoreImpl() override;
106 
107   // DtlsIdentityStoreInterface override;
108   void RequestIdentity(
109       rtc::KeyType key_type,
110       const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) override;
111 
112   // rtc::MessageHandler override;
113   void OnMessage(rtc::Message* msg) override;
114 
115   // Returns true if there is a free RSA identity, used for unit tests.
116   bool HasFreeIdentityForTesting(rtc::KeyType key_type) const;
117 
118  private:
119   void GenerateIdentity(
120       rtc::KeyType key_type,
121       const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer);
122   void OnIdentityGenerated(rtc::KeyType key_type,
123                            rtc::scoped_ptr<rtc::SSLIdentity> identity);
124 
125   class WorkerTask;
126   typedef rtc::ScopedMessageData<DtlsIdentityStoreImpl::WorkerTask>
127       WorkerTaskMessageData;
128 
129   // A key type-identity pair.
130   struct IdentityResult {
IdentityResultIdentityResult131     IdentityResult(rtc::KeyType key_type,
132                    rtc::scoped_ptr<rtc::SSLIdentity> identity)
133         : key_type_(key_type), identity_(std::move(identity)) {}
134 
135     rtc::KeyType key_type_;
136     rtc::scoped_ptr<rtc::SSLIdentity> identity_;
137   };
138 
139   typedef rtc::ScopedMessageData<IdentityResult> IdentityResultMessageData;
140 
141   sigslot::signal0<> SignalDestroyed;
142 
143   rtc::Thread* const signaling_thread_;
144   // TODO(hbos): RSA generation is slow and would be VERY slow if we switch over
145   // to 2048, DtlsIdentityStore should use a new thread and not the "general
146   // purpose" worker thread.
147   rtc::Thread* const worker_thread_;
148 
149   struct RequestInfo {
RequestInfoRequestInfo150     RequestInfo()
151         : request_observers_(), gen_in_progress_counts_(0), free_identity_() {}
152 
153     std::queue<rtc::scoped_refptr<DtlsIdentityRequestObserver>>
154         request_observers_;
155     size_t gen_in_progress_counts_;
156     rtc::scoped_ptr<rtc::SSLIdentity> free_identity_;
157   };
158 
159   // One RequestInfo per KeyType. Only touch on the |signaling_thread_|.
160   RequestInfo request_info_[rtc::KT_LAST];
161 };
162 
163 }  // namespace webrtc
164 
165 #endif  // TALK_APP_WEBRTC_DTLSIDENTITYSTORE_H_
166