2 * Copyright (c) 2014, Ericsson AB. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or other
12 * materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 #include "gstdtlsconnection.h"
34 #include "gstdtlsagent.h"
35 #include "gstdtlscertificate.h"
38 # define __AVAILABILITYMACROS__
39 # define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
42 #include <openssl/err.h>
43 #include <openssl/ssl.h>
52 GST_DEBUG_CATEGORY_STATIC (gst_dtls_connection_debug);
53 #define GST_CAT_DEFAULT gst_dtls_connection_debug
55 #define SRTP_KEY_LEN 16
56 #define SRTP_SALT_LEN 14
60 SIGNAL_ON_ENCODER_KEY,
61 SIGNAL_ON_DECODER_KEY,
62 SIGNAL_ON_PEER_CERTIFICATE,
66 static guint signals[NUM_SIGNALS];
72 PROP_CONNECTION_STATE,
76 static GParamSpec *properties[NUM_PROPERTIES];
78 static int connection_ex_index;
80 static void handle_timeout (gpointer data, gpointer user_data);
82 struct _GstDtlsConnectionPrivate
89 gboolean keys_exported;
91 GstDtlsConnectionState connection_state;
92 gboolean sent_close_notify;
93 gboolean received_close_notify;
99 gint bio_buffer_offset;
101 GstDtlsConnectionSendCallback send_callback;
102 gpointer send_callback_user_data;
103 GDestroyNotify send_callback_destroy_notify;
104 GstFlowReturn syscall_flow_return;
106 gboolean timeout_pending;
107 GThreadPool *thread_pool;
110 G_DEFINE_TYPE_WITH_CODE (GstDtlsConnection, gst_dtls_connection, G_TYPE_OBJECT,
111 G_ADD_PRIVATE (GstDtlsConnection)
112 GST_DEBUG_CATEGORY_INIT (gst_dtls_connection_debug, "dtlsconnection", 0,
115 static void gst_dtls_connection_finalize (GObject * gobject);
116 static void gst_dtls_connection_set_property (GObject *, guint prop_id,
117 const GValue *, GParamSpec *);
118 static void gst_dtls_connection_get_property (GObject *, guint prop_id,
119 GValue *, GParamSpec *);
121 static void log_state (GstDtlsConnection *, const gchar * str);
122 static gboolean export_srtp_keys (GstDtlsConnection *, GError ** err);
123 static GstFlowReturn openssl_poll (GstDtlsConnection *, gboolean * notify_state,
125 static GstFlowReturn handle_error (GstDtlsConnection * self, int ret,
126 GstResourceError error_type, gboolean * notify_state, GError ** err);
127 static int openssl_verify_callback (int preverify_ok,
128 X509_STORE_CTX * x509_ctx);
130 static BIO_METHOD *BIO_s_gst_dtls_connection (void);
131 static int bio_method_write (BIO *, const char *data, int size);
132 static int bio_method_read (BIO *, char *out_buffer, int size);
133 static long bio_method_ctrl (BIO *, int cmd, long arg1, void *arg2);
134 static int bio_method_new (BIO *);
135 static int bio_method_free (BIO *);
138 gst_dtls_connection_class_init (GstDtlsConnectionClass * klass)
140 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
142 gobject_class->set_property = gst_dtls_connection_set_property;
143 gobject_class->get_property = gst_dtls_connection_get_property;
145 connection_ex_index =
146 SSL_get_ex_new_index (0, (gpointer) "gstdtlsagent connection index", NULL,
149 signals[SIGNAL_ON_DECODER_KEY] =
150 g_signal_new ("on-decoder-key", G_TYPE_FROM_CLASS (klass),
151 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
152 G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT);
154 signals[SIGNAL_ON_ENCODER_KEY] =
155 g_signal_new ("on-encoder-key", G_TYPE_FROM_CLASS (klass),
156 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
157 G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT);
159 signals[SIGNAL_ON_PEER_CERTIFICATE] =
160 g_signal_new ("on-peer-certificate", G_TYPE_FROM_CLASS (klass),
161 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
163 properties[PROP_AGENT] =
164 g_param_spec_object ("agent",
166 "Agent to use in creation of the connection",
168 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
170 properties[PROP_CONNECTION_STATE] =
171 g_param_spec_enum ("connection-state",
173 "Current connection state",
174 GST_DTLS_TYPE_CONNECTION_STATE,
175 GST_DTLS_CONNECTION_STATE_NEW, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
177 g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
179 _gst_dtls_init_openssl ();
181 gobject_class->finalize = gst_dtls_connection_finalize;
185 gst_dtls_connection_init (GstDtlsConnection * self)
187 GstDtlsConnectionPrivate *priv;
189 self->priv = priv = gst_dtls_connection_get_instance_private (self);
194 priv->is_client = FALSE;
195 priv->is_alive = TRUE;
196 priv->keys_exported = FALSE;
198 priv->bio_buffer = NULL;
199 priv->bio_buffer_len = 0;
200 priv->bio_buffer_offset = 0;
202 g_mutex_init (&priv->mutex);
203 g_cond_init (&priv->condition);
205 /* Thread pool for handling timeouts, we only need one thread for that
206 * really and share threads with all other thread pools around there as
207 * this is not going to happen very often */
208 priv->thread_pool = g_thread_pool_new (handle_timeout, self, 1, FALSE, NULL);
209 g_assert (priv->thread_pool);
210 priv->timeout_pending = FALSE;
214 gst_dtls_connection_finalize (GObject * gobject)
216 GstDtlsConnection *self = GST_DTLS_CONNECTION (gobject);
217 GstDtlsConnectionPrivate *priv = self->priv;
219 g_thread_pool_free (priv->thread_pool, TRUE, TRUE);
220 priv->thread_pool = NULL;
222 SSL_free (priv->ssl);
225 if (priv->send_callback_destroy_notify)
226 priv->send_callback_destroy_notify (priv->send_callback_user_data);
228 g_mutex_clear (&priv->mutex);
229 g_cond_clear (&priv->condition);
231 GST_DEBUG_OBJECT (self, "finalized");
233 G_OBJECT_CLASS (gst_dtls_connection_parent_class)->finalize (gobject);
236 #if OPENSSL_VERSION_NUMBER < 0x10100001L
238 BIO_set_data (BIO * bio, void *ptr)
244 BIO_get_data (BIO * bio)
250 BIO_set_shutdown (BIO * bio, int shutdown)
252 bio->shutdown = shutdown;
256 BIO_set_init (BIO * bio, int init)
262 X509_STORE_CTX_get0_cert (X509_STORE_CTX * ctx)
269 gst_dtls_connection_set_property (GObject * object, guint prop_id,
270 const GValue * value, GParamSpec * pspec)
272 GstDtlsConnection *self = GST_DTLS_CONNECTION (object);
274 GstDtlsConnectionPrivate *priv = self->priv;
275 SSL_CTX *ssl_context;
279 g_return_if_fail (!priv->ssl);
280 agent = GST_DTLS_AGENT (g_value_get_object (value));
281 g_return_if_fail (GST_IS_DTLS_AGENT (agent));
283 ssl_context = _gst_dtls_agent_peek_context (agent);
285 priv->ssl = SSL_new (ssl_context);
286 g_return_if_fail (priv->ssl);
288 priv->bio = BIO_new (BIO_s_gst_dtls_connection ());
289 g_return_if_fail (priv->bio);
291 BIO_set_data (priv->bio, self);
292 SSL_set_bio (priv->ssl, priv->bio, priv->bio);
294 SSL_set_verify (priv->ssl,
295 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
296 openssl_verify_callback);
297 SSL_set_ex_data (priv->ssl, connection_ex_index, self);
299 log_state (self, "connection created");
302 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
307 gst_dtls_connection_get_property (GObject * object, guint prop_id,
308 GValue * value, GParamSpec * pspec)
310 GstDtlsConnection *self = GST_DTLS_CONNECTION (object);
311 GstDtlsConnectionPrivate *priv = self->priv;
314 case PROP_CONNECTION_STATE:
315 g_mutex_lock (&priv->mutex);
316 g_value_set_enum (value, priv->connection_state);
317 g_mutex_unlock (&priv->mutex);
320 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
325 gst_dtls_connection_start (GstDtlsConnection * self, gboolean is_client,
328 GstDtlsConnectionPrivate *priv;
330 gboolean notify_state = FALSE;
334 g_return_val_if_fail (priv->send_callback, FALSE);
335 g_return_val_if_fail (priv->ssl, FALSE);
336 g_return_val_if_fail (priv->bio, FALSE);
338 GST_TRACE_OBJECT (self, "locking @ start");
339 g_mutex_lock (&priv->mutex);
340 GST_TRACE_OBJECT (self, "locked @ start");
342 priv->is_alive = TRUE;
343 priv->bio_buffer = NULL;
344 priv->bio_buffer_len = 0;
345 priv->bio_buffer_offset = 0;
346 priv->keys_exported = FALSE;
348 priv->sent_close_notify = FALSE;
349 priv->received_close_notify = FALSE;
351 /* Client immediately starts connecting, the server waits for a client to
352 * start the handshake process */
353 priv->is_client = is_client;
354 if (priv->is_client) {
355 priv->connection_state = GST_DTLS_CONNECTION_STATE_CONNECTING;
357 SSL_set_connect_state (priv->ssl);
359 if (priv->connection_state != GST_DTLS_CONNECTION_STATE_NEW) {
360 priv->connection_state = GST_DTLS_CONNECTION_STATE_NEW;
363 SSL_set_accept_state (priv->ssl);
365 log_state (self, "initial state set");
367 ret = openssl_poll (self, ¬ify_state, err);
368 if (ret == GST_FLOW_EOS && err) {
370 g_error_new_literal (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_OPEN_WRITE,
371 "Connection closed");
374 log_state (self, "first poll done");
376 GST_TRACE_OBJECT (self, "unlocking @ start");
377 g_mutex_unlock (&priv->mutex);
380 g_object_notify_by_pspec (G_OBJECT (self),
381 properties[PROP_CONNECTION_STATE]);
384 return ret == GST_FLOW_OK;
388 handle_timeout (gpointer data, gpointer user_data)
390 GstDtlsConnection *self = user_data;
391 GstDtlsConnectionPrivate *priv;
393 gboolean notify_state = FALSE;
397 g_mutex_lock (&priv->mutex);
398 priv->timeout_pending = FALSE;
399 if (priv->is_alive) {
400 ret = DTLSv1_handle_timeout (priv->ssl);
402 GST_DEBUG_OBJECT (self, "handle timeout returned %d, is_alive: %d", ret,
406 GST_WARNING_OBJECT (self, "handling timeout failed");
407 } else if (ret > 0) {
408 log_state (self, "handling timeout before poll");
409 openssl_poll (self, ¬ify_state, NULL);
410 log_state (self, "handling timeout after poll");
413 g_mutex_unlock (&priv->mutex);
416 g_object_notify_by_pspec (G_OBJECT (self),
417 properties[PROP_CONNECTION_STATE]);
422 schedule_timeout_handling (GstClock * clock, GstClockTime time, GstClockID id,
425 GstDtlsConnection *self = user_data;
427 g_mutex_lock (&self->priv->mutex);
428 if (self->priv->is_alive && !self->priv->timeout_pending) {
429 self->priv->timeout_pending = TRUE;
431 GST_TRACE_OBJECT (self, "Schedule timeout now");
432 g_thread_pool_push (self->priv->thread_pool, GINT_TO_POINTER (0xc0ffee),
435 g_mutex_unlock (&self->priv->mutex);
441 gst_dtls_connection_check_timeout_locked (GstDtlsConnection * self)
443 GstDtlsConnectionPrivate *priv;
444 struct timeval timeout;
445 gint64 end_time, wait_time;
447 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
451 if (DTLSv1_get_timeout (priv->ssl, &timeout)) {
452 wait_time = timeout.tv_sec * G_USEC_PER_SEC + timeout.tv_usec;
454 GST_DEBUG_OBJECT (self, "waiting for %" G_GINT64_FORMAT " usec", wait_time);
456 GstClock *system_clock = gst_system_clock_obtain ();
458 #ifndef G_DISABLE_ASSERT
459 GstClockReturn clock_return;
462 end_time = gst_clock_get_time (system_clock) + wait_time * GST_USECOND;
464 clock_id = gst_clock_new_single_shot_id (system_clock, end_time);
465 #ifndef G_DISABLE_ASSERT
470 gst_clock_id_wait_async (clock_id, schedule_timeout_handling,
471 g_object_ref (self), (GDestroyNotify) g_object_unref);
472 g_assert (clock_return == GST_CLOCK_OK);
473 gst_clock_id_unref (clock_id);
474 gst_object_unref (system_clock);
476 if (self->priv->is_alive && !self->priv->timeout_pending) {
477 self->priv->timeout_pending = TRUE;
478 GST_TRACE_OBJECT (self, "Schedule timeout now");
480 g_thread_pool_push (self->priv->thread_pool, GINT_TO_POINTER (0xc0ffee),
485 GST_DEBUG_OBJECT (self, "no timeout set");
490 gst_dtls_connection_check_timeout (GstDtlsConnection * self)
492 GstDtlsConnectionPrivate *priv;
494 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
498 GST_TRACE_OBJECT (self, "locking @ start_timeout");
499 g_mutex_lock (&priv->mutex);
500 GST_TRACE_OBJECT (self, "locked @ start_timeout");
501 gst_dtls_connection_check_timeout_locked (self);
502 g_mutex_unlock (&priv->mutex);
503 GST_TRACE_OBJECT (self, "unlocking @ start_timeout");
507 gst_dtls_connection_stop (GstDtlsConnection * self)
509 gboolean notify_state = FALSE;
511 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
512 g_return_if_fail (self->priv->ssl);
513 g_return_if_fail (self->priv->bio);
515 GST_DEBUG_OBJECT (self, "stopping connection");
517 GST_TRACE_OBJECT (self, "locking @ stop");
518 g_mutex_lock (&self->priv->mutex);
519 GST_TRACE_OBJECT (self, "locked @ stop");
521 self->priv->is_alive = FALSE;
522 if (self->priv->connection_state != GST_DTLS_CONNECTION_STATE_FAILED
523 && self->priv->connection_state != GST_DTLS_CONNECTION_STATE_CLOSED) {
524 self->priv->connection_state = GST_DTLS_CONNECTION_STATE_CLOSED;
527 GST_TRACE_OBJECT (self, "signaling @ stop");
528 g_cond_signal (&self->priv->condition);
529 GST_TRACE_OBJECT (self, "signaled @ stop");
531 GST_TRACE_OBJECT (self, "unlocking @ stop");
532 g_mutex_unlock (&self->priv->mutex);
534 GST_DEBUG_OBJECT (self, "stopped connection");
537 g_object_notify_by_pspec (G_OBJECT (self),
538 properties[PROP_CONNECTION_STATE]);
543 gst_dtls_connection_close (GstDtlsConnection * self)
545 gboolean notify_state = FALSE;
547 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
548 g_return_if_fail (self->priv->ssl);
549 g_return_if_fail (self->priv->bio);
551 GST_DEBUG_OBJECT (self, "closing connection");
553 GST_TRACE_OBJECT (self, "locking @ close");
554 g_mutex_lock (&self->priv->mutex);
555 GST_TRACE_OBJECT (self, "locked @ close");
557 if (self->priv->is_alive) {
558 self->priv->is_alive = FALSE;
559 g_cond_signal (&self->priv->condition);
562 if (self->priv->connection_state != GST_DTLS_CONNECTION_STATE_FAILED
563 && self->priv->connection_state != GST_DTLS_CONNECTION_STATE_CLOSED) {
564 self->priv->connection_state = GST_DTLS_CONNECTION_STATE_CLOSED;
568 GST_TRACE_OBJECT (self, "unlocking @ close");
569 g_mutex_unlock (&self->priv->mutex);
571 GST_DEBUG_OBJECT (self, "closed connection");
574 g_object_notify_by_pspec (G_OBJECT (self),
575 properties[PROP_CONNECTION_STATE]);
580 gst_dtls_connection_set_send_callback (GstDtlsConnection * self,
581 GstDtlsConnectionSendCallback callback, gpointer user_data,
582 GDestroyNotify destroy_notify)
584 GstDtlsConnectionPrivate *priv;
586 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
590 GST_TRACE_OBJECT (self, "locking @ set_send_callback");
591 g_mutex_lock (&priv->mutex);
592 GST_TRACE_OBJECT (self, "locked @ set_send_callback");
594 if (priv->send_callback_destroy_notify)
595 priv->send_callback_destroy_notify (priv->send_callback_user_data);
596 priv->send_callback = callback;
597 priv->send_callback_user_data = user_data;
598 priv->send_callback_destroy_notify = destroy_notify;
600 GST_TRACE_OBJECT (self, "unlocking @ set_send_callback");
601 g_mutex_unlock (&priv->mutex);
605 gst_dtls_connection_set_flow_return (GstDtlsConnection * self,
606 GstFlowReturn flow_ret)
608 g_return_if_fail (GST_IS_DTLS_CONNECTION (self));
609 self->priv->syscall_flow_return = flow_ret;
613 gst_dtls_connection_process (GstDtlsConnection * self, gpointer data, gsize len,
614 gsize * written, GError ** err)
616 GstFlowReturn flow_ret = GST_FLOW_OK;
617 GstDtlsConnectionPrivate *priv;
619 gboolean notify_state = FALSE;
621 g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), 0);
622 g_return_val_if_fail (self->priv->ssl, 0);
623 g_return_val_if_fail (self->priv->bio, 0);
627 GST_TRACE_OBJECT (self, "locking @ process");
628 g_mutex_lock (&priv->mutex);
629 GST_TRACE_OBJECT (self, "locked @ process");
631 if (self->priv->received_close_notify
632 || self->priv->connection_state == GST_DTLS_CONNECTION_STATE_CLOSED) {
633 GST_DEBUG_OBJECT (self, "Already received close_notify");
634 g_mutex_unlock (&priv->mutex);
638 if (self->priv->connection_state == GST_DTLS_CONNECTION_STATE_FAILED) {
639 GST_ERROR_OBJECT (self, "Had a fatal error before");
640 g_mutex_unlock (&priv->mutex);
643 g_error_new_literal (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ,
644 "Had fatal error before");
645 return GST_FLOW_ERROR;
648 g_warn_if_fail (!priv->bio_buffer);
650 priv->bio_buffer = data;
651 priv->bio_buffer_len = len;
652 priv->bio_buffer_offset = 0;
654 log_state (self, "process start");
656 if (SSL_want_write (priv->ssl)) {
657 flow_ret = openssl_poll (self, ¬ify_state, err);
658 log_state (self, "process want write, after poll");
659 if (flow_ret != GST_FLOW_OK) {
660 g_mutex_unlock (&priv->mutex);
665 /* If we're a server and were in new state then by receiving the first data
666 * we would start the connection process */
667 if (!priv->is_client) {
668 if (self->priv->connection_state == GST_DTLS_CONNECTION_STATE_NEW) {
669 priv->connection_state = GST_DTLS_CONNECTION_STATE_CONNECTING;
674 ret = SSL_read (priv->ssl, data, len);
675 *written = ret >= 0 ? ret : 0;
676 GST_DEBUG_OBJECT (self, "read result: %d", ret);
679 handle_error (self, ret, GST_RESOURCE_ERROR_READ, ¬ify_state, err);
680 if (flow_ret == GST_FLOW_EOS) {
681 self->priv->received_close_notify = TRUE;
682 if (self->priv->connection_state != GST_DTLS_CONNECTION_STATE_FAILED
683 && self->priv->connection_state != GST_DTLS_CONNECTION_STATE_CLOSED) {
684 self->priv->connection_state = GST_DTLS_CONNECTION_STATE_CLOSED;
687 /* Notify about the connection being properly closed now if both
689 if (self->priv->sent_close_notify && self->priv->send_callback)
690 self->priv->send_callback (self, NULL, 0, NULL);
692 g_mutex_unlock (&priv->mutex);
695 g_object_notify_by_pspec (G_OBJECT (self),
696 properties[PROP_CONNECTION_STATE]);
700 } else if (flow_ret != GST_FLOW_OK) {
701 g_mutex_unlock (&priv->mutex);
704 g_object_notify_by_pspec (G_OBJECT (self),
705 properties[PROP_CONNECTION_STATE]);
711 log_state (self, "process after read");
713 flow_ret = openssl_poll (self, ¬ify_state, err);
715 log_state (self, "process after poll");
717 GST_TRACE_OBJECT (self, "unlocking @ process");
718 g_mutex_unlock (&priv->mutex);
721 g_object_notify_by_pspec (G_OBJECT (self),
722 properties[PROP_CONNECTION_STATE]);
729 gst_dtls_connection_send (GstDtlsConnection * self, gconstpointer data,
730 gsize len, gsize * written, GError ** err)
732 GstFlowReturn flow_ret;
734 gboolean notify_state = FALSE;
736 g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), 0);
738 g_return_val_if_fail (self->priv->ssl, 0);
739 g_return_val_if_fail (self->priv->bio, 0);
741 GST_TRACE_OBJECT (self, "locking @ send");
742 g_mutex_lock (&self->priv->mutex);
743 GST_TRACE_OBJECT (self, "locked @ send");
745 if (self->priv->connection_state == GST_DTLS_CONNECTION_STATE_FAILED) {
746 GST_ERROR_OBJECT (self, "Had a fatal error before");
747 g_mutex_unlock (&self->priv->mutex);
750 g_error_new_literal (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_WRITE,
751 "Had fatal error before");
752 return GST_FLOW_ERROR;
755 if (self->priv->sent_close_notify) {
757 GST_DEBUG_OBJECT (self, "Not sending new data after close_notify");
763 GST_DEBUG_OBJECT (self, "Sending close_notify");
764 ret = SSL_shutdown (self->priv->ssl);
765 if (self->priv->connection_state != GST_DTLS_CONNECTION_STATE_CLOSED &&
766 self->priv->connection_state != GST_DTLS_CONNECTION_STATE_FAILED) {
767 self->priv->connection_state = GST_DTLS_CONNECTION_STATE_CLOSED;
771 GST_LOG_OBJECT (self, "received peer close_notify already");
772 self->priv->received_close_notify = TRUE;
773 flow_ret = GST_FLOW_EOS;
774 } else if (ret == 0) {
775 GST_LOG_OBJECT (self, "did not receive peer close_notify yet");
776 flow_ret = GST_FLOW_OK;
779 handle_error (self, ret, GST_RESOURCE_ERROR_WRITE, ¬ify_state,
782 } else if (SSL_is_init_finished (self->priv->ssl)) {
783 GST_DEBUG_OBJECT (self, "sending data of %" G_GSIZE_FORMAT " B", len);
784 ret = SSL_write (self->priv->ssl, data, len);
789 handle_error (self, ret, GST_RESOURCE_ERROR_WRITE, ¬ify_state,
794 flow_ret = GST_FLOW_OK;
799 GST_WARNING_OBJECT (self,
800 "tried to send data before handshake was complete");
803 g_error_new_literal (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_WRITE,
804 "Tried to send data before handshake was complete");
805 flow_ret = GST_FLOW_ERROR;
808 GST_TRACE_OBJECT (self, "unlocking @ send");
809 g_mutex_unlock (&self->priv->mutex);
812 g_object_notify_by_pspec (G_OBJECT (self),
813 properties[PROP_CONNECTION_STATE]);
830 log_state (GstDtlsConnection * self, const gchar * str)
832 GstDtlsConnectionPrivate *priv = self->priv;
835 states |= (! !SSL_is_init_finished (priv->ssl) << 0);
836 states |= (! !SSL_in_init (priv->ssl) << 4);
837 states |= (! !SSL_in_before (priv->ssl) << 8);
838 states |= (! !SSL_in_connect_init (priv->ssl) << 12);
839 states |= (! !SSL_in_accept_init (priv->ssl) << 16);
840 states |= (! !SSL_want_write (priv->ssl) << 20);
841 states |= (! !SSL_want_read (priv->ssl) << 24);
843 #if OPENSSL_VERSION_NUMBER < 0x10100001L
844 GST_LOG_OBJECT (self, "%s: role=%s buf=(%d,%p:%d/%d) %x|%x %s",
846 priv->is_client ? "client" : "server",
847 pqueue_size (priv->ssl->d1->sent_messages),
849 priv->bio_buffer_offset,
850 priv->bio_buffer_len,
851 states, SSL_get_state (priv->ssl), SSL_state_string_long (priv->ssl));
853 GST_LOG_OBJECT (self, "%s: role=%s buf=(%p:%d/%d) %x|%x %s",
855 priv->is_client ? "client" : "server",
857 priv->bio_buffer_offset,
858 priv->bio_buffer_len,
859 states, SSL_get_state (priv->ssl), SSL_state_string_long (priv->ssl));
864 export_srtp_keys (GstDtlsConnection * self, GError ** err)
868 guint8 v[SRTP_KEY_LEN];
873 guint8 v[SRTP_SALT_LEN];
888 } client_key, server_key;
890 SRTP_PROTECTION_PROFILE *profile;
891 GstDtlsSrtpCipher cipher;
892 GstDtlsSrtpAuth auth;
895 static gchar export_string[] = "EXTRACTOR-dtls_srtp";
897 success = SSL_export_keying_material (self->priv->ssl,
898 (gpointer) & exported_keys, 60, export_string, strlen (export_string),
902 GST_WARNING_OBJECT (self, "Failed to export SRTP keys");
905 g_error_new_literal (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ,
906 "Failed to export SRTP keys");
910 profile = SSL_get_selected_srtp_profile (self->priv->ssl);
913 GST_WARNING_OBJECT (self,
914 "No SRTP capabilities negotiated during handshake");
917 g_error_new_literal (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ,
918 "No SRTP capabilities negotiated during handshake");
922 GST_INFO_OBJECT (self, "keys received, profile is %s", profile->name);
924 switch (profile->id) {
925 case SRTP_AES128_CM_SHA1_80:
926 cipher = GST_DTLS_SRTP_CIPHER_AES_128_ICM;
927 auth = GST_DTLS_SRTP_AUTH_HMAC_SHA1_80;
929 case SRTP_AES128_CM_SHA1_32:
930 cipher = GST_DTLS_SRTP_CIPHER_AES_128_ICM;
931 auth = GST_DTLS_SRTP_AUTH_HMAC_SHA1_32;
934 GST_WARNING_OBJECT (self,
935 "Invalid/unsupported crypto suite set by handshake");
938 g_error_new_literal (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ,
939 "Invalid/unsupported crypto suite set by handshake");
943 client_key.key = exported_keys.client_key;
944 server_key.key = exported_keys.server_key;
945 client_key.salt = exported_keys.client_salt;
946 server_key.salt = exported_keys.server_salt;
948 if (self->priv->is_client) {
949 g_signal_emit (self, signals[SIGNAL_ON_ENCODER_KEY], 0, &client_key, cipher,
951 g_signal_emit (self, signals[SIGNAL_ON_DECODER_KEY], 0, &server_key,
954 g_signal_emit (self, signals[SIGNAL_ON_ENCODER_KEY], 0, &server_key,
956 g_signal_emit (self, signals[SIGNAL_ON_DECODER_KEY], 0, &client_key, cipher,
960 self->priv->keys_exported = TRUE;
966 ssl_warn_cb (const char *str, size_t len, void *u)
968 GstDtlsConnection *self = u;
969 GST_WARNING_OBJECT (self, "ssl error: %s", str);
974 ssl_err_cb (const char *str, size_t len, void *u)
976 GstDtlsConnection *self = u;
977 GST_ERROR_OBJECT (self, "ssl error: %s", str);
982 handle_error (GstDtlsConnection * self, int ret, GstResourceError error_type,
983 gboolean * notify_state, GError ** err)
987 error = SSL_get_error (self->priv->ssl, ret);
991 GST_TRACE_OBJECT (self, "No error");
994 GST_ERROR_OBJECT (self, "Fatal SSL error");
995 if (self->priv->connection_state != GST_DTLS_CONNECTION_STATE_FAILED) {
996 self->priv->connection_state = GST_DTLS_CONNECTION_STATE_FAILED;
997 *notify_state = TRUE;
999 ERR_print_errors_cb (ssl_err_cb, self);
1002 g_error_new_literal (GST_RESOURCE_ERROR, error_type,
1004 return GST_FLOW_ERROR;
1005 case SSL_ERROR_ZERO_RETURN:
1006 GST_LOG_OBJECT (self, "Connection was closed");
1007 return GST_FLOW_EOS;
1008 case SSL_ERROR_WANT_READ:
1009 GST_LOG_OBJECT (self, "SSL wants read");
1011 case SSL_ERROR_WANT_WRITE:
1012 GST_LOG_OBJECT (self, "SSL wants write");
1014 case SSL_ERROR_SYSCALL:{
1015 GstFlowReturn rc = GST_FLOW_OK;
1016 /* OpenSSL shouldn't be making real system calls, so we can safely
1017 * ignore syscall errors. System interactions should happen through
1020 if (error_type == GST_RESOURCE_ERROR_WRITE) {
1021 rc = self->priv->syscall_flow_return;
1023 GST_DEBUG_OBJECT (self,
1024 "OpenSSL reported a syscall error. flow_return=%i", rc);
1028 if (self->priv->connection_state != GST_DTLS_CONNECTION_STATE_FAILED) {
1029 self->priv->connection_state = GST_DTLS_CONNECTION_STATE_FAILED;
1030 *notify_state = TRUE;
1032 GST_ERROR_OBJECT (self, "Unknown SSL error: %d, ret: %d", error, ret);
1035 g_error_new (GST_RESOURCE_ERROR, error_type,
1036 "Unknown SSL error: %d, ret: %d", error, ret);
1037 return GST_FLOW_ERROR;
1041 static GstFlowReturn
1042 openssl_poll (GstDtlsConnection * self, gboolean * notify_state, GError ** err)
1045 GstFlowReturn flow_ret;
1047 log_state (self, "poll: before handshake");
1050 ret = SSL_do_handshake (self->priv->ssl);
1052 log_state (self, "poll: after handshake");
1056 if (!self->priv->keys_exported) {
1057 GST_INFO_OBJECT (self,
1058 "handshake just completed successfully, exporting keys");
1060 if (!export_srtp_keys (self, err))
1061 return GST_FLOW_ERROR;
1063 if (self->priv->connection_state != GST_DTLS_CONNECTION_STATE_FAILED
1064 && self->priv->connection_state != GST_DTLS_CONNECTION_STATE_CLOSED
1065 && self->priv->connection_state !=
1066 GST_DTLS_CONNECTION_STATE_CONNECTED) {
1067 self->priv->connection_state = GST_DTLS_CONNECTION_STATE_CONNECTED;
1068 *notify_state = TRUE;
1071 GST_INFO_OBJECT (self, "handshake is completed");
1075 GST_DEBUG_OBJECT (self, "do_handshake encountered EOF");
1078 GST_DEBUG_OBJECT (self, "do_handshake encountered potential BIO error");
1081 GST_DEBUG_OBJECT (self, "do_handshake returned %d", ret);
1086 handle_error (self, ret, GST_RESOURCE_ERROR_OPEN_WRITE, notify_state,
1089 ERR_print_errors_cb (ssl_warn_cb, self);
1095 openssl_verify_callback (int preverify_ok, X509_STORE_CTX * x509_ctx)
1097 GstDtlsConnection *self;
1101 gboolean accepted = FALSE;
1104 X509_STORE_CTX_get_ex_data (x509_ctx,
1105 SSL_get_ex_data_X509_STORE_CTX_idx ());
1106 self = SSL_get_ex_data (ssl, connection_ex_index);
1107 g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), FALSE);
1109 pem = _gst_dtls_x509_to_pem (X509_STORE_CTX_get0_cert (x509_ctx));
1112 GST_WARNING_OBJECT (self,
1113 "failed to convert received certificate to pem format");
1115 bio = BIO_new (BIO_s_mem ());
1121 X509_NAME_print_ex (bio,
1122 X509_get_subject_name (X509_STORE_CTX_get0_cert (x509_ctx)), 1,
1124 BIO_read (bio, buffer, len);
1126 GST_DEBUG_OBJECT (self, "Peer certificate received:\n%s", buffer);
1129 GST_DEBUG_OBJECT (self, "failed to create certificate print membio");
1132 g_signal_emit (self, signals[SIGNAL_ON_PEER_CERTIFICATE], 0, pem,
1141 ######## #### #######
1147 ######## #### #######
1150 #if OPENSSL_VERSION_NUMBER < 0x10100001L
1151 static BIO_METHOD custom_bio_methods = {
1165 BIO_s_gst_dtls_connection (void)
1167 return &custom_bio_methods;
1170 static BIO_METHOD *custom_bio_methods;
1173 BIO_s_gst_dtls_connection (void)
1175 if (custom_bio_methods != NULL)
1176 return custom_bio_methods;
1178 custom_bio_methods = BIO_meth_new (BIO_TYPE_BIO, "stream");
1179 if (custom_bio_methods == NULL
1180 || !BIO_meth_set_write (custom_bio_methods, bio_method_write)
1181 || !BIO_meth_set_read (custom_bio_methods, bio_method_read)
1182 || !BIO_meth_set_ctrl (custom_bio_methods, bio_method_ctrl)
1183 || !BIO_meth_set_create (custom_bio_methods, bio_method_new)
1184 || !BIO_meth_set_destroy (custom_bio_methods, bio_method_free)) {
1185 BIO_meth_free (custom_bio_methods);
1189 return custom_bio_methods;
1194 bio_method_write (BIO * bio, const char *data, int size)
1196 GstDtlsConnection *self = GST_DTLS_CONNECTION (BIO_get_data (bio));
1197 gboolean ret = TRUE;
1199 GST_LOG_OBJECT (self, "BIO: writing %d", size);
1200 self->priv->syscall_flow_return = GST_FLOW_OK;
1202 if (self->priv->send_callback)
1203 ret = self->priv->send_callback (self, data, size,
1204 self->priv->send_callback_user_data);
1206 return ret ? size : -1;
1210 bio_method_read (BIO * bio, char *out_buffer, int size)
1212 GstDtlsConnection *self = GST_DTLS_CONNECTION (BIO_get_data (bio));
1213 GstDtlsConnectionPrivate *priv = self->priv;
1214 guint internal_size;
1217 internal_size = priv->bio_buffer_len - priv->bio_buffer_offset;
1219 if (!priv->bio_buffer) {
1220 GST_LOG_OBJECT (self, "BIO: EOF");
1224 if (!out_buffer || size <= 0) {
1225 GST_WARNING_OBJECT (self, "BIO: read got invalid arguments");
1226 if (internal_size) {
1227 BIO_set_retry_read (bio);
1229 return internal_size;
1232 if (size > internal_size) {
1233 copy_size = internal_size;
1238 GST_DEBUG_OBJECT (self,
1239 "reading %d/%d bytes %d at offset %d, output buff size is %d", copy_size,
1240 priv->bio_buffer_len, internal_size, priv->bio_buffer_offset, size);
1242 memcpy (out_buffer, (guint8 *) priv->bio_buffer + priv->bio_buffer_offset,
1244 priv->bio_buffer_offset += copy_size;
1246 if (priv->bio_buffer_len == priv->bio_buffer_offset) {
1247 priv->bio_buffer = NULL;
1254 bio_method_ctrl (BIO * bio, int cmd, long arg1, void *arg2)
1256 GstDtlsConnection *self = GST_DTLS_CONNECTION (BIO_get_data (bio));
1257 GstDtlsConnectionPrivate *priv = self->priv;
1260 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
1261 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
1262 GST_LOG_OBJECT (self, "BIO: Timeout set");
1263 gst_dtls_connection_check_timeout_locked (self);
1265 case BIO_CTRL_RESET:
1266 priv->bio_buffer = NULL;
1267 priv->bio_buffer_len = 0;
1268 priv->bio_buffer_offset = 0;
1269 GST_LOG_OBJECT (self, "BIO: EOF reset");
1272 gint eof = priv->is_alive == FALSE;
1273 GST_LOG_OBJECT (self, "BIO: EOF query returned %d", eof);
1276 case BIO_CTRL_WPENDING:
1277 GST_LOG_OBJECT (self, "BIO: pending write");
1279 case BIO_CTRL_PENDING:{
1280 gint pending = priv->bio_buffer_len - priv->bio_buffer_offset;
1281 GST_LOG_OBJECT (self, "BIO: %d bytes pending", pending);
1284 case BIO_CTRL_FLUSH:
1285 GST_LOG_OBJECT (self, "BIO: flushing");
1287 case BIO_CTRL_DGRAM_QUERY_MTU:
1288 GST_DEBUG_OBJECT (self, "BIO: MTU query, returning 0...");
1290 case BIO_CTRL_DGRAM_MTU_EXCEEDED:
1291 GST_WARNING_OBJECT (self, "BIO: MTU exceeded");
1294 GST_LOG_OBJECT (self, "BIO: unhandled ctrl, %d", cmd);
1300 bio_method_new (BIO * bio)
1302 GST_LOG_OBJECT (NULL, "BIO: new");
1304 BIO_set_shutdown (bio, 0);
1305 BIO_set_init (bio, 1);
1311 bio_method_free (BIO * bio)
1314 GST_LOG_OBJECT (NULL, "BIO free called with null bio");
1318 GST_LOG_OBJECT (GST_DTLS_CONNECTION (BIO_get_data (bio)), "BIO free");
1323 gst_dtls_connection_state_get_type (void)
1325 static GType type = 0;
1326 static const GEnumValue values[] = {
1327 {GST_DTLS_CONNECTION_STATE_NEW, "New connection", "new"},
1328 {GST_DTLS_CONNECTION_STATE_CLOSED, "Closed connection on either side",
1330 {GST_DTLS_CONNECTION_STATE_FAILED, "Failed connection", "failed"},
1331 {GST_DTLS_CONNECTION_STATE_CONNECTING, "Connecting", "connecting"},
1332 {GST_DTLS_CONNECTION_STATE_CONNECTED, "Successfully connected",
1338 type = g_enum_register_static ("GstDtlsConnectionState", values);