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