aboutsummaryrefslogtreecommitdiff
path: root/talk/app/webrtc/dtlsidentitystore.h
blob: a0eef98e1bbfc315f30d46af44d32384a924a79f (plain)
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
157
158
159
160
161
162
163
164
/*
 * libjingle
 * Copyright 2015 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef TALK_APP_WEBRTC_DTLSIDENTITYSTORE_H_
#define TALK_APP_WEBRTC_DTLSIDENTITYSTORE_H_

#include <queue>
#include <string>

#include "webrtc/base/messagehandler.h"
#include "webrtc/base/messagequeue.h"
#include "webrtc/base/refcount.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/scoped_ref_ptr.h"
#include "webrtc/base/sslidentity.h"
#include "webrtc/base/thread.h"

namespace webrtc {

// Passed to SSLIdentity::Generate.
extern const char kIdentityName[];

class SSLIdentity;
class Thread;

// Used to receive callbacks of DTLS identity requests.
class DtlsIdentityRequestObserver : public rtc::RefCountInterface {
 public:
  virtual void OnFailure(int error) = 0;
  // TODO(hbos): Unify the OnSuccess method once Chrome code is updated.
  virtual void OnSuccess(const std::string& der_cert,
                         const std::string& der_private_key) = 0;
  // |identity| is a scoped_ptr because rtc::SSLIdentity is not copyable and the
  // client has to get the ownership of the object to make use of it.
  virtual void OnSuccess(rtc::scoped_ptr<rtc::SSLIdentity> identity) = 0;

 protected:
  virtual ~DtlsIdentityRequestObserver() {}
};

// This interface defines an in-memory DTLS identity store, which generates DTLS
// identities.
// APIs calls must be made on the signaling thread and the callbacks are also
// called on the signaling thread.
class DtlsIdentityStoreInterface {
 public:
  virtual ~DtlsIdentityStoreInterface() { }

  // The |observer| will be called when the requested identity is ready, or when
  // identity generation fails.
  // TODO(torbjorng,hbos): The following RequestIdentity is about to be removed,
  // see below todo.
  virtual void RequestIdentity(
      rtc::KeyType key_type,
      const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) {
    // Add default parameterization.
    RequestIdentity(rtc::KeyParams(key_type), observer);
  }
  // TODO(torbjorng,hbos): Parameterized key types! The following
  // RequestIdentity should replace the old one that takes rtc::KeyType. When
  // the new one is implemented by Chromium and WebRTC the old one should be
  // removed. crbug.com/544902, webrtc:5092.
  virtual void RequestIdentity(
      rtc::KeyParams key_params,
      const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) {
    // Drop parameterization.
    RequestIdentity(key_params.type(), observer);
  }
};

// The WebRTC default implementation of DtlsIdentityStoreInterface.
// Identity generation is performed on the worker thread.
class DtlsIdentityStoreImpl : public DtlsIdentityStoreInterface,
                              public rtc::MessageHandler {
 public:
  // This will start to preemptively generating an RSA identity in the
  // background if the worker thread is not the same as the signaling thread.
  DtlsIdentityStoreImpl(rtc::Thread* signaling_thread,
                        rtc::Thread* worker_thread);
  ~DtlsIdentityStoreImpl() override;

  // DtlsIdentityStoreInterface override;
  void RequestIdentity(
      rtc::KeyType key_type,
      const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) override;

  // rtc::MessageHandler override;
  void OnMessage(rtc::Message* msg) override;

  // Returns true if there is a free RSA identity, used for unit tests.
  bool HasFreeIdentityForTesting(rtc::KeyType key_type) const;

 private:
  void GenerateIdentity(
      rtc::KeyType key_type,
      const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer);
  void OnIdentityGenerated(rtc::KeyType key_type,
                           rtc::scoped_ptr<rtc::SSLIdentity> identity);

  class WorkerTask;
  typedef rtc::ScopedMessageData<DtlsIdentityStoreImpl::WorkerTask>
      WorkerTaskMessageData;

  // A key type-identity pair.
  struct IdentityResult {
    IdentityResult(rtc::KeyType key_type,
                   rtc::scoped_ptr<rtc::SSLIdentity> identity)
        : key_type_(key_type), identity_(identity.Pass()) {}

    rtc::KeyType key_type_;
    rtc::scoped_ptr<rtc::SSLIdentity> identity_;
  };

  typedef rtc::ScopedMessageData<IdentityResult> IdentityResultMessageData;

  sigslot::signal0<> SignalDestroyed;

  rtc::Thread* const signaling_thread_;
  // TODO(hbos): RSA generation is slow and would be VERY slow if we switch over
  // to 2048, DtlsIdentityStore should use a new thread and not the "general
  // purpose" worker thread.
  rtc::Thread* const worker_thread_;

  struct RequestInfo {
    RequestInfo()
        : request_observers_(), gen_in_progress_counts_(0), free_identity_() {}

    std::queue<rtc::scoped_refptr<DtlsIdentityRequestObserver>>
        request_observers_;
    size_t gen_in_progress_counts_;
    rtc::scoped_ptr<rtc::SSLIdentity> free_identity_;
  };

  // One RequestInfo per KeyType. Only touch on the |signaling_thread_|.
  RequestInfo request_info_[rtc::KT_LAST];
};

}  // namespace webrtc

#endif  // TALK_APP_WEBRTC_DTLSIDENTITYSTORE_H_