1 /**
2 * @file zrtp.c ZRTP: Media Path Key Agreement for Unicast Secure RTP
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6 #include <re.h>
7 #include <baresip.h>
8 #include <zrtp.h>
9
10 #include <string.h>
11
12 /**
13 * @defgroup zrtp zrtp
14 *
15 * ZRTP: Media Path Key Agreement for Unicast Secure RTP
16 *
17 * Experimental support for ZRTP
18 *
19 * See http://tools.ietf.org/html/rfc6189
20 *
21 * Briefly tested with Twinkle 1.4.2 and Jitsi 2.2.4603.9615
22 *
23 * This module is using ZRTP implementation in Freeswitch
24 * https://github.com/juha-h/libzrtp
25 *
26 * Thanks:
27 *
28 * Ingo Feinerer
29 *
30 * Configuration options:
31 *
32 \verbatim
33 zrtp_hash {yes,no} # Enable SDP zrtp-hash (recommended)
34 \endverbatim
35 *
36 */
37
38
39 enum {
40 PRESZ = 36 /* Preamble size for TURN/STUN header */
41 };
42
43 struct menc_sess {
44 zrtp_session_t *zrtp_session;
45 menc_error_h *errorh;
46 void *arg;
47 struct tmr abort_timer;
48 int err;
49 };
50
51 struct menc_media {
52 struct menc_sess *sess;
53 struct udp_helper *uh_rtp;
54 struct udp_helper *uh_rtcp;
55 struct sa raddr;
56 void *rtpsock;
57 void *rtcpsock;
58 zrtp_stream_t *zrtp_stream;
59 };
60
61
62 static zrtp_global_t *zrtp_global;
63 static zrtp_config_t zrtp_config;
64 static zrtp_zid_t zid;
65
66
67 /* RFC 6189, section 8.1. */
68 static bool use_sig_hash = true;
69
70
71 enum pkt_type {
72 PKT_TYPE_UNKNOWN = 0,
73 PKT_TYPE_RTP = 1,
74 PKT_TYPE_RTCP = 2,
75 PKT_TYPE_ZRTP = 4
76 };
77
78
get_packet_type(const struct mbuf * mb)79 static enum pkt_type get_packet_type(const struct mbuf *mb)
80 {
81 uint8_t b, pt;
82 uint32_t magic;
83
84 if (mbuf_get_left(mb) < 8)
85 return PKT_TYPE_UNKNOWN;
86
87 b = mbuf_buf(mb)[0];
88
89 if (127 < b && b < 192) {
90 pt = mbuf_buf(mb)[1] & 0x7f;
91 if (72 <= pt && pt <= 76)
92 return PKT_TYPE_RTCP;
93 else
94 return PKT_TYPE_RTP;
95 }
96 else {
97 memcpy(&magic, &mbuf_buf(mb)[4], 4);
98 magic = ntohl(magic);
99 if (magic == ZRTP_PACKETS_MAGIC)
100 return PKT_TYPE_ZRTP;
101 }
102
103 return PKT_TYPE_UNKNOWN;
104 }
105
106
session_destructor(void * arg)107 static void session_destructor(void *arg)
108 {
109 struct menc_sess *st = arg;
110
111 tmr_cancel(&st->abort_timer);
112
113 if (st->zrtp_session)
114 zrtp_session_down(st->zrtp_session);
115 }
116
117
media_destructor(void * arg)118 static void media_destructor(void *arg)
119 {
120 struct menc_media *st = arg;
121
122 mem_deref(st->uh_rtp);
123 mem_deref(st->uh_rtcp);
124 mem_deref(st->rtpsock);
125 mem_deref(st->rtcpsock);
126
127 if (st->zrtp_stream)
128 zrtp_stream_stop(st->zrtp_stream);
129 }
130
131
abort_timer_h(void * arg)132 static void abort_timer_h(void *arg)
133 {
134 struct menc_sess *sess = arg;
135
136 if (sess->errorh) {
137 sess->errorh(sess->err, sess->arg);
138 sess->errorh = NULL;
139 }
140 }
141
142
abort_call(struct menc_sess * sess)143 static void abort_call(struct menc_sess *sess)
144 {
145 if (!sess->err) {
146 sess->err = EPIPE;
147 tmr_start(&sess->abort_timer, 0, abort_timer_h, sess);
148 }
149 }
150
151
drop_packets(const struct menc_media * st)152 static bool drop_packets(const struct menc_media *st)
153 {
154 return (st)? st->sess->err != 0 : true;
155 }
156
157
udp_helper_send(int * err,struct sa * dst,struct mbuf * mb,void * arg)158 static bool udp_helper_send(int *err, struct sa *dst,
159 struct mbuf *mb, void *arg)
160 {
161 struct menc_media *st = arg;
162 unsigned int length;
163 zrtp_status_t s;
164 const char *proto_name = "rtp";
165 enum pkt_type ptype = get_packet_type(mb);
166
167 if (drop_packets(st))
168 return true;
169
170 length = (unsigned int)mbuf_get_left(mb);
171
172 /* only RTP/RTCP packets should be processed */
173 if (ptype == PKT_TYPE_RTCP) {
174 proto_name = "rtcp";
175 s = zrtp_process_rtcp(st->zrtp_stream,
176 (char *)mbuf_buf(mb), &length);
177 }
178 else if (ptype == PKT_TYPE_RTP) {
179 s = zrtp_process_rtp(st->zrtp_stream,
180 (char *)mbuf_buf(mb), &length);
181 }
182 else
183 return false;
184
185 if (s != zrtp_status_ok) {
186
187 if (s == zrtp_status_drop)
188 return true;
189
190 warning("zrtp: send(port=%d): zrtp_process_%s failed"
191 " (status = %d '%s')\n",
192 sa_port(dst), proto_name, s, zrtp_log_status2str(s));
193 return false;
194 }
195
196 /* make sure target buffer is large enough */
197 if (length > mbuf_get_space(mb)) {
198 warning("zrtp: zrtp_process_%s: length > space (%u > %u)\n",
199 proto_name, length, mbuf_get_space(mb));
200 *err = ENOMEM;
201 }
202
203 mb->end = mb->pos + length;
204
205 return false;
206 }
207
208
udp_helper_recv(struct sa * src,struct mbuf * mb,void * arg)209 static bool udp_helper_recv(struct sa *src, struct mbuf *mb, void *arg)
210 {
211 struct menc_media *st = arg;
212 unsigned int length;
213 zrtp_status_t s;
214 const char *proto_name = "srtp";
215 enum pkt_type ptype = get_packet_type(mb);
216
217 if (drop_packets(st))
218 return true;
219
220 length = (unsigned int)mbuf_get_left(mb);
221
222 if (ptype == PKT_TYPE_RTCP) {
223 proto_name = "srtcp";
224 s = zrtp_process_srtcp(st->zrtp_stream,
225 (char *)mbuf_buf(mb), &length);
226 }
227 else if (ptype == PKT_TYPE_RTP || ptype == PKT_TYPE_ZRTP) {
228 s = zrtp_process_srtp(st->zrtp_stream,
229 (char *)mbuf_buf(mb), &length);
230 }
231 else
232 return false;
233
234 if (s != zrtp_status_ok) {
235
236 if (s == zrtp_status_drop)
237 return true;
238
239 warning("zrtp: recv(port=%d): zrtp_process_%s: %d '%s'\n",
240 sa_port(src), proto_name, s, zrtp_log_status2str(s));
241 return false;
242 }
243
244 mb->end = mb->pos + length;
245
246 return false;
247 }
248
249
sig_hash_encode(struct zrtp_stream_t * stream,struct sdp_media * m)250 static int sig_hash_encode(struct zrtp_stream_t *stream,
251 struct sdp_media *m)
252 {
253 char buf[ZRTP_SIGN_ZRTP_HASH_LENGTH + 1];
254 zrtp_status_t s;
255 int err = 0;
256
257 s = zrtp_signaling_hash_get(stream, buf, sizeof(buf));
258 if (s != zrtp_status_ok) {
259 warning("zrtp: zrtp_signaling_hash_get: status = %d\n", s);
260 return EINVAL;
261 }
262
263 err = sdp_media_set_lattr(m, true, "zrtp-hash", "%s %s",
264 ZRTP_PROTOCOL_VERSION, buf);
265 if (err) {
266 warning("zrtp: sdp_media_set_lattr: %d\n", err);
267 }
268
269 return err;
270 }
271
272
sig_hash_decode(struct zrtp_stream_t * stream,const struct sdp_media * m)273 static void sig_hash_decode(struct zrtp_stream_t *stream,
274 const struct sdp_media *m)
275 {
276 const char *attr_val;
277 struct pl major, minor, hash;
278 uint32_t version;
279 int err;
280 zrtp_status_t s;
281
282 attr_val = sdp_media_rattr(m, "zrtp-hash");
283 if (!attr_val)
284 return;
285
286 err = re_regex(attr_val, strlen(attr_val),
287 "[0-9]+.[0-9]2 [0-9a-f]+",
288 &major, &minor, &hash);
289 if (err || hash.l < ZRTP_SIGN_ZRTP_HASH_LENGTH) {
290 warning("zrtp: malformed zrtp-hash attribute, ignoring...\n");
291 return;
292 }
293
294 version = pl_u32(&major) * 100 + pl_u32(&minor);
295 /* more version checks? */
296 if (version < 110) {
297 warning("zrtp: zrtp-hash: version (%d) is too low, "
298 "ignoring...", version);
299 }
300
301 s = zrtp_signaling_hash_set(stream, hash.p, (uint32_t)hash.l);
302 if (s != zrtp_status_ok)
303 warning("zrtp: zrtp_signaling_hash_set: status = %d\n", s);
304 }
305
306
session_alloc(struct menc_sess ** sessp,struct sdp_session * sdp,bool offerer,menc_error_h * errorh,void * arg)307 static int session_alloc(struct menc_sess **sessp, struct sdp_session *sdp,
308 bool offerer, menc_error_h *errorh, void *arg)
309 {
310 struct menc_sess *st;
311 zrtp_status_t s;
312 int err = 0;
313 (void)offerer;
314
315 if (!sessp || !sdp)
316 return EINVAL;
317
318 st = mem_zalloc(sizeof(*st), session_destructor);
319 if (!st)
320 return ENOMEM;
321
322 st->errorh = errorh;
323 st->arg = arg;
324 st->err = 0;
325 tmr_init(&st->abort_timer);
326
327 s = zrtp_session_init(zrtp_global, NULL, zid,
328 ZRTP_SIGNALING_ROLE_UNKNOWN, &st->zrtp_session);
329 if (s != zrtp_status_ok) {
330 warning("zrtp: zrtp_session_init failed (status = %d)\n", s);
331 err = EPROTO;
332 goto out;
333 }
334
335 out:
336 if (err)
337 mem_deref(st);
338 else
339 *sessp = st;
340
341 return err;
342 }
343
344
media_alloc(struct menc_media ** stp,struct menc_sess * sess,struct rtp_sock * rtp,int proto,void * rtpsock,void * rtcpsock,struct sdp_media * sdpm)345 static int media_alloc(struct menc_media **stp, struct menc_sess *sess,
346 struct rtp_sock *rtp,
347 int proto, void *rtpsock, void *rtcpsock,
348 struct sdp_media *sdpm)
349 {
350 struct menc_media *st;
351 zrtp_status_t s;
352 int layer = 10; /* above zero */
353 int err = 0;
354
355 if (!stp || !sess || proto != IPPROTO_UDP)
356 return EINVAL;
357
358 st = *stp;
359 if (st)
360 goto start;
361
362 st = mem_zalloc(sizeof(*st), media_destructor);
363 if (!st)
364 return ENOMEM;
365
366 st->sess = sess;
367 if (rtpsock) {
368 st->rtpsock = mem_ref(rtpsock);
369 err |= udp_register_helper(&st->uh_rtp, rtpsock, layer,
370 udp_helper_send, udp_helper_recv, st);
371 }
372 if (rtcpsock && (rtcpsock != rtpsock)) {
373 st->rtcpsock = mem_ref(rtcpsock);
374 err |= udp_register_helper(&st->uh_rtcp, rtcpsock, layer,
375 udp_helper_send, udp_helper_recv, st);
376 }
377 if (err)
378 goto out;
379
380 s = zrtp_stream_attach(sess->zrtp_session, &st->zrtp_stream);
381 if (s != zrtp_status_ok) {
382 warning("zrtp: zrtp_stream_attach failed (status=%d)\n", s);
383 err = EPROTO;
384 goto out;
385 }
386
387 zrtp_stream_set_userdata(st->zrtp_stream, st);
388
389 if (use_sig_hash) {
390 err = sig_hash_encode(st->zrtp_stream, sdpm);
391 if (err)
392 goto out;
393 }
394
395 out:
396 if (err) {
397 mem_deref(st);
398 return err;
399 }
400 else
401 *stp = st;
402
403 start:
404 if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) {
405 st->raddr = *sdp_media_raddr(sdpm);
406
407 if (use_sig_hash)
408 sig_hash_decode(st->zrtp_stream, sdpm);
409
410 s = zrtp_stream_start(st->zrtp_stream, rtp_sess_ssrc(rtp));
411 if (s != zrtp_status_ok) {
412 warning("zrtp: zrtp_stream_start: status = %d\n", s);
413 }
414 }
415
416 return err;
417 }
418
419
on_send_packet(const zrtp_stream_t * stream,char * rtp_packet,unsigned int rtp_packet_length)420 static int on_send_packet(const zrtp_stream_t *stream,
421 char *rtp_packet,
422 unsigned int rtp_packet_length)
423 {
424 struct menc_media *st = zrtp_stream_get_userdata(stream);
425 struct mbuf *mb;
426 int err;
427
428 if (drop_packets(st))
429 return zrtp_status_ok;
430
431 if (!sa_isset(&st->raddr, SA_ALL))
432 return zrtp_status_ok;
433
434 mb = mbuf_alloc(PRESZ + rtp_packet_length);
435 if (!mb)
436 return zrtp_status_alloc_fail;
437
438 mb->pos = PRESZ;
439 (void)mbuf_write_mem(mb, (void *)rtp_packet, rtp_packet_length);
440 mb->pos = PRESZ;
441
442 err = udp_send_helper(st->rtpsock, &st->raddr, mb, st->uh_rtp);
443 if (err) {
444 warning("zrtp: udp_send %u bytes (%m)\n",
445 rtp_packet_length, err);
446 }
447
448 mem_deref(mb);
449
450 return zrtp_status_ok;
451 }
452
453
on_zrtp_secure(zrtp_stream_t * stream)454 static void on_zrtp_secure(zrtp_stream_t *stream)
455 {
456 const struct menc_media *st = zrtp_stream_get_userdata(stream);
457 const struct menc_sess *sess = st->sess;
458 zrtp_session_info_t sess_info;
459
460 zrtp_session_get(sess->zrtp_session, &sess_info);
461 if (!sess_info.sas_is_verified && sess_info.sas_is_ready) {
462 info("zrtp: verify SAS <%s> <%s> for remote peer %w"
463 " (type /zrtp %w to verify)\n",
464 sess_info.sas1.buffer,
465 sess_info.sas2.buffer,
466 sess_info.peer_zid.buffer,
467 (size_t)sess_info.peer_zid.length,
468 sess_info.peer_zid.buffer,
469 (size_t)sess_info.peer_zid.length);
470 }
471 else if (sess_info.sas_is_verified) {
472 info("zrtp: secure session with verified remote peer %w\n",
473 sess_info.peer_zid.buffer,
474 (size_t)sess_info.peer_zid.length);
475 }
476 }
477
478
on_zrtp_security_event(zrtp_stream_t * stream,zrtp_security_event_t event)479 static void on_zrtp_security_event(zrtp_stream_t *stream,
480 zrtp_security_event_t event)
481 {
482 if (event == ZRTP_EVENT_WRONG_SIGNALING_HASH) {
483 const struct menc_media *st = zrtp_stream_get_userdata(stream);
484
485 warning("zrtp: Attack detected!!! Signaling hash from the "
486 "zrtp-hash SDP attribute doesn't match the hash of "
487 "the Hello message. Aborting the call.\n");
488
489 /* As this was called from zrtp_process_xxx(), we need
490 a safe shutdown. */
491 abort_call(st->sess);
492 }
493 }
494
495
496 static struct menc menc_zrtp = {
497 LE_INIT, "zrtp", "RTP/AVP", session_alloc, media_alloc
498 };
499
500
verify_sas(struct re_printf * pf,void * arg)501 static int verify_sas(struct re_printf *pf, void *arg)
502 {
503 const struct cmd_arg *carg = arg;
504 (void)pf;
505
506 if (str_isset(carg->prm)) {
507 char rzid[ZRTP_STRING16] = "";
508 zrtp_status_t s;
509 zrtp_string16_t local_zid = ZSTR_INIT_EMPTY(local_zid);
510 zrtp_string16_t remote_zid = ZSTR_INIT_EMPTY(remote_zid);
511
512 zrtp_zstrncpyc(ZSTR_GV(local_zid), (const char*)zid,
513 sizeof(zrtp_zid_t));
514
515 if (str_len(carg->prm) != 24) {
516 warning("zrtp: invalid remote ZID (%s)\n", carg->prm);
517 return EINVAL;
518 }
519
520 (void) str2hex(carg->prm, (int) str_len(carg->prm),
521 rzid, sizeof(rzid));
522 zrtp_zstrncpyc(ZSTR_GV(remote_zid), (const char*)rzid,
523 sizeof(zrtp_zid_t));
524
525 s = zrtp_verified_set(zrtp_global, &local_zid, &remote_zid,
526 true);
527 if (s == zrtp_status_ok)
528 info("zrtp: SAS for peer %s verified\n", carg->prm);
529 else {
530 warning("zrtp: zrtp_verified_set"
531 " failed (status = %d)\n", s);
532 return EINVAL;
533 }
534 }
535
536 return 0;
537 }
538
539
zrtp_log(int level,char * data,int len,int offset)540 static void zrtp_log(int level, char *data, int len, int offset)
541 {
542 (void)offset;
543
544 if (level == 1) {
545 warning("%b\n", data, len);
546 }
547 else if (level == 2) {
548 info("%b\n", data, len);
549 }
550 else {
551 debug("%b\n", data, len);
552 }
553 }
554
555
556 static const struct cmd cmdv[] = {
557 {"zrtp", 0, CMD_PRM, "Verify ZRTP SAS <remote ZID>", verify_sas },
558 };
559
560
module_init(void)561 static int module_init(void)
562 {
563 zrtp_status_t s;
564 char config_path[256] = "";
565 char zrtp_zid_path[256] = "";
566 FILE *f;
567 int ret, err;
568
569 (void)conf_get_bool(conf_cur(), "zrtp_hash", &use_sig_hash);
570
571 zrtp_log_set_log_engine(zrtp_log);
572
573 zrtp_config_defaults(&zrtp_config);
574
575 str_ncpy(zrtp_config.client_id, "baresip/zrtp",
576 sizeof(zrtp_config.client_id));
577
578 zrtp_config.lic_mode = ZRTP_LICENSE_MODE_UNLIMITED;
579
580 zrtp_config.cb.misc_cb.on_send_packet = on_send_packet;
581 zrtp_config.cb.event_cb.on_zrtp_secure = on_zrtp_secure;
582 zrtp_config.cb.event_cb.on_zrtp_security_event =
583 on_zrtp_security_event;
584
585 err = conf_path_get(config_path, sizeof(config_path));
586 if (err) {
587 warning("zrtp: could not get config path: %m\n", err);
588 return err;
589 }
590 ret = re_snprintf(zrtp_config.def_cache_path.buffer,
591 zrtp_config.def_cache_path.max_length,
592 "%s/zrtp_cache.dat", config_path);
593 if (ret < 0) {
594 warning("zrtp: could not write cache path\n");
595 return ENOMEM;
596 }
597 zrtp_config.def_cache_path.length = ret;
598
599 if (re_snprintf(zrtp_zid_path,
600 sizeof(zrtp_zid_path),
601 "%s/zrtp_zid", config_path) < 0)
602 return ENOMEM;
603 if ((f = fopen(zrtp_zid_path, "rb")) != NULL) {
604 if (fread(zid, sizeof(zid), 1, f) != 1) {
605 if (feof(f) || ferror(f)) {
606 warning("zrtp: invalid zrtp_zid file\n");
607 }
608 }
609 }
610 else if ((f = fopen(zrtp_zid_path, "wb")) != NULL) {
611 rand_bytes(zid, sizeof(zid));
612 if (fwrite(zid, sizeof(zid), 1, f) != 1) {
613 warning("zrtp: zrtp_zid file write failed\n");
614 }
615 info("zrtp: generated new persistent ZID (%s)\n",
616 zrtp_zid_path);
617 }
618 else {
619 err = errno;
620 warning("zrtp: fopen() %s (%m)\n", zrtp_zid_path, err);
621 }
622 if (f)
623 (void) fclose(f);
624
625 s = zrtp_init(&zrtp_config, &zrtp_global);
626 if (zrtp_status_ok != s) {
627 warning("zrtp: zrtp_init() failed (status = %d)\n", s);
628 return ENOSYS;
629 }
630
631 menc_register(baresip_mencl(), &menc_zrtp);
632
633 debug("zrtp: cache_file: %s\n", zrtp_config.def_cache_path.buffer);
634 debug(" zid_file: %s\n", zrtp_zid_path);
635 debug(" zid: %w\n",
636 zid, sizeof(zid));
637
638 return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv));
639 }
640
641
module_close(void)642 static int module_close(void)
643 {
644 cmd_unregister(baresip_commands(), cmdv);
645 menc_unregister(&menc_zrtp);
646
647 if (zrtp_global) {
648 zrtp_down(zrtp_global);
649 zrtp_global = NULL;
650 }
651
652 return 0;
653 }
654
655
656 EXPORT_SYM const struct mod_export DECL_EXPORTS(zrtp) = {
657 "zrtp",
658 "menc",
659 module_init,
660 module_close
661 };
662