1/*
2 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_BASE_OPENSSLSTREAMADAPTER_H__
12#define WEBRTC_BASE_OPENSSLSTREAMADAPTER_H__
13
14#include <string>
15#include <vector>
16
17#include "webrtc/base/buffer.h"
18#include "webrtc/base/sslstreamadapter.h"
19#include "webrtc/base/opensslidentity.h"
20
21typedef struct ssl_st SSL;
22typedef struct ssl_ctx_st SSL_CTX;
23typedef struct x509_store_ctx_st X509_STORE_CTX;
24
25namespace rtc {
26
27// This class was written with OpenSSLAdapter (a socket adapter) as a
28// starting point. It has similar structure and functionality, with
29// the peer-to-peer mode added.
30//
31// Static methods to initialize and deinit the SSL library are in
32// OpenSSLAdapter. This class also uses
33// OpenSSLAdapter::custom_verify_callback_ (a static field). These
34// should probably be moved out to a neutral class.
35//
36// In a few cases I have factored out some OpenSSLAdapter code into
37// static methods so it can be reused from this class. Eventually that
38// code should probably be moved to a common support
39// class. Unfortunately there remain a few duplicated sections of
40// code. I have not done more restructuring because I did not want to
41// affect existing code that uses OpenSSLAdapter.
42//
43// This class does not support the SSL connection restart feature
44// present in OpenSSLAdapter. I am not entirely sure how the feature
45// is useful and I am not convinced that it works properly.
46//
47// This implementation is careful to disallow data exchange after an
48// SSL error, and it has an explicit SSL_CLOSED state. It should not
49// be possible to send any data in clear after one of the StartSSL
50// methods has been called.
51
52// Look in sslstreamadapter.h for documentation of the methods.
53
54class OpenSSLIdentity;
55
56///////////////////////////////////////////////////////////////////////////////
57
58class OpenSSLStreamAdapter : public SSLStreamAdapter {
59 public:
60  explicit OpenSSLStreamAdapter(StreamInterface* stream);
61  virtual ~OpenSSLStreamAdapter();
62
63  virtual void SetIdentity(SSLIdentity* identity);
64
65  // Default argument is for compatibility
66  virtual void SetServerRole(SSLRole role = SSL_SERVER);
67  virtual bool SetPeerCertificateDigest(const std::string& digest_alg,
68                                        const unsigned char* digest_val,
69                                        size_t digest_len);
70
71  virtual bool GetPeerCertificate(SSLCertificate** cert) const;
72
73  virtual int StartSSLWithServer(const char* server_name);
74  virtual int StartSSLWithPeer();
75  virtual void SetMode(SSLMode mode);
76
77  virtual StreamResult Read(void* data, size_t data_len,
78                            size_t* read, int* error);
79  virtual StreamResult Write(const void* data, size_t data_len,
80                             size_t* written, int* error);
81  virtual void Close();
82  virtual StreamState GetState() const;
83
84  // Key Extractor interface
85  virtual bool ExportKeyingMaterial(const std::string& label,
86                                    const uint8* context,
87                                    size_t context_len,
88                                    bool use_context,
89                                    uint8* result,
90                                    size_t result_len);
91
92
93  // DTLS-SRTP interface
94  virtual bool SetDtlsSrtpCiphers(const std::vector<std::string>& ciphers);
95  virtual bool GetDtlsSrtpCipher(std::string* cipher);
96
97  // Capabilities interfaces
98  static bool HaveDtls();
99  static bool HaveDtlsSrtp();
100  static bool HaveExporter();
101
102 protected:
103  virtual void OnEvent(StreamInterface* stream, int events, int err);
104
105 private:
106  enum SSLState {
107    // Before calling one of the StartSSL methods, data flows
108    // in clear text.
109    SSL_NONE,
110    SSL_WAIT,  // waiting for the stream to open to start SSL negotiation
111    SSL_CONNECTING,  // SSL negotiation in progress
112    SSL_CONNECTED,  // SSL stream successfully established
113    SSL_ERROR,  // some SSL error occurred, stream is closed
114    SSL_CLOSED  // Clean close
115  };
116
117  enum { MSG_TIMEOUT = MSG_MAX+1};
118
119  // The following three methods return 0 on success and a negative
120  // error code on failure. The error code may be from OpenSSL or -1
121  // on some other error cases, so it can't really be interpreted
122  // unfortunately.
123
124  // Go from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT,
125  // depending on whether the underlying stream is already open or
126  // not.
127  int StartSSL();
128  // Prepare SSL library, state is SSL_CONNECTING.
129  int BeginSSL();
130  // Perform SSL negotiation steps.
131  int ContinueSSL();
132
133  // Error handler helper. signal is given as true for errors in
134  // asynchronous contexts (when an error method was not returned
135  // through some other method), and in that case an SE_CLOSE event is
136  // raised on the stream with the specified error.
137  // A 0 error means a graceful close, otherwise there is not really enough
138  // context to interpret the error code.
139  void Error(const char* context, int err, bool signal);
140  void Cleanup();
141
142  // Override MessageHandler
143  virtual void OnMessage(Message* msg);
144
145  // Flush the input buffers by reading left bytes (for DTLS)
146  void FlushInput(unsigned int left);
147
148  // SSL library configuration
149  SSL_CTX* SetupSSLContext();
150  // SSL verification check
151  bool SSLPostConnectionCheck(SSL* ssl, const char* server_name,
152                              const X509* peer_cert,
153                              const std::string& peer_digest);
154  // SSL certification verification error handler, called back from
155  // the openssl library. Returns an int interpreted as a boolean in
156  // the C style: zero means verification failure, non-zero means
157  // passed.
158  static int SSLVerifyCallback(int ok, X509_STORE_CTX* store);
159
160  SSLState state_;
161  SSLRole role_;
162  int ssl_error_code_;  // valid when state_ == SSL_ERROR or SSL_CLOSED
163  // Whether the SSL negotiation is blocked on needing to read or
164  // write to the wrapped stream.
165  bool ssl_read_needs_write_;
166  bool ssl_write_needs_read_;
167
168  SSL* ssl_;
169  SSL_CTX* ssl_ctx_;
170
171  // Our key and certificate, mostly useful in peer-to-peer mode.
172  scoped_ptr<OpenSSLIdentity> identity_;
173  // in traditional mode, the server name that the server's certificate
174  // must specify. Empty in peer-to-peer mode.
175  std::string ssl_server_name_;
176  // The certificate that the peer must present or did present. Initially
177  // null in traditional mode, until the connection is established.
178  scoped_ptr<OpenSSLCertificate> peer_certificate_;
179  // In peer-to-peer mode, the digest of the certificate that
180  // the peer must present.
181  Buffer peer_certificate_digest_value_;
182  std::string peer_certificate_digest_algorithm_;
183
184  // OpenSSLAdapter::custom_verify_callback_ result
185  bool custom_verification_succeeded_;
186
187  // The DtlsSrtp ciphers
188  std::string srtp_ciphers_;
189
190  // Do DTLS or not
191  SSLMode ssl_mode_;
192};
193
194/////////////////////////////////////////////////////////////////////////////
195
196}  // namespace rtc
197
198#endif  // WEBRTC_BASE_OPENSSLSTREAMADAPTER_H__
199