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