blob: db3cd8e225e3184617e8cfb440c856ac9c517a54 [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001/*
2 * Tivi client glue code for ZRTP.
3 * Copyright (c) 2012 Slient Circle LLC. All rights reserved.
4 *
5 *
6 * @author Werner Dittmann <Werner.Dittmann@t-online.de>
7 */
8
9#include <stdint.h>
10
11#include <common/osSpecifics.h>
12
13#include <libzrtpcpp/ZRtp.h>
14#include <libzrtpcpp/ZrtpStateClass.h>
15#include <libzrtpcpp/ZrtpCrc32.h>
16#include <srtp/CryptoContext.h>
17#include <srtp/CryptoContextCtrl.h>
18#include <srtp/SrtpHandler.h>
19
20#include <CtZrtpStream.h>
21#include <CtZrtpCallback.h>
22#include <TiviTimeoutProvider.h>
23#include <cryptcommon/aes.h>
24#include <cryptcommon/ZrtpRandom.h>
25
26// #define DEBUG_CTSTREAM
27#ifdef DEBUG_CTSTREAM
28static char debBuf[500];
29#define DEBUG(deb) deb
30#else
31#define DEBUG(deb)
32#endif
33
34static TimeoutProvider<std::string, CtZrtpStream*>* staticTimeoutProvider = NULL;
35
36static std::map<int32_t, std::string*> infoMap;
37static std::map<int32_t, std::string*> warningMap;
38static std::map<int32_t, std::string*> severeMap;
39static std::map<int32_t, std::string*> zrtpMap;
40static std::map<int32_t, std::string*> enrollMap;
41static int initialized = 0;
42
43static const char* peerHelloMismatchMsg = "s2_c050: Received Hello hash does not match computed Hello hash";
44static const char* srtpDecodeFailedMsg = "s2_c051: Parsing of received SRTP packet failed";
45static const char* zrtpEncap = "zrtp";
46
47using namespace GnuZrtpCodes;
48
49/**
50 * The following code is for internal logging only
51 *
52 */
53static void (*_zrtp_log_cb)(void *ret, const char *tag, const char *buf) = NULL;
54static void *pLogRet=NULL;
55
56// this function must be public. Tivi C++ code set its internal log function
57void set_zrtp_log_cb(void *pRet, void (*cb)(void *ret, const char *tag, const char *buf)){
58 _zrtp_log_cb=cb;
59 pLogRet=pRet;
60}
61
62// This function is static (could be global) to reduce visibility
63static void zrtp_log( const char *tag, const char *buf){
64 if(_zrtp_log_cb){
65 _zrtp_log_cb(pLogRet, tag, buf);
66 }
67}
68
69CtZrtpStream::CtZrtpStream():
70 index(CtZrtpSession::AudioStream), type(CtZrtpSession::NoStream), zrtpEngine(NULL),
71 ownSSRC(0), zrtpProtect(0), sdesProtect(0), zrtpUnprotect(0), sdesUnprotect(0), unprotectFailed(0),
72 enableZrtp(0), started(false), isStopped(false), session(NULL), tiviState(CtZrtpSession::eLookingPeer),
73 prevTiviState(CtZrtpSession::eLookingPeer), recvSrtp(NULL), recvSrtcp(NULL), sendSrtp(NULL), sendSrtcp(NULL),
74 zrtpUserCallback(NULL), zrtpSendCallback(NULL), senderZrtpSeqNo(0), peerSSRC(0), zrtpHashMatch(false),
75 sasVerified(false), helloReceived(false), useSdesForMedia(false), useZrtpTunnel(false), zrtpEncapSignaled(false),
76 sdes(NULL), supressCounter(0), srtpAuthErrorBurst(0), srtpReplayErrorBurst(0), srtpDecodeErrorBurst(0),
77 zrtpCrcErrors(0), role(NoRole)
78{
79 synchLock = new CMutexClass();
80
81 // TODO: do we need mutex or can tivi do it
82 if (staticTimeoutProvider == NULL) {
83 staticTimeoutProvider = new TimeoutProvider<std::string, CtZrtpStream*>();
84 staticTimeoutProvider->Event(&staticTimeoutProvider); // Event argument is dummy, not used
85 }
86 initStrings();
87 ZrtpRandom::getRandomData((uint8_t*)&senderZrtpSeqNo, 2);
88 senderZrtpSeqNo &= 0x7fff;
89}
90
91void CtZrtpStream::setUserCallback(CtZrtpCb* ucb) {
92 zrtpUserCallback = ucb;
93}
94
95void CtZrtpStream::setSendCallback(CtZrtpSendCb* scb) {
96 zrtpSendCallback = scb;
97}
98
99CtZrtpStream::~CtZrtpStream() {
100 stopStream();
101 delete synchLock;
102 synchLock = NULL;
103}
104//
105void CtZrtpStream::stopStream() {
106
107 // If we got only a small amout of valid SRTP packets after ZRTP negotiation then
108 // assume that our peer couldn't store the RS data, thus make sure we have a second
109 // retained shared secret available. Refer to RFC 6189bis, chapter 4.6.1
110 // 50 packets are about 1 second of audio data
111 if (zrtpEngine != NULL && zrtpUnprotect < 10 && !zrtpEngine->isMultiStream()) {
112 zrtpEngine->setRs2Valid();
113 }
114
115 index = CtZrtpSession::AudioStream;
116 type = CtZrtpSession::NoStream;
117 tiviState = CtZrtpSession::eLookingPeer;
118 prevTiviState = CtZrtpSession::eLookingPeer;
119 ownSSRC = 0;
120 enableZrtp = 0;
121 started = false;
122 isStopped = false;
123 peerSSRC = 0;
124
125 zrtpUnprotect = 0;
126 sdesUnprotect = 0;
127 zrtpProtect = 0;
128 sdesProtect = 0;
129 unprotectFailed = 0;
130
131 ZrtpRandom::getRandomData((uint8_t*)&senderZrtpSeqNo, 2);
132 senderZrtpSeqNo &= 0x7fff;
133 zrtpHashMatch= false;
134 sasVerified = false;
135 useSdesForMedia = false;
136 useZrtpTunnel = false;
137 zrtpEncapSignaled = false;
138 supressCounter = 0;
139 srtpAuthErrorBurst = 0;
140 srtpReplayErrorBurst = 0;
141 srtpDecodeErrorBurst = 0;
142 zrtpCrcErrors = 0;
143 helloReceived = false;
144
145 peerHelloHashes.clear();
146
147 delete zrtpEngine;
148 zrtpEngine = NULL;
149
150 delete recvSrtp;
151 recvSrtp = NULL;
152
153 delete recvSrtcp;
154 recvSrtcp = NULL;
155
156 delete sendSrtp;
157 sendSrtp = NULL;
158
159 delete sendSrtcp;
160 sendSrtcp = NULL;
161
162 delete sdes;
163 sdes = NULL;
164
165 // Don't delete the next classes, we don't own them.
166 zrtpUserCallback = NULL;
167 zrtpSendCallback = NULL;
168 session = NULL;
169}
170
171bool CtZrtpStream::processOutgoingRtp(uint8_t *buffer, size_t length, size_t *newLength) {
172 bool rc = true;
173 if (sendSrtp == NULL) { // ZRTP/SRTP inactive
174 *newLength = length;
175 // Check if ZRTP engine is started and check states to determine if we should send the RTP packet.
176 // Do not send in states: CommitSent, WaitDHPart2, WaitConfirm1, WaitConfirm2, WaitConfAck
177 if (started && (zrtpEngine->inState(CommitSent) || zrtpEngine->inState(WaitDHPart2) || zrtpEngine->inState(WaitConfirm1) ||
178 zrtpEngine->inState(WaitConfirm2) || zrtpEngine->inState(WaitConfAck))) {
179 ZrtpRandom::addEntropy(buffer, length);
180 return false;
181 }
182 if (useSdesForMedia && sdes != NULL) { // SDES stream available, let SDES protect if necessary
183 rc = sdes->outgoingRtp(buffer, length, newLength);
184 sdesProtect++;
185 }
186 return rc;
187 }
188 // At this point ZRTP/SRTP is active
189 if (useSdesForMedia && sdes != NULL) { // We still have a SDES - other client did not send zrtp-hash thus we protect twice
190 rc = sdes->outgoingRtp(buffer, length, newLength);
191 if (!rc) {
192 return rc;
193 }
194 sdesProtect++;
195 }
196 rc = SrtpHandler::protect(sendSrtp, buffer, length, newLength);
197 if (rc) {
198 zrtpProtect++;
199 }
200 return rc;
201}
202
203int32_t CtZrtpStream::processIncomingRtp(uint8_t *buffer, const size_t length, size_t *newLength) {
204 int32_t rc = 0;
205 // check if this could be a real RTP/SRTP packet.
206 if ((*buffer & 0xc0) == 0x80) { // A real RTP, check if we are in secure mode
207 if (supressCounter < supressWarn) // Don't report SRTP problems while in startup mode
208 supressCounter++;
209
210 if (recvSrtp == NULL) { // no ZRTP/SRTP available
211 if (!useSdesForMedia || sdes == NULL) { // no SDES stream available, just set length and return
212 *newLength = length;
213 return 1;
214 }
215 rc = sdes->incomingRtp(buffer, length, newLength);
216 if (rc == 1) { // SDES unprotect OK, do some statistics and return success
217 if (*sdesTempBuffer != 0) // clear SDES crypto string if not already done
218 memset(sdesTempBuffer, 0, maxSdesString);
219
220 srtpAuthErrorBurst = 0;
221 srtpReplayErrorBurst = 0;
222 srtpDecodeErrorBurst = 0;
223 sdesUnprotect++;
224 return 1;
225 }
226 }
227 else {
228 // At this point we have an active ZRTP/SRTP context, unprotect with ZRTP/SRTP first
229 rc = SrtpHandler::unprotect(recvSrtp, buffer, length, newLength);
230 if (rc == 1) {
231 zrtpUnprotect++;
232 // Got a good SRTP, check state and if in WaitConfAck (an Initiator state)
233 // then simulate a conf2Ack, refer to RFC 6189, chapter 4.6, last paragraph
234 if (zrtpEngine->inState(WaitConfAck)) {
235 zrtpEngine->conf2AckSecure();
236 }
237 if (useSdesForMedia && sdes != NULL) { // We still have a SDES - other client did not send matching zrtp-hash
238 rc = sdes->incomingRtp(buffer, *newLength, newLength);
239 }
240 if (rc == 1) { // if rc is still OK: either no SDES or layered SDES unprotect OK
241 srtpAuthErrorBurst = 0;
242 srtpReplayErrorBurst = 0;
243 srtpDecodeErrorBurst = 0;
244 return 1;
245 }
246 }
247 }
248 // We come to this point only if we have some problems during SRTP unprotect
249 if (rc == 0)
250 srtpDecodeErrorBurst++;
251 else if (rc == -1)
252 srtpAuthErrorBurst++;
253 else if (rc == -2)
254 srtpReplayErrorBurst++;
255
256 unprotectFailed++;
257 if (supressCounter >= supressWarn) {
258 if (rc == 0 && srtpDecodeErrorBurst > srtpErrorBurstThreshold && zrtpUserCallback != NULL) {
259 zrtpUserCallback->onZrtpWarning(session, (char*)srtpDecodeFailedMsg, index);
260 }
261 if (rc == -1 && srtpAuthErrorBurst >= srtpErrorBurstThreshold) {
262 sendInfo(Warning, WarningSRTPauthError);
263 }
264 if (rc == -2 && srtpReplayErrorBurst >= srtpErrorBurstThreshold){
265 sendInfo(Warning, WarningSRTPreplayError);
266 }
267 }
268 return rc;
269 }
270
271 // At this point we assume the packet is not an RTP packet. Check if it is a ZRTP packet.
272 // Process it if ZRTP processing is started. In any case, let the application drop
273 // the packet.
274 if (started) {
275 // Fixed header length + smallest ZRTP packet (includes CRC)
276 if (length < (12 + sizeof(HelloAckPacket_t))) // data too small, dismiss
277 return 0;
278
279 size_t useLength = length;
280
281 uint32_t magic = *(uint32_t*)(buffer + 4);
282 magic = zrtpNtohl(magic);
283
284 // Check if it is really a ZRTP packet, return, no further processing
285 if (magic != ZRTP_MAGIC) {
286 return 0;
287 }
288 if (useZrtpTunnel) {
289 size_t newLength;
290 *buffer = 0x80; // make it look like a real RTP packet
291 rc = sdes->incomingZrtpTunnel(buffer, length, &newLength);
292 if (rc < 0) {
293 if (rc == -1) {
294 zrtp_log("CtZrtpStream", "Receiving tunneled ZRTP - SRTP failure -1");
295 sendInfo(Warning, WarningSRTPauthError);
296 }
297 else {
298 zrtp_log("CtZrtpStream", "Receiving tunneled ZRTP - SRTP failure -2");
299 sendInfo(Warning, WarningSRTPreplayError);
300 }
301 return 0;
302 }
303 if (*sdesTempBuffer != 0) // clear SDES crypto string if not already done
304 memset(sdesTempBuffer, 0, maxSdesString);
305 useLength = newLength + CRC_SIZE; // length check assumes a ZRTP CRC
306 }
307 else {
308 DEBUG(char tmpBuffer[500];)
309 useZrtpTunnel = false;
310 // Get CRC value into crc (see above how to compute the offset)
311 uint16_t temp = length - CRC_SIZE;
312 uint32_t crc = *(uint32_t*)(buffer + temp);
313 crc = zrtpNtohl(crc);
314 if (!zrtpCheckCksum(buffer, temp, crc)) {
315 zrtpCrcErrors++;
316 if (zrtpCrcErrors > 15) {
317 DEBUG(snprintf(debBuf, 499, "len: %d, sdes: %p, sdesMedia: %d, zrtpEncap: %d", temp, (void*)sdes, useSdesForMedia, zrtpEncapSignaled); zrtp_log("CtZrtpStream", debBuf);)
318
319 sendInfo(Warning, WarningCRCmismatch);
320 zrtpCrcErrors = 0;
321 }
322 return 0;
323 }
324 }
325 // this now points to the plain ZRTP message.
326 unsigned char* zrtpMsg = (buffer + 12);
327
328 // store peer's SSRC in host order, used when creating the CryptoContext
329 if (peerSSRC == 0) {
330 peerSSRC = *(uint32_t*)(buffer + 8);
331 peerSSRC = zrtpNtohl(peerSSRC);
332 }
333 zrtpEngine->processZrtpMessage(zrtpMsg, peerSSRC, useLength);
334 }
335 return 0;
336}
337
338int CtZrtpStream::getSignalingHelloHash(char *hHash, int32_t index) {
339
340 if (hHash == NULL)
341 return 0;
342
343 std::string hash;
344 hash = zrtpEngine->getHelloHash(index);
345 strcpy(hHash, hash.c_str());
346 return hash.size();
347}
348
349void CtZrtpStream::setSignalingHelloHash(const char *hHash) {
350 synchEnter();
351
352 std::string hashStr;
353 hashStr.assign(hHash);
354
355 bool found = false;
356 for (std::vector<std::string>::iterator it = peerHelloHashes.begin() ; it != peerHelloHashes.end(); ++it) {
357 if ((*it).compare(hashStr) == 0) {
358 found = true;
359 break;
360 }
361 }
362 if (!found)
363 peerHelloHashes.push_back(hashStr);
364
365 std::string ph = zrtpEngine->getPeerHelloHash();
366 if (ph.empty()) {
367 synchLeave();
368 return;
369 }
370 size_t hexStringStart = ph.find_last_of(' ');
371 std::string hexString = ph.substr(hexStringStart+1);
372
373 for (std::vector<std::string>::iterator it = peerHelloHashes.begin() ; it != peerHelloHashes.end(); ++it) {
374 int match;
375 if ((*it).size() > SHA256_DIGEST_LENGTH*2) // got the full string incl. version prefix, compare with full peer hash string
376 match = (*it).compare(ph);
377 else
378 match = (*it).compare(hexString);
379 if (match == 0) {
380 zrtpHashMatch = true;
381 // We have a matching zrtp-hash. If ZRTP/SRTP is active we may need to release
382 // an existig SDES stream.
383 if (sdes != NULL && sendSrtp != NULL && recvSrtp != NULL) {
384 useSdesForMedia = false;
385 }
386 break;
387 }
388 }
389 if (!zrtpHashMatch && zrtpUserCallback != NULL)
390 zrtpUserCallback->onZrtpWarning(session, (char*)peerHelloMismatchMsg, index);
391 synchLeave();
392}
393
394int CtZrtpStream::isSecure() {
395 return tiviState == CtZrtpSession::eSecure || tiviState == CtZrtpSession::eSecureMitm ||
396 tiviState == CtZrtpSession::eSecureMitmVia || tiviState == CtZrtpSession::eSecureSdes;
397}
398
399
400#define T_ZRTP_LB(_K,_V) \
401 if(iLen+1 == sizeof(_K) && strncmp(key, _K, iLen) == 0){ \
402 return snprintf(p, maxLen, "%s", _V);}
403
404#define T_ZRTP_F(_K,_FV) \
405 if(iLen+1 == sizeof(_K) && strncmp(key,_K, iLen) == 0){ \
406 return snprintf(p, maxLen, "%d", (!!(info->secretsCached & _FV)) << (!!(info->secretsMatchedDH & _FV)));}
407
408#define T_ZRTP_I(_K,_I) \
409 if(iLen+1 == sizeof(_K) && strncmp(key,_K, iLen) == 0){ \
410 return snprintf(p, maxLen, "%d", _I);}
411
412int CtZrtpStream::getInfo(const char *key, char *p, int maxLen) {
413
414// if ((sdes == NULL /*&& !started*/) || isStopped || !isSecure())
415// return 0;
416
417 memset(p, 0, maxLen);
418 const ZRtp::zrtpInfo *info = NULL;
419 ZRtp::zrtpInfo tmpInfo;
420
421 int iLen = strlen(key);
422
423 // set the security state as a combination of tivi state and stateflags
424 int secState = tiviState & 0xff;
425 if (useSdesForMedia)
426 secState |= 0x100;
427
428 T_ZRTP_I("sec_state", secState);
429 T_ZRTP_LB("buildInfo", zrtpBuildInfo);
430
431 // Compute Hello-hash info string
432 const char *strng = NULL;
433 if (peerHelloHashes.empty()) {
434 strng = "None";
435 }
436 else if (zrtpHashMatch) {
437 strng = "Good";
438 }
439 else {
440 strng = !sdes || helloReceived ? "Bad" : "No hello";
441 }
442 T_ZRTP_LB("sdp_hash", strng);
443
444 std::string client = zrtpEngine->getPeerProtcolVersion();
445 if (role != NoRole) {
446 if (useZrtpTunnel)
447 client.append(role == Initiator ? "(IT)" : "(RT)");
448 else
449 client.append(role == Initiator ? "(I)" : "(R)");
450 }
451 T_ZRTP_LB("lbClient", zrtpEngine->getPeerClientId().c_str());
452 T_ZRTP_LB("lbVersion", client.c_str());
453
454 if (recvSrtp != NULL || sendSrtp != NULL) {
455 info = zrtpEngine->getDetailInfo();
456
457 if (iLen == 1 && key[0] == 'v') {
458 return snprintf(p, maxLen, "%d", sasVerified);
459 }
460 if(strncmp("sc_secure", key, iLen) == 0) {
461 int v = (zrtpHashMatch && sasVerified && !peerHelloHashes.empty() && tiviState == CtZrtpSession::eSecure);
462
463 if (v && (info->secretsCached & ZRtp::Rs1) == 0 && !sasVerified)
464 v = 0;
465 if (v && (info->secretsMatched & ZRtp::Rs1) == 0 && !sasVerified)
466 v = 0;
467 return snprintf(p, maxLen, "%d", v);
468 }
469 }
470 else if (useSdesForMedia && sdes != NULL) {
471 T_ZRTP_LB("lbClient", (const char*)"SDES");
472 T_ZRTP_LB("lbVersion", (const char*)"");
473
474 tmpInfo.secretsMatched = 0;
475 tmpInfo.secretsCached = 0;
476 tmpInfo.hash = (const char*)"";
477 if (sdes->getHmacTypeMix() == ZrtpSdesStream::MIX_NONE) {
478 tmpInfo.pubKey = (const char*)"SIP SDES";
479 }
480 else {
481 if (sdes->getCryptoMixAttribute(mixAlgoName, sizeof(mixAlgoName)) > 0)
482 tmpInfo.hash = mixAlgoName;
483 tmpInfo.pubKey = (const char*)"SIP SDES-MIX";
484 }
485 tmpInfo.cipher = sdes->getCipher();
486 tmpInfo.authLength = sdes->getAuthAlgo();
487 info = &tmpInfo;
488 }
489 else
490 return 0;
491
492 T_ZRTP_F("rs1",ZRtp::Rs1);
493 T_ZRTP_F("rs2",ZRtp::Rs2);
494 T_ZRTP_F("aux",ZRtp::Aux);
495 T_ZRTP_F("pbx",ZRtp::Pbx);
496
497 T_ZRTP_LB("lbChiper", info->cipher);
498 T_ZRTP_LB("lbAuthTag", info->authLength);
499 T_ZRTP_LB("lbHash", info->hash);
500 T_ZRTP_LB("lbKeyExchange", info->pubKey);
501
502 return 0;
503}
504
505int CtZrtpStream::enrollAccepted(char *p) {
506 zrtpEngine->acceptEnrollment(true);
507
508 uint8_t peerZid[IDENTIFIER_LEN];
509 std::string name;
510
511 zrtpEngine->getPeerZid(peerZid);
512 int32_t nmLen = getZidCacheInstance()->getPeerName(peerZid, &name);
513
514 if (nmLen == 0)
515 getZidCacheInstance()->putPeerName(peerZid, std::string(p));
516 return CtZrtpSession::ok;
517}
518
519int CtZrtpStream::enrollDenied() {
520 zrtpEngine->acceptEnrollment(false);
521
522 uint8_t peerZid[IDENTIFIER_LEN];
523 std::string name;
524
525 zrtpEngine->getPeerZid(peerZid);
526 int32_t nmLen = getZidCacheInstance()->getPeerName(peerZid, &name);
527
528 if (nmLen == 0)
529 getZidCacheInstance()->putPeerName(peerZid, std::string(""));
530 return CtZrtpSession::ok;
531}
532
533
534bool CtZrtpStream::createSdes(char *cryptoString, size_t *maxLen, const ZrtpSdesStream::sdesSuites sdesSuite) {
535 if (isSecure() || isSdesActive()) // don't take action if we are already secure or SDES already in active state
536 return false;
537
538 if (sdes == NULL)
539 sdes = new ZrtpSdesStream(sdesSuite);
540
541 if (sdes == NULL || !sdes->createSdes(cryptoString, maxLen, true)) {
542 delete sdes;
543 sdes = NULL;
544 return false;
545 }
546 return true;
547}
548
549bool CtZrtpStream::parseSdes(char *recvCryptoStr, size_t recvLength, char *sendCryptoStr, size_t *sendLength, bool sipInvite) {
550 if (isSecure() || isSdesActive()) // don't take action if we are already secure or SDES already in active state
551 return false;
552
553 // The ZrtpSdesStream determines its suite by parsing the crypto string.
554 if (sdes == NULL)
555 sdes = new ZrtpSdesStream();
556
557 if (sdes == NULL || !sdes->parseSdes(recvCryptoStr, recvLength, sipInvite))
558 goto cleanup;
559
560 if (!sipInvite) {
561 size_t len;
562 if (sendCryptoStr == NULL) {
563 sendCryptoStr = sdesTempBuffer;
564 len = maxSdesString;
565 sendLength = &len;
566 }
567 if (!sdes->createSdes(sendCryptoStr, sendLength, sipInvite))
568 goto cleanup;
569 }
570 if (sdes->getState() == ZrtpSdesStream::SDES_SRTP_ACTIVE) {
571 tiviState = CtZrtpSession::eSecureSdes;
572 if (zrtpUserCallback != NULL) {
573 zrtpUserCallback->onNewZrtpStatus(session, NULL, index); // Inform client about new state
574 }
575 useSdesForMedia = true;
576 if (zrtpEncapSignaled) {
577 useZrtpTunnel = true;
578 }
579 return true;
580 }
581
582 cleanup:
583 useSdesForMedia = false;
584 useZrtpTunnel = false;
585 delete sdes;
586 sdes = NULL;
587 return false;
588}
589
590bool CtZrtpStream::getSavedSdes(char *sendCryptoStr, size_t *sendLength) {
591
592 size_t len = strlen(sdesTempBuffer);
593
594 if (len >= *sendLength)
595 return false;
596
597 strcpy(sendCryptoStr, sdesTempBuffer);
598 *sendLength = len;
599
600 if (zrtpUserCallback != NULL)
601 zrtpUserCallback->onNewZrtpStatus(session, NULL, index);
602 return true;
603}
604
605bool CtZrtpStream::isSdesActive() {
606 return (sdes != NULL && sdes->getState() == ZrtpSdesStream::SDES_SRTP_ACTIVE);
607}
608
609int CtZrtpStream::getCryptoMixAttribute(char *algoNames, size_t length) {
610
611 if (sdes == NULL)
612 sdes = new ZrtpSdesStream();
613
614 return sdes->getCryptoMixAttribute(algoNames, length);
615}
616
617void CtZrtpStream::resetSdesContext(bool force) {
618 if (force || !isSdesActive()) {
619 useSdesForMedia = false;
620 useZrtpTunnel = false;
621 delete sdes;
622 sdes = NULL;
623 }
624}
625
626bool CtZrtpStream::setCryptoMixAttribute(const char *algoNames) {
627 if (isSecure() || isSdesActive()) // don't take action if we are already secure or SDES already in active state
628 return false;
629
630 if (sdes == NULL)
631 sdes = new ZrtpSdesStream();
632
633 return sdes->setCryptoMixAttribute(algoNames);
634}
635
636int32_t CtZrtpStream::getNumberSupportedVersions() {
637
638 return zrtpEngine->getNumberSupportedVersions();
639}
640
641const char* CtZrtpStream::getZrtpEncapAttribute() {
642 return zrtpEncap;
643}
644
645void CtZrtpStream::setZrtpEncapAttribute(const char *attribute) {
646 if (attribute != NULL && strncmp(attribute, zrtpEncap, 4) == 0) {
647 zrtpEncapSignaled = true;
648 if (useSdesForMedia) {
649 useZrtpTunnel = true;
650 }
651 }
652}
653
654void CtZrtpStream::setAuxSecret(const unsigned char *secret, int length) {
655 zrtpEngine->setAuxSecret((unsigned char*)secret, length);
656}
657
658/* *********************
659 * Here the callback methods required by the ZRTP implementation
660 *
661 * The ZRTP functions calls most of the callback functions with syncLock set. Exception
662 * is inform enrollement callback. When in doubt: check!
663 */
664int32_t CtZrtpStream::sendDataZRTP(const unsigned char *data, int32_t length) {
665
666 uint16_t totalLen = length + 12; /* Fixed number of bytes of ZRTP header */
667 uint32_t crc;
668
669 uint16_t* pus;
670 uint32_t* pui;
671
672 size_t newLength;
673
674 if ((totalLen) > maxZrtpSize)
675 return 0;
676
677 /* Get some handy pointers */
678 pus = (uint16_t*)zrtpBuffer;
679 pui = (uint32_t*)zrtpBuffer;
680
681 /* set up fixed ZRTP header */
682 *(zrtpBuffer + 1) = 0;
683 pus[1] = zrtpHtons(senderZrtpSeqNo++);
684 pui[1] = zrtpHtonl(ZRTP_MAGIC);
685 pui[2] = zrtpHtonl(ownSSRC); // ownSSRC is stored in host order
686
687 memcpy(zrtpBuffer+12, data, length); // Copy ZRTP message data behind the header data
688
689 if (useZrtpTunnel) {
690 *zrtpBuffer = 0x80; // temporarily make it to a real RTP packet
691 sdes->outgoingZrtpTunnel(zrtpBuffer, totalLen-CRC_SIZE, &newLength);
692 *zrtpBuffer = 0x10; // invalid RTP version - refer to ZRTP spec chap 5
693 totalLen = newLength;
694 }
695 else {
696 *zrtpBuffer = 0x10; // invalid RTP version - refer to ZRTP spec chap 5
697 crc = zrtpGenerateCksum(zrtpBuffer, totalLen-CRC_SIZE); // Setup and compute ZRTP CRC
698 crc = zrtpEndCksum(crc); // convert and store CRC in ZRTP packet.
699 *(uint32_t*)(zrtpBuffer+totalLen-CRC_SIZE) = zrtpHtonl(crc);
700 }
701
702 /* Send the ZRTP packet using callback */
703 if (zrtpSendCallback != NULL) {
704 zrtpSendCallback->sendRtp(session, zrtpBuffer, totalLen, index);
705 return 1;
706 }
707 return 0;
708}
709
710bool CtZrtpStream::srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part)
711{
712 CryptoContext* recvCryptoContext;
713 CryptoContext* senderCryptoContext;
714 CryptoContextCtrl* recvCryptoContextCtrl;
715 CryptoContextCtrl* senderCryptoContextCtrl;
716
717 int cipher;
718 int authn;
719 int authKeyLen;
720
721 if (secrets->authAlgorithm == Sha1) {
722 authn = SrtpAuthenticationSha1Hmac;
723 authKeyLen = 20;
724 }
725
726 if (secrets->authAlgorithm == Skein) {
727 authn = SrtpAuthenticationSkeinHmac;
728 authKeyLen = 32;
729 }
730
731 if (secrets->symEncAlgorithm == Aes)
732 cipher = SrtpEncryptionAESCM;
733
734 if (secrets->symEncAlgorithm == TwoFish)
735 cipher = SrtpEncryptionTWOCM;
736
737 role = secrets->role;
738
739 if (part == ForSender) {
740 // To encrypt packets: intiator uses initiator keys,
741 // responder uses responder keys
742 // Create a "half baked" crypto context first and store it. This is
743 // the main crypto context for the sending part of the connection.
744 if (secrets->role == Initiator) {
745 senderCryptoContext =
746 new CryptoContext(0, // SSRC (used for lookup)
747 0, // Roll-Over-Counter (ROC)
748 0L, // keyderivation << 48,
749 cipher, // encryption algo
750 authn, // authtentication algo
751 (unsigned char*)secrets->keyInitiator, // Master Key
752 secrets->initKeyLen / 8, // Master Key length
753 (unsigned char*)secrets->saltInitiator, // Master Salt
754 secrets->initSaltLen / 8, // Master Salt length
755 secrets->initKeyLen / 8, // encryption keyl
756 authKeyLen, // authentication key len
757 secrets->initSaltLen / 8, // session salt len
758 secrets->srtpAuthTagLen / 8); // authentication tag lenA
759 senderCryptoContextCtrl =
760 new CryptoContextCtrl(0, // SSRC (used for lookup)
761 cipher, // encryption algo
762 authn, // authtication algo
763 (unsigned char*)secrets->keyInitiator, // Master Key
764 secrets->initKeyLen / 8, // Master Key length
765 (unsigned char*)secrets->saltInitiator, // Master Salt
766 secrets->initSaltLen / 8, // Master Salt length
767 secrets->initKeyLen / 8, // encryption keyl
768 authKeyLen, // authentication key len
769 secrets->initSaltLen / 8, // session salt len
770 secrets->srtpAuthTagLen / 8); // authentication tag len
771 }
772 else {
773 senderCryptoContext =
774 new CryptoContext(0, // SSRC (used for lookup)
775 0, // Roll-Over-Counter (ROC)
776 0L, // keyderivation << 48,
777 cipher, // encryption algo
778 authn, // authtentication algo
779 (unsigned char*)secrets->keyResponder, // Master Key
780 secrets->respKeyLen / 8, // Master Key length
781 (unsigned char*)secrets->saltResponder, // Master Salt
782 secrets->respSaltLen / 8, // Master Salt length
783 secrets->respKeyLen / 8, // encryption keyl
784 authKeyLen, // authentication key len
785 secrets->respSaltLen / 8, // session salt len
786 secrets->srtpAuthTagLen / 8); // authentication tag len
787 senderCryptoContextCtrl =
788 new CryptoContextCtrl(0, // SSRC (used for lookup)
789 cipher, // encryption algo
790 authn, // authtication algo
791 (unsigned char*)secrets->keyResponder, // Master Key
792 secrets->respKeyLen / 8, // Master Key length
793 (unsigned char*)secrets->saltResponder, // Master Salt
794 secrets->respSaltLen / 8, // Master Salt length
795 secrets->respKeyLen / 8, // encryption keyl
796 authKeyLen, // authentication key len
797 secrets->respSaltLen / 8, // session salt len
798 secrets->srtpAuthTagLen / 8); // authentication tag len
799 }
800 if (senderCryptoContext == NULL) {
801 return false;
802 }
803 senderCryptoContext->deriveSrtpKeys(0L);
804 sendSrtp = senderCryptoContext;
805
806 senderCryptoContextCtrl->deriveSrtcpKeys();
807 sendSrtcp = senderCryptoContextCtrl;
808 }
809 if (part == ForReceiver) {
810 // To decrypt packets: intiator uses responder keys,
811 // responder initiator keys
812 // See comment above.
813 if (secrets->role == Initiator) {
814 recvCryptoContext =
815 new CryptoContext(0, // SSRC (used for lookup)
816 0, // Roll-Over-Counter (ROC)
817 0L, // keyderivation << 48,
818 cipher, // encryption algo
819 authn, // authtentication algo
820 (unsigned char*)secrets->keyResponder, // Master Key
821 secrets->respKeyLen / 8, // Master Key length
822 (unsigned char*)secrets->saltResponder, // Master Salt
823 secrets->respSaltLen / 8, // Master Salt length
824 secrets->respKeyLen / 8, // encryption keyl
825 authKeyLen, // authentication key len
826 secrets->respSaltLen / 8, // session salt len
827 secrets->srtpAuthTagLen / 8); // authentication tag len
828 recvCryptoContextCtrl =
829 new CryptoContextCtrl(0, // SSRC (used for lookup)
830 cipher, // encryption algo
831 authn, // authtication algo
832 (unsigned char*)secrets->keyResponder, // Master Key
833 secrets->respKeyLen / 8, // Master Key length
834 (unsigned char*)secrets->saltResponder, // Master Salt
835 secrets->respSaltLen / 8, // Master Salt length
836 secrets->respKeyLen / 8, // encryption keyl
837 authKeyLen, // authentication key len
838 secrets->respSaltLen / 8, // session salt len
839 secrets->srtpAuthTagLen / 8); // authentication tag len
840 }
841 else {
842 recvCryptoContext =
843 new CryptoContext(0, // SSRC (used for lookup)
844 0, // Roll-Over-Counter (ROC)
845 0L, // keyderivation << 48,
846 cipher, // encryption algo
847 authn, // authtentication algo
848 (unsigned char*)secrets->keyInitiator, // Master Key
849 secrets->initKeyLen / 8, // Master Key length
850 (unsigned char*)secrets->saltInitiator, // Master Salt
851 secrets->initSaltLen / 8, // Master Salt length
852 secrets->initKeyLen / 8, // encryption keyl
853 authKeyLen, // authentication key len
854 secrets->initSaltLen / 8, // session salt len
855 secrets->srtpAuthTagLen / 8); // authentication tag len
856 recvCryptoContextCtrl =
857 new CryptoContextCtrl(0, // SSRC (used for lookup)
858 cipher, // encryption algo
859 authn, // authtication algo
860 (unsigned char*)secrets->keyInitiator, // Master Key
861 secrets->initKeyLen / 8, // Master Key length
862 (unsigned char*)secrets->saltInitiator, // Master Salt
863 secrets->initSaltLen / 8, // Master Salt length
864 secrets->initKeyLen / 8, // encryption keyl
865 authKeyLen, // authentication key len
866 secrets->initSaltLen / 8, // session salt len
867 secrets->srtpAuthTagLen / 8); // authentication tag len
868 }
869 if (recvCryptoContext == NULL) {
870 return false;
871 }
872 recvCryptoContext->deriveSrtpKeys(0L);
873 recvSrtp = recvCryptoContext;
874
875 recvCryptoContextCtrl->deriveSrtcpKeys();
876 recvSrtcp = recvCryptoContextCtrl;
877
878 supressCounter = 0; // supress SRTP warnings for some packets after we switch to SRTP
879 }
880 if (peerHelloHashes.size() > 0 && recvSrtp != NULL && sendSrtp != NULL) {
881 useSdesForMedia = false;
882 }
883 return true;
884}
885
886void CtZrtpStream::srtpSecretsOn(std::string cipher, std::string sas, bool verified)
887{
888 // p->setStatus(ctx->peer_mitm_flag || iMitm?CTZRTP::eSecureMitm:CTZRTP::eSecure,&buf[0],iIsVideo);
889
890 prevTiviState = tiviState;
891
892 // TODO Discuss with Janis what else to do? Set other state, for example eSecureMitmVia or some string?
893 tiviState = CtZrtpSession::eSecure;
894 if (cipher.find ("SASviaMitM", cipher.size() - 10, 10) != std::string::npos) { // Found: SAS via PBX
895 tiviState = CtZrtpSession::eSecureMitmVia; //eSecureMitmVia
896 }
897 else if (cipher.find ("MitM", cipher.size() - 4, 4) != std::string::npos) {
898 tiviState = CtZrtpSession::eSecureMitm;
899 }
900 else if (cipher.find ("EndAtMitM", cipher.size() - 9, 9) != std::string::npos) {
901 tiviState = CtZrtpSession::eSecureMitm;
902 }
903 sasVerified = verified;
904 if (zrtpUserCallback != NULL) {
905 char *strng = NULL;
906 std::string sasTmp;
907
908 if (!sas.empty()) { // Multi-stream mode streams don't have SAS, no reporting
909 uint8_t peerZid[IDENTIFIER_LEN];
910 std::string name;
911
912 zrtpEngine->getPeerZid(peerZid);
913 getZidCacheInstance()->getPeerName(peerZid, &name);
914 zrtpUserCallback->onPeer(session, (char*)name.c_str(), (int)verified, index);
915
916 // If SAS does not contain a : then it's a short SAS
917 size_t found = sas.find_first_of(':');
918 if (found == std::string::npos) {
919 strng = (char*)sas.c_str();
920 }
921 else {
922 sasTmp = sas.substr(0, found);
923 sasTmp.append(" ").append(sas.substr(found+1));
924 strng = (char*)sasTmp.c_str();
925 }
926 }
927 zrtpUserCallback->onNewZrtpStatus(session, strng, index);
928 }
929}
930
931void CtZrtpStream::srtpSecretsOff(EnableSecurity part) {
932 if (part == ForSender) {
933 delete sendSrtp;
934 delete sendSrtcp;
935 sendSrtp = NULL;
936 sendSrtcp = NULL;
937 }
938 if (part == ForReceiver) {
939 delete recvSrtp;
940 delete recvSrtcp;
941 recvSrtp = NULL;
942 recvSrtcp = NULL;
943 }
944}
945
946int32_t CtZrtpStream::activateTimer(int32_t time) {
947 std::string s("ZRTP");
948 if (staticTimeoutProvider != NULL) {
949 staticTimeoutProvider->requestTimeout(time, this, s);
950 }
951 return 1;
952}
953
954int32_t CtZrtpStream::cancelTimer() {
955 std::string s("ZRTP");
956 if (staticTimeoutProvider != NULL) {
957 staticTimeoutProvider->cancelRequest(this, s);
958 }
959 return 1;
960}
961
962void CtZrtpStream::handleTimeout(const std::string &c) {
963 if (zrtpEngine != NULL) {
964 zrtpEngine->processTimeout();
965 }
966}
967
968void CtZrtpStream::handleGoClear() {
969 fprintf(stderr, "Need to process a GoClear message!\n");
970}
971
972void CtZrtpStream::sendInfo(MessageSeverity severity, int32_t subCode) {
973 std::string *msg;
974
975 if (severity == Info) {
976
977 std::string peerHash;
978 std::string hexString;
979 size_t hexStringStart;
980 switch (subCode) {
981 case InfoHelloReceived:
982 // The Tivi client stores the 64 char hex string only, thus
983 // split the string that we get from ZRTP engine that contains
984 // the version info as well (which is the right way to do because
985 // the engine knows which version of the ZRTP protocol it uses.)
986 if (peerHelloHashes.empty())
987 break;
988
989 peerHash = zrtpEngine->getPeerHelloHash();
990 hexStringStart = peerHash.find_last_of(' ');
991 hexString = peerHash.substr(hexStringStart+1);
992 helloReceived = true;
993
994 for (std::vector<std::string>::iterator it = peerHelloHashes.begin() ; it != peerHelloHashes.end(); ++it) {
995 int match;
996 if ((*it).size() > SHA256_DIGEST_LENGTH*2) // got the full string incl. version prefix, compare with full peer hash string
997 match = (*it).compare(peerHash);
998 else
999 match = (*it).compare(hexString);
1000 if (match == 0) {
1001 zrtpHashMatch = true;
1002 break;
1003 }
1004 }
1005 if (!zrtpHashMatch && zrtpUserCallback != NULL)
1006 zrtpUserCallback->onZrtpWarning(session, (char*)peerHelloMismatchMsg, index);
1007 break;
1008
1009 case InfoSecureStateOn:
1010 if (type == CtZrtpSession::Master) { // Master stream entered secure mode (security done)
1011 session->masterStreamSecure(this);
1012 }
1013 // Tivi client does not expect a status change information on this
1014 break;
1015
1016 // These two states correspond to going secure
1017 case InfoRespCommitReceived:
1018 case InfoInitDH1Received:
1019 prevTiviState = tiviState;
1020 tiviState = CtZrtpSession::eGoingSecure;
1021 if (zrtpUserCallback != NULL)
1022 zrtpUserCallback->onNewZrtpStatus(session, NULL, index);
1023 break;
1024
1025 // other information states are not handled by tivi client
1026 default:
1027 break;
1028 }
1029 return;
1030 }
1031 if (severity == Warning) {
1032 switch (subCode) {
1033 case WarningNoRSMatch:
1034 return;
1035 break; // supress this warning message
1036
1037 default:
1038 msg = warningMap[subCode];
1039 if (zrtpUserCallback != NULL)
1040 zrtpUserCallback->onZrtpWarning(session, (char*)msg->c_str(), index);
1041 return;
1042 break;
1043 }
1044 }
1045 // handle severe and ZRTP errors
1046 zrtpNegotiationFailed(severity, subCode);
1047}
1048
1049void CtZrtpStream::zrtpNegotiationFailed(MessageSeverity severity, int32_t subCode) {
1050
1051 std::string cs;
1052 std::string *strng;
1053 const char *inOut;
1054 if (severity == ZrtpError) {
1055 if (subCode < 0) { // received an error packet from peer
1056 subCode *= -1;
1057 inOut = "(<--)";
1058 }
1059 else {
1060 inOut = "(-->)";
1061 }
1062 strng = zrtpMap[subCode];
1063 if (strng != NULL)
1064 cs.assign(*strng);
1065 else
1066 cs.assign("s4_c255: ZRTP protocol: Unkown ZRTP error packet.");
1067 cs.append(inOut);
1068 }
1069 else {
1070 cs = *severeMap[subCode];
1071 }
1072
1073 prevTiviState = tiviState;
1074 tiviState = CtZrtpSession::eError;
1075 if (zrtpUserCallback != NULL) {
1076 zrtpUserCallback->onNewZrtpStatus(session, (char*)cs.c_str(), index);
1077 }
1078}
1079
1080void CtZrtpStream::zrtpNotSuppOther() {
1081 prevTiviState = tiviState;
1082 // if other party does not support ZRTP but we have SDES active set SDES state,
1083 // otherwise inform client about failed ZRTP negotiation.
1084 tiviState = isSdesActive() ? CtZrtpSession::eSecureSdes : CtZrtpSession::eNoPeer;
1085 if (zrtpUserCallback != NULL) {
1086 zrtpUserCallback->onNewZrtpStatus(session, NULL, index);
1087 }
1088}
1089
1090void CtZrtpStream::synchEnter() {
1091 synchLock->Lock();
1092}
1093
1094void CtZrtpStream::synchLeave() {
1095 synchLock->Unlock();
1096}
1097
1098void CtZrtpStream::zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info) {
1099 // TODO: Discuss with Janis
1100 if (zrtpUserCallback != NULL) {
1101 zrtpUserCallback->onNeedEnroll(session, index, (int32_t)info);
1102 }
1103}
1104
1105void CtZrtpStream::zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info) {
1106// Tivi does not use this information event
1107// if (zrtpUserCallback != NULL) {
1108// zrtpUserCallback->zrtpInformEnrollment(info);
1109// }
1110}
1111
1112void CtZrtpStream::signSAS(uint8_t* sasHash) {
1113// if (zrtpUserCallback != NULL) {
1114// zrtpUserCallback->signSAS(sasHash);
1115// }
1116}
1117
1118bool CtZrtpStream::checkSASSignature(uint8_t* sasHash) {
1119// if (zrtpUserCallback != NULL) {
1120// return zrtpUserCallback->checkSASSignature(sasHash);
1121// }
1122 return false;
1123}
1124
1125void CtZrtpStream::initStrings() {
1126 if (initialized) {
1127 return;
1128 }
1129 initialized = true;
1130
1131 infoMap.insert(std::pair<int32_t, std::string*>(InfoHelloReceived, new std::string("s1_c001: Hello received, preparing a Commit")));
1132 infoMap.insert(std::pair<int32_t, std::string*>(InfoCommitDHGenerated, new std::string("s1_c002: Commit: Generated a public DH key")));
1133 infoMap.insert(std::pair<int32_t, std::string*>(InfoRespCommitReceived, new std::string("s1_c003: Responder: Commit received, preparing DHPart1")));
1134 infoMap.insert(std::pair<int32_t, std::string*>(InfoDH1DHGenerated, new std::string("s1_c004: DH1Part: Generated a public DH key")));
1135 infoMap.insert(std::pair<int32_t, std::string*>(InfoInitDH1Received, new std::string("s1_c005: Initiator: DHPart1 received, preparing DHPart2")));
1136 infoMap.insert(std::pair<int32_t, std::string*>(InfoRespDH2Received, new std::string("s1_c006: Responder: DHPart2 received, preparing Confirm1")));
1137 infoMap.insert(std::pair<int32_t, std::string*>(InfoInitConf1Received, new std::string("s1_c007: Initiator: Confirm1 received, preparing Confirm2")));
1138 infoMap.insert(std::pair<int32_t, std::string*>(InfoRespConf2Received, new std::string("s1_c008: Responder: Confirm2 received, preparing Conf2Ack")));
1139 infoMap.insert(std::pair<int32_t, std::string*>(InfoRSMatchFound, new std::string("s1_c009: At least one retained secrets matches - security OK")));
1140 infoMap.insert(std::pair<int32_t, std::string*>(InfoSecureStateOn, new std::string("s1_c010: Entered secure state")));
1141 infoMap.insert(std::pair<int32_t, std::string*>(InfoSecureStateOff, new std::string("s1_c011: No more security for this session")));
1142
1143 warningMap.insert(std::pair<int32_t, std::string*>(WarningDHAESmismatch, new std::string("s2_c001: Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096")));
1144 warningMap.insert(std::pair<int32_t, std::string*>(WarningGoClearReceived, new std::string("s2_c002: Received a GoClear message")));
1145 warningMap.insert(std::pair<int32_t, std::string*>(WarningDHShort, new std::string("s2_c003: Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096")));
1146 warningMap.insert(std::pair<int32_t, std::string*>(WarningNoRSMatch, new std::string("s2_c004: No retained secret matches - verify SAS")));
1147 warningMap.insert(std::pair<int32_t, std::string*>(WarningCRCmismatch, new std::string("s2_c005: Internal ZRTP packet CRC mismatch - packet dropped")));
1148 warningMap.insert(std::pair<int32_t, std::string*>(WarningSRTPauthError, new std::string("s2_c006: Dropping packet because SRTP authentication failed!")));
1149 warningMap.insert(std::pair<int32_t, std::string*>(WarningSRTPreplayError, new std::string("s2_c007: Dropping packet because SRTP replay check failed!")));
1150 warningMap.insert(std::pair<int32_t, std::string*>(WarningNoExpectedRSMatch,
1151 new std::string("s2_c008: You MUST check SAS with your partner. If it doesn't match, it indicates the presence of a wiretapper.")));
1152 warningMap.insert(std::pair<int32_t, std::string*>(WarningNoExpectedAuxMatch, new std::string("s2_c009: Expected auxilliary secret match failed")));
1153
1154 severeMap.insert(std::pair<int32_t, std::string*>(SevereHelloHMACFailed, new std::string("s3_c001: Hash HMAC check of Hello failed!")));
1155 severeMap.insert(std::pair<int32_t, std::string*>(SevereCommitHMACFailed, new std::string("s3_c002: Hash HMAC check of Commit failed!")));
1156 severeMap.insert(std::pair<int32_t, std::string*>(SevereDH1HMACFailed, new std::string("s3_c003: Hash HMAC check of DHPart1 failed!")));
1157 severeMap.insert(std::pair<int32_t, std::string*>(SevereDH2HMACFailed, new std::string("s3_c004: Hash HMAC check of DHPart2 failed!")));
1158 severeMap.insert(std::pair<int32_t, std::string*>(SevereCannotSend, new std::string("s3_c005: Cannot send data - connection or peer down?")));
1159 severeMap.insert(std::pair<int32_t, std::string*>(SevereProtocolError, new std::string("s3_c006: Internal protocol error occured!")));
1160 severeMap.insert(std::pair<int32_t, std::string*>(SevereNoTimer, new std::string("s3_c007: Cannot start a timer - internal resources exhausted?")));
1161 severeMap.insert(std::pair<int32_t, std::string*>(SevereTooMuchRetries, new std::string("s3_c008: Too many retries during ZRTP negotiation - connection or peer down?")));
1162
1163 zrtpMap.insert(std::pair<int32_t, std::string*>(MalformedPacket, new std::string("s4_c016: Malformed packet (CRC OK, but wrong structure)")));
1164 zrtpMap.insert(std::pair<int32_t, std::string*>(CriticalSWError, new std::string("s4_c020: Critical software error")));
1165 zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppZRTPVersion, new std::string("s4_c048: Unsupported ZRTP version")));
1166 zrtpMap.insert(std::pair<int32_t, std::string*>(HelloCompMismatch, new std::string("s4_c064: Hello components mismatch")));
1167 zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppHashType, new std::string("s4_c081: Hash type not supported")));
1168 zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppCiphertype, new std::string("s4_c082: Cipher type not supported")));
1169 zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppPKExchange, new std::string("s4_c083: Public key exchange not supported")));
1170 zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppSRTPAuthTag, new std::string("s4_c084: SRTP auth. tag not supported")));
1171 zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppSASScheme, new std::string("s4_c085: SAS scheme not supported")));
1172 zrtpMap.insert(std::pair<int32_t, std::string*>(NoSharedSecret, new std::string("s4_c086: No shared secret available, DH mode required")));
1173 zrtpMap.insert(std::pair<int32_t, std::string*>(DHErrorWrongPV, new std::string("s4_c097: DH Error: bad pvi or pvr ( == 1, 0, or p-1)")));
1174 zrtpMap.insert(std::pair<int32_t, std::string*>(DHErrorWrongHVI, new std::string("s4_c098: DH Error: hvi != hashed data")));
1175 zrtpMap.insert(std::pair<int32_t, std::string*>(SASuntrustedMiTM, new std::string("s4_c099: Received relayed SAS from untrusted MiTM")));
1176 zrtpMap.insert(std::pair<int32_t, std::string*>(ConfirmHMACWrong, new std::string("s4_c112: Auth. Error: Bad Confirm pkt HMAC")));
1177 zrtpMap.insert(std::pair<int32_t, std::string*>(NonceReused, new std::string("s4_c128: Nonce reuse")));
1178 zrtpMap.insert(std::pair<int32_t, std::string*>(EqualZIDHello, new std::string("s4_c144: Duplicate ZIDs in Hello Packets")));
1179 zrtpMap.insert(std::pair<int32_t, std::string*>(GoCleatNotAllowed, new std::string("s4_c160: GoClear packet received, but not allowed")));
1180
1181 enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentRequest, new std::string("s5_c000: Trusted MitM enrollment requested")));
1182 enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentCanceled, new std::string("s5_c001: Trusted MitM enrollment canceled by user")));
1183 enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentFailed, new std::string("s5_c003: Trusted MitM enrollment failed")));
1184 enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentOk, new std::string("s5_c004: Trusted MitM enrollment OK")));
1185}