* #35924 (zrtp): switch to libzrtpcpp
diff --git a/jni/libzrtp/sources/clients/tivi/CtZrtpStream.cpp b/jni/libzrtp/sources/clients/tivi/CtZrtpStream.cpp
new file mode 100644
index 0000000..db3cd8e
--- /dev/null
+++ b/jni/libzrtp/sources/clients/tivi/CtZrtpStream.cpp
@@ -0,0 +1,1185 @@
+/*
+ * Tivi client glue code for ZRTP.
+ * Copyright (c) 2012 Slient Circle LLC.  All rights reserved.
+ *
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <stdint.h>
+
+#include <common/osSpecifics.h>
+
+#include <libzrtpcpp/ZRtp.h>
+#include <libzrtpcpp/ZrtpStateClass.h>
+#include <libzrtpcpp/ZrtpCrc32.h>
+#include <srtp/CryptoContext.h>
+#include <srtp/CryptoContextCtrl.h>
+#include <srtp/SrtpHandler.h>
+
+#include <CtZrtpStream.h>
+#include <CtZrtpCallback.h>
+#include <TiviTimeoutProvider.h>
+#include <cryptcommon/aes.h>
+#include <cryptcommon/ZrtpRandom.h>
+
+// #define DEBUG_CTSTREAM
+#ifdef DEBUG_CTSTREAM
+static char debBuf[500];
+#define DEBUG(deb)   deb
+#else
+#define DEBUG(deb)
+#endif
+
+static TimeoutProvider<std::string, CtZrtpStream*>* staticTimeoutProvider = NULL;
+
+static std::map<int32_t, std::string*> infoMap;
+static std::map<int32_t, std::string*> warningMap;
+static std::map<int32_t, std::string*> severeMap;
+static std::map<int32_t, std::string*> zrtpMap;
+static std::map<int32_t, std::string*> enrollMap;
+static int initialized = 0;
+
+static const char* peerHelloMismatchMsg = "s2_c050: Received Hello hash does not match computed Hello hash"; 
+static const char* srtpDecodeFailedMsg  = "s2_c051: Parsing of received SRTP packet failed"; 
+static const char* zrtpEncap = "zrtp";
+
+using namespace GnuZrtpCodes;
+
+/**
+ * The following code is for internal logging only
+ *
+ */
+static void (*_zrtp_log_cb)(void *ret, const char *tag, const char *buf) = NULL;
+static void *pLogRet=NULL;
+
+// this function must be public. Tivi C++ code set its internal log function
+void set_zrtp_log_cb(void *pRet, void (*cb)(void *ret, const char *tag, const char *buf)){
+    _zrtp_log_cb=cb;
+    pLogRet=pRet;
+}
+
+// This function is static (could be global) to reduce visibility
+static void zrtp_log( const char *tag, const char *buf){
+    if(_zrtp_log_cb){
+        _zrtp_log_cb(pLogRet, tag, buf);
+    }
+}
+
+CtZrtpStream::CtZrtpStream():
+    index(CtZrtpSession::AudioStream), type(CtZrtpSession::NoStream), zrtpEngine(NULL),
+    ownSSRC(0), zrtpProtect(0), sdesProtect(0), zrtpUnprotect(0), sdesUnprotect(0), unprotectFailed(0),
+    enableZrtp(0), started(false), isStopped(false), session(NULL), tiviState(CtZrtpSession::eLookingPeer),
+    prevTiviState(CtZrtpSession::eLookingPeer), recvSrtp(NULL), recvSrtcp(NULL), sendSrtp(NULL), sendSrtcp(NULL),
+    zrtpUserCallback(NULL), zrtpSendCallback(NULL), senderZrtpSeqNo(0), peerSSRC(0), zrtpHashMatch(false),
+    sasVerified(false), helloReceived(false), useSdesForMedia(false), useZrtpTunnel(false), zrtpEncapSignaled(false), 
+    sdes(NULL), supressCounter(0), srtpAuthErrorBurst(0), srtpReplayErrorBurst(0), srtpDecodeErrorBurst(0), 
+    zrtpCrcErrors(0), role(NoRole)
+{
+    synchLock = new CMutexClass();
+
+    // TODO: do we need mutex or can tivi do it
+    if (staticTimeoutProvider == NULL) {
+        staticTimeoutProvider = new TimeoutProvider<std::string, CtZrtpStream*>();
+        staticTimeoutProvider->Event(&staticTimeoutProvider);  // Event argument is dummy, not used
+    }
+    initStrings();
+    ZrtpRandom::getRandomData((uint8_t*)&senderZrtpSeqNo, 2);
+    senderZrtpSeqNo &= 0x7fff;
+}
+
+void CtZrtpStream::setUserCallback(CtZrtpCb* ucb) {
+    zrtpUserCallback = ucb;
+}
+
+void CtZrtpStream::setSendCallback(CtZrtpSendCb* scb) {
+    zrtpSendCallback = scb;
+}
+
+CtZrtpStream::~CtZrtpStream() {
+    stopStream();
+    delete synchLock;
+    synchLock = NULL;
+}
+//
+void CtZrtpStream::stopStream() {
+
+    // If we got only a small amout of valid SRTP packets after ZRTP negotiation then
+    // assume that our peer couldn't store the RS data, thus make sure we have a second
+    // retained shared secret available. Refer to RFC 6189bis, chapter 4.6.1
+    // 50 packets are about 1 second of audio data
+    if (zrtpEngine != NULL && zrtpUnprotect < 10 && !zrtpEngine->isMultiStream()) {
+        zrtpEngine->setRs2Valid();
+    }
+
+    index = CtZrtpSession::AudioStream;
+    type = CtZrtpSession::NoStream;
+    tiviState = CtZrtpSession::eLookingPeer;
+    prevTiviState = CtZrtpSession::eLookingPeer;
+    ownSSRC = 0;
+    enableZrtp = 0;
+    started = false;
+    isStopped = false;
+    peerSSRC = 0;
+
+    zrtpUnprotect = 0;
+    sdesUnprotect = 0;
+    zrtpProtect = 0;
+    sdesProtect = 0;
+    unprotectFailed = 0;
+
+    ZrtpRandom::getRandomData((uint8_t*)&senderZrtpSeqNo, 2);
+    senderZrtpSeqNo &= 0x7fff;
+    zrtpHashMatch= false;
+    sasVerified = false;
+    useSdesForMedia = false;
+    useZrtpTunnel = false;
+    zrtpEncapSignaled = false;
+    supressCounter = 0;
+    srtpAuthErrorBurst = 0;
+    srtpReplayErrorBurst = 0;
+    srtpDecodeErrorBurst = 0;
+    zrtpCrcErrors = 0;
+    helloReceived = false;
+
+    peerHelloHashes.clear();
+
+    delete zrtpEngine;
+    zrtpEngine = NULL;
+
+    delete recvSrtp;
+    recvSrtp = NULL;
+
+    delete recvSrtcp;
+    recvSrtcp = NULL;
+
+    delete sendSrtp;
+    sendSrtp = NULL;
+
+    delete sendSrtcp;
+    sendSrtcp = NULL;
+
+    delete sdes;
+    sdes = NULL;
+
+    // Don't delete the next classes, we don't own them.
+    zrtpUserCallback = NULL;
+    zrtpSendCallback = NULL;
+    session = NULL;
+}
+
+bool CtZrtpStream::processOutgoingRtp(uint8_t *buffer, size_t length, size_t *newLength) {
+    bool rc = true;
+    if (sendSrtp == NULL) {                 // ZRTP/SRTP inactive
+        *newLength = length;
+        // Check if ZRTP engine is started and check states to determine if we should send the RTP packet.
+        // Do not send in states: CommitSent, WaitDHPart2, WaitConfirm1, WaitConfirm2, WaitConfAck
+        if (started && (zrtpEngine->inState(CommitSent) || zrtpEngine->inState(WaitDHPart2) || zrtpEngine->inState(WaitConfirm1) ||
+            zrtpEngine->inState(WaitConfirm2) || zrtpEngine->inState(WaitConfAck))) {
+            ZrtpRandom::addEntropy(buffer, length);
+            return false;
+        }
+        if (useSdesForMedia && sdes != NULL) {   // SDES stream available, let SDES protect if necessary
+            rc = sdes->outgoingRtp(buffer, length, newLength);
+            sdesProtect++;
+        }
+        return rc;
+    }
+    // At this point ZRTP/SRTP is active
+    if (useSdesForMedia && sdes != NULL) {       // We still have a SDES - other client did not send zrtp-hash thus we protect twice
+        rc = sdes->outgoingRtp(buffer, length, newLength);
+        if (!rc) {
+            return rc;
+        }
+        sdesProtect++;
+    }
+    rc = SrtpHandler::protect(sendSrtp, buffer, length, newLength);
+    if (rc) {
+        zrtpProtect++;
+    }
+    return rc;
+}
+
+int32_t CtZrtpStream::processIncomingRtp(uint8_t *buffer, const size_t length, size_t *newLength) {
+    int32_t rc = 0;
+    // check if this could be a real RTP/SRTP packet.
+    if ((*buffer & 0xc0) == 0x80) {             // A real RTP, check if we are in secure mode
+        if (supressCounter < supressWarn)       // Don't report SRTP problems while in startup mode
+            supressCounter++;
+
+        if (recvSrtp == NULL) {                 // no ZRTP/SRTP available
+            if (!useSdesForMedia || sdes == NULL) {  // no SDES stream available, just set length and return
+                *newLength = length;
+                return 1;
+            }
+            rc = sdes->incomingRtp(buffer, length, newLength);
+            if (rc == 1) {                      // SDES unprotect OK, do some statistics and return success
+                if (*sdesTempBuffer != 0)       // clear SDES crypto string if not already done
+                    memset(sdesTempBuffer, 0, maxSdesString);
+
+                srtpAuthErrorBurst = 0;
+                srtpReplayErrorBurst = 0;
+                srtpDecodeErrorBurst = 0;
+                sdesUnprotect++;
+                return 1;
+            }
+        }
+        else {
+            // At this point we have an active ZRTP/SRTP context, unprotect with ZRTP/SRTP first
+            rc = SrtpHandler::unprotect(recvSrtp, buffer, length, newLength);
+            if (rc == 1) {
+                zrtpUnprotect++;
+                // Got a good SRTP, check state and if in WaitConfAck (an Initiator state)
+                // then simulate a conf2Ack, refer to RFC 6189, chapter 4.6, last paragraph
+                if (zrtpEngine->inState(WaitConfAck)) {
+                    zrtpEngine->conf2AckSecure();
+                }
+                if (useSdesForMedia && sdes != NULL) {    // We still have a SDES - other client did not send matching zrtp-hash
+                    rc = sdes->incomingRtp(buffer, *newLength, newLength);
+                }
+                if (rc == 1) {                       // if rc is still OK: either no SDES or layered SDES unprotect OK
+                    srtpAuthErrorBurst = 0;
+                    srtpReplayErrorBurst = 0;
+                    srtpDecodeErrorBurst = 0;
+                    return 1;
+                }
+            }
+        }
+        // We come to this point only if we have some problems during SRTP unprotect
+        if (rc == 0) 
+            srtpDecodeErrorBurst++;
+        else if (rc == -1)
+            srtpAuthErrorBurst++;
+        else if (rc == -2)
+            srtpReplayErrorBurst++;
+
+        unprotectFailed++;
+        if (supressCounter >= supressWarn) {
+            if (rc == 0 && srtpDecodeErrorBurst > srtpErrorBurstThreshold && zrtpUserCallback != NULL) {
+                zrtpUserCallback->onZrtpWarning(session, (char*)srtpDecodeFailedMsg, index);
+            }
+            if (rc == -1 && srtpAuthErrorBurst >= srtpErrorBurstThreshold) {
+                sendInfo(Warning, WarningSRTPauthError);
+            }
+            if (rc == -2 && srtpReplayErrorBurst >= srtpErrorBurstThreshold){
+                sendInfo(Warning, WarningSRTPreplayError);
+            }
+        }
+        return rc;
+    }
+
+    // At this point we assume the packet is not an RTP packet. Check if it is a ZRTP packet.
+    // Process it if ZRTP processing is started. In any case, let the application drop
+    // the packet.
+    if (started) {
+        // Fixed header length + smallest ZRTP packet (includes CRC)
+        if (length < (12 + sizeof(HelloAckPacket_t))) // data too small, dismiss
+            return 0;
+
+        size_t useLength = length;
+ 
+        uint32_t magic = *(uint32_t*)(buffer + 4);
+        magic = zrtpNtohl(magic);
+
+        // Check if it is really a ZRTP packet, return, no further processing
+        if (magic != ZRTP_MAGIC) {
+            return 0;
+        }
+        if (useZrtpTunnel) {
+            size_t newLength;
+            *buffer = 0x80;                                    // make it look like a real RTP packet
+            rc = sdes->incomingZrtpTunnel(buffer, length, &newLength);
+            if (rc < 0) {
+                if (rc == -1) {
+                    zrtp_log("CtZrtpStream", "Receiving tunneled ZRTP - SRTP failure -1");
+                    sendInfo(Warning, WarningSRTPauthError);
+                }
+                else {
+                    zrtp_log("CtZrtpStream", "Receiving tunneled ZRTP - SRTP failure -2");
+                    sendInfo(Warning, WarningSRTPreplayError);
+                }
+                return 0;
+            }
+            if (*sdesTempBuffer != 0)                          // clear SDES crypto string if not already done
+                memset(sdesTempBuffer, 0, maxSdesString);
+            useLength = newLength + CRC_SIZE;                  // length check assumes a ZRTP CRC
+        }
+        else {
+            DEBUG(char tmpBuffer[500];)
+            useZrtpTunnel = false;
+            // Get CRC value into crc (see above how to compute the offset)
+            uint16_t temp = length - CRC_SIZE;
+            uint32_t crc = *(uint32_t*)(buffer + temp);
+            crc = zrtpNtohl(crc);
+            if (!zrtpCheckCksum(buffer, temp, crc)) {
+                zrtpCrcErrors++;
+                if (zrtpCrcErrors > 15) {
+                    DEBUG(snprintf(debBuf, 499, "len: %d, sdes: %p, sdesMedia: %d, zrtpEncap: %d", temp, (void*)sdes, useSdesForMedia, zrtpEncapSignaled); zrtp_log("CtZrtpStream", debBuf);)
+
+                    sendInfo(Warning, WarningCRCmismatch);
+                    zrtpCrcErrors = 0;
+                }
+                return 0;
+            }
+        }
+        // this now points to the plain ZRTP message.
+        unsigned char* zrtpMsg = (buffer + 12);
+
+        // store peer's SSRC in host order, used when creating the CryptoContext
+        if (peerSSRC == 0) {
+            peerSSRC = *(uint32_t*)(buffer + 8);
+            peerSSRC = zrtpNtohl(peerSSRC);
+        }
+        zrtpEngine->processZrtpMessage(zrtpMsg, peerSSRC, useLength);
+    }
+    return 0;
+}
+
+int CtZrtpStream::getSignalingHelloHash(char *hHash, int32_t index) {
+
+    if (hHash == NULL)
+        return 0;
+
+    std::string hash;
+    hash = zrtpEngine->getHelloHash(index);
+    strcpy(hHash, hash.c_str());
+    return hash.size();
+}
+
+void CtZrtpStream::setSignalingHelloHash(const char *hHash) {
+    synchEnter();
+
+    std::string hashStr;
+    hashStr.assign(hHash);
+
+    bool found = false;
+    for (std::vector<std::string>::iterator it = peerHelloHashes.begin() ; it != peerHelloHashes.end(); ++it) {
+        if ((*it).compare(hashStr) == 0) {
+            found = true;
+            break;
+        }
+    }
+    if (!found)
+        peerHelloHashes.push_back(hashStr);
+
+    std::string ph = zrtpEngine->getPeerHelloHash();
+    if (ph.empty()) {
+        synchLeave();
+        return;
+    }
+    size_t hexStringStart = ph.find_last_of(' ');
+    std::string hexString = ph.substr(hexStringStart+1);
+
+    for (std::vector<std::string>::iterator it = peerHelloHashes.begin() ; it != peerHelloHashes.end(); ++it) {
+        int match;
+        if ((*it).size() > SHA256_DIGEST_LENGTH*2)      // got the full string incl. version prefix, compare with full peer hash string
+            match = (*it).compare(ph);
+        else
+            match = (*it).compare(hexString);
+        if (match == 0) {
+            zrtpHashMatch = true;
+            // We have a matching zrtp-hash. If ZRTP/SRTP is active we may need to release
+            // an existig SDES stream.
+            if (sdes != NULL && sendSrtp != NULL && recvSrtp != NULL) {
+                useSdesForMedia = false;
+            }
+            break;
+        }
+    }
+    if (!zrtpHashMatch && zrtpUserCallback != NULL)
+        zrtpUserCallback->onZrtpWarning(session, (char*)peerHelloMismatchMsg, index);
+    synchLeave();
+}
+
+int CtZrtpStream::isSecure() {
+    return tiviState == CtZrtpSession::eSecure || tiviState == CtZrtpSession::eSecureMitm ||
+           tiviState == CtZrtpSession::eSecureMitmVia || tiviState == CtZrtpSession::eSecureSdes;
+}
+
+
+#define T_ZRTP_LB(_K,_V)                                \
+        if(iLen+1 == sizeof(_K) && strncmp(key, _K, iLen) == 0){  \
+            return snprintf(p, maxLen, "%s", _V);}
+
+#define T_ZRTP_F(_K,_FV)                                                \
+        if(iLen+1 == sizeof(_K) && strncmp(key,_K, iLen) == 0){              \
+            return snprintf(p, maxLen, "%d", (!!(info->secretsCached & _FV)) << (!!(info->secretsMatchedDH & _FV)));}
+
+#define T_ZRTP_I(_K,_I)                                                \
+        if(iLen+1 == sizeof(_K) && strncmp(key,_K, iLen) == 0){              \
+            return snprintf(p, maxLen, "%d", _I);}
+
+int CtZrtpStream::getInfo(const char *key, char *p, int maxLen) {
+
+//     if ((sdes == NULL /*&& !started*/) || isStopped || !isSecure())
+//         return 0;
+
+    memset(p, 0, maxLen);
+    const ZRtp::zrtpInfo *info = NULL;
+    ZRtp::zrtpInfo tmpInfo;
+
+    int iLen = strlen(key);
+
+    // set the security state as a combination of tivi state and stateflags
+    int secState = tiviState & 0xff;
+    if (useSdesForMedia)
+        secState |= 0x100;
+
+    T_ZRTP_I("sec_state", secState);
+    T_ZRTP_LB("buildInfo",  zrtpBuildInfo);
+
+    // Compute Hello-hash info string
+    const char *strng = NULL;
+    if (peerHelloHashes.empty()) {
+        strng = "None";
+    }
+    else if (zrtpHashMatch) {
+        strng = "Good";
+    }
+    else {
+        strng = !sdes || helloReceived ? "Bad" : "No hello";
+    }
+    T_ZRTP_LB("sdp_hash", strng);
+
+    std::string client = zrtpEngine->getPeerProtcolVersion();
+    if (role != NoRole) {
+        if (useZrtpTunnel)
+            client.append(role == Initiator ? "(IT)" : "(RT)");
+        else
+            client.append(role == Initiator ? "(I)" : "(R)");
+    }
+    T_ZRTP_LB("lbClient",  zrtpEngine->getPeerClientId().c_str());
+    T_ZRTP_LB("lbVersion", client.c_str());
+
+    if (recvSrtp != NULL || sendSrtp != NULL) {
+        info = zrtpEngine->getDetailInfo();
+
+        if (iLen == 1 && key[0] == 'v') {
+            return snprintf(p, maxLen, "%d", sasVerified);
+        }
+        if(strncmp("sc_secure", key, iLen) == 0) {
+            int v = (zrtpHashMatch && sasVerified && !peerHelloHashes.empty() && tiviState == CtZrtpSession::eSecure);
+
+            if (v && (info->secretsCached & ZRtp::Rs1) == 0  && !sasVerified)
+                v = 0;
+            if (v && (info->secretsMatched & ZRtp::Rs1) == 0 && !sasVerified)
+                v = 0;
+            return snprintf(p, maxLen, "%d", v);
+        }
+    }
+    else if (useSdesForMedia && sdes != NULL) {
+        T_ZRTP_LB("lbClient",      (const char*)"SDES");
+        T_ZRTP_LB("lbVersion",     (const char*)"");
+
+        tmpInfo.secretsMatched = 0;
+        tmpInfo.secretsCached = 0;
+        tmpInfo.hash = (const char*)"";
+        if (sdes->getHmacTypeMix() == ZrtpSdesStream::MIX_NONE) {
+            tmpInfo.pubKey = (const char*)"SIP SDES";
+        }
+        else {
+            if (sdes->getCryptoMixAttribute(mixAlgoName, sizeof(mixAlgoName)) > 0)
+                tmpInfo.hash = mixAlgoName;
+            tmpInfo.pubKey = (const char*)"SIP SDES-MIX";
+        }
+        tmpInfo.cipher = sdes->getCipher();
+        tmpInfo.authLength = sdes->getAuthAlgo();
+        info = &tmpInfo;
+    }
+    else
+        return 0;
+
+    T_ZRTP_F("rs1",ZRtp::Rs1);
+    T_ZRTP_F("rs2",ZRtp::Rs2);
+    T_ZRTP_F("aux",ZRtp::Aux);
+    T_ZRTP_F("pbx",ZRtp::Pbx);
+
+    T_ZRTP_LB("lbChiper",      info->cipher);
+    T_ZRTP_LB("lbAuthTag",     info->authLength);
+    T_ZRTP_LB("lbHash",        info->hash);
+    T_ZRTP_LB("lbKeyExchange", info->pubKey);
+
+    return 0;
+}
+
+int CtZrtpStream::enrollAccepted(char *p) {
+    zrtpEngine->acceptEnrollment(true);
+
+    uint8_t peerZid[IDENTIFIER_LEN];
+    std::string name;
+
+    zrtpEngine->getPeerZid(peerZid);
+    int32_t nmLen = getZidCacheInstance()->getPeerName(peerZid, &name);
+
+    if (nmLen == 0)
+        getZidCacheInstance()->putPeerName(peerZid, std::string(p));
+    return CtZrtpSession::ok;
+}
+
+int CtZrtpStream::enrollDenied() {
+    zrtpEngine->acceptEnrollment(false);
+
+    uint8_t peerZid[IDENTIFIER_LEN];
+    std::string name;
+
+    zrtpEngine->getPeerZid(peerZid);
+    int32_t nmLen = getZidCacheInstance()->getPeerName(peerZid, &name);
+
+    if (nmLen == 0)
+        getZidCacheInstance()->putPeerName(peerZid, std::string(""));
+    return CtZrtpSession::ok;
+}
+
+
+bool CtZrtpStream::createSdes(char *cryptoString, size_t *maxLen, const ZrtpSdesStream::sdesSuites sdesSuite) {
+    if (isSecure() || isSdesActive())   // don't take action if we are already secure or SDES already in active state
+        return false;
+
+    if (sdes == NULL)
+        sdes = new ZrtpSdesStream(sdesSuite);
+
+    if (sdes == NULL || !sdes->createSdes(cryptoString, maxLen, true)) {
+        delete sdes;
+        sdes = NULL;
+        return false;
+    }
+    return true;
+}
+
+bool CtZrtpStream::parseSdes(char *recvCryptoStr, size_t recvLength, char *sendCryptoStr, size_t *sendLength, bool sipInvite) {
+    if (isSecure() || isSdesActive())   // don't take action if we are already secure or SDES already in active state
+        return false;
+
+    // The ZrtpSdesStream determines its suite by parsing the crypto string.
+    if (sdes == NULL)
+        sdes = new ZrtpSdesStream();
+
+    if (sdes == NULL || !sdes->parseSdes(recvCryptoStr, recvLength, sipInvite))
+        goto cleanup;
+
+    if (!sipInvite) {
+        size_t len;
+        if (sendCryptoStr == NULL) {
+            sendCryptoStr = sdesTempBuffer;
+            len = maxSdesString;
+            sendLength = &len;
+        }
+        if (!sdes->createSdes(sendCryptoStr, sendLength, sipInvite))
+            goto cleanup;
+    }
+    if (sdes->getState() == ZrtpSdesStream::SDES_SRTP_ACTIVE) {
+        tiviState = CtZrtpSession::eSecureSdes;
+        if (zrtpUserCallback != NULL) {
+            zrtpUserCallback->onNewZrtpStatus(session, NULL, index);    // Inform client about new state
+        }
+        useSdesForMedia = true;
+        if (zrtpEncapSignaled) {
+            useZrtpTunnel = true;
+        }
+        return true;
+    }
+
+ cleanup:
+    useSdesForMedia = false;
+    useZrtpTunnel = false;
+    delete sdes;
+    sdes = NULL;
+    return false;
+}
+
+bool CtZrtpStream::getSavedSdes(char *sendCryptoStr, size_t *sendLength) {
+
+    size_t len = strlen(sdesTempBuffer);
+
+    if (len >= *sendLength)
+        return false;
+
+    strcpy(sendCryptoStr, sdesTempBuffer);
+    *sendLength = len;
+
+    if (zrtpUserCallback != NULL)
+        zrtpUserCallback->onNewZrtpStatus(session, NULL, index);
+    return true;
+}
+
+bool CtZrtpStream::isSdesActive() {
+    return (sdes != NULL && sdes->getState() == ZrtpSdesStream::SDES_SRTP_ACTIVE);
+}
+
+int CtZrtpStream::getCryptoMixAttribute(char *algoNames, size_t length) {
+
+    if (sdes == NULL)
+        sdes = new ZrtpSdesStream();
+
+    return sdes->getCryptoMixAttribute(algoNames, length);
+}
+
+void CtZrtpStream::resetSdesContext(bool force) {
+    if (force || !isSdesActive()) {
+        useSdesForMedia = false;
+        useZrtpTunnel = false;
+        delete sdes;
+        sdes = NULL;
+    }
+}
+
+bool  CtZrtpStream::setCryptoMixAttribute(const char *algoNames) {
+    if (isSecure() || isSdesActive())   // don't take action if we are already secure or SDES already in active state
+        return false;
+
+    if (sdes == NULL)
+        sdes = new ZrtpSdesStream();
+
+    return sdes->setCryptoMixAttribute(algoNames);
+}
+
+int32_t CtZrtpStream::getNumberSupportedVersions() {
+
+    return zrtpEngine->getNumberSupportedVersions();
+}
+
+const char* CtZrtpStream::getZrtpEncapAttribute() {
+    return zrtpEncap;
+}
+
+void CtZrtpStream::setZrtpEncapAttribute(const char *attribute) {
+    if (attribute != NULL && strncmp(attribute, zrtpEncap, 4) == 0) {
+        zrtpEncapSignaled = true;
+        if (useSdesForMedia) {
+            useZrtpTunnel = true;
+        }
+    }
+}
+
+void CtZrtpStream::setAuxSecret(const unsigned char *secret, int length) {
+    zrtpEngine->setAuxSecret((unsigned char*)secret, length);
+}
+
+/* *********************
+ * Here the callback methods required by the ZRTP implementation
+ *
+ * The ZRTP functions calls most of the callback functions with syncLock set. Exception
+ * is inform enrollement callback. When in doubt: check!
+ */
+int32_t CtZrtpStream::sendDataZRTP(const unsigned char *data, int32_t length) {
+
+    uint16_t totalLen = length + 12;     /* Fixed number of bytes of ZRTP header */
+    uint32_t crc;
+
+    uint16_t* pus;
+    uint32_t* pui;
+
+    size_t newLength;
+
+    if ((totalLen) > maxZrtpSize)
+        return 0;
+
+    /* Get some handy pointers */
+    pus = (uint16_t*)zrtpBuffer;
+    pui = (uint32_t*)zrtpBuffer;
+
+    /* set up fixed ZRTP header */
+    *(zrtpBuffer + 1) = 0;
+    pus[1] = zrtpHtons(senderZrtpSeqNo++);
+    pui[1] = zrtpHtonl(ZRTP_MAGIC);
+    pui[2] = zrtpHtonl(ownSSRC);            // ownSSRC is stored in host order
+
+    memcpy(zrtpBuffer+12, data, length);    // Copy ZRTP message data behind the header data
+
+    if (useZrtpTunnel) {
+        *zrtpBuffer = 0x80;                                            // temporarily make it to a real RTP packet 
+        sdes->outgoingZrtpTunnel(zrtpBuffer, totalLen-CRC_SIZE, &newLength);
+        *zrtpBuffer = 0x10;                                            // invalid RTP version - refer to ZRTP spec chap 5
+        totalLen = newLength;
+    }
+    else {
+        *zrtpBuffer = 0x10;                                            // invalid RTP version - refer to ZRTP spec chap 5
+        crc = zrtpGenerateCksum(zrtpBuffer, totalLen-CRC_SIZE);        // Setup and compute ZRTP CRC
+        crc = zrtpEndCksum(crc);                                       // convert and store CRC in ZRTP packet.
+        *(uint32_t*)(zrtpBuffer+totalLen-CRC_SIZE) = zrtpHtonl(crc);
+    }
+
+    /* Send the ZRTP packet using callback */
+    if (zrtpSendCallback != NULL) {
+        zrtpSendCallback->sendRtp(session, zrtpBuffer, totalLen, index);
+        return 1;
+    }
+    return 0;
+}
+
+bool CtZrtpStream::srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part)
+{
+    CryptoContext* recvCryptoContext;
+    CryptoContext* senderCryptoContext;
+    CryptoContextCtrl* recvCryptoContextCtrl;
+    CryptoContextCtrl* senderCryptoContextCtrl;
+
+    int cipher;
+    int authn;
+    int authKeyLen;
+
+    if (secrets->authAlgorithm == Sha1) {
+        authn = SrtpAuthenticationSha1Hmac;
+        authKeyLen = 20;
+    }
+
+    if (secrets->authAlgorithm == Skein) {
+        authn = SrtpAuthenticationSkeinHmac;
+        authKeyLen = 32;
+    }
+
+    if (secrets->symEncAlgorithm == Aes)
+        cipher = SrtpEncryptionAESCM;
+
+    if (secrets->symEncAlgorithm == TwoFish)
+        cipher = SrtpEncryptionTWOCM;
+
+    role = secrets->role;
+
+    if (part == ForSender) {
+        // To encrypt packets: intiator uses initiator keys,
+        // responder uses responder keys
+        // Create a "half baked" crypto context first and store it. This is
+        // the main crypto context for the sending part of the connection.
+        if (secrets->role == Initiator) {
+            senderCryptoContext = 
+                new CryptoContext(0,                                       // SSRC (used for lookup)
+                                  0,                                       // Roll-Over-Counter (ROC)
+                                  0L,                                      // keyderivation << 48,
+                                  cipher,                                  // encryption algo
+                                  authn,                                   // authtentication algo
+                                  (unsigned char*)secrets->keyInitiator,   // Master Key
+                                  secrets->initKeyLen / 8,                 // Master Key length
+                                  (unsigned char*)secrets->saltInitiator,  // Master Salt
+                                  secrets->initSaltLen / 8,                // Master Salt length
+                                  secrets->initKeyLen / 8,                 // encryption keyl
+                                  authKeyLen,                              // authentication key len
+                                  secrets->initSaltLen / 8,                // session salt len
+                                  secrets->srtpAuthTagLen / 8);            // authentication tag lenA
+            senderCryptoContextCtrl = 
+                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
+                                      cipher,                                    // encryption algo
+                                      authn,                                     // authtication algo
+                                      (unsigned char*)secrets->keyInitiator,     // Master Key
+                                      secrets->initKeyLen / 8,                   // Master Key length
+                                      (unsigned char*)secrets->saltInitiator,    // Master Salt
+                                      secrets->initSaltLen / 8,                  // Master Salt length
+                                      secrets->initKeyLen / 8,                   // encryption keyl
+                                      authKeyLen,                                // authentication key len
+                                      secrets->initSaltLen / 8,                  // session salt len
+                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
+        }
+        else {
+            senderCryptoContext = 
+                new CryptoContext(0,                                       // SSRC (used for lookup)
+                                  0,                                       // Roll-Over-Counter (ROC)
+                                  0L,                                      // keyderivation << 48,
+                                  cipher,                                  // encryption algo
+                                  authn,                                   // authtentication algo
+                                  (unsigned char*)secrets->keyResponder,   // Master Key
+                                  secrets->respKeyLen / 8,                 // Master Key length
+                                  (unsigned char*)secrets->saltResponder,  // Master Salt
+                                  secrets->respSaltLen / 8,                // Master Salt length
+                                  secrets->respKeyLen / 8,                 // encryption keyl
+                                  authKeyLen,                              // authentication key len
+                                  secrets->respSaltLen / 8,                // session salt len
+                                  secrets->srtpAuthTagLen / 8);            // authentication tag len
+            senderCryptoContextCtrl = 
+                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
+                                      cipher,                                    // encryption algo
+                                      authn,                                     // authtication algo
+                                      (unsigned char*)secrets->keyResponder,     // Master Key
+                                      secrets->respKeyLen / 8,                   // Master Key length
+                                      (unsigned char*)secrets->saltResponder,    // Master Salt
+                                      secrets->respSaltLen / 8,                  // Master Salt length
+                                      secrets->respKeyLen / 8,                   // encryption keyl
+                                      authKeyLen,                                // authentication key len
+                                      secrets->respSaltLen / 8,                  // session salt len
+                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
+        }
+        if (senderCryptoContext == NULL) {
+            return false;
+        }
+        senderCryptoContext->deriveSrtpKeys(0L);
+        sendSrtp = senderCryptoContext;
+
+        senderCryptoContextCtrl->deriveSrtcpKeys();
+        sendSrtcp = senderCryptoContextCtrl;
+    }
+    if (part == ForReceiver) {
+        // To decrypt packets: intiator uses responder keys,
+        // responder initiator keys
+        // See comment above.
+        if (secrets->role == Initiator) {
+            recvCryptoContext = 
+                new CryptoContext(0,                                       // SSRC (used for lookup)
+                                  0,                                       // Roll-Over-Counter (ROC)
+                                  0L,                                      // keyderivation << 48,
+                                  cipher,                                  // encryption algo
+                                  authn,                                   // authtentication algo
+                                  (unsigned char*)secrets->keyResponder,   // Master Key
+                                  secrets->respKeyLen / 8,                 // Master Key length
+                                  (unsigned char*)secrets->saltResponder,  // Master Salt
+                                  secrets->respSaltLen / 8,                // Master Salt length
+                                  secrets->respKeyLen / 8,                 // encryption keyl
+                                  authKeyLen,                              // authentication key len
+                                  secrets->respSaltLen / 8,                // session salt len
+                                  secrets->srtpAuthTagLen / 8);            // authentication tag len
+            recvCryptoContextCtrl = 
+                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
+                                      cipher,                                    // encryption algo
+                                      authn,                                     // authtication algo
+                                      (unsigned char*)secrets->keyResponder,     // Master Key
+                                      secrets->respKeyLen / 8,                   // Master Key length
+                                      (unsigned char*)secrets->saltResponder,    // Master Salt
+                                      secrets->respSaltLen / 8,                  // Master Salt length
+                                      secrets->respKeyLen / 8,                   // encryption keyl
+                                      authKeyLen,                                // authentication key len
+                                      secrets->respSaltLen / 8,                  // session salt len
+                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
+        }
+        else {
+            recvCryptoContext = 
+                new CryptoContext(0,                                       // SSRC (used for lookup)
+                                  0,                                       // Roll-Over-Counter (ROC)
+                                  0L,                                      // keyderivation << 48,
+                                  cipher,                                  // encryption algo
+                                  authn,                                   // authtentication algo
+                                  (unsigned char*)secrets->keyInitiator,   // Master Key
+                                  secrets->initKeyLen / 8,                 // Master Key length
+                                  (unsigned char*)secrets->saltInitiator,  // Master Salt
+                                  secrets->initSaltLen / 8,                // Master Salt length
+                                  secrets->initKeyLen / 8,                 // encryption keyl
+                                  authKeyLen,                              // authentication key len
+                                  secrets->initSaltLen / 8,                // session salt len
+                                  secrets->srtpAuthTagLen / 8);            // authentication tag len
+            recvCryptoContextCtrl = 
+                new CryptoContextCtrl(0,                                         // SSRC (used for lookup)
+                                      cipher,                                    // encryption algo
+                                      authn,                                     // authtication algo
+                                      (unsigned char*)secrets->keyInitiator,     // Master Key
+                                      secrets->initKeyLen / 8,                   // Master Key length
+                                      (unsigned char*)secrets->saltInitiator,    // Master Salt
+                                      secrets->initSaltLen / 8,                  // Master Salt length
+                                      secrets->initKeyLen / 8,                   // encryption keyl
+                                      authKeyLen,                                // authentication key len
+                                      secrets->initSaltLen / 8,                  // session salt len
+                                      secrets->srtpAuthTagLen / 8);              // authentication tag len
+        }
+        if (recvCryptoContext == NULL) {
+            return false;
+        }
+        recvCryptoContext->deriveSrtpKeys(0L);
+        recvSrtp = recvCryptoContext;
+
+        recvCryptoContextCtrl->deriveSrtcpKeys();
+        recvSrtcp = recvCryptoContextCtrl;
+
+        supressCounter = 0;         // supress SRTP warnings for some packets after we switch to SRTP
+    }
+    if (peerHelloHashes.size() > 0 && recvSrtp != NULL && sendSrtp != NULL) {
+        useSdesForMedia = false;
+    }
+    return true;
+}
+
+void CtZrtpStream::srtpSecretsOn(std::string cipher, std::string sas, bool verified)
+{
+     // p->setStatus(ctx->peer_mitm_flag || iMitm?CTZRTP::eSecureMitm:CTZRTP::eSecure,&buf[0],iIsVideo);
+
+    prevTiviState = tiviState;
+
+    // TODO Discuss with Janis what else to do? Set other state, for example eSecureMitmVia or some string?
+    tiviState = CtZrtpSession::eSecure;
+    if (cipher.find ("SASviaMitM", cipher.size() - 10, 10) != std::string::npos) { // Found: SAS via PBX
+        tiviState = CtZrtpSession::eSecureMitmVia;  //eSecureMitmVia
+    }
+    else if (cipher.find ("MitM", cipher.size() - 4, 4) != std::string::npos) {
+        tiviState = CtZrtpSession::eSecureMitm;
+    }
+    else if (cipher.find ("EndAtMitM", cipher.size() - 9, 9) != std::string::npos) {
+        tiviState = CtZrtpSession::eSecureMitm;
+    }
+    sasVerified = verified;
+    if (zrtpUserCallback != NULL) {
+        char *strng = NULL;
+        std::string sasTmp;
+
+        if (!sas.empty()) {                 // Multi-stream mode streams don't have SAS, no reporting
+            uint8_t peerZid[IDENTIFIER_LEN];
+            std::string name;
+
+            zrtpEngine->getPeerZid(peerZid);
+            getZidCacheInstance()->getPeerName(peerZid, &name);
+            zrtpUserCallback->onPeer(session, (char*)name.c_str(), (int)verified, index);
+
+            // If SAS does not contain a : then it's a short SAS
+            size_t found = sas.find_first_of(':');
+            if (found == std::string::npos) {
+                strng = (char*)sas.c_str();
+            }
+            else {
+                sasTmp = sas.substr(0, found);
+                sasTmp.append("  ").append(sas.substr(found+1));
+                strng = (char*)sasTmp.c_str();
+            }
+        }
+        zrtpUserCallback->onNewZrtpStatus(session, strng, index);
+    }
+}
+
+void CtZrtpStream::srtpSecretsOff(EnableSecurity part) {
+    if (part == ForSender) {
+        delete sendSrtp;
+        delete sendSrtcp;
+        sendSrtp = NULL;
+        sendSrtcp = NULL;
+    }
+    if (part == ForReceiver) {
+        delete recvSrtp;
+        delete recvSrtcp;
+        recvSrtp = NULL;
+        recvSrtcp = NULL;
+    }
+}
+
+int32_t CtZrtpStream::activateTimer(int32_t time) {
+    std::string s("ZRTP");
+    if (staticTimeoutProvider != NULL) {
+        staticTimeoutProvider->requestTimeout(time, this, s);
+    }
+    return 1;
+}
+
+int32_t CtZrtpStream::cancelTimer() {
+    std::string s("ZRTP");
+    if (staticTimeoutProvider != NULL) {
+        staticTimeoutProvider->cancelRequest(this, s);
+    }
+    return 1;
+}
+
+void CtZrtpStream::handleTimeout(const std::string &c) {
+    if (zrtpEngine != NULL) {
+        zrtpEngine->processTimeout();
+    }
+}
+
+void CtZrtpStream::handleGoClear() {
+    fprintf(stderr, "Need to process a GoClear message!\n");
+}
+
+void CtZrtpStream::sendInfo(MessageSeverity severity, int32_t subCode) {
+    std::string *msg;
+
+    if (severity == Info) {
+
+        std::string peerHash;
+        std::string hexString;
+        size_t hexStringStart;
+        switch (subCode) {
+            case InfoHelloReceived:
+                // The Tivi client stores the 64 char hex string only, thus
+                // split the string that we get from ZRTP engine that contains
+                // the version info as well (which is the right way to do because
+                // the engine knows which version of the ZRTP protocol it uses.)
+                if (peerHelloHashes.empty())
+                    break;
+
+                peerHash = zrtpEngine->getPeerHelloHash();
+                hexStringStart = peerHash.find_last_of(' ');
+                hexString = peerHash.substr(hexStringStart+1);
+                helloReceived = true;
+
+                for (std::vector<std::string>::iterator it = peerHelloHashes.begin() ; it != peerHelloHashes.end(); ++it) {
+                    int match;
+                    if ((*it).size() > SHA256_DIGEST_LENGTH*2)      // got the full string incl. version prefix, compare with full peer hash string
+                        match = (*it).compare(peerHash);
+                    else
+                        match = (*it).compare(hexString);
+                    if (match == 0) {
+                        zrtpHashMatch = true;
+                        break;
+                    }
+                }
+                if (!zrtpHashMatch && zrtpUserCallback != NULL)
+                    zrtpUserCallback->onZrtpWarning(session, (char*)peerHelloMismatchMsg, index);
+                break;
+
+            case InfoSecureStateOn:
+                if (type == CtZrtpSession::Master) {               // Master stream entered secure mode (security done)
+                    session->masterStreamSecure(this);
+                }
+                // Tivi client does not expect a status change information on this
+                break;
+
+                // These two states correspond to going secure
+            case InfoRespCommitReceived:
+            case InfoInitDH1Received:
+                prevTiviState = tiviState;
+                tiviState = CtZrtpSession::eGoingSecure;
+                if (zrtpUserCallback != NULL)
+                    zrtpUserCallback->onNewZrtpStatus(session, NULL, index);
+                break;
+
+                // other information states are not handled by tivi client
+            default:
+                break;
+        }
+        return;
+    }
+    if (severity == Warning) {
+        switch (subCode) {
+            case WarningNoRSMatch:
+                return;
+                break;                          // supress this warning message
+
+            default:
+                msg = warningMap[subCode];
+                if (zrtpUserCallback != NULL)
+                    zrtpUserCallback->onZrtpWarning(session, (char*)msg->c_str(), index);
+                return;
+                break;
+        }
+    }
+    // handle severe and ZRTP errors
+    zrtpNegotiationFailed(severity, subCode);
+}
+
+void CtZrtpStream::zrtpNegotiationFailed(MessageSeverity severity, int32_t subCode) {
+
+    std::string cs;
+    std::string *strng;
+    const char *inOut;
+    if (severity == ZrtpError) {
+        if (subCode < 0) {                  // received an error packet from peer
+            subCode *= -1;
+            inOut = "(<--)";
+        }
+        else {
+            inOut = "(-->)";
+        }
+        strng = zrtpMap[subCode];
+        if (strng != NULL)
+            cs.assign(*strng);
+        else
+            cs.assign("s4_c255: ZRTP protocol: Unkown ZRTP error packet.");
+        cs.append(inOut);
+    }
+    else {
+        cs = *severeMap[subCode];
+    }
+
+    prevTiviState = tiviState;
+    tiviState = CtZrtpSession::eError;
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->onNewZrtpStatus(session, (char*)cs.c_str(), index);
+    }
+}
+
+void CtZrtpStream::zrtpNotSuppOther() {
+    prevTiviState = tiviState;
+    // if other party does not support ZRTP but we have SDES active set SDES state,
+    // otherwise inform client about failed ZRTP negotiation.
+    tiviState = isSdesActive() ? CtZrtpSession::eSecureSdes : CtZrtpSession::eNoPeer;
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->onNewZrtpStatus(session, NULL, index);
+    }
+}
+
+void CtZrtpStream::synchEnter() {
+    synchLock->Lock();
+}
+
+void CtZrtpStream::synchLeave() {
+    synchLock->Unlock();
+}
+
+void CtZrtpStream::zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment  info) {
+    // TODO: Discuss with Janis
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->onNeedEnroll(session, index, (int32_t)info);
+    }
+}
+
+void CtZrtpStream::zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment  info) {
+// Tivi does not use this information event
+//     if (zrtpUserCallback != NULL) {
+//         zrtpUserCallback->zrtpInformEnrollment(info);
+//     }
+}
+
+void CtZrtpStream::signSAS(uint8_t* sasHash) {
+//     if (zrtpUserCallback != NULL) {
+//         zrtpUserCallback->signSAS(sasHash);
+//     }
+}
+
+bool CtZrtpStream::checkSASSignature(uint8_t* sasHash) {
+//     if (zrtpUserCallback != NULL) {
+//         return zrtpUserCallback->checkSASSignature(sasHash);
+//     }
+     return false;
+}
+
+void CtZrtpStream::initStrings() {
+    if (initialized) {
+        return;
+    }
+    initialized = true;
+
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoHelloReceived,      new std::string("s1_c001: Hello received, preparing a Commit")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoCommitDHGenerated,  new std::string("s1_c002: Commit: Generated a public DH key")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoRespCommitReceived, new std::string("s1_c003: Responder: Commit received, preparing DHPart1")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoDH1DHGenerated,     new std::string("s1_c004: DH1Part: Generated a public DH key")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoInitDH1Received,    new std::string("s1_c005: Initiator: DHPart1 received, preparing DHPart2")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoRespDH2Received,    new std::string("s1_c006: Responder: DHPart2 received, preparing Confirm1")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoInitConf1Received,  new std::string("s1_c007: Initiator: Confirm1 received, preparing Confirm2")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoRespConf2Received,  new std::string("s1_c008: Responder: Confirm2 received, preparing Conf2Ack")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoRSMatchFound,       new std::string("s1_c009: At least one retained secrets matches - security OK")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoSecureStateOn,      new std::string("s1_c010: Entered secure state")));
+    infoMap.insert(std::pair<int32_t, std::string*>(InfoSecureStateOff,     new std::string("s1_c011: No more security for this session")));
+
+    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")));
+    warningMap.insert(std::pair<int32_t, std::string*>(WarningGoClearReceived, new std::string("s2_c002: Received a GoClear message")));
+    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")));
+    warningMap.insert(std::pair<int32_t, std::string*>(WarningNoRSMatch,       new std::string("s2_c004: No retained secret matches - verify SAS")));
+    warningMap.insert(std::pair<int32_t, std::string*>(WarningCRCmismatch,     new std::string("s2_c005: Internal ZRTP packet CRC mismatch - packet dropped")));
+    warningMap.insert(std::pair<int32_t, std::string*>(WarningSRTPauthError,   new std::string("s2_c006: Dropping packet because SRTP authentication failed!")));
+    warningMap.insert(std::pair<int32_t, std::string*>(WarningSRTPreplayError, new std::string("s2_c007: Dropping packet because SRTP replay check failed!")));
+    warningMap.insert(std::pair<int32_t, std::string*>(WarningNoExpectedRSMatch,
+                                                new std::string("s2_c008: You MUST check SAS with your partner. If it doesn't match, it indicates the presence of a wiretapper.")));
+    warningMap.insert(std::pair<int32_t, std::string*>(WarningNoExpectedAuxMatch, new std::string("s2_c009: Expected auxilliary secret match failed")));
+
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereHelloHMACFailed,  new std::string("s3_c001: Hash HMAC check of Hello failed!")));
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereCommitHMACFailed, new std::string("s3_c002: Hash HMAC check of Commit failed!")));
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereDH1HMACFailed,    new std::string("s3_c003: Hash HMAC check of DHPart1 failed!")));
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereDH2HMACFailed,    new std::string("s3_c004: Hash HMAC check of DHPart2 failed!")));
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereCannotSend,       new std::string("s3_c005: Cannot send data - connection or peer down?")));
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereProtocolError,    new std::string("s3_c006: Internal protocol error occured!")));
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereNoTimer,          new std::string("s3_c007: Cannot start a timer - internal resources exhausted?")));
+    severeMap.insert(std::pair<int32_t, std::string*>(SevereTooMuchRetries,   new std::string("s3_c008: Too many retries during ZRTP negotiation - connection or peer down?")));
+
+    zrtpMap.insert(std::pair<int32_t, std::string*>(MalformedPacket,   new std::string("s4_c016: Malformed packet (CRC OK, but wrong structure)")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(CriticalSWError,   new std::string("s4_c020: Critical software error")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppZRTPVersion, new std::string("s4_c048: Unsupported ZRTP version")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(HelloCompMismatch, new std::string("s4_c064: Hello components mismatch")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppHashType,    new std::string("s4_c081: Hash type not supported")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppCiphertype,  new std::string("s4_c082: Cipher type not supported")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppPKExchange,  new std::string("s4_c083: Public key exchange not supported")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppSRTPAuthTag, new std::string("s4_c084: SRTP auth. tag not supported")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(UnsuppSASScheme,   new std::string("s4_c085: SAS scheme not supported")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(NoSharedSecret,    new std::string("s4_c086: No shared secret available, DH mode required")));
+    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)")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(DHErrorWrongHVI,   new std::string("s4_c098: DH Error: hvi != hashed data")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(SASuntrustedMiTM,  new std::string("s4_c099: Received relayed SAS from untrusted MiTM")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(ConfirmHMACWrong,  new std::string("s4_c112: Auth. Error: Bad Confirm pkt HMAC")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(NonceReused,       new std::string("s4_c128: Nonce reuse")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(EqualZIDHello,     new std::string("s4_c144: Duplicate ZIDs in Hello Packets")));
+    zrtpMap.insert(std::pair<int32_t, std::string*>(GoCleatNotAllowed, new std::string("s4_c160: GoClear packet received, but not allowed")));
+
+    enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentRequest,  new std::string("s5_c000: Trusted MitM enrollment requested")));
+    enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentCanceled, new std::string("s5_c001: Trusted MitM enrollment canceled by user")));
+    enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentFailed,   new std::string("s5_c003: Trusted MitM enrollment failed")));
+    enrollMap.insert(std::pair<int32_t, std::string*>(EnrollmentOk,       new std::string("s5_c004: Trusted MitM enrollment OK")));
+}