1f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org/*
2f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org *
4f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org */
10f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
11f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#if HAVE_CONFIG_H
12f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "config.h"
13f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif  // HAVE_CONFIG_H
14f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
15f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#if HAVE_OPENSSL_SSL_H
16f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
17f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/opensslstreamadapter.h"
18f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
19f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include <openssl/bio.h>
20f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include <openssl/crypto.h>
21f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include <openssl/err.h>
22f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include <openssl/rand.h>
23f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include <openssl/x509v3.h>
24f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
25f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include <vector>
26f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
27f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/common.h"
28f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/logging.h"
29f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/stream.h"
30f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/openssl.h"
31f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/openssladapter.h"
32f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/openssldigest.h"
33f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/opensslidentity.h"
34f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/stringutils.h"
35f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#include "webrtc/base/thread.h"
36f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
37f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgnamespace rtc {
38f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
39f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#if (OPENSSL_VERSION_NUMBER >= 0x10001000L)
40f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#define HAVE_DTLS_SRTP
41f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
42f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
43f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef HAVE_DTLS_SRTP
44f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// SRTP cipher suite table
45f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstruct SrtpCipherMapEntry {
46f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  const char* external_name;
47f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  const char* internal_name;
48f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org};
49f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
50f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// This isn't elegant, but it's better than an external reference
51f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic SrtpCipherMapEntry SrtpCipherMap[] = {
52f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  {"AES_CM_128_HMAC_SHA1_80", "SRTP_AES128_CM_SHA1_80"},
53f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  {"AES_CM_128_HMAC_SHA1_32", "SRTP_AES128_CM_SHA1_32"},
54f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  {NULL, NULL}
55f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org};
56f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
57f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
58f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org//////////////////////////////////////////////////////////////////////
59f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// StreamBIO
60f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org//////////////////////////////////////////////////////////////////////
61f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
62f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_write(BIO* h, const char* buf, int num);
63f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_read(BIO* h, char* buf, int size);
64f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_puts(BIO* h, const char* str);
65f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic long stream_ctrl(BIO* h, int cmd, long arg1, void* arg2);
66f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_new(BIO* h);
67f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_free(BIO* data);
68f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
69f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic BIO_METHOD methods_stream = {
70f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  BIO_TYPE_BIO,
71f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  "stream",
72f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  stream_write,
73f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  stream_read,
74f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  stream_puts,
75f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  0,
76f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  stream_ctrl,
77f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  stream_new,
78f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  stream_free,
79f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  NULL,
80f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org};
81f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
82f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic BIO_METHOD* BIO_s_stream() { return(&methods_stream); }
83f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
84f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic BIO* BIO_new_stream(StreamInterface* stream) {
85f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  BIO* ret = BIO_new(BIO_s_stream());
86f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (ret == NULL)
87f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return NULL;
88f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ret->ptr = stream;
89f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return ret;
90f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
91f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
92f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// bio methods return 1 (or at least non-zero) on success and 0 on failure.
93f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
94f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_new(BIO* b) {
95f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  b->shutdown = 0;
96f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  b->init = 1;
97f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  b->num = 0;  // 1 means end-of-stream
98f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  b->ptr = 0;
99f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return 1;
100f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
101f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
102f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_free(BIO* b) {
103f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (b == NULL)
104f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return 0;
105f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return 1;
106f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
107f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
108f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_read(BIO* b, char* out, int outl) {
109f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!out)
110f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return -1;
111f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  StreamInterface* stream = static_cast<StreamInterface*>(b->ptr);
112f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  BIO_clear_retry_flags(b);
113f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  size_t read;
114f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int error;
115f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  StreamResult result = stream->Read(out, outl, &read, &error);
116f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (result == SR_SUCCESS) {
117f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return read;
118f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  } else if (result == SR_EOS) {
119f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    b->num = 1;
120f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  } else if (result == SR_BLOCK) {
121f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    BIO_set_retry_read(b);
122f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
123f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return -1;
124f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
125f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
126f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_write(BIO* b, const char* in, int inl) {
127f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!in)
128f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return -1;
129f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  StreamInterface* stream = static_cast<StreamInterface*>(b->ptr);
130f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  BIO_clear_retry_flags(b);
131f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  size_t written;
132f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int error;
133f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  StreamResult result = stream->Write(in, inl, &written, &error);
134f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (result == SR_SUCCESS) {
135f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return written;
136f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  } else if (result == SR_BLOCK) {
137f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    BIO_set_retry_write(b);
138f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
139f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return -1;
140f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
141f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
142f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic int stream_puts(BIO* b, const char* str) {
143f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return stream_write(b, str, strlen(str));
144f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
145f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
146f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgstatic long stream_ctrl(BIO* b, int cmd, long num, void* ptr) {
147fda34e7b12a53d3f76e5bd2de658eebc8c5d711bhenrike@webrtc.org  RTC_UNUSED(num);
148fda34e7b12a53d3f76e5bd2de658eebc8c5d711bhenrike@webrtc.org  RTC_UNUSED(ptr);
149f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
150f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  switch (cmd) {
151f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case BIO_CTRL_RESET:
152f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return 0;
153f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case BIO_CTRL_EOF:
154f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return b->num;
155f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case BIO_CTRL_WPENDING:
156f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case BIO_CTRL_PENDING:
157f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return 0;
158f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case BIO_CTRL_FLUSH:
159f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return 1;
160f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    default:
161f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return 0;
162f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
163f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
164f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
165f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
166f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// OpenSSLStreamAdapter
167f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
168f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
169f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgOpenSSLStreamAdapter::OpenSSLStreamAdapter(StreamInterface* stream)
170f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    : SSLStreamAdapter(stream),
171f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      state_(SSL_NONE),
172f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      role_(SSL_CLIENT),
173f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      ssl_read_needs_write_(false), ssl_write_needs_read_(false),
174f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      ssl_(NULL), ssl_ctx_(NULL),
175f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      custom_verification_succeeded_(false),
176f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      ssl_mode_(SSL_MODE_TLS) {
177f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
178f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
179f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgOpenSSLStreamAdapter::~OpenSSLStreamAdapter() {
180f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  Cleanup();
181f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
182f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
183f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::SetIdentity(SSLIdentity* identity) {
184f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(!identity_);
185f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  identity_.reset(static_cast<OpenSSLIdentity*>(identity));
186f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
187f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
188f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::SetServerRole(SSLRole role) {
189f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  role_ = role;
190f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
191f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
192f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::GetPeerCertificate(SSLCertificate** cert) const {
193f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!peer_certificate_)
194f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
195f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
196f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  *cert = peer_certificate_->GetReference();
197f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return true;
198f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
199f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
200f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::SetPeerCertificateDigest(const std::string
201f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                    &digest_alg,
202f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                    const unsigned char*
203f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                    digest_val,
204f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                    size_t digest_len) {
205f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(!peer_certificate_);
206f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(peer_certificate_digest_algorithm_.size() == 0);
207f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(ssl_server_name_.empty());
208f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  size_t expected_len;
209f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
210f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!OpenSSLDigest::GetDigestSize(digest_alg, &expected_len)) {
211f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_WARNING) << "Unknown digest algorithm: " << digest_alg;
212f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
213f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
214f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (expected_len != digest_len)
215f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
216f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
217f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  peer_certificate_digest_value_.SetData(digest_val, digest_len);
218f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  peer_certificate_digest_algorithm_ = digest_alg;
219f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
220f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return true;
221f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
222f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
223f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// Key Extractor interface
224f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::ExportKeyingMaterial(const std::string& label,
225f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                const uint8* context,
226f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                size_t context_len,
227f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                bool use_context,
228f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                uint8* result,
229f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                size_t result_len) {
230f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef HAVE_DTLS_SRTP
231f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int i;
232f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
233f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  i = SSL_export_keying_material(ssl_, result, result_len,
234f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                 label.c_str(), label.length(),
235f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                 const_cast<uint8 *>(context),
236f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                 context_len, use_context);
237f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
238f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (i != 1)
239f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
240f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
241f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return true;
242f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#else
243f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return false;
244f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
245f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
246f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
247f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::SetDtlsSrtpCiphers(
248f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    const std::vector<std::string>& ciphers) {
249f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef HAVE_DTLS_SRTP
250f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  std::string internal_ciphers;
251f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
252f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (state_ != SSL_NONE)
253f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
254f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
255f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  for (std::vector<std::string>::const_iterator cipher = ciphers.begin();
256f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org       cipher != ciphers.end(); ++cipher) {
257f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    bool found = false;
258f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    for (SrtpCipherMapEntry *entry = SrtpCipherMap; entry->internal_name;
259f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org         ++entry) {
260f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (*cipher == entry->external_name) {
261f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        found = true;
262f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        if (!internal_ciphers.empty())
263f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          internal_ciphers += ":";
264f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        internal_ciphers += entry->internal_name;
265f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        break;
266f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
267f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
268f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
269f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (!found) {
270f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_ERROR) << "Could not find cipher: " << *cipher;
271f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return false;
272f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
273f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
274f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
275f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (internal_ciphers.empty())
276f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
277f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
278f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  srtp_ciphers_ = internal_ciphers;
279f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return true;
280f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#else
281f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return false;
282f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
283f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
284f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
285f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::GetDtlsSrtpCipher(std::string* cipher) {
286f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef HAVE_DTLS_SRTP
287f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(state_ == SSL_CONNECTED);
288f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (state_ != SSL_CONNECTED)
289f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
290f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
291f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SRTP_PROTECTION_PROFILE *srtp_profile =
292f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      SSL_get_selected_srtp_profile(ssl_);
293f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
294f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!srtp_profile)
295f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return false;
296f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
297f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  for (SrtpCipherMapEntry *entry = SrtpCipherMap;
298f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org       entry->internal_name; ++entry) {
299f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (!strcmp(entry->internal_name, srtp_profile->name)) {
300f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      *cipher = entry->external_name;
301f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return true;
302f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
303f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
304f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
305f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(false);  // This should never happen
306f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
307f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return false;
308f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#else
309f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return false;
310f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
311f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
312f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
313f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgint OpenSSLStreamAdapter::StartSSLWithServer(const char* server_name) {
314f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(server_name != NULL && server_name[0] != '\0');
315f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ssl_server_name_ = server_name;
316f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return StartSSL();
317f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
318f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
319f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgint OpenSSLStreamAdapter::StartSSLWithPeer() {
320f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(ssl_server_name_.empty());
321f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // It is permitted to specify peer_certificate_ only later.
322f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return StartSSL();
323f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
324f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
325f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::SetMode(SSLMode mode) {
326f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(state_ == SSL_NONE);
327f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ssl_mode_ = mode;
328f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
329f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
330f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org//
331f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// StreamInterface Implementation
332f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org//
333f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
334f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgStreamResult OpenSSLStreamAdapter::Write(const void* data, size_t data_len,
335f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                         size_t* written, int* error) {
336f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  LOG(LS_VERBOSE) << "OpenSSLStreamAdapter::Write(" << data_len << ")";
337f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
338f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  switch (state_) {
339f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_NONE:
340f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    // pass-through in clear text
341f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return StreamAdapterInterface::Write(data, data_len, written, error);
342f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
343f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_WAIT:
344f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_CONNECTING:
345f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_BLOCK;
346f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
347f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_CONNECTED:
348f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    break;
349f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
350f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_ERROR:
351f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_CLOSED:
352f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  default:
353f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (error)
354f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      *error = ssl_error_code_;
355f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_ERROR;
356f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
357f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
358f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // OpenSSL will return an error if we try to write zero bytes
359f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (data_len == 0) {
360f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (written)
361f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      *written = 0;
362f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_SUCCESS;
363f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
364f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
365f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ssl_write_needs_read_ = false;
366f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
367f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int code = SSL_write(ssl_, data, data_len);
368f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int ssl_error = SSL_get_error(ssl_, code);
369f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  switch (ssl_error) {
370f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_ERROR_NONE:
371f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_VERBOSE) << " -- success";
372f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ASSERT(0 < code && static_cast<unsigned>(code) <= data_len);
373f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (written)
374f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      *written = code;
375f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_SUCCESS;
376f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_ERROR_WANT_READ:
377f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_VERBOSE) << " -- error want read";
378f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ssl_write_needs_read_ = true;
379f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_BLOCK;
380f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_ERROR_WANT_WRITE:
381f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_VERBOSE) << " -- error want write";
382f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_BLOCK;
383f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
384f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  case SSL_ERROR_ZERO_RETURN:
385f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  default:
386f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    Error("SSL_write", (ssl_error ? ssl_error : -1), false);
387f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (error)
388f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      *error = ssl_error_code_;
389f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_ERROR;
390f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
391f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // not reached
392f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
393f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
394f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgStreamResult OpenSSLStreamAdapter::Read(void* data, size_t data_len,
395f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                        size_t* read, int* error) {
396f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  LOG(LS_VERBOSE) << "OpenSSLStreamAdapter::Read(" << data_len << ")";
397f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  switch (state_) {
398f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_NONE:
399f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      // pass-through in clear text
400f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return StreamAdapterInterface::Read(data, data_len, read, error);
401f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
402f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_WAIT:
403f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_CONNECTING:
404f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_BLOCK;
405f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
406f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_CONNECTED:
407f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      break;
408f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
409f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_CLOSED:
410f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_EOS;
411f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
412f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR:
413f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    default:
414f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (error)
415f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        *error = ssl_error_code_;
416f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_ERROR;
417f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
418f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
419f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Don't trust OpenSSL with zero byte reads
420f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (data_len == 0) {
421f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (read)
422f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      *read = 0;
423f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return SR_SUCCESS;
424f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
425f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
426f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ssl_read_needs_write_ = false;
427f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
428f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int code = SSL_read(ssl_, data, data_len);
429f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int ssl_error = SSL_get_error(ssl_, code);
430f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  switch (ssl_error) {
431f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_NONE:
432f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- success";
433f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      ASSERT(0 < code && static_cast<unsigned>(code) <= data_len);
434f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (read)
435f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        *read = code;
436f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
437f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (ssl_mode_ == SSL_MODE_DTLS) {
438f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        // Enforce atomic reads -- this is a short read
439f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        unsigned int pending = SSL_pending(ssl_);
440f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
441f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        if (pending) {
442f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          LOG(LS_INFO) << " -- short DTLS read. flushing";
443f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          FlushInput(pending);
444f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          if (error)
445f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org            *error = SSE_MSG_TRUNC;
446f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          return SR_ERROR;
447f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        }
448f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
449f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_SUCCESS;
450f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_WANT_READ:
451f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- error want read";
452f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_BLOCK;
453f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_WANT_WRITE:
454f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- error want write";
455f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      ssl_read_needs_write_ = true;
456f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_BLOCK;
457f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_ZERO_RETURN:
458f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- remote side closed";
459f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_EOS;
460f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      break;
461f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    default:
462f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- error " << code;
463f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      Error("SSL_read", (ssl_error ? ssl_error : -1), false);
464f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (error)
465f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        *error = ssl_error_code_;
466f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SR_ERROR;
467f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
468f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // not reached
469f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
470f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
471f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::FlushInput(unsigned int left) {
472f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  unsigned char buf[2048];
473f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
474f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  while (left) {
475f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    // This should always succeed
476f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    int toread = (sizeof(buf) < left) ? sizeof(buf) : left;
477f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    int code = SSL_read(ssl_, buf, toread);
478f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
479f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    int ssl_error = SSL_get_error(ssl_, code);
480f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ASSERT(ssl_error == SSL_ERROR_NONE);
481f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
482f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (ssl_error != SSL_ERROR_NONE) {
483f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- error " << code;
484f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      Error("SSL_read", (ssl_error ? ssl_error : -1), false);
485f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return;
486f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
487f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
488f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_VERBOSE) << " -- flushed " << code << " bytes";
489f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    left -= code;
490f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
491f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
492f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
493f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::Close() {
494f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  Cleanup();
495f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(state_ == SSL_CLOSED || state_ == SSL_ERROR);
496f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  StreamAdapterInterface::Close();
497f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
498f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
499f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgStreamState OpenSSLStreamAdapter::GetState() const {
500f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  switch (state_) {
501f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_WAIT:
502f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_CONNECTING:
503f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SS_OPENING;
504f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_CONNECTED:
505f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SS_OPEN;
506f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    default:
507f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return SS_CLOSED;
508f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  };
509f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // not reached
510f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
511f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
512f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::OnEvent(StreamInterface* stream, int events,
513f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                   int err) {
514f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int events_to_signal = 0;
515f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int signal_error = 0;
516f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(stream == this->stream());
517f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if ((events & SE_OPEN)) {
518f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_VERBOSE) << "OpenSSLStreamAdapter::OnEvent SE_OPEN";
519f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (state_ != SSL_WAIT) {
520f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      ASSERT(state_ == SSL_NONE);
521f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      events_to_signal |= SE_OPEN;
522f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    } else {
523f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      state_ = SSL_CONNECTING;
524f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (int err = BeginSSL()) {
525f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        Error("BeginSSL", err, true);
526f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        return;
527f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
528f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
529f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
530f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if ((events & (SE_READ|SE_WRITE))) {
531f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_VERBOSE) << "OpenSSLStreamAdapter::OnEvent"
532f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                 << ((events & SE_READ) ? " SE_READ" : "")
533f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                 << ((events & SE_WRITE) ? " SE_WRITE" : "");
534f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (state_ == SSL_NONE) {
535f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      events_to_signal |= events & (SE_READ|SE_WRITE);
536f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    } else if (state_ == SSL_CONNECTING) {
537f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (int err = ContinueSSL()) {
538f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        Error("ContinueSSL", err, true);
539f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        return;
540f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
541f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    } else if (state_ == SSL_CONNECTED) {
542f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (((events & SE_READ) && ssl_write_needs_read_) ||
543f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          (events & SE_WRITE)) {
544f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        LOG(LS_VERBOSE) << " -- onStreamWriteable";
545f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        events_to_signal |= SE_WRITE;
546f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
547f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (((events & SE_WRITE) && ssl_read_needs_write_) ||
548f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          (events & SE_READ)) {
549f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        LOG(LS_VERBOSE) << " -- onStreamReadable";
550f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        events_to_signal |= SE_READ;
551f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
552f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
553f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
554f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if ((events & SE_CLOSE)) {
555f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_VERBOSE) << "OpenSSLStreamAdapter::OnEvent(SE_CLOSE, " << err << ")";
556f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    Cleanup();
557f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    events_to_signal |= SE_CLOSE;
558f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    // SE_CLOSE is the only event that uses the final parameter to OnEvent().
559f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ASSERT(signal_error == 0);
560f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    signal_error = err;
561f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
562f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (events_to_signal)
563f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    StreamAdapterInterface::OnEvent(stream, events_to_signal, signal_error);
564f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
565f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
566f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgint OpenSSLStreamAdapter::StartSSL() {
567f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(state_ == SSL_NONE);
568f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
569f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (StreamAdapterInterface::GetState() != SS_OPEN) {
570f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    state_ = SSL_WAIT;
571f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return 0;
572f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
573f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
574f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  state_ = SSL_CONNECTING;
575f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (int err = BeginSSL()) {
576f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    Error("BeginSSL", err, false);
577f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return err;
578f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
579f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
580f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return 0;
581f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
582f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
583f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgint OpenSSLStreamAdapter::BeginSSL() {
584f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(state_ == SSL_CONNECTING);
585f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // The underlying stream has open. If we are in peer-to-peer mode
586f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // then a peer certificate must have been specified by now.
587f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(!ssl_server_name_.empty() ||
588f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org         !peer_certificate_digest_algorithm_.empty());
589f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  LOG(LS_INFO) << "BeginSSL: "
590f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org               << (!ssl_server_name_.empty() ? ssl_server_name_ :
591f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                               "with peer");
592f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
593f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  BIO* bio = NULL;
594f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
595f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // First set up the context
596f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(ssl_ctx_ == NULL);
597f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ssl_ctx_ = SetupSSLContext();
598f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!ssl_ctx_)
599f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return -1;
600f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
601f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  bio = BIO_new_stream(static_cast<StreamInterface*>(stream()));
602f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!bio)
603f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return -1;
604f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
605f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ssl_ = SSL_new(ssl_ctx_);
606f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!ssl_) {
607f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    BIO_free(bio);
608f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return -1;
609f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
610f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
611f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL_set_app_data(ssl_, this);
612f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
613f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL_set_bio(ssl_, bio, bio);  // the SSL object owns the bio now.
614f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
615f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
616f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org               SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
617f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
618b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  // Specify an ECDH group for ECDHE ciphers, otherwise they cannot be
619b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  // negotiated when acting as the server. Use NIST's P-256 which is commonly
620b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  // supported.
621b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
622b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  if (ecdh == NULL)
623b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org    return -1;
624b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  SSL_set_options(ssl_, SSL_OP_SINGLE_ECDH_USE);
625b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  SSL_set_tmp_ecdh(ssl_, ecdh);
626b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org  EC_KEY_free(ecdh);
627b6dafc1db62c6f7e5114084713a3ad0bc329254fjiayl@webrtc.org
628f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Do the connect
629f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return ContinueSSL();
630f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
631f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
632f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgint OpenSSLStreamAdapter::ContinueSSL() {
633f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  LOG(LS_VERBOSE) << "ContinueSSL";
634f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(state_ == SSL_CONNECTING);
635f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
636f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Clear the DTLS timer
637f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  Thread::Current()->Clear(this, MSG_TIMEOUT);
638f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
639f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
640f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  int ssl_error;
641f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  switch (ssl_error = SSL_get_error(ssl_, code)) {
642f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_NONE:
643f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- success";
644f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
645f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      if (!SSLPostConnectionCheck(ssl_, ssl_server_name_.c_str(), NULL,
646f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                  peer_certificate_digest_algorithm_)) {
647f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        LOG(LS_ERROR) << "TLS post connection check failed";
648f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        return -1;
649f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
650f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
651f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      state_ = SSL_CONNECTED;
652f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      StreamAdapterInterface::OnEvent(stream(), SE_OPEN|SE_READ|SE_WRITE, 0);
653f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      break;
654f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
655f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_WANT_READ: {
656f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        LOG(LS_VERBOSE) << " -- error want read";
657f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        struct timeval timeout;
658f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        if (DTLSv1_get_timeout(ssl_, &timeout)) {
659f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          int delay = timeout.tv_sec * 1000 + timeout.tv_usec/1000;
660f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
661f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org          Thread::Current()->PostDelayed(delay, this, MSG_TIMEOUT, 0);
662f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        }
663f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      }
664f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      break;
665f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
666f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_WANT_WRITE:
667f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- error want write";
668f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      break;
669f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
670f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    case SSL_ERROR_ZERO_RETURN:
671f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    default:
672f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      LOG(LS_VERBOSE) << " -- error " << code;
673f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return (ssl_error != 0) ? ssl_error : -1;
674f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
675f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
676f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return 0;
677f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
678f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
679f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::Error(const char* context, int err, bool signal) {
680f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  LOG(LS_WARNING) << "OpenSSLStreamAdapter::Error("
681f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                  << context << ", " << err << ")";
682f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  state_ = SSL_ERROR;
683f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ssl_error_code_ = err;
684f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  Cleanup();
685f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (signal)
686f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    StreamAdapterInterface::OnEvent(stream(), SE_CLOSE, err);
687f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
688f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
689f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::Cleanup() {
690f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  LOG(LS_INFO) << "Cleanup";
691f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
692f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (state_ != SSL_ERROR) {
693f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    state_ = SSL_CLOSED;
694f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ssl_error_code_ = 0;
695f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
696f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
697f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (ssl_) {
6985cc77017d808f4e9c2c53115eadbc951e675269cjiayl@webrtc.org    int ret = SSL_shutdown(ssl_);
6995cc77017d808f4e9c2c53115eadbc951e675269cjiayl@webrtc.org    if (ret < 0) {
7005cc77017d808f4e9c2c53115eadbc951e675269cjiayl@webrtc.org      LOG(LS_WARNING) << "SSL_shutdown failed, error = "
7015cc77017d808f4e9c2c53115eadbc951e675269cjiayl@webrtc.org                      << SSL_get_error(ssl_, ret);
7025cc77017d808f4e9c2c53115eadbc951e675269cjiayl@webrtc.org    }
7035cc77017d808f4e9c2c53115eadbc951e675269cjiayl@webrtc.org
704f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    SSL_free(ssl_);
705f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ssl_ = NULL;
706f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
707f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (ssl_ctx_) {
708f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    SSL_CTX_free(ssl_ctx_);
709f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ssl_ctx_ = NULL;
710f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
711f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  identity_.reset();
712f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  peer_certificate_.reset();
713f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
714f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Clear the DTLS timer
715f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  Thread::Current()->Clear(this, MSG_TIMEOUT);
716f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
717f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
718f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
719f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgvoid OpenSSLStreamAdapter::OnMessage(Message* msg) {
720f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Process our own messages and then pass others to the superclass
721f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (MSG_TIMEOUT == msg->message_id) {
722f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_INFO) << "DTLS timeout expired";
723f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    DTLSv1_handle_timeout(ssl_);
724f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ContinueSSL();
725f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  } else {
726f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    StreamInterface::OnMessage(msg);
727f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
728f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
729f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
730f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgSSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
731f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL_CTX *ctx = NULL;
732f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
733f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (role_ == SSL_CLIENT) {
734f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ?
735f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        DTLSv1_client_method() : TLSv1_client_method());
736f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  } else {
737f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ?
738f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org        DTLSv1_server_method() : TLSv1_server_method());
739f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
740f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (ctx == NULL)
741f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return NULL;
742f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
743f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (identity_ && !identity_->ConfigureIdentity(ctx)) {
744f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    SSL_CTX_free(ctx);
745f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return NULL;
746f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
747f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
748f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef _DEBUG
749f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL_CTX_set_info_callback(ctx, OpenSSLAdapter::SSLInfoCallback);
750f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
751f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
752e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org  int mode = SSL_VERIFY_PEER;
753e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org  if (client_auth_enabled()) {
754e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org    // Require a certificate from the client.
755e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org    // Note: Normally this is always true in production, but it may be disabled
756e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org    // for testing purposes (e.g. SSLAdapter unit tests).
757e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org    mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
758e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org  }
759e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org
760e987b732456ada71d1dee156e6aa3ee238da1e33tkchin@webrtc.org  SSL_CTX_set_verify(ctx, mode, SSLVerifyCallback);
761f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL_CTX_set_verify_depth(ctx, 4);
762f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
763f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
764f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef HAVE_DTLS_SRTP
765f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!srtp_ciphers_.empty()) {
766f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_ciphers_.c_str())) {
767f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      SSL_CTX_free(ctx);
768f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      return NULL;
769f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
770f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
771f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
772f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
773f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return ctx;
774f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
775f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
776f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgint OpenSSLStreamAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
777f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Get our SSL structure from the store
778f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(
779f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                        store,
780f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                        SSL_get_ex_data_X509_STORE_CTX_idx()));
781f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  OpenSSLStreamAdapter* stream =
782f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    reinterpret_cast<OpenSSLStreamAdapter*>(SSL_get_app_data(ssl));
783f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
784f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (stream->peer_certificate_digest_algorithm_.empty()) {
785f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return 0;
786f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
787f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  X509* cert = X509_STORE_CTX_get_current_cert(store);
788005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  int depth = X509_STORE_CTX_get_error_depth(store);
789005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org
790005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  // For now We ignore the parent certificates and verify the leaf against
791005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  // the digest.
792005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  //
793005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  // TODO(jiayl): Verify the chain is a proper chain and report the chain to
794005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  // |stream->peer_certificate_|, like what NSS does.
795005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  if (depth > 0) {
796005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org    LOG(LS_INFO) << "Ignored chained certificate at depth " << depth;
797005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org    return 1;
798005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org  }
799005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org
800f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  unsigned char digest[EVP_MAX_MD_SIZE];
801f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  size_t digest_length;
802f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!OpenSSLCertificate::ComputeDigest(
803f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org           cert,
804f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org           stream->peer_certificate_digest_algorithm_,
805f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org           digest, sizeof(digest),
806f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org           &digest_length)) {
807f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_WARNING) << "Failed to compute peer cert digest.";
808f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return 0;
809f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
810005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org
811f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  Buffer computed_digest(digest, digest_length);
812f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (computed_digest != stream->peer_certificate_digest_value_) {
813f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_WARNING) << "Rejected peer certificate due to mismatched digest.";
814f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    return 0;
815f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
816f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Ignore any verification error if the digest matches, since there is no
817f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // value in checking the validity of a self-signed cert issued by untrusted
818f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // sources.
819f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  LOG(LS_INFO) << "Accepted peer certificate.";
820005ef1e3a0b7d76568e6b80a3d6d67ae840501dbhenrike@webrtc.org
821f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  // Record the peer's certificate.
822f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  stream->peer_certificate_.reset(new OpenSSLCertificate(cert));
823f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return 1;
824f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
825f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
826f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// This code is taken from the "Network Security with OpenSSL"
827f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org// sample in chapter 5
828f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::SSLPostConnectionCheck(SSL* ssl,
829f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                  const char* server_name,
830f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                  const X509* peer_cert,
831f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                  const std::string
832f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                                                  &peer_digest) {
833f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  ASSERT(server_name != NULL);
834f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  bool ok;
835f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (server_name[0] != '\0') {  // traditional mode
836f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ok = OpenSSLAdapter::VerifyServerName(ssl, server_name, ignore_bad_cert());
837f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
838f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    if (ok) {
839f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org      ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
840f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org            custom_verification_succeeded_);
841f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    }
842f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  } else {  // peer-to-peer mode
843f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ASSERT((peer_cert != NULL) || (!peer_digest.empty()));
844f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    // no server name validation
845f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ok = true;
846f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
847f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
848f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  if (!ok && ignore_bad_cert()) {
849f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_ERROR) << "SSL_get_verify_result(ssl) = "
850f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org                  << SSL_get_verify_result(ssl);
851f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    LOG(LS_INFO) << "Other TLS post connection checks failed.";
852f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org    ok = true;
853f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  }
854f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
855f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return ok;
856f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
857f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
858f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::HaveDtls() {
859f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return true;
860f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
861f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
862f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::HaveDtlsSrtp() {
863f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef HAVE_DTLS_SRTP
864f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return true;
865f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#else
866f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return false;
867f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
868f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
869f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
870f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.orgbool OpenSSLStreamAdapter::HaveExporter() {
871f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#ifdef HAVE_DTLS_SRTP
872f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return true;
873f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#else
874f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org  return false;
875f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif
876f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}
877f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
878f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org}  // namespace rtc
879f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org
880f7795df4261877af9eaf982cccfafc3fc52aeb4ahenrike@webrtc.org#endif  // HAVE_OPENSSL_SSL_H
881