1 /*
2  * Copyright (C) 2008 iptego GmbH
3  *
4  * This file is part of SEMS, a free SIP media server.
5  *
6  * SEMS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version. This program is released under
10  * the GPL with the additional exemption that compiling, linking,
11  * and/or using OpenSSL is allowed.
12  *
13  * For a license to use the SEMS software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * SEMS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 
28 #ifdef WITH_ZRTP
29 
30 #include "AmZRTP.h"
31 
32 #include "AmSession.h"
33 #include "log.h"
34 #include "AmConfigReader.h"
35 #include "AmUtils.h"
36 #include <stdlib.h>
37 
38 #define ZRTP_CACHE_SAVE_INTERVAL 1
39 #define SEMS_CLIENT_ID "SEMS"
40 
41 string AmZRTP::cache_path = "zrtp_cache.dat";
42 string AmZRTP::entropy_path;
43 
44 int AmZRTP::zrtp_cache_save_cntr = 0;
45 AmMutex AmZRTP::zrtp_cache_mut;
46 
47 zrtp_global_t* AmZRTP::zrtp_global;      // persistent storage for libzrtp data
48 zrtp_config_t AmZRTP::zrtp_config;
49 zrtp_zid_t AmZRTP::zrtp_instance_zid = {"defaultsems"};
50 
zrtp_log(int level,char * data,int len,int offset)51 void zrtp_log(int level, char *data, int len, int offset) {
52   int sems_lvl = L_DBG;
53   if (level==2)
54     sems_lvl = L_WARN; // ??
55   else if (level==1)
56     sems_lvl = L_INFO; // ??
57 
58   if (sems_lvl==L_DBG && !AmConfig::enable_zrtp_debuglog)
59     return;
60 
61   _LOG(sems_lvl, "%.*s", len, data);
62 }
63 
init()64 int AmZRTP::init() {
65   zrtp_log_set_log_engine(zrtp_log);
66 
67   AmConfigReader cfg;
68   string cfgname=add2path(AmConfig::ModConfigPath, 1,  "zrtp.conf");
69   if(cfg.loadFile(cfgname)) {
70     ERROR("No %s config file present.\n", cfgname.c_str());
71     return -1;
72   }
73 
74   cache_path = cfg.getParameter("cache_path");
75   if (cfg.hasParameter("zid_hex")) {
76     string zid_hex = cfg.getParameter("zid_hex");
77     if (zid_hex.size() != 2*sizeof(zrtp_instance_zid)) {
78       ERROR("zid_hex config parameter in zrtp.conf must be %lu characters long.\n",
79 	    sizeof(zrtp_zid_t)*2);
80       return -1;
81     }
82 
83     for (size_t i=0;i<sizeof(zrtp_instance_zid);i++) {
84       unsigned int h;
85       if (reverse_hex2int(zid_hex.substr(i*2, 2), h)) {
86 	ERROR("in zid_hex in zrtp.conf: '%s' is no hex number\n", zid_hex.substr(i*2, 2).c_str());
87 	return -1;
88       }
89 
90       zrtp_instance_zid[i]=h % 0xff;
91     }
92 
93   } else if (cfg.hasParameter("zid")) {
94     string zid = cfg.getParameter("zid");
95     WARN("zid parameter in zrtp.conf is only supported for backwards compatibility. Please use zid_hex\n");
96     if (zid.length() != sizeof(zrtp_zid_t)) {
97       ERROR("zid config parameter in zrtp.conf must be %lu characters long.\n",
98 	    sizeof(zrtp_zid_t));
99       return -1;
100     }
101     for (size_t i=0;i<zid.length();i++)
102       zrtp_instance_zid[i]=zid[i];
103   } else {
104     // generate one
105     string zid_hex;
106     for (size_t i=0;i<sizeof(zrtp_instance_zid);i++) {
107       zrtp_instance_zid[i]=get_random() % 0xff;
108       zid_hex+=char2hex(zrtp_instance_zid[i], true);
109     }
110 
111     WARN("Generated random ZID. To support key continuity through key cache "
112 	 "on the peers, add this to zrtp.conf: 'zid_hex=\"%s\"'", zid_hex.c_str());
113   }
114 
115 
116   DBG("initializing ZRTP library with cache path '%s'.\n", cache_path.c_str());
117 
118   zrtp_config_defaults(&zrtp_config);
119 
120   strcpy(zrtp_config.client_id, SEMS_CLIENT_ID);
121   zrtp_config.lic_mode = ZRTP_LICENSE_MODE_UNLIMITED;
122 
123   strncpy(zrtp_config.def_cache_path.buffer, cache_path.c_str(),
124 	  zrtp_config.def_cache_path.max_length);
125   zrtp_config.def_cache_path.length = cache_path.length();
126 
127   zrtp_config.cb.misc_cb.on_send_packet           = AmZRTP::on_send_packet;
128   zrtp_config.cb.event_cb.on_zrtp_secure          = AmZRTP::on_zrtp_secure;
129   zrtp_config.cb.event_cb.on_zrtp_security_event  = AmZRTP::on_zrtp_security_event;
130   zrtp_config.cb.event_cb.on_zrtp_protocol_event  = AmZRTP::on_zrtp_protocol_event;
131 
132   if ( zrtp_status_ok != zrtp_init(&zrtp_config, &zrtp_global) ) {
133     ERROR("Error during ZRTP initialization\n");
134     return -1;
135   }
136 
137   // Use saved entropy data (if available) when adding more entropy
138   entropy_path = cfg.getParameter("entropy_path");
139   unsigned char entropy_buffer[256];
140   unsigned int read_bytes = 0;
141   FILE* fp = fopen(entropy_path.c_str(), "r");
142   if (fp) {
143     read_bytes = fread(entropy_buffer, 1, 256, fp);
144     DBG("read %u bytes of ZRTP entropy data\n", read_bytes);
145     fclose(fp);
146   } else {
147     DBG("ZRTP entropy data is not available yet\n");
148   }
149 
150   // Add more entroypy
151   int bytes_added;
152   bytes_added = zrtp_entropy_add(zrtp_global, entropy_buffer, read_bytes);
153   if (bytes_added == -1) {
154     ERROR("failed to add ZRTP entropy bytes\n");
155     return -1;
156   } else {
157     DBG("added %u bytes of ZRTP entropy\n", bytes_added);
158   }
159 
160   DBG("ZRTP initialized ok.\n");
161 
162   return 0;
163 }
164 
shut_down()165 int AmZRTP::shut_down() {
166 
167   // Save 256 bytes of entropy to file for use at next start
168 
169   FILE* fp = fopen(entropy_path.c_str(), "w");
170   if (fp) {
171     unsigned char entropy_buffer[256];
172     unsigned int write_bytes = 0;
173     write_bytes = zrtp_randstr(zrtp_global, entropy_buffer, 256);
174     if (write_bytes == 256) {
175       fwrite(entropy_buffer, 1, write_bytes, fp);
176       fclose(fp);
177       DBG("saved 256 bytes of ZRTP entropy data\n");
178       return 0;
179     } else {
180       ERROR("failed to generate entropy data\n");
181     }
182   } else {
183     ERROR("failed to open entropy file for writing\n");
184   }
185   return -1;
186 }
187 
AmZRTPSessionState()188 AmZRTPSessionState::AmZRTPSessionState()
189   : zrtp_session(NULL), zrtp_audio(NULL)
190 {
191 }
192 
initSession(AmSession * session)193 int AmZRTPSessionState::initSession(AmSession* session) {
194   DBG("Initializing ZRTP stream...\n");
195 
196   // Allocate zrtp session
197   zrtp_status_t status =
198     zrtp_session_init( AmZRTP::zrtp_global,
199 		       NULL, AmZRTP::zrtp_instance_zid,
200 		       ZRTP_SIGNALING_ROLE_UNKNOWN, // fixme
201 		       &zrtp_session);
202   if (zrtp_status_ok != status) {
203     // Check error code and debug logs
204     return status;
205   }
206 
207   // Set call-back pointer to our parent structure
208   zrtp_session_set_userdata(zrtp_session, session);
209 
210   // Attach audio stream
211   status = zrtp_stream_attach(zrtp_session, &zrtp_audio);
212   if (zrtp_status_ok != status) {
213     // Check error code and debug logs
214     return status;
215   }
216   zrtp_stream_set_userdata(zrtp_audio, session);
217   return 0;
218 }
219 
startStreams(uint32_t ssrc)220 int AmZRTPSessionState::startStreams(uint32_t ssrc){
221   if (NULL == zrtp_audio)
222     return -1;
223 
224   zrtp_status_t status = zrtp_stream_start(zrtp_audio, ssrc);
225   if (zrtp_status_ok != status) {
226     ERROR("starting ZRTP stream\n");
227     return -1;
228   }
229   return 0;
230 }
231 
stopStreams()232 int AmZRTPSessionState::stopStreams(){
233   if (NULL == zrtp_audio)
234     return -1;
235 
236   zrtp_status_t status = zrtp_stream_stop(zrtp_audio);
237   if (zrtp_status_ok != status) {
238     ERROR("stopping ZRTP stream\n");
239     return -1;
240   }
241   return 0;
242 }
243 
freeSession()244 void AmZRTPSessionState::freeSession() {
245   if (NULL == zrtp_session)
246     return;
247 
248   zrtp_session_down(zrtp_session);
249 
250   // // save zrtp cache
251   // zrtp_cache_mut.lock();
252   // if (!((++zrtp_cache_save_cntr) % ZRTP_CACHE_SAVE_INTERVAL)) {
253   //   if (zrtp_cache_user_down() != zrtp_status_ok) {
254   //     ERROR("while writing ZRTP cache.\n");
255   //   }
256   // }
257   // zrtp_cache_mut.unlock();
258 }
259 
~AmZRTPSessionState()260 AmZRTPSessionState::~AmZRTPSessionState() {
261 
262 }
263 
264 // void zrtp_get_cache_path(char *path, uint32_t length) {
265 // }
266 
on_send_packet(const zrtp_stream_t * stream,char * packet,unsigned int length)267 int AmZRTP::on_send_packet(const zrtp_stream_t *stream, char *packet, unsigned int length) {
268   DBG("on_send_packet(stream [%p], len=%u)\n", stream, length);
269   if (NULL==stream) {
270     ERROR("on_send_packet without stream context.\n");
271     return -1;
272   }
273 
274   void* udata = zrtp_stream_get_userdata(stream);
275   if (NULL == udata) {
276     ERROR("ZRTP on_send_packet without session context.\n");
277     return -1;
278   }
279   AmSession* sess = reinterpret_cast<AmSession*>(udata);
280 
281   return sess->RTPStream()->send_raw(packet, length);
282 }
283 
on_zrtp_secure(zrtp_stream_t * stream)284 void AmZRTP::on_zrtp_secure(zrtp_stream_t *stream) {
285   DBG("on_zrtp_secure(stream [%p])\n", stream);
286 
287   // if (NULL==stream) {
288   //   ERROR("event received without stream context.\n");
289   //   return;
290   // }
291 
292   // void* udata = zrtp_stream_get_userdata(stream);
293   // if (NULL == udata) {
294   //   ERROR("ZRTP on_send_packet without session set context.\n");
295   //   return;
296   // }
297   // AmSession* sess = reinterpret_cast<AmSession*>(udata);
298 
299   // sess->onZrtpSecure();
300 }
301 
on_zrtp_security_event(zrtp_stream_t * stream,zrtp_security_event_t event)302 void AmZRTP::on_zrtp_security_event(zrtp_stream_t *stream, zrtp_security_event_t event) {
303   DBG("on_zrtp_security_event(stream [%p])\n", stream);
304   if (NULL==stream) {
305     ERROR("event received without stream context.\n");
306     return;
307   }
308   void* udata = zrtp_stream_get_userdata(stream);
309   if (NULL == udata) {
310     ERROR("ZRTP on_send_packet without session set context.\n");
311     return;
312   }
313   AmSession* sess = reinterpret_cast<AmSession*>(udata);
314   sess->postEvent(new AmZRTPSecurityEvent(event, stream));
315 }
316 
on_zrtp_protocol_event(zrtp_stream_t * stream,zrtp_protocol_event_t event)317 void AmZRTP::on_zrtp_protocol_event(zrtp_stream_t *stream, zrtp_protocol_event_t event) {
318   DBG("on_zrtp_protocol_event(stream [%p])\n", stream);
319   if (NULL==stream) {
320     ERROR("event received without stream context.\n");
321     return;
322   }
323   void* udata = zrtp_stream_get_userdata(stream);
324   if (NULL == udata) {
325     ERROR("ZRTP on_send_packet without session set context.\n");
326     return;
327   }
328   AmSession* sess = reinterpret_cast<AmSession*>(udata);
329   sess->postEvent(new AmZRTPProtocolEvent(event, stream));
330 }
331 
zrtp_protocol_event_desc(zrtp_protocol_event_t e)332 const char* zrtp_protocol_event_desc(zrtp_protocol_event_t e) {
333   switch (e) {
334   case ZRTP_EVENT_UNSUPPORTED: return "ZRTP_EVENT_UNSUPPORTED";
335 
336   case ZRTP_EVENT_IS_CLEAR: return "ZRTP_EVENT_IS_CLEAR";
337   case ZRTP_EVENT_IS_INITIATINGSECURE: return "ZRTP_EVENT_IS_INITIATINGSECURE";
338   case ZRTP_EVENT_IS_PENDINGSECURE: return "ZRTP_EVENT_IS_PENDINGSECURE";
339   case ZRTP_EVENT_IS_PENDINGCLEAR: return "ZRTP_EVENT_IS_PENDINGCLEAR";
340   case ZRTP_EVENT_NO_ZRTP: return "ZRTP_EVENT_NO_ZRTP";
341   case ZRTP_EVENT_NO_ZRTP_QUICK: return "ZRTP_EVENT_NO_ZRTP_QUICK";
342   case ZRTP_EVENT_IS_CLIENT_ENROLLMENT: return "ZRTP_EVENT_IS_CLIENT_ENROLLMENT";
343   case ZRTP_EVENT_NEW_USER_ENROLLED: return "ZRTP_EVENT_NEW_USER_ENROLLED";
344   case ZRTP_EVENT_USER_ALREADY_ENROLLED: return "ZRTP_EVENT_USER_ALREADY_ENROLLED";
345   case ZRTP_EVENT_USER_UNENROLLED: return "ZRTP_EVENT_USER_UNENROLLED";
346   case ZRTP_EVENT_LOCAL_SAS_UPDATED: return "ZRTP_EVENT_LOCAL_SAS_UPDATED";
347   case ZRTP_EVENT_REMOTE_SAS_UPDATED: return "ZRTP_EVENT_REMOTE_SAS_UPDATED";
348   case ZRTP_EVENT_IS_SECURE: return "ZRTP_EVENT_IS_SECURE";
349   case ZRTP_EVENT_IS_SECURE_DONE: return "ZRTP_EVENT_IS_SECURE_DONE";
350   case ZRTP_EVENT_IS_PASSIVE_RESTRICTION: return "ZRTP_EVENT_IS_PASSIVE_RESTRICTION";
351   case ZRTP_EVENT_COUNT: return "ZRTP_EVENT_COUNT"; // ?
352   default:    return "UNKNOWN_ZRTP_PROTOCOL_EVENT";
353   }
354 };
355 
zrtp_security_event_desc(zrtp_security_event_t e)356 const char* zrtp_security_event_desc(zrtp_security_event_t e) {
357   switch (e) {
358   case ZRTP_EVENT_PROTOCOL_ERROR: return "ZRTP_EVENT_PROTOCOL_ERROR";
359   case ZRTP_EVENT_WRONG_SIGNALING_HASH: return "ZRTP_EVENT_WRONG_SIGNALING_HASH";
360   case ZRTP_EVENT_WRONG_MESSAGE_HMAC: return "ZRTP_EVENT_WRONG_MESSAGE_HMAC";
361   case ZRTP_EVENT_MITM_WARNING: return "ZRTP_EVENT_MITM_WARNING";
362   default:    return "UNKNOWN_ZRTP_SECURITY_EVENT";
363   }
364 }
365 
366 #endif
367