• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer - GStreamer SRTP encoder and decoder
3  *
4  * Copyright 2009-2013 Collabora Ltd.
5  *  @author: Gabriel Millaire <gabriel.millaire@collabora.co.uk>
6  *  @author: Olivier Crete <olivier.crete@collabora.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 
24 
25 #define GLIB_DISABLE_DEPRECATION_WARNINGS
26 
27 #include "gstsrtp.h"
28 
29 #include <gst/rtp/gstrtcpbuffer.h>
30 
31 #include "gstsrtpenc.h"
32 #include "gstsrtpdec.h"
33 
34 #ifndef HAVE_SRTP2
35 srtp_err_status_t
srtp_set_stream_roc(srtp_t session,guint32 ssrc,guint32 roc)36 srtp_set_stream_roc (srtp_t session, guint32 ssrc, guint32 roc)
37 {
38   srtp_stream_t stream;
39 
40   stream = srtp_get_stream (session, htonl (ssrc));
41   if (stream == NULL) {
42     return srtp_err_status_bad_param;
43   }
44 
45   rdbx_set_roc (&stream->rtp_rdbx, roc);
46   return srtp_err_status_ok;
47 }
48 
49 srtp_err_status_t
srtp_get_stream_roc(srtp_t session,guint32 ssrc,guint32 * roc)50 srtp_get_stream_roc (srtp_t session, guint32 ssrc, guint32 * roc)
51 {
52   srtp_stream_t stream;
53 
54   stream = srtp_get_stream (session, htonl (ssrc));
55   if (stream == NULL) {
56     return srtp_err_status_bad_param;
57   }
58 
59   *roc = stream->rtp_rdbx.index >> 16;
60   return srtp_err_status_ok;
61 }
62 #endif
63 
64 static void free_reporter_data (gpointer data);
65 
66 GPrivate current_callback = G_PRIVATE_INIT (free_reporter_data);
67 
68 struct GstSrtpEventReporterData
69 {
70   gboolean soft_limit_reached;
71 };
72 
73 static void
free_reporter_data(gpointer data)74 free_reporter_data (gpointer data)
75 {
76   g_slice_free (struct GstSrtpEventReporterData, data);
77 }
78 
79 
80 static void
srtp_event_reporter(srtp_event_data_t * data)81 srtp_event_reporter (srtp_event_data_t * data)
82 {
83   struct GstSrtpEventReporterData *dat = g_private_get (&current_callback);
84 
85   if (!dat)
86     return;
87 
88   switch (data->event) {
89     case event_key_soft_limit:
90       dat->soft_limit_reached = TRUE;
91       break;
92 
93     default:
94       break;
95   }
96 }
97 
98 void
gst_srtp_init_event_reporter(void)99 gst_srtp_init_event_reporter (void)
100 {
101   struct GstSrtpEventReporterData *dat = g_private_get (&current_callback);
102 
103   if (!dat) {
104     dat = g_slice_new (struct GstSrtpEventReporterData);
105     g_private_set (&current_callback, dat);
106   }
107 
108   dat->soft_limit_reached = FALSE;
109 
110   srtp_install_event_handler (srtp_event_reporter);
111 }
112 
113 const gchar *
enum_nick_from_value(GType enum_gtype,gint value)114 enum_nick_from_value (GType enum_gtype, gint value)
115 {
116   GEnumClass *enum_class = g_type_class_ref (enum_gtype);
117   GEnumValue *enum_value;
118   const gchar *nick;
119 
120   if (!enum_gtype)
121     return NULL;
122 
123   enum_value = g_enum_get_value (enum_class, value);
124   if (!enum_value)
125     return NULL;
126   nick = enum_value->value_nick;
127   g_type_class_unref (enum_class);
128 
129   return nick;
130 }
131 
132 
133 gint
enum_value_from_nick(GType enum_gtype,const gchar * nick)134 enum_value_from_nick (GType enum_gtype, const gchar * nick)
135 {
136   GEnumClass *enum_class = g_type_class_ref (enum_gtype);
137   GEnumValue *enum_value;
138   gint value;
139 
140   if (!enum_gtype)
141     return -1;
142 
143   enum_value = g_enum_get_value_by_nick (enum_class, nick);
144   if (!enum_value)
145     return -1;
146   value = enum_value->value;
147   g_type_class_unref (enum_class);
148 
149   return value;
150 }
151 
152 gboolean
gst_srtp_get_soft_limit_reached(void)153 gst_srtp_get_soft_limit_reached (void)
154 {
155   struct GstSrtpEventReporterData *dat = g_private_get (&current_callback);
156 
157   if (dat)
158     return dat->soft_limit_reached;
159   return FALSE;
160 }
161 
162 /* Get SSRC from RTCP buffer
163  */
164 gboolean
rtcp_buffer_get_ssrc(GstBuffer * buf,guint32 * ssrc)165 rtcp_buffer_get_ssrc (GstBuffer * buf, guint32 * ssrc)
166 {
167   gboolean ret = FALSE;
168   GstRTCPBuffer rtcpbuf = GST_RTCP_BUFFER_INIT;
169   GstRTCPPacket packet;
170 
171   /* Get SSRC from RR or SR packet (RTCP) */
172 
173   if (!gst_rtcp_buffer_map (buf, GST_MAP_READ, &rtcpbuf))
174     return FALSE;
175 
176   if (gst_rtcp_buffer_get_first_packet (&rtcpbuf, &packet)) {
177     GstRTCPType type;
178     do {
179       type = gst_rtcp_packet_get_type (&packet);
180       switch (type) {
181         case GST_RTCP_TYPE_RR:
182           *ssrc = gst_rtcp_packet_rr_get_ssrc (&packet);
183           ret = TRUE;
184           break;
185         case GST_RTCP_TYPE_SR:
186           gst_rtcp_packet_sr_get_sender_info (&packet, ssrc, NULL, NULL, NULL,
187               NULL);
188           ret = TRUE;
189           break;
190         case GST_RTCP_TYPE_RTPFB:
191         case GST_RTCP_TYPE_PSFB:
192           *ssrc = gst_rtcp_packet_fb_get_sender_ssrc (&packet);
193           ret = TRUE;
194           break;
195         case GST_RTCP_TYPE_APP:
196           *ssrc = gst_rtcp_packet_app_get_ssrc (&packet);
197           ret = TRUE;
198           break;
199         default:
200           break;
201       }
202     } while ((ret == FALSE) && (type != GST_RTCP_TYPE_INVALID) &&
203         gst_rtcp_packet_move_to_next (&packet));
204   }
205 
206   gst_rtcp_buffer_unmap (&rtcpbuf);
207 
208   return ret;
209 }
210 
211 void
set_crypto_policy_cipher_auth(GstSrtpCipherType cipher,GstSrtpAuthType auth,srtp_crypto_policy_t * policy)212 set_crypto_policy_cipher_auth (GstSrtpCipherType cipher,
213     GstSrtpAuthType auth, srtp_crypto_policy_t * policy)
214 {
215   switch (cipher) {
216     case GST_SRTP_CIPHER_AES_128_ICM:
217       policy->cipher_type = SRTP_AES_ICM_128;
218       break;
219     case GST_SRTP_CIPHER_AES_256_ICM:
220       policy->cipher_type = SRTP_AES_ICM_256;
221       break;
222     case GST_SRTP_CIPHER_AES_128_GCM:
223       policy->cipher_type = SRTP_AES_GCM_128;
224       break;
225     case GST_SRTP_CIPHER_AES_256_GCM:
226       policy->cipher_type = SRTP_AES_GCM_256;
227       break;
228     case GST_SRTP_CIPHER_NULL:
229       policy->cipher_type = SRTP_NULL_CIPHER;
230       break;
231     default:
232       g_assert_not_reached ();
233   }
234 
235   policy->cipher_key_len = cipher_key_size (cipher);
236 
237   switch (auth) {
238     case GST_SRTP_AUTH_HMAC_SHA1_80:
239       policy->auth_type = SRTP_HMAC_SHA1;
240       policy->auth_key_len = 20;
241       policy->auth_tag_len = 10;
242       break;
243     case GST_SRTP_AUTH_HMAC_SHA1_32:
244       policy->auth_type = SRTP_HMAC_SHA1;
245       policy->auth_key_len = 20;
246       policy->auth_tag_len = 4;
247       break;
248     case GST_SRTP_AUTH_NULL:
249       policy->auth_type = SRTP_NULL_AUTH;
250       policy->auth_key_len = 0;
251       if (cipher == GST_SRTP_CIPHER_AES_128_GCM
252           || cipher == GST_SRTP_CIPHER_AES_256_GCM) {
253         policy->auth_tag_len = 16;
254       } else {
255         policy->auth_tag_len = 0;
256       }
257       break;
258   }
259 
260   if (cipher == GST_SRTP_CIPHER_NULL && auth == GST_SRTP_AUTH_NULL)
261     policy->sec_serv = sec_serv_none;
262   else if (cipher == GST_SRTP_CIPHER_NULL)
263     policy->sec_serv = sec_serv_auth;
264   else if (auth == GST_SRTP_AUTH_NULL)
265     policy->sec_serv = sec_serv_conf;
266   else
267     policy->sec_serv = sec_serv_conf_and_auth;
268 }
269 
270 guint
cipher_key_size(GstSrtpCipherType cipher)271 cipher_key_size (GstSrtpCipherType cipher)
272 {
273   guint size = 0;
274 
275   switch (cipher) {
276     case GST_SRTP_CIPHER_AES_128_ICM:
277       size = SRTP_AES_ICM_128_KEY_LEN_WSALT;
278       break;
279     case GST_SRTP_CIPHER_AES_256_ICM:
280       size = SRTP_AES_ICM_256_KEY_LEN_WSALT;
281       break;
282     case GST_SRTP_CIPHER_AES_128_GCM:
283       size = SRTP_AES_GCM_128_KEY_LEN_WSALT;
284       break;
285     case GST_SRTP_CIPHER_AES_256_GCM:
286       size = SRTP_AES_GCM_256_KEY_LEN_WSALT;
287       break;
288     case GST_SRTP_CIPHER_NULL:
289       break;
290     default:
291       g_assert_not_reached ();
292   }
293 
294   return size;
295 }
296 
297 static gboolean
plugin_init(GstPlugin * plugin)298 plugin_init (GstPlugin * plugin)
299 {
300   srtp_init ();
301 
302   if (!gst_srtp_enc_plugin_init (plugin))
303     return FALSE;
304 
305   if (!gst_srtp_dec_plugin_init (plugin))
306     return FALSE;
307 
308   return TRUE;
309 }
310 
311 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
312     GST_VERSION_MINOR,
313     srtp,
314     "GStreamer SRTP",
315     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
316