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 (¤t_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 (¤t_callback);
102
103 if (!dat) {
104 dat = g_slice_new (struct GstSrtpEventReporterData);
105 g_private_set (¤t_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 (¤t_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