* #35924: added zrtp module build instructions
diff --git a/jni/libzrtp/src/Base32.cpp b/jni/libzrtp/src/Base32.cpp
new file mode 100644
index 0000000..ccc8034
--- /dev/null
+++ b/jni/libzrtp/src/Base32.cpp
@@ -0,0 +1,335 @@
+/**
+ *
+ * Copyright (c) 2002 Bryce "Zooko" Wilcox-O'Hearn Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software to
+ * deal in this software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of this software, and to permit persons to whom this software
+ * is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THIS SOFTWARE.
+ *
+ * Converted to C++ by:
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+#ifndef UNIT_TEST
+#include <libzrtpcpp/Base32.h>
+#else
+#include "libzrtpcpp/Base32.h"
+#endif
+
+int divceil(int a, int b) {
+    int c;
+    if (a>0) {
+	if (b>0) c=a+b-1;
+	else c=a;
+    } else {
+	if (b>0) c=a;
+	else c=a+b+1;
+    }
+    return c/b;
+}
+
+//                                         1         2         3
+//                               01234567890123456789012345678901
+static const char* const chars= "ybndrfg8ejkmcpqxot1uwisza345h769";
+
+/*
+ * revchars: index into this table with the ASCII value of the char.
+ * The result is the value of that quintet.
+ */
+static const unsigned char revchars[]= {
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255,  18, 255,  25,  26,  27,  30,  29,
+      7,  31, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255,  24,   1,  12,   3,   8,   5,   6,
+    28,   21,   9,  10, 255,  11,   2,  16,
+    13,   14,   4,  22,  17,  19, 255,  20,
+    15,    0,  23, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255
+};
+
+
+Base32::Base32(const string encoded):
+    binaryResult(NULL), resultLength(0) {
+
+    a2b_l(encoded, encoded.size(), (encoded.size()*5/8)*8);
+}
+
+Base32::Base32(const string encoded, int noOfBits):
+    binaryResult(NULL), resultLength(0) {
+
+    a2b_l(encoded, divceil(noOfBits, 5), noOfBits);
+}
+
+Base32::Base32(const unsigned char* data, int noOfBits):
+    binaryResult(NULL), resultLength(0) {
+
+    b2a_l(data, (noOfBits+7)/8, noOfBits);
+}
+
+Base32::~Base32() {
+    if (binaryResult != NULL && binaryResult != smallBuffer) {
+	delete [] binaryResult;
+    }
+    binaryResult = NULL;
+}
+
+const unsigned char* Base32::getDecoded(int &length) {
+    length = resultLength;
+    return binaryResult;
+}
+
+void Base32::b2a_l(const unsigned char* os, int len,
+		   const size_t lengthinbits) {
+
+    /* if lengthinbits is not a multiple of 8 then this is allocating
+     * space for 0, 1, or 2 extra quintets that will be truncated at the
+     * end of this function if they are not needed
+     */
+    string result(divceil(len*8, 5), ' ');
+
+    /* index into the result buffer, initially pointing to the
+     * "one-past-the-end" quintet
+     */
+    int resp = result.size();
+
+    /* pointer into the os buffer, initially pointing to the
+     * "one-past-the-end" octet
+     */
+    const unsigned char* osp = os + len;
+
+    /* Now this is a real live Duff's device.  You gotta love it. */
+
+    unsigned long x = 0;	// to hold up to 32 bits worth of the input
+    switch ((osp - os) % 5) {
+
+	case 0:
+	    do {
+		x = *--osp;
+		result[--resp] = chars[x % 32]; /* The least sig 5 bits go into the final quintet. */
+		x /= 32;	/* ... now we have 3 bits worth in x... */
+		case 4:
+		    x |= ((unsigned long)(*--osp)) << 3; /* ... now we have 11 bits worth in x... */
+		    result[--resp] = chars[x % 32];
+		    x /= 32; /* ... now we have 6 bits worth in x... */
+		    result[--resp] = chars[x % 32];
+		    x /= 32; /* ... now we have 1 bits worth in x... */
+		case 3:
+		    x |= ((unsigned long)(*--osp)) << 1; /* The 8 bits from the 2-indexed octet.
+							    So now we have 9 bits worth in x... */
+		    result[--resp] = chars[x % 32];
+		    x /= 32; /* ... now we have 4 bits worth in x... */
+		case 2:
+		    x |= ((unsigned long)(*--osp)) << 4; /* The 8 bits from the 1-indexed octet.
+							    So now we have 12 bits worth in x... */
+		    result[--resp] = chars[x%32];
+		    x /= 32; /* ... now we have 7 bits worth in x... */
+		    result[--resp] = chars[x%32];
+		    x /= 32; /* ... now we have 2 bits worth in x... */
+		case 1:
+		    x |= ((unsigned long)(*--osp)) << 2; /* The 8 bits from the 0-indexed octet.
+							    So now we have 10 bits worth in x... */
+		    result[--resp] = chars[x%32];
+		    x /= 32; /* ... now we have 5 bits worth in x... */
+		    result[--resp] = chars[x];
+	    } while (osp > os);
+    } /* switch ((osp - os.buf) % 5) */
+
+    /* truncate any unused trailing zero quintets */
+    encoded = result.substr(0, divceil(lengthinbits, 5));
+    return;
+}
+
+void Base32::a2b_l(const string cs, size_t size, const size_t lengthinbits ) {
+    unsigned long x = 0;	// to hold up to 32 bits worth of the input
+
+    int len = divceil(size*5, 8);
+
+    /* if lengthinbits is not a multiple of 5 then this is
+     * allocating space for 0 or 1 extra octets that will be
+     * truncated at the end of this function if they are
+     * not needed
+     */
+
+    if (len < 128) {
+        binaryResult = smallBuffer;
+    }
+    else {
+        binaryResult = new unsigned char[len];
+    }
+
+    /* pointer into the result buffer, initially pointing to
+     * the "one-past-the-end" octet
+     */
+    unsigned char* resp = binaryResult + len;
+
+    /* index into the input buffer, initially pointing to the
+     * "one-past-the-end" character
+     */
+    int csp = size;
+
+    /* Now this is a real live Duff's device.  You gotta love it. */
+    switch (csp % 8) {
+	case 0:
+	    do {
+		x = revchars[cs[--csp]&0xff]; /* 5 bits... */
+		case 7:
+		    x |= revchars[cs[--csp]&0xff] << 5; /* 10 bits... */
+		    *--resp = x % 256;
+		    x /= 256; /* 2 bits... */
+		case 6:
+		    x |= revchars[cs[--csp]&0xff] << 2; /* 7 bits... */
+		case 5:
+		    x |= revchars[cs[--csp]&0xff] << 7; /* 12 bits... */
+		    *--resp = x % 256;
+		    x /= 256; /* 4 bits... */
+		case 4:
+		    x |= revchars[cs[--csp]&0xff] << 4; /* 9 bits... */
+		    *--resp = x % 256;
+		    x /= 256; /* 1 bit... */
+		case 3:
+		    x |= revchars[cs[--csp]&0xff] << 1; /* 6 bits... */
+		case 2:
+		    x |= revchars[cs[--csp]&0xff] << 6; /* 11 bits... */
+		    *--resp = x % 256;
+		    x /= 256; /* 3 bits... */
+		case 1:
+		    x |= revchars[cs[--csp]&0xff] << 3; /* 8 bits... */
+		    *--resp = x % 256;
+	    } while (csp);
+    } /* switch ((csp - cs.buf) % 8) */
+
+    /* truncate any unused trailing zero octets */
+    resultLength = divceil(lengthinbits, 8);
+    return;
+}
+
+#ifdef UNIT_TEST
+#include <math.h>
+
+
+static uint8_t *randz(const size_t len)
+{
+    uint8_t* result = (uint8_t*)malloc(len);
+    size_t i;
+    for (i=0; i<len; i++) {
+        result[i] = rand() % 256;
+    }
+    return result;
+}
+
+int main(int argc, char *argv[]) {
+
+    int32_t resLen;
+    string a;
+    const uint8_t* zrecovered;
+    uint8_t ones[] = {1, 1, 1, 1, 1};
+    uint8_t zrtpVec01[] = {0x00, 0x00, 0x00, 0x00};
+    uint8_t zrtpVec02[] = {0x80, 0x00, 0x00, 0x00};
+    uint8_t zrtpVec03[] = {0x40, 0x00, 0x00, 0x00};
+    uint8_t zrtpVec04[] = {0xc0, 0x00, 0x00, 0x00};
+    uint8_t zrtpVec05[] = {0x00, 0x00, 0x00, 0x00};
+    uint8_t zrtpVec06[] = {0x80, 0x80, 0x00, 0x00};
+    uint8_t zrtpVec07[] = {0x8b, 0x88, 0x80, 0x00};
+    uint8_t zrtpVec08[] = {0xf0, 0xbf, 0xc7, 0x00};
+    uint8_t zrtpVec09[] = {0xd4, 0x7a, 0x04, 0x00};
+    uint8_t zrtpVec10[] = {0xf5, 0x57, 0xbb, 0x0c};
+
+    // Encode all bits of the 5 one bytes (= 40 bits)
+    a = Base32(ones, 5*8).getEncoded();
+
+    // The string should be: "yryonyeb"
+    cout << "Encoded 5 ones: '" << a << "', Expected: 'yryonyeb'" << endl;
+
+    // Now decode all bits and check
+    Base32 *y = new Base32(a);
+    zrecovered = y->getDecoded(resLen);
+    if (resLen != 5 && memcmp(ones, zrecovered, 5)) {
+        printf("Failed basic 5 ones recovery test.\n");
+        return -1;
+    }
+    delete y;
+
+    a = Base32(ones, 15).getEncoded();
+    cout << "Encoded 5 ones, 15 bits only: '" << a << "', Expected: 'yry'" << endl;
+    // now decode 15 bits (out of 40 possible)
+    y = new Base32(a, 15);
+    zrecovered = y->getDecoded(resLen);
+    printf("Decoded 15 bits, result length: %d (should be 2)\n", resLen);
+    printf("Decoded bytes: %x %x (should be 1 0)\n", zrecovered[0], zrecovered[1]);
+    delete y;
+
+    // Encode 20 bits of the test vectors
+    a = Base32(zrtpVec01, 20).getEncoded();
+    cout << "Encoded ZRTP vector 01: '" << a << "', Expected: 'yyyy'" << endl;
+    a = Base32(zrtpVec02, 20).getEncoded();
+    cout << "Encoded ZRTP vector 02: '" << a << "', Expected: 'oyyy'" << endl;
+    a = Base32(zrtpVec03, 20).getEncoded();
+    cout << "Encoded ZRTP vector 02: '" << a << "', Expected: 'eyyy'" << endl;
+    a = Base32(zrtpVec04, 20).getEncoded();
+    cout << "Encoded ZRTP vector 04: '" << a << "', Expected: 'ayyy'" << endl;
+    a = Base32(zrtpVec05, 20).getEncoded();
+    cout << "Encoded ZRTP vector 05: '" << a << "', Expected: 'yyyy'" << endl;
+    a = Base32(zrtpVec06, 20).getEncoded();
+    cout << "Encoded ZRTP vector 06: '" << a << "', Expected: 'onyy'" << endl;
+    a = Base32(zrtpVec07, 20).getEncoded();
+    cout << "Encoded ZRTP vector 07: '" << a << "', Expected: 'tqre'" << endl;
+    a = Base32(zrtpVec08, 20).getEncoded();
+    cout << "Encoded ZRTP vector 08: '" << a << "', Expected: '6n9h'" << endl;
+    a = Base32(zrtpVec09, 20).getEncoded();
+    cout << "Encoded ZRTP vector 09: '" << a << "', Expected: '4t7y'" << endl;
+    a = Base32(zrtpVec10, 20).getEncoded();
+    cout << "Encoded ZRTP vector 10: '" << a << "', Expected: '6im5'" << endl;
+
+    // test the 30 bit output of same data as 20 bit
+    a = Base32(zrtpVec10, 30).getEncoded();
+    cout << "Encoded ZRTP vector 10 (30bit): '" << a << "', Expected: '6im5sd'" << endl;
+
+    for (int i = 0; i < 2; i++) {
+        uint8_t* z = randz(16);
+        a = Base32(z, 16*8).getEncoded();
+//        cout << "Result: " << a << endl;
+        assert (a.size() == Base32::b2alen(16*8));
+        zrecovered = Base32(a).getDecoded(resLen);
+        if (resLen != 16 && memcmp(z, zrecovered, 16)) {
+            printf("Failed basic recovery test.\n");
+            return -1;
+        }
+        free((void*)z);
+    }
+}
+#endif
diff --git a/jni/libzrtp/src/CMakeLists.txt b/jni/libzrtp/src/CMakeLists.txt
new file mode 100755
index 0000000..4febbde
--- /dev/null
+++ b/jni/libzrtp/src/CMakeLists.txt
@@ -0,0 +1,87 @@
+cmake_minimum_required (VERSION 2.6)
+
+# add_subdirectory(libzrtpcpp)
+# add_subdirectory(libzrtpcpp/crypto)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+set(gcrypt_src
+    libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp
+    libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp
+    libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp
+    libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp
+    libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp
+    libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp
+    libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp)
+
+set(openssl_src
+    libzrtpcpp/crypto/openssl/ZrtpDH.cpp
+    libzrtpcpp/crypto/openssl/hmac256.cpp
+    libzrtpcpp/crypto/openssl/sha256.cpp
+    libzrtpcpp/crypto/openssl/hmac384.cpp
+    libzrtpcpp/crypto/openssl/sha384.cpp
+    libzrtpcpp/crypto/openssl/AesCFB.cpp
+    libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp)
+
+if (GCRYPT_FOUND)
+    set(crypto_src ${gcrypt_src})
+endif()
+
+if (OPENSSL_FOUND AND HAVE_OPENSSL_EC_H)
+    set(crypto_src ${openssl_src})
+endif()
+
+if(enable_ccrtp)
+  set(ccrtp_src ZrtpQueue.cpp)
+endif()
+
+set(twofish_srcs libzrtpcpp/crypto/twofish.c
+         libzrtpcpp/crypto/twofish_cfb.c
+         libzrtpcpp/crypto/TwoCFB.cpp)
+
+set(zrtp_src
+    ZrtpCallbackWrapper.cpp
+    ZIDFile.cpp
+    ZIDRecord.cpp
+    Zrtp.cpp
+    ZrtpCrc32.cpp
+    ZrtpPacketCommit.cpp
+    ZrtpPacketConf2Ack.cpp
+    ZrtpPacketConfirm.cpp
+    ZrtpPacketDHPart.cpp
+    ZrtpPacketGoClear.cpp
+    ZrtpPacketClearAck.cpp
+    ZrtpPacketHelloAck.cpp
+    ZrtpPacketHello.cpp
+    ZrtpPacketError.cpp
+    ZrtpPacketErrorAck.cpp
+    ZrtpPacketPingAck.cpp
+    ZrtpPacketPing.cpp
+    ZrtpPacketSASrelay.cpp
+    ZrtpPacketRelayAck.cpp
+    ZrtpStateClass.cpp
+    ZrtpTextData.cpp
+    ZrtpConfigure.cpp
+    ZrtpCWrapper.cpp
+    Base32.cpp)
+
+set(zrtpcpp_src ${zrtp_src} ${ccrtp_src} ${crypto_src} ${twofish_srcs})
+
+if(BUILD_STATIC AND NOT BUILD_SHARED)
+    set(LIBRARY_BUILD_TYPE STATIC)
+else()
+    set(LIBRARY_BUILD_TYPE SHARED)
+endif()
+
+add_library(${zrtplib} ${LIBRARY_BUILD_TYPE} ${zrtpcpp_src})
+set_target_properties(${zrtplib} PROPERTIES VERSION ${VERSION} SOVERSION ${SOVERSION})
+target_link_libraries(${zrtplib} ${LIBS})
+
+if(enable_ccrtp)
+    add_dependencies(${zrtplib} ccrtp)
+endif()
+
+add_subdirectory(libzrtpcpp)
+
+install(TARGETS ${zrtplib} DESTINATION ${LIBDIRNAME})
+
diff --git a/jni/libzrtp/src/ZIDFile.cpp b/jni/libzrtp/src/ZIDFile.cpp
new file mode 100644
index 0000000..69b43eb
--- /dev/null
+++ b/jni/libzrtp/src/ZIDFile.cpp
@@ -0,0 +1,430 @@
+/*
+  Copyright (C) 2006-2008 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+// #define UNIT_TEST
+
+#include <string>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libzrtpcpp/ZIDFile.h>
+
+
+static ZIDFile* instance;
+static int errors = 0;  // maybe we will use as member of ZIDFile later...
+
+void ZIDFile::createZIDFile(char* name) {
+    zidFile = fopen(name, "wb+");
+    // New file, generate an associated random ZID and save
+    // it as first record
+    if (zidFile != NULL) {
+        unsigned int* ip;
+        ip = (unsigned int*) associatedZid;
+        srand(time(NULL));
+        *ip++ = rand();
+        *ip++ = rand();
+        *ip = rand();
+
+        ZIDRecord rec(associatedZid);
+        rec.setOwnZIDRecord();
+        fseek(zidFile, 0L, SEEK_SET);
+        if (fwrite(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) < 1)
+            ++errors;
+        fflush(zidFile);
+    }
+}
+
+/**
+ * Migrate old ZID file format to new one.
+ *
+ * If ZID file is old format:
+ * - close it, rename it, then re-open
+ * - create ZID file for new format
+ * - copy over contents and flags.
+ */
+void ZIDFile::checkDoMigration(char* name) {
+    FILE* fdOld;
+    unsigned char inb[2];
+    zidrecord1_t recOld;
+
+    fseek(zidFile, 0L, SEEK_SET);
+    if (fread(inb, 2, 1, zidFile) < 1) {
+        ++errors;
+        inb[0] = 0;
+    }
+
+    if (inb[0] > 0) {           // if it's new format just return
+        return;
+    }
+    fclose(zidFile);            // close old ZID file
+    zidFile = NULL;
+
+    // create save file name, rename and re-open
+    // if rename fails, just unlink old ZID file and create a brand new file
+    // just a little inconvenience for the user, need to verify new SAS
+    std::string fn = std::string(name) + std::string(".save");
+    if (rename(name, fn.c_str()) < 0) {
+	unlink(name);
+        createZIDFile(name);
+        return;
+    }
+    fdOld = fopen(fn.c_str(), "rb");    // reopen old format in read only mode
+
+    // Get first record from old file - is the own ZID
+    fseek(fdOld, 0L, SEEK_SET);
+    if (fread(&recOld, sizeof(zidrecord1_t), 1, fdOld) != 1) {
+        fclose(fdOld);
+        return;
+    }
+    if (recOld.ownZid != 1) {
+        fclose(fdOld);
+        return;
+    }
+    zidFile = fopen(name, "wb+");    // create new format file in binary r/w mode
+    if (zidFile == NULL) {
+        return;
+    }
+    // create ZIDRecord in new format, copy over own ZID and write the record
+    ZIDRecord rec(recOld.identifier);
+    rec.setOwnZIDRecord();
+    if (fwrite(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) < 1)
+        ++errors;
+
+    // now copy over all valid records from old ZID file format.
+    // Sequentially read old records, sequentially write new records
+    int numRead;
+    do {
+        numRead = fread(&recOld, sizeof(zidrecord1_t), 1, fdOld);
+        if (numRead == 0) {     // all old records processed
+            break;
+        }
+        // skip own ZID record and invalid records
+        if (recOld.ownZid == 1 || recOld.recValid == 0) {
+            continue;
+        }
+        ZIDRecord rec2(recOld.identifier);
+        rec2.setValid();
+        if (recOld.rs1Valid & SASVerified) {
+            rec2.setSasVerified();
+        }
+        rec2.setNewRs1(recOld.rs2Data);
+        rec2.setNewRs1(recOld.rs1Data);
+        if (fwrite(rec2.getRecordData(), rec2.getRecordLength(), 1, zidFile) < 1)
+            ++errors;
+
+    } while (numRead == 1);
+    fflush(zidFile);
+}
+
+ZIDFile::~ZIDFile() {
+    close();
+}
+
+ZIDFile* ZIDFile::getInstance() {
+
+    if (instance == NULL) {
+        instance = new ZIDFile();
+    }
+    return instance;
+}
+
+int ZIDFile::open(char* name) {
+
+    // check for an already active ZID file
+    if (zidFile != NULL) {
+        return 0;
+    }
+    if ((zidFile = fopen(name, "rb+")) == NULL) {
+        createZIDFile(name);
+    } else {
+        checkDoMigration(name);
+        if (zidFile != NULL) {
+            ZIDRecord rec;
+            fseek(zidFile, 0L, SEEK_SET);
+            if (fread(rec.getRecordData(), rec.getRecordLength(), 1, zidFile) != 1) {
+                fclose(zidFile);
+                zidFile = NULL;
+                return -1;
+            }
+            if (!rec.isOwnZIDRecord()) {
+                fclose(zidFile);
+                zidFile = NULL;
+                return -1;
+            }
+            memcpy(associatedZid, rec.getIdentifier(), IDENTIFIER_LEN);
+        }
+    }
+    return ((zidFile == NULL) ? -1 : 1);
+}
+
+void ZIDFile::close() {
+
+    if (zidFile != NULL) {
+        fclose(zidFile);
+        zidFile = NULL;
+    }
+}
+
+unsigned int ZIDFile::getRecord(ZIDRecord* zidRecord) {
+    unsigned long pos;
+    ZIDRecord rec;
+    int numRead;
+
+    // set read pointer behind first record (
+    fseek(zidFile, rec.getRecordLength(), SEEK_SET);
+
+    do {
+        pos = ftell(zidFile);
+        numRead = fread(rec.getRecordData(), rec.getRecordLength(), 1, zidFile);
+        if (numRead == 0) {
+            break;
+        }
+
+        // skip own ZID record and invalid records
+        if (rec.isOwnZIDRecord() || !rec.isValid()) {
+            continue;
+        }
+
+    } while (numRead == 1 &&
+             memcmp(zidRecord->getIdentifier(), rec.getIdentifier(), IDENTIFIER_LEN) != 0);
+
+    // If we reached end of file, then no record with the ZID
+    // found. We need to create a new ZID record.
+    if (numRead == 0) {
+        // create new record
+        ZIDRecord rec1(zidRecord->getIdentifier());
+        rec1.setValid();
+        if (fwrite(rec1.getRecordData(), rec1.getRecordLength(), 1, zidFile) < 1)
+            ++errors;
+        memcpy(zidRecord->getRecordData(), rec1.getRecordData(), rec1.getRecordLength());
+    } else {
+        // Copy the read data into caller's the record storage
+        memcpy(zidRecord->getRecordData(), rec.getRecordData(), rec.getRecordLength());
+    }
+
+    //  remember position of record in file for save operation
+    zidRecord->setPosition(pos);
+    return 1;
+}
+
+unsigned int ZIDFile::saveRecord(ZIDRecord *zidRecord) {
+
+    fseek(zidFile, zidRecord->getPosition(), SEEK_SET);
+    if (fwrite(zidRecord->getRecordData(), zidRecord->getRecordLength(), 1, zidFile) < 1)
+        ++errors;
+    fflush(zidFile);
+    return 1;
+}
+
+
+#ifdef UNIT_TEST
+
+#include <iostream>
+#include <unistd.h>
+using namespace std;
+
+static void hexdump(const char* title, const unsigned char *s, int l) {
+    int n=0;
+
+    if (s == NULL) return;
+
+    fprintf(stderr, "%s",title);
+    for (; n < l ; ++n) {
+        if ((n%16) == 0)
+            fprintf(stderr, "\n%04x",n);
+        fprintf(stderr, " %02x",s[n]);
+    }
+    fprintf(stderr, "\n");
+}
+
+int main(int argc, char *argv[]) {
+
+    unsigned char myId[IDENTIFIER_LEN];
+    ZIDFile *zid = ZIDFile::getInstance();
+
+    unlink("testzid2");
+    zid->open("testzid2");
+    hexdump("My ZID: ", zid->getZid(), IDENTIFIER_LEN);
+    memcpy(myId, zid->getZid(), IDENTIFIER_LEN);
+    zid->close();
+
+    zid->open("testzid2");
+    if (memcmp(myId, zid->getZid(), IDENTIFIER_LEN) != 0) {
+        cerr << "Wrong ZID in testfile" << endl;
+        return 1;
+    }
+
+    // Create a new ZID record for peer ZID "123456789012"
+    ZIDRecord zr3((unsigned char*) "123456789012");
+    zid->getRecord(&zr3);
+    if (!zr3.isValid()) {
+        cerr << "New ZID record '123456789012' not set to valid" << endl;
+        return 1;
+    }
+    zid->saveRecord(&zr3);
+
+    // create a second record with peer ZID "210987654321"
+    ZIDRecord zr4((unsigned char*) "210987654321");
+    zid->getRecord(&zr4);
+    if (!zr4.isValid()) {
+        cerr << "New ZID record '210987654321' not set to valid" << endl;
+        return 1;
+    }
+    zid->saveRecord(&zr4);
+
+    // now set a first RS1 with default expiration interval, check
+    // if set correctly, valid flag and expiration interval
+    zr3.setNewRs1((unsigned char*) "11122233344455566677788899900012");
+    if (memcmp(zr3.getRs1(), "11122233344455566677788899900012", RS_LENGTH) != 0) {
+        cerr << "RS1 was not set (111...012)" << endl;
+        return 1;
+    }
+    if (!zr3.isRs1Valid()) {
+        cerr << "RS1 was not set to valid state (111...012)" << endl;
+        return 1;
+    }
+    if (!zr3.isRs1NotExpired()) {
+        cerr << "RS1 expired (111...012)" << endl;
+        return 1;
+    }
+    if (zr3.isRs2Valid()) {
+        cerr << "RS2 was set to valid state (111...012)" << endl;
+        return 1;
+    }
+    zid->saveRecord(&zr3);
+
+    // create a second RS1, RS2 will become the first RS1,  check
+    // if set correctly, valid flag and expiration interval for both
+    // RS1 and RS2
+    zr3.setNewRs1((unsigned char*) "00099988877766655544433322211121");
+    if (memcmp(zr3.getRs1(), "00099988877766655544433322211121", RS_LENGTH) != 0) {
+        cerr << "RS1 was not set (000...121)" << endl;
+        return 1;
+    }
+    if (!zr3.isRs1Valid()) {
+        cerr << "RS1 was not set to valid state (000...121)" << endl;
+        return 1;
+    }
+    if (!zr3.isRs1NotExpired()) {
+        cerr << "RS1 expired (000...121)" << endl;
+        return 1;
+    }
+    if (memcmp(zr3.getRs2(), "11122233344455566677788899900012", RS_LENGTH) != 0) {
+        cerr << "RS2 was not set (111...012)" << endl;
+        return 1;
+    }
+    if (!zr3.isRs2Valid()) {
+        cerr << "RS2 was not set to valid state (111...012)" << endl;
+        return 1;
+    }
+    if (!zr3.isRs2NotExpired()) {
+        cerr << "RS2 expired (111...012)" << endl;
+        return 1;
+    }
+    zid->saveRecord(&zr3);
+
+    zid->close();
+
+    // Reopen, check if first record is still valid, RSx vaild and
+    // not expired. Then manipulate 2nd record.
+    zid->open("testzid2");
+
+    ZIDRecord zr3a((unsigned char*) "123456789012");
+    zid->getRecord(&zr3a);
+    if (!zr3a.isValid()) {
+        cerr << "Re-read ZID record '123456789012' not set to valid" << endl;
+        return 1;
+    }
+    if (memcmp(zr3a.getRs1(), "00099988877766655544433322211121", RS_LENGTH) != 0) {
+        cerr << "re-read RS1 was not set (000...121)" << endl;
+        return 1;
+    }
+    if (!zr3a.isRs1Valid()) {
+        cerr << "Re-read RS1 was not set to valid state (000...121)" << endl;
+        return 1;
+    }
+    if (!zr3a.isRs1NotExpired()) {
+        cerr << "re-read RS1 expired (000...121)" << endl;
+        return 1;
+    }
+    if (memcmp(zr3a.getRs2(), "11122233344455566677788899900012", RS_LENGTH) != 0) {
+        cerr << "re-read RS2 was not set (111...012)" << endl;
+        return 1;
+    }
+    if (!zr3a.isRs2Valid()) {
+        cerr << "Re-read RS2 was not set to valid state (111...012)" << endl;
+        return 1;
+    }
+    if (!zr3a.isRs2NotExpired()) {
+        cerr << "Re-read RS2 expired (111...012)" << endl;
+        return 1;
+    }
+
+    ZIDRecord zr5((unsigned char*) "210987654321");
+    zid->getRecord(&zr5);
+
+
+    // set new RS1 with expire interval of 5 second, then check immediatly
+    zr5.setNewRs1((unsigned char*) "aaa22233344455566677788899900012", 5);
+    if (!zr5.isValid()) {
+        cerr << "Re-read ZID record '210987654321' not set to valid" << endl;
+        return 1;
+    }
+    if (memcmp(zr5.getRs1(), "aaa22233344455566677788899900012", RS_LENGTH) != 0) {
+        cerr << "RS1 (2) was not set (aaa...012)" << endl;
+        return 1;
+    }
+    if (!zr5.isRs1Valid()) {
+        cerr << "RS1 (2) was not set to valid state (aaa...012)" << endl;
+        return 1;
+    }
+    if (!zr5.isRs1NotExpired()) {
+        cerr << "RS1 (2) expired (aaa...012)" << endl;
+        return 1;
+    }
+
+    // wait for 6 second, now the expire check shall fail
+    sleep(6);
+    if (zr5.isRs1NotExpired()) {
+        cerr << "RS1 (2) is not expired after defined interval (aaa...012)" << endl;
+        return 1;
+    }
+
+    zr5.setNewRs1((unsigned char*) "bbb99988877766655544433322211121", 256);
+    zid->saveRecord(&zr5);
+
+    zid->close();
+
+    // Test migration
+    zid->open("testzidOld");
+    zid->close();
+
+}
+
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/ZIDRecord.cpp b/jni/libzrtp/src/ZIDRecord.cpp
new file mode 100644
index 0000000..d62c2e3
--- /dev/null
+++ b/jni/libzrtp/src/ZIDRecord.cpp
@@ -0,0 +1,113 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <time.h>
+
+#include <libzrtpcpp/ZIDRecord.h>
+
+void ZIDRecord::setNewRs1(const unsigned char* data, int32_t expire) {
+
+    // shift RS1 data into RS2 position
+    memcpy(record.rs2Data, record.rs1Data, RS_LENGTH);
+    memcpy(record.rs2Interval, record.rs1Interval, TIME_LENGTH);
+
+    // now propagate flags as well
+    if (isRs1Valid()) {
+	setRs2Valid();
+    }
+
+    // set new RS1 data
+    memcpy(record.rs1Data, data, RS_LENGTH);
+
+    time_t validThru;
+    if (expire == -1) {
+	validThru = -1;
+    }
+    else if (expire <= 0) {
+	validThru = 0;
+    }
+    else {
+	validThru = time(NULL) + expire;
+    }
+
+    if (sizeof(time_t) == 4) {
+	long long temp = validThru;
+	memcpy(record.rs1Interval, (unsigned char*)&temp, TIME_LENGTH);
+    }
+    else {
+	memcpy(record.rs1Interval, (unsigned char*)&validThru, TIME_LENGTH);
+    }
+    setRs1Valid();
+}
+
+
+const bool ZIDRecord::isRs1NotExpired() {
+    time_t current = time(NULL);
+    time_t validThru;
+
+    if (sizeof(time_t) == 4) {
+	long long temp;
+	memcpy((unsigned char*)&temp, record.rs1Interval, TIME_LENGTH);
+	validThru = temp;
+    }
+    else {
+	memcpy((unsigned char*)&validThru, record.rs1Interval, TIME_LENGTH);
+    }
+
+    if (validThru == -1)
+	return true;
+    if (validThru == 0)
+	return false;
+    return (current <= validThru) ? true : false;
+}
+
+const bool ZIDRecord::isRs2NotExpired() {
+    time_t current = time(NULL);
+    time_t validThru;
+
+    if (sizeof(time_t) == 4) {
+	long long temp;
+	memcpy((unsigned char*)&temp, record.rs2Interval, TIME_LENGTH);
+	validThru = temp;
+    }
+    else {
+	memcpy((unsigned char*)&validThru, record.rs2Interval, TIME_LENGTH);
+    }
+
+    if (validThru == -1)
+	return true;
+    if (validThru == 0)
+	return false;
+    return (current <= validThru) ? true : false;
+}
+
+void ZIDRecord::setMiTMData(const unsigned char* data) {
+    memcpy(record.mitmKey, data, RS_LENGTH);
+    setMITMKeyAvailable();
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/Zrtp.cpp b/jni/libzrtp/src/Zrtp.cpp
new file mode 100644
index 0000000..2002462
--- /dev/null
+++ b/jni/libzrtp/src/Zrtp.cpp
@@ -0,0 +1,2527 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*F
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+#include <sstream>
+
+#include <libzrtpcpp/crypto/ZrtpDH.h>
+#include <libzrtpcpp/crypto/hmac256.h>
+#include <libzrtpcpp/crypto/sha256.h>
+#include <libzrtpcpp/crypto/hmac384.h>
+#include <libzrtpcpp/crypto/sha384.h>
+#include <libzrtpcpp/crypto/aesCFB.h>
+#include <libzrtpcpp/crypto/twoCFB.h>
+
+#include <libzrtpcpp/ZRtp.h>
+#include <libzrtpcpp/ZrtpStateClass.h>
+#include <libzrtpcpp/ZIDFile.h>
+#include <libzrtpcpp/ZIDRecord.h>
+#include <libzrtpcpp/Base32.h>
+
+using namespace GnuZrtpCodes;
+
+/* disabled...but used in testing and debugging, probably should have a
+   controlling #define...
+   *
+static void hexdump(const char* title, const unsigned char *s, int l) {
+    int n=0;
+
+    if (s == NULL) return;
+
+    fprintf(stderr, "%s",title);
+    for( ; n < l ; ++n)
+    {
+        if((n%16) == 0)
+            fprintf(stderr, "\n%04x",n);
+        fprintf(stderr, " %02x",s[n]);
+    }
+    fprintf(stderr, "\n");
+}
+ */
+
+/*
+ * This method simplifies detection of libzrtpcpp inside Automake, configure
+ * and friends
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+    int ZrtpAvailable()
+    {
+        return 1;
+    }
+#ifdef __cplusplus
+}
+#endif
+
+ZRtp::ZRtp(uint8_t *myZid, ZrtpCallback *cb, std::string id, ZrtpConfigure* config, bool mitmm, bool sasSignSupport):
+        callback(cb), dhContext(NULL), DHss(NULL), auxSecret(NULL), auxSecretLength(0), rs1Valid(false),
+        rs2Valid(false), msgShaContext(NULL), multiStream(false), multiStreamAvailable(false), pbxSecretTmp(NULL),
+        configureAlgos(*config) {
+
+    enableMitmEnrollment = config->isTrustedMitM();
+    paranoidMode = config->isParanoidMode();
+
+    // setup the implicit hash function pointers and length
+    hashLengthImpl = SHA256_DIGEST_LENGTH;
+    hashFunctionImpl = sha256;
+    hashListFunctionImpl = sha256;
+
+    hmacFunctionImpl = hmac_sha256;
+    hmacListFunctionImpl = hmac_sha256;
+
+    /*
+     * Generate H0 as a random number (256 bits, 32 bytes) and then
+     * the hash chain, refer to chapter 9. Use the implicit hash function.
+     */
+    randomZRTP(H0, HASH_IMAGE_SIZE);
+    sha256(H0, HASH_IMAGE_SIZE, H1);        // hash H0 and generate H1
+    sha256(H1, HASH_IMAGE_SIZE, H2);        // H2
+    sha256(H2, HASH_IMAGE_SIZE, H3);        // H3
+
+    zrtpHello.configureHello(&configureAlgos);
+    zrtpHello.setH3(H3);                    // set H3 in Hello, included in helloHash
+
+    memcpy(zid, myZid, ZID_SIZE);
+    zrtpHello.setZid(zid);
+
+    if (mitmm)                              // this session acts for a trusted MitM (PBX)
+        zrtpHello.setMitmMode();
+
+    if (sasSignSupport)                     // the application supports SAS signing
+        zrtpHello.setSasSign();
+
+    setClientId(id);                        // set id, compute HMAC and final helloHash
+
+    stateEngine = new ZrtpStateClass(this);
+}
+
+ZRtp::~ZRtp() {
+    stopZrtp();
+    if (DHss != NULL) {
+        delete DHss;
+        DHss = NULL;
+    }
+    if (stateEngine != NULL) {
+        delete stateEngine;
+        stateEngine = NULL;
+    }
+    if (dhContext != NULL) {
+        delete dhContext;
+        dhContext = NULL;
+    }
+    if (msgShaContext != NULL) {
+        closeHashCtx(msgShaContext, NULL);
+        msgShaContext = NULL;
+    }
+    if (auxSecret != NULL) {
+        delete auxSecret;
+        auxSecret = NULL;
+        auxSecretLength = 0;
+    }
+    memset(hmacKeyI, 0, MAX_DIGEST_LENGTH);
+    memset(hmacKeyR, 0, MAX_DIGEST_LENGTH);
+
+    memset(zrtpKeyI, 0, MAX_DIGEST_LENGTH);
+    memset(zrtpKeyR, 0, MAX_DIGEST_LENGTH);
+    /*
+     * Clear the Initiator's srtp key and salt
+     */
+    memset(srtpKeyI, 0, MAX_DIGEST_LENGTH);
+    memset(srtpSaltI, 0,  MAX_DIGEST_LENGTH);
+    /*
+     * Clear he Responder's srtp key and salt
+     */
+    memset(srtpKeyR, 0, MAX_DIGEST_LENGTH);
+    memset(srtpSaltR, 0, MAX_DIGEST_LENGTH);
+
+    memset(zrtpSession, 0, MAX_DIGEST_LENGTH);
+}
+
+void ZRtp::processZrtpMessage(uint8_t *message, uint32_t pSSRC) {
+    Event_t ev;
+
+    peerSSRC = pSSRC;
+    ev.type = ZrtpPacket;
+    ev.packet = message;
+
+    if (stateEngine != NULL) {
+        stateEngine->processEvent(&ev);
+    }
+}
+
+void ZRtp::processTimeout() {
+    Event_t ev;
+
+    ev.type = Timer;
+    if (stateEngine != NULL) {
+        stateEngine->processEvent(&ev);
+    }
+}
+
+#ifdef oldgoclear
+bool ZRtp::handleGoClear(uint8_t *message)
+{
+    char *msg, first, last;
+
+    msg = (char *)message + 4;
+    first = tolower(*msg);
+    last = tolower(*(msg+6));
+
+    if (first == 'g' && last == 'r') {
+        Event_t ev;
+
+        ev.type = ZrtpGoClear;
+        ev.packet = message;
+        if (stateEngine != NULL) {
+            stateEngine->processEvent(&ev);
+        }
+        return true;
+    }
+    else {
+        return false;
+    }
+}
+#endif
+
+void ZRtp::startZrtpEngine() {
+    Event_t ev;
+
+    if (stateEngine != NULL && stateEngine->inState(Initial)) {
+        ev.type = ZrtpInitial;
+        stateEngine->processEvent(&ev);
+    }
+}
+
+void ZRtp::stopZrtp() {
+    Event_t ev;
+
+    if (stateEngine != NULL) {
+        ev.type = ZrtpClose;
+        stateEngine->processEvent(&ev);
+    }
+}
+
+bool ZRtp::inState(int32_t state)
+{
+    if (stateEngine != NULL) {
+        return stateEngine->inState(state);
+    }
+    else {
+        return false;
+    }
+}
+
+ZrtpPacketHello* ZRtp::prepareHello() {
+    return &zrtpHello;
+}
+
+ZrtpPacketHelloAck* ZRtp::prepareHelloAck() {
+    return &zrtpHelloAck;
+}
+
+/*
+ * At this point we will assume the role of Initiator. This role may change
+ * in case we have a commit-clash. Refer to chapter 5.2 in the spec how
+ * to break this tie.
+ */
+ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) {
+
+    sendInfo(Info, InfoHelloReceived);
+
+    if (memcmp(hello->getVersion(), zrtpVersion, ZRTP_WORD_SIZE-1) != 0) {
+        *errMsg = UnsuppZRTPVersion;
+        return NULL;
+    }
+    // Save our peer's (presumably the Responder) ZRTP id
+    memcpy(peerZid, hello->getZid(), ZID_SIZE);
+    if (memcmp(peerZid, zid, ZID_SIZE) == 0) {       // peers have same ZID????
+        *errMsg = EqualZIDHello;
+        return NULL;
+    }
+    memcpy(peerH3, hello->getH3(), HASH_IMAGE_SIZE);
+
+    /*
+     * The Following section extracts the algorithm from the peer's Hello
+     * packet. Always the preferend offered algorithms are
+     * used. If the received Hello does not contain algo specifiers
+     * or offers only unsupported optional algos then replace
+     * these with mandatory algos and put them into the Commit packet.
+     * Refer to the findBest*() functions.
+     * If this is a MultiStream ZRTP object then do not get the cipher,
+     * authentication from hello packet but use the pre-initialized values
+     * as proposed by the standard. If we switch to responder mode the
+     * commit packet may contain other algos - see function
+     * prepareConfirm2MultiStream(...).
+     */
+    sasType = findBestSASType(hello);
+
+    if (!multiStream) {
+        authLength = findBestAuthLen(hello);
+        pubKey = findBestPubkey(hello);
+        cipher = findBestCipher(hello, pubKey);
+        hash = findBestHash(hello);
+        multiStreamAvailable = checkMultiStream(hello);
+    }
+    else {
+        if (checkMultiStream(hello)) {
+            return prepareCommitMultiStream(hello);
+        }
+        else {
+            // we are in multi-stream but peer does not offer multi-stream
+            // return error code to other party - unsupported PK, must be Mult
+            *errMsg = UnsuppPKExchange;
+            return NULL;
+        }
+    }
+    setNegotiatedHash(hash);
+
+    // Modify here when introducing new DH key agreement, for example
+    // elliptic curves.
+    dhContext = new ZrtpDH(pubKey->getName());
+    dhContext->generatePublicKey();
+
+    dhContext->getPubKeyBytes(pubKeyBytes);
+    sendInfo(Info, InfoCommitDHGenerated);
+
+    // Prepare IV data that we will use during confirm packet encryption.
+    randomZRTP(randomIV, sizeof(randomIV));
+
+    /*
+     * Prepare our DHPart2 packet here. Required to compute HVI. If we stay
+     * in Initiator role then we reuse this packet later in prepareDHPart2().
+     * To create this DH packet we have to compute the retained secret ids
+     * first. Thus get our peer's retained secret data first.
+     */
+    ZIDRecord zidRec(peerZid);
+    ZIDFile *zidFile = ZIDFile::getInstance();
+    zidFile->getRecord(&zidRec);
+
+    //Compute the Initator's and Responder's retained secret ids.
+    computeSharedSecretSet(zidRec);
+
+    // Check if a PBX application set the MitM flag.
+    if (hello->isMitmMode()) {
+        mitmSeen = true;
+    }
+    // Flag to record that fact that we have a MitM key of the other peer.
+    peerIsEnrolled = zidRec.isMITMKeyAvailable();
+
+    signSasSeen = hello->isSasSign();
+    // Construct a DHPart2 message (Initiator's DH message). This packet
+    // is required to compute the HVI (Hash Value Initiator), refer to
+    // chapter 5.4.1.1.
+
+    // Fill the values in the DHPart2 packet
+    zrtpDH2.setPubKeyType(pubKey->getName());
+    zrtpDH2.setMessageType((uint8_t*)DHPart2Msg);
+    zrtpDH2.setRs1Id(rs1IDi);
+    zrtpDH2.setRs2Id(rs2IDi);
+    zrtpDH2.setAuxSecretId(auxSecretIDi);
+    zrtpDH2.setPbxSecretId(pbxSecretIDi);
+    zrtpDH2.setPv(pubKeyBytes);
+    zrtpDH2.setH1(H1);
+
+    int32_t len = zrtpDH2.getLength() * ZRTP_WORD_SIZE;
+
+    // Compute HMAC over DH2, excluding the HMAC field (HMAC_SIZE)
+    // and store in DH2. Key to HMAC is H0, use HASH_IMAGE_SIZE bytes only.
+    // Must use implicit HMAC functions.
+    uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+    hmacFunctionImpl(H0, HASH_IMAGE_SIZE, (uint8_t*)zrtpDH2.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
+    zrtpDH2.setHMAC(hmac);
+
+    // Compute the HVI, refer to chapter 5.4.1.1 of the specification
+    computeHvi(&zrtpDH2, hello);
+
+    zrtpCommit.setZid(zid);
+    zrtpCommit.setHashType((uint8_t*)hash->getName());
+    zrtpCommit.setCipherType((uint8_t*)cipher->getName());
+    zrtpCommit.setAuthLen((uint8_t*)authLength->getName());
+    zrtpCommit.setPubKeyType((uint8_t*)pubKey->getName());
+    zrtpCommit.setSasType((uint8_t*)sasType->getName());
+    zrtpCommit.setHvi(hvi);
+    zrtpCommit.setH2(H2);
+
+    len = zrtpCommit.getLength() * ZRTP_WORD_SIZE;
+
+    // Compute HMAC over Commit, excluding the HMAC field (HMAC_SIZE)
+    // and store in Hello. Key to HMAC is H1, use HASH_IMAGE_SIZE bytes only.
+    // Must use implicit HMAC functions.
+    hmacFunctionImpl(H1, HASH_IMAGE_SIZE, (uint8_t*)zrtpCommit.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
+    zrtpCommit.setHMAC(hmac);
+
+    // hash first messages to produce overall message hash
+    // First the Responder's Hello message, second the Commit (always Initator's).
+    // Must use negotiated hash.
+    int32_t helloLen = hello->getLength() * ZRTP_WORD_SIZE;
+    msgShaContext = createHashCtx();
+    hashCtxFunction(msgShaContext, (unsigned char*)hello->getHeaderBase(), helloLen);
+    hashCtxFunction(msgShaContext, (unsigned char*)zrtpCommit.getHeaderBase(), len);
+
+    // store Hello data temporarily until we can check HMAC after receiving Commit as
+    // Responder or DHPart1 as Initiator
+    storeMsgTemp(hello);
+
+    // calculate hash over the received Hello packet - is peer's hello hash.
+    // Use implicit hash algorithm
+    hashFunctionImpl((unsigned char*)hello->getHeaderBase(), helloLen, peerHelloHash);
+    memcpy(peerHelloVersion, hello->getVersion(), ZRTP_WORD_SIZE);
+    peerHelloVersion[ZRTP_WORD_SIZE] = 0;
+
+    return &zrtpCommit;
+}
+
+ZrtpPacketCommit* ZRtp::prepareCommitMultiStream(ZrtpPacketHello *hello) {
+
+    randomZRTP(hvi, ZRTP_WORD_SIZE*4);  // This is the Multi-Stream NONCE size
+
+    zrtpCommit.setZid(zid);
+    zrtpCommit.setHashType((uint8_t*)hash->getName());
+    zrtpCommit.setCipherType((uint8_t*)cipher->getName());
+    zrtpCommit.setAuthLen((uint8_t*)authLength->getName());
+    zrtpCommit.setPubKeyType((uint8_t*)"Mult");  // this is fixed because of Multi Stream mode
+    zrtpCommit.setSasType((uint8_t*)sasType->getName());
+    zrtpCommit.setNonce(hvi);
+    zrtpCommit.setH2(H2);
+
+    int32_t len = zrtpCommit.getLength() * ZRTP_WORD_SIZE;
+
+    // Compute HMAC over Commit, excluding the HMAC field (HMAC_SIZE)
+    // and store in Hello. Key to HMAC is H1, use HASH_IMAGE_SIZE bytes only.
+    // Must use the implicit HMAC function.
+    uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+    hmacFunctionImpl(H1, HASH_IMAGE_SIZE, (uint8_t*)zrtpCommit.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
+    zrtpCommit.setHMACMulti(hmac);
+
+
+    // hash first messages to produce overall message hash
+    // First the Responder's Hello message, second the Commit
+    // (always Initator's).
+    // Must use the negotiated hash.
+    msgShaContext = createHashCtx();
+
+    int32_t helloLen = hello->getLength() * ZRTP_WORD_SIZE;
+    hashCtxFunction(msgShaContext, (unsigned char*)hello->getHeaderBase(), helloLen);
+    hashCtxFunction(msgShaContext, (unsigned char*)zrtpCommit.getHeaderBase(), len);
+
+    // store Hello data temporarily until we can check HMAC after receiving Commit as
+    // Responder or DHPart1 as Initiator
+    storeMsgTemp(hello);
+
+    // calculate hash over the received Hello packet - is peer's hello hash.
+    // Use implicit hash algorithm
+    hashFunctionImpl((unsigned char*)hello->getHeaderBase(), helloLen, peerHelloHash);
+    memcpy(peerHelloVersion, hello->getVersion(), ZRTP_WORD_SIZE);
+    peerHelloVersion[ZRTP_WORD_SIZE] = 0;
+
+    return &zrtpCommit;
+}
+
+/*
+ * At this point we will take the role of the Responder. We may have been in
+ * the role of the Initiator before and already sent a commit packet that
+ * clashed with a commit packet from our peer. If our HVI was lower than our
+ * peer's HVI then we switched to Responder and handle our peer's commit packet
+ * here. This method takes care to delete and refresh data left over from a
+ * possible Initiator preparation. This belongs to prepared DH data, message
+ * hash SHA context
+ */
+ZrtpPacketDHPart* ZRtp::prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMsg) {
+
+    sendInfo(Info, InfoRespCommitReceived);
+
+    // The following code check the hash chain according chapter 10 to detect
+    // false ZRTP packets.
+    // Must use the implicit hash function.
+    uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH];
+    memcpy(peerH2, commit->getH2(), HASH_IMAGE_SIZE);
+    hashFunctionImpl(peerH2, HASH_IMAGE_SIZE, tmpH3);
+
+    if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) {
+        *errMsg = IgnorePacket;
+        return NULL;
+    }
+
+    // Check HMAC of previous Hello packet stored in temporary buffer. The
+    // HMAC key of peer's Hello packet is peer's H2 that is contained in the
+    // Commit packet. Refer to chapter 9.1.
+    if (!checkMsgHmac(peerH2)) {
+        sendInfo(Severe, SevereHelloHMACFailed);
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+
+    // check if we support the commited Cipher type
+    AlgorithmEnum* cp = &zrtpSymCiphers.getByName((const char*)commit->getCipherType());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppCiphertype;
+        return NULL;
+    }
+    cipher = cp;
+
+    // check if we support the commited Authentication length
+    cp = &zrtpAuthLengths.getByName((const char*)commit->getAuthLen());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppSRTPAuthTag;
+        return NULL;
+    }
+    authLength = cp;
+
+    // check if we support the commited hash type
+    cp = &zrtpHashes.getByName((const char*)commit->getHashType());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppHashType;
+        return NULL;
+    }
+    // check if the peer's commited hash is the same that we used when
+    // preparing our commit packet. If not do the necessary resets and
+    // recompute some data.
+    if (*(int32_t*)(hash->getName()) != *(int32_t*)(cp->getName())) {
+        hash = cp;
+        setNegotiatedHash(hash);
+
+        ZIDRecord zidRec(peerZid);
+        ZIDFile *zidFile = ZIDFile::getInstance();
+        zidFile->getRecord(&zidRec);
+
+        // Compute the Initator's and Responder's retained secret ids
+        // with the committed hash.
+        computeSharedSecretSet(zidRec);
+    }
+
+    // check if we support the commited pub key type
+    cp = &zrtpPubKeys.getByName((const char*)commit->getPubKeysType());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppPKExchange;
+        return NULL;
+    }
+    pubKey = cp;
+
+    // check if we support the commited SAS type
+    cp = &zrtpSasTypes.getByName((const char*)commit->getSasType());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppSASScheme;
+        return NULL;
+    }
+    sasType = cp;
+
+    // dhContext cannot be NULL - always setup during prepareCommit()
+    // check if we can use the dhContext prepared by prepareCOmmit(),
+    // if not delete old DH context and generate new one
+    // The algorithm names are 4 chars only, thus we can cast to int32_t
+    if (*(int32_t*)(dhContext->getDHtype()) != *(int32_t*)(pubKey->getName())) {
+        delete dhContext;
+        dhContext = new ZrtpDH(pubKey->getName());
+        dhContext->generatePublicKey();
+    }
+    sendInfo(Info, InfoDH1DHGenerated);
+
+    dhContext->getPubKeyBytes(pubKeyBytes);
+
+    // Setup a DHPart1 packet.
+    zrtpDH1.setPubKeyType(pubKey->getName());
+    zrtpDH1.setMessageType((uint8_t*)DHPart1Msg);
+    zrtpDH1.setRs1Id(rs1IDr);
+    zrtpDH1.setRs2Id(rs2IDr);
+    zrtpDH1.setAuxSecretId(auxSecretIDr);
+    zrtpDH1.setPbxSecretId(pbxSecretIDr);
+    zrtpDH1.setPv(pubKeyBytes);
+    zrtpDH1.setH1(H1);
+
+    int32_t len = zrtpDH1.getLength() * ZRTP_WORD_SIZE;
+
+    // Compute HMAC over DHPart1, excluding the HMAC field (HMAC_SIZE)
+    // and store in DHPart1.
+    // Use implicit Hash function
+    uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+    hmacFunctionImpl(H0, HASH_IMAGE_SIZE, (uint8_t*)zrtpDH1.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
+    zrtpDH1.setHMAC(hmac);
+
+    // We are definitly responder. Save the peer's hvi for later compare.
+    myRole = Responder;
+    memcpy(peerHvi, commit->getHvi(), HVI_SIZE);
+
+    // We are responder. Release a possibly pre-computed SHA context
+    // because this was prepared for Initiator. Then create a new one.
+    if (msgShaContext != NULL) {
+        closeHashCtx(msgShaContext, NULL);
+    }
+    msgShaContext = createHashCtx();
+
+    // Hash messages to produce overall message hash:
+    // First the Responder's (my) Hello message, second the Commit
+    // (always Initator's), then the DH1 message (which is always a
+    // Responder's message).
+    // Must use negotiated hash
+    hashCtxFunction(msgShaContext, (unsigned char*)zrtpHello.getHeaderBase(), zrtpHello.getLength() * ZRTP_WORD_SIZE);
+    hashCtxFunction(msgShaContext, (unsigned char*)commit->getHeaderBase(), commit->getLength() * ZRTP_WORD_SIZE);
+    hashCtxFunction(msgShaContext, (unsigned char*)zrtpDH1.getHeaderBase(), zrtpDH1.getLength() * ZRTP_WORD_SIZE);
+
+    // store Commit data temporarily until we can check HMAC after we got DHPart2
+    storeMsgTemp(commit);
+
+    return &zrtpDH1;
+}
+
+/*
+ * At this point we will take the role of the Initiator.
+ */
+ZrtpPacketDHPart* ZRtp::prepareDHPart2(ZrtpPacketDHPart *dhPart1, uint32_t* errMsg) {
+
+    uint8_t* pvr;
+
+    sendInfo(Info, InfoInitDH1Received);
+
+    // Because we are initiator the protocol engine didn't receive Commit
+    // thus could not store a peer's H2. A two step SHA256 is required to
+    // re-compute H3. Then compare with peer's H3 from peer's Hello packet.
+    // Must use implicit hash function.
+    uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
+    hashFunctionImpl(dhPart1->getH1(), HASH_IMAGE_SIZE, tmpHash); // Compute peer's H2
+    memcpy(peerH2, tmpHash, HASH_IMAGE_SIZE);
+    hashFunctionImpl(peerH2, HASH_IMAGE_SIZE, tmpHash);          // Compute peer's H3 (tmpHash)
+
+    if (memcmp(tmpHash, peerH3, HASH_IMAGE_SIZE) != 0) {
+        *errMsg = IgnorePacket;
+        return NULL;
+    }
+
+    // Check HMAC of previous Hello packet stored in temporary buffer. The
+    // HMAC key of the Hello packet is peer's H2 that was computed above.
+    // Refer to chapter 9.1 and chapter 10.
+    if (!checkMsgHmac(peerH2)) {
+        sendInfo(Severe, SevereHelloHMACFailed);
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+
+    // get memory to store DH result TODO: make it fixed memory
+    DHss = new uint8_t[dhContext->getDhSize()];
+    if (DHss == NULL) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+
+    // get and check Responder's public value, see chap. 5.4.3 in the spec
+    pvr = dhPart1->getPv();
+    if (!dhContext->checkPubKey(pvr)) {
+        *errMsg = DHErrorWrongPV;
+        return NULL;
+    }
+    dhContext->computeSecretKey(pvr, DHss);
+
+    myRole = Initiator;
+
+    // We are Initiator: the Responder's Hello and the Initiator's (our) Commit
+    // are already hashed in the context. Now hash the Responder's DH1 and then
+    // the Initiator's (our) DH2 in that order.
+    // Use the negotiated hash function.
+    hashCtxFunction(msgShaContext, (unsigned char*)dhPart1->getHeaderBase(), dhPart1->getLength() * ZRTP_WORD_SIZE);
+    hashCtxFunction(msgShaContext, (unsigned char*)zrtpDH2.getHeaderBase(), zrtpDH2.getLength() * ZRTP_WORD_SIZE);
+
+    // Compute the message Hash
+    closeHashCtx(msgShaContext, messageHash);
+    msgShaContext = NULL;
+
+    // To compute the keys for the Initiator we need the retained secrets of our
+    // peer. Get them from the storage.
+    ZIDRecord zidRec(peerZid);
+    ZIDFile *zid = ZIDFile::getInstance();
+    zid->getRecord(&zidRec);
+
+    // Now compute the S0, all dependend keys and the new RS1. The function
+    // also performs sign SAS callback if it's active.
+    generateKeysInitiator(dhPart1, zidRec);
+    zid->saveRecord(&zidRec);
+
+    delete dhContext;
+    dhContext = NULL;
+
+    // TODO: at initiator we can call signSAS at this point, don't dealy until confirm1 reveived
+    // store DHPart1 data temporarily until we can check HMAC after receiving Confirm1
+    storeMsgTemp(dhPart1);
+    return &zrtpDH2;
+}
+
+/*
+ * At this point we are Responder.
+ */
+ZrtpPacketConfirm* ZRtp::prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* errMsg) {
+
+    uint8_t* pvi;
+
+    sendInfo(Info, InfoRespDH2Received);
+
+    // Because we are responder we received a Commit and stored its H2.
+    // Now re-compute H2 from received H1 and compare with stored peer's H2.
+    // Use implicit hash function
+    uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
+    hashFunctionImpl(dhPart2->getH1(), HASH_IMAGE_SIZE, tmpHash);
+    if (memcmp(tmpHash, peerH2, HASH_IMAGE_SIZE) != 0) {
+        *errMsg = IgnorePacket;
+        return NULL;
+    }
+
+    // Check HMAC of Commit packet stored in temporary buffer. The
+    // HMAC key of the Commit packet is peer's H1 that is contained in
+    // DHPart2. Refer to chapter 9.1 and chapter 10.
+    if (!checkMsgHmac(dhPart2->getH1())) {
+        sendInfo(Severe, SevereCommitHMACFailed);
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+    // Now we have the peer's pvi. Because we are responder re-compute my hvi
+    // using my Hello packet and the Initiator's DHPart2 and compare with
+    // hvi sent in commit packet. If it doesn't macht then a MitM attack
+    // may have occured.
+    computeHvi(dhPart2, &zrtpHello);
+    if (memcmp(hvi, peerHvi, HVI_SIZE) != 0) {
+        *errMsg = DHErrorWrongHVI;
+        return NULL;
+    }
+    DHss = new uint8_t[dhContext->getDhSize()];
+    if (DHss == NULL) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+    // Get and check the Initiator's public value, see chap. 5.4.2 of the spec
+    pvi = dhPart2->getPv();
+    if (!dhContext->checkPubKey(pvi)) {
+        *errMsg = DHErrorWrongPV;
+        return NULL;
+    }
+    dhContext->computeSecretKey(pvi, DHss);
+    // Hash the Initiator's DH2 into the message Hash (other messages already
+    // prepared, see method prepareDHPart1().
+    // Use neotiated hash function
+    hashCtxFunction(msgShaContext, (unsigned char*)dhPart2->getHeaderBase(), dhPart2->getLength() * ZRTP_WORD_SIZE);
+
+    closeHashCtx(msgShaContext, messageHash);
+    msgShaContext = NULL;
+
+    // To compute the Keys for the Initiator we need the retained secrets of our
+    // peer. Get them from the storage.
+    ZIDRecord zidRec(peerZid);
+    ZIDFile *zid = ZIDFile::getInstance();
+    zid->getRecord(&zidRec);
+
+    /*
+     * The expected shared secret Ids were already computed when we built the
+     * DHPart1 packet. Generate s0, all depended keys, and the new RS1 value
+     * for the ZID record. The functions also performs sign SAS callback if it's active.
+     */
+    generateKeysResponder(dhPart2, zidRec);
+    zid->saveRecord(&zidRec);
+
+    delete dhContext;
+    dhContext = NULL;
+
+    // Fill in Confirm1 packet.
+    zrtpConfirm1.setMessageType((uint8_t*)Confirm1Msg);
+
+    // Check if user verfied the SAS in a previous call and thus verfied
+    // the retained secret. Don't set the verified flag if paranoidMode is true.
+    if (zidRec.isSasVerified() && !paranoidMode) {
+        zrtpConfirm1.setSASFlag();
+    }
+    zrtpConfirm1.setExpTime(0xFFFFFFFF);
+    zrtpConfirm1.setIv(randomIV);
+    zrtpConfirm1.setHashH0(H0);
+
+    // if this run at PBX user agent enrollment service then set flag in confirm
+    // packet and store the MitM key
+    if (enrollmentMode) {
+        computePBXSecret();
+        zrtpConfirm1.setPBXEnrollment();
+        writeEnrollmentPBX();
+    }
+    uint8_t confMac[MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+
+    // Encrypt and HMAC with Responder's key - we are Respondere here
+    int hmlen = (zrtpConfirm1.getLength() - 9) * ZRTP_WORD_SIZE;
+    cipher->getEncrypt()(zrtpKeyR, cipher->getKeylen(), randomIV, zrtpConfirm1.getHashH0(), hmlen);
+    hmacFunction(hmacKeyR, hashLength, (unsigned char*)zrtpConfirm1.getHashH0(), hmlen, confMac, &macLen);
+
+    zrtpConfirm1.setHmac(confMac);
+
+    // store DHPart2 data temporarily until we can check HMAC after receiving Confirm2
+    storeMsgTemp(dhPart2);
+    return &zrtpConfirm1;
+}
+
+/*
+ * At this point we are Responder.
+ */
+ZrtpPacketConfirm* ZRtp::prepareConfirm1MultiStream(ZrtpPacketCommit* commit, uint32_t* errMsg) {
+
+    sendInfo(Info, InfoRespCommitReceived);
+
+    // The following code checks the hash chain according chapter 10 to detect
+    // false ZRTP packets.
+    // Use implicit hash function
+    uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH];
+    memcpy(peerH2, commit->getH2(), HASH_IMAGE_SIZE);
+    hashFunctionImpl(peerH2, HASH_IMAGE_SIZE, tmpH3);
+
+    if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) {
+        *errMsg = IgnorePacket;
+        return NULL;
+    }
+
+    // Check HMAC of previous Hello packet stored in temporary buffer. The
+    // HMAC key of peer's Hello packet is peer's H2 that is contained in the
+    // Commit packet. Refer to chapter 9.1.
+    if (!checkMsgHmac(peerH2)) {
+        sendInfo(Severe, SevereHelloHMACFailed);
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+
+    // check if Commit contains "Mult" as pub key type
+    AlgorithmEnum* cp = &zrtpPubKeys.getByName((const char*)commit->getPubKeysType());
+    if (!cp->isValid() || *(int32_t*)(cp->getName()) != *(int32_t*)mult) {
+        *errMsg = UnsuppPKExchange;
+        return NULL;
+    }
+
+    // check if we support the commited cipher
+    cp = &zrtpSymCiphers.getByName((const char*)commit->getCipherType());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppCiphertype;
+        return NULL;
+    }
+    cipher = cp;
+
+    // check if we support the commited Authentication length
+    cp = &zrtpAuthLengths.getByName((const char*)commit->getAuthLen());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppSRTPAuthTag;
+        return NULL;
+    }
+    authLength = cp;
+
+    // check if we support the commited hash type
+    cp = &zrtpHashes.getByName((const char*)commit->getHashType());
+    if (!cp->isValid()) { // no match - something went wrong
+        *errMsg = UnsuppHashType;
+        return NULL;
+    }
+    // check if the peer's commited hash is the same that we used when
+    // preparing our commit packet. If not do the necessary resets and
+    // recompute some data.
+    if (*(int32_t*)(hash->getName()) != *(int32_t*)(cp->getName())) {
+        hash = cp;
+        setNegotiatedHash(hash);
+    }
+    myRole = Responder;
+
+    // We are responder. Release a possibly pre-computed SHA256 context
+    // because this was prepared for Initiator. Then create a new one.
+    if (msgShaContext != NULL) {
+        closeHashCtx(msgShaContext, NULL);
+    }
+    msgShaContext = createHashCtx();
+
+    // Hash messages to produce overall message hash:
+    // First the Responder's (my) Hello message, second the Commit
+    // (always Initator's)
+    // use negotiated hash
+    hashCtxFunction(msgShaContext, (unsigned char*)zrtpHello.getHeaderBase(), zrtpHello.getLength() * ZRTP_WORD_SIZE);
+    hashCtxFunction(msgShaContext, (unsigned char*)commit->getHeaderBase(), commit->getLength() * ZRTP_WORD_SIZE);
+
+    closeHashCtx(msgShaContext, messageHash);
+    msgShaContext = NULL;
+
+    generateKeysMultiStream();
+
+    // Fill in Confirm1 packet.
+    zrtpConfirm1.setMessageType((uint8_t*)Confirm1Msg);
+    zrtpConfirm1.setExpTime(0xFFFFFFFF);
+    zrtpConfirm1.setIv(randomIV);
+    zrtpConfirm1.setHashH0(H0);
+
+    uint8_t confMac[MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+
+    // Encrypt and HMAC with Responder's key - we are Respondere here
+    int32_t hmlen = (zrtpConfirm1.getLength() - 9) * ZRTP_WORD_SIZE;
+    cipher->getEncrypt()(zrtpKeyR, cipher->getKeylen(), randomIV, zrtpConfirm1.getHashH0(), hmlen);
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hmacKeyR, hashLength, (unsigned char*)zrtpConfirm1.getHashH0(), hmlen, confMac, &macLen);
+
+    zrtpConfirm1.setHmac(confMac);
+
+    // Store Commit data temporarily until we can check HMAC after receiving Confirm2
+    storeMsgTemp(commit);
+    return &zrtpConfirm1;
+}
+
+/*
+ * At this point we are Initiator.
+ */
+ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* errMsg) {
+
+    sendInfo(Info, InfoInitConf1Received);
+
+    uint8_t confMac[MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+
+    // Use the Responder's keys here because we are Initiator here and
+    // receive packets from Responder
+    int16_t hmlen = (confirm1->getLength() - 9) * ZRTP_WORD_SIZE;
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hmacKeyR, hashLength, (unsigned char*)confirm1->getHashH0(), hmlen, confMac, &macLen);
+
+    if (memcmp(confMac, confirm1->getHmac(), HMAC_SIZE) != 0) {
+        *errMsg = ConfirmHMACWrong;
+        return NULL;
+    }
+    cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), confirm1->getIv(), confirm1->getHashH0(), hmlen);
+
+    std::string cs(cipher->getReadable());
+    cs.append("/").append(pubKey->getName());
+
+    // Check HMAC of DHPart1 packet stored in temporary buffer. The
+    // HMAC key of the DHPart1 packet is peer's H0 that is contained in
+    // Confirm1. Refer to chapter 9.
+    if (!checkMsgHmac(confirm1->getHashH0())) {
+        sendInfo(Severe, SevereDH1HMACFailed);
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+    signatureLength = confirm1->getSignatureLength();
+    if (signSasSeen && signatureLength > 0) {
+        signatureData = confirm1->getSignatureData();
+        callback->checkSASSignature(sasHash);
+        // TODO: error handling if checkSASSignature returns false.
+    }
+    /*
+     * The Confirm1 is ok, handle the Retained secret stuff and inform
+     * GUI about state.
+     */
+    bool sasFlag = confirm1->isSASFlag();
+
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+
+    ZIDFile *zid = ZIDFile::getInstance();
+    zid->getRecord(&zidRec);
+
+    // Our peer did not confirm the SAS in last session, thus reset
+    // our SAS flag too. Reset the flag also if paranoidMode is true.
+    if (!sasFlag || paranoidMode) {
+        zidRec.resetSasVerified();
+    }
+    // get verified flag from current RS1 before set a new RS1. This
+    // may not be set even if peer's flag is set in confirm1 message.
+    sasFlag = zidRec.isSasVerified();
+
+    callback->srtpSecretsOn(cs, SAS, sasFlag);
+
+    // now we are ready to save the new RS1 which inherits the verified
+    // flag from old RS1
+    zidRec.setNewRs1((const uint8_t*)newRs1);
+    zid->saveRecord(&zidRec);
+
+    // now generate my Confirm2 message
+    zrtpConfirm2.setMessageType((uint8_t*)Confirm2Msg);
+    zrtpConfirm2.setHashH0(H0);
+
+    if (sasFlag) {
+        zrtpConfirm2.setSASFlag();
+    }
+    zrtpConfirm2.setExpTime(0xFFFFFFFF);
+    zrtpConfirm2.setIv(randomIV);
+
+    // Compute PBX secret if we are in enrollemnt mode (PBX user agent)
+    // or enrollment was enabled at normal user agent and flag in confirm packet
+    if (enrollmentMode || (enableMitmEnrollment && confirm1->isPBXEnrollment())) {
+        computePBXSecret();
+
+        // if this runs at PBX user agent enrollment service then set flag in confirm
+        // packet and store the MitM key. The PBX user agent service always stores
+        // its MitM key.
+        if (enrollmentMode) {
+            zrtpConfirm2.setPBXEnrollment();
+            writeEnrollmentPBX();
+        }
+    }
+    // Encrypt and HMAC with Initiator's key - we are Initiator here
+    hmlen = (zrtpConfirm2.getLength() - 9) * ZRTP_WORD_SIZE;
+    cipher->getEncrypt()(zrtpKeyI, cipher->getKeylen(), randomIV, zrtpConfirm2.getHashH0(), hmlen);
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hmacKeyI, hashLength, (unsigned char*)zrtpConfirm2.getHashH0(), hmlen, confMac, &macLen);
+
+    zrtpConfirm2.setHmac(confMac);
+
+    // Ask for enrollment only if enabled via configuration and the
+    // confirm1 packet contains the enrollment flag. The enrolling user
+    // agent stores the MitM key only if the user accepts the enrollment
+    // request.
+    if (enableMitmEnrollment && confirm1->isPBXEnrollment()) {
+        callback->zrtpAskEnrollment(EnrollmentRequest);
+    }
+    return &zrtpConfirm2;
+}
+
+/**
+ * Save the computed MitM secret to the ZID record of the peer
+ */
+void ZRtp::writeEnrollmentPBX() {
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+
+    ZIDFile *zid = ZIDFile::getInstance();
+    zid->getRecord(&zidRec);
+
+    if (pbxSecretTmp != NULL) {
+        zidRec.setMiTMData(pbxSecretTmp);
+    }
+    zid->saveRecord(&zidRec);
+}
+
+/*
+ * At this point we are Initiator.
+ */
+ZrtpPacketConfirm* ZRtp::prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, uint32_t* errMsg) {
+
+    // check Confirm1 packet using the keys
+    // prepare Confirm2 packet
+    // don't update SAS, RS
+    sendInfo(Info, InfoInitConf1Received);
+
+    uint8_t confMac[MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+
+    closeHashCtx(msgShaContext, messageHash);
+    msgShaContext = NULL;
+    myRole = Initiator;
+
+    generateKeysMultiStream();
+
+    // Use the Responder's keys here because we are Initiator here and
+    // receive packets from Responder
+    int32_t hmlen = (confirm1->getLength() - 9) * ZRTP_WORD_SIZE;
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hmacKeyR, hashLength, (unsigned char*)confirm1->getHashH0(), hmlen, confMac, &macLen);
+
+    if (memcmp(confMac, confirm1->getHmac(), HMAC_SIZE) != 0) {
+        *errMsg = ConfirmHMACWrong;
+        return NULL;
+    }
+    cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), confirm1->getIv(), confirm1->getHashH0(), hmlen);
+    std::string cs(cipher->getReadable());
+
+    // Because we are initiator the protocol engine didn't receive Commit and
+    // because we are using multi-stream mode here we also did not receive a DHPart1 and
+    // thus could not store a responder's H2 or H1. A two step hash is required to
+    // re-compute H1, H2.
+    // USe implicit hash function.
+    uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
+    hashFunctionImpl(confirm1->getHashH0(), HASH_IMAGE_SIZE, tmpHash); // Compute peer's H1 in tmpHash
+    hashFunctionImpl(tmpHash, HASH_IMAGE_SIZE, tmpHash);               // Compute peer's H2 in tmpHash
+    memcpy(peerH2, tmpHash, HASH_IMAGE_SIZE);                          // copy and truncate to peerH2
+
+    // Check HMAC of previous Hello packet stored in temporary buffer. The
+    // HMAC key of the Hello packet is peer's H2 that was computed above.
+    // Refer to chapter 9.1 and chapter 10.
+    if (!checkMsgHmac(peerH2)) {
+        sendInfo(Severe, SevereHelloHMACFailed);
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+    // TODO: here we have a SAS signature from reponder, call checkSASsignature (save / compare in case of resend)
+
+    // Inform GUI about security state, don't show SAS and its state
+    std::string cs1("");
+    callback->srtpSecretsOn(cs, cs1, true);
+
+    // now generate my Confirm2 message
+    zrtpConfirm2.setMessageType((uint8_t*)Confirm2Msg);
+    zrtpConfirm2.setHashH0(H0);
+    zrtpConfirm2.setExpTime(0xFFFFFFFF);
+    zrtpConfirm2.setIv(randomIV);
+
+    // Encrypt and HMAC with Initiator's key - we are Initiator here
+    hmlen = (zrtpConfirm2.getLength() - 9) * ZRTP_WORD_SIZE;
+    cipher->getEncrypt()(zrtpKeyI, cipher->getKeylen(), randomIV, zrtpConfirm2.getHashH0(), hmlen);
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hmacKeyI, hashLength, (unsigned char*)zrtpConfirm2.getHashH0(), hmlen, confMac, &macLen);
+
+    zrtpConfirm2.setHmac(confMac);
+    return &zrtpConfirm2;
+}
+
+/*
+ * At this point we are Responder.
+ */
+ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* errMsg) {
+
+    sendInfo(Info, InfoRespConf2Received);
+
+    uint8_t confMac[MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+
+    // Use the Initiator's keys here because we are Responder here and
+    // reveice packets from Initiator
+    int16_t hmlen = (confirm2->getLength() - 9) * ZRTP_WORD_SIZE;
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hmacKeyI, hashLength,
+                 (unsigned char*)confirm2->getHashH0(),
+                 hmlen, confMac, &macLen);
+
+    if (memcmp(confMac, confirm2->getHmac(), HMAC_SIZE) != 0) {
+        *errMsg = ConfirmHMACWrong;
+        return NULL;
+    }
+    cipher->getDecrypt()(zrtpKeyI, cipher->getKeylen(), confirm2->getIv(), confirm2->getHashH0(), hmlen);
+
+    std::string cs(cipher->getReadable());
+
+    if (!multiStream) {
+        // Check HMAC of DHPart2 packet stored in temporary buffer. The
+        // HMAC key of the DHPart2 packet is peer's H0 that is contained in
+        // Confirm2. Refer to chapter 9.1 and chapter 10.
+        if (!checkMsgHmac(confirm2->getHashH0())) {
+            sendInfo(Severe, SevereDH2HMACFailed);
+            *errMsg = CriticalSWError;
+            return NULL;
+        }
+        signatureLength = confirm2->getSignatureLength();
+        if (signSasSeen && signatureLength > 0) {
+            signatureData = confirm2->getSignatureData();
+            callback->checkSASSignature(sasHash);
+            // TODO: error handling if checkSASSignature returns false.
+        }
+        /*
+        * The Confirm2 is ok, handle the Retained secret stuff and inform
+        * GUI about state.
+        */
+        bool sasFlag = confirm2->isSASFlag();
+
+        // Initialize a ZID record to get peer's retained secrets
+        ZIDRecord zidRec(peerZid);
+
+        ZIDFile *zid = ZIDFile::getInstance();
+        zid->getRecord(&zidRec);
+
+        // Our peer did not confirm the SAS in last session, thus reset
+        // our SAS flag too. Reset the flag also if paranoidMode is true.
+        if (!sasFlag || paranoidMode) {
+            zidRec.resetSasVerified();
+        }
+
+        // Now get the resulting SAS verified flag from current RS1 before setting a new RS1.
+        // It's a combination of our SAS verfied flag and peer's verified flag. Only if both
+        // were set (true) then sasFlag becomes true.
+        sasFlag = zidRec.isSasVerified();
+        cs.append("/").append(pubKey->getName());
+        callback->srtpSecretsOn(cs, SAS, sasFlag);
+
+        // save new RS1, this inherits the verified flag from old RS1
+        zidRec.setNewRs1((const uint8_t*)newRs1);
+        zid->saveRecord(&zidRec);
+
+        // Ask for enrollment only if enabled via configuration and the
+        // confirm packet contains the enrollment flag. The enrolling user
+        // agent stores the MitM key only if the user accepts the enrollment
+        // request.
+        if (enableMitmEnrollment && confirm2->isPBXEnrollment()) {
+            computePBXSecret();
+            callback->zrtpAskEnrollment(EnrollmentRequest);
+        }
+    }
+    else {
+        // Check HMAC of Commit packet stored in temporary buffer. The
+        // HMAC key of the Commit packet is initiator's H1
+        // use implicit hash function.
+        uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
+        hashFunctionImpl(confirm2->getHashH0(), HASH_IMAGE_SIZE, tmpHash); // Compute initiator's H1 in tmpHash
+
+        if (!checkMsgHmac(tmpHash)) {
+            sendInfo(Severe, SevereCommitHMACFailed);
+            *errMsg = CriticalSWError;
+            return NULL;
+        }
+        std::string cs1("");
+
+        // Inform GUI about security state, don't show SAS and its state
+        callback->srtpSecretsOn(cs, cs1, true);
+    }
+    return &zrtpConf2Ack;
+}
+
+ZrtpPacketErrorAck* ZRtp::prepareErrorAck(ZrtpPacketError* epkt) {
+    sendInfo(ZrtpError, epkt->getErrorCode() * -1);
+    return &zrtpErrorAck;
+}
+
+ZrtpPacketError* ZRtp::prepareError(uint32_t errMsg) {
+    zrtpError.setErrorCode(errMsg);
+    return &zrtpError;
+}
+
+ZrtpPacketPingAck* ZRtp::preparePingAck(ZrtpPacketPing* ppkt) {
+    if (ppkt->getLength() != 6)                    // A PING packet must have a length of 6 words
+        return NULL; 
+    // Because we do not support ZRTP proxy mode use the truncated ZID.
+    // If this code shall be used in ZRTP proxy implementation the computation
+    // of the endpoint hash must be enhanced (see chaps 5.15ff and 5.16)
+    zrtpPingAck.setLocalEpHash(zid);
+    zrtpPingAck.setRemoteEpHash(ppkt->getEpHash());
+    zrtpPingAck.setSSRC(peerSSRC);
+    return &zrtpPingAck;
+}
+
+ZrtpPacketRelayAck* ZRtp::prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* errMsg) {
+    // handle and render SAS relay data only if the peer announced that it is a trusted
+    // PBX. Don't handle SAS relay in paranoidMode.
+    if (!mitmSeen || paranoidMode)
+        return &zrtpRelayAck;
+
+    uint8_t* hkey, *ekey;
+    // If we are responder then the PBX used it's Initiator keys
+    if (myRole == Responder) {
+        hkey = hmacKeyI;
+        ekey = zrtpKeyI;
+    }
+    else {
+        hkey = hmacKeyR;
+        ekey = zrtpKeyR;
+    }
+
+    uint8_t confMac[MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+
+    // Use the Initiator's keys here because we are Responder here and
+    // reveice packets from Initiator
+    int16_t hmlen = (srly->getLength() - 9) * ZRTP_WORD_SIZE;
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hkey, hashLength, (unsigned char*)srly->getFiller(), hmlen, confMac, &macLen);
+
+    if (memcmp(confMac, srly->getHmac(), HMAC_SIZE) != 0) {
+        *errMsg = ConfirmHMACWrong;
+        return NULL;                // TODO - check error handling
+    }
+    cipher->getDecrypt()(ekey, cipher->getKeylen(), srly->getIv(), (uint8_t*)srly->getFiller(), hmlen);
+
+    const uint8_t* render = srly->getSas();
+    const uint8_t* newSasHash = srly->getTrustedSas();
+
+    bool sasHashNull = true;
+    for (int i = 0; i < HASH_IMAGE_SIZE; i++) {
+        if (newSasHash[i] != 0) {
+            sasHashNull = false;
+            break;
+        }
+    }
+    // Check if new SAS is null or a trusted MitM relationship doesn't exist.
+    // If this is the case then don't render and don't show the new SAS - use
+    // the computed SAS hash but we may use a different SAS rendering algorithm to
+    // render the computed SAS.
+    if (sasHashNull || !peerIsEnrolled) {
+        newSasHash = sasHash;
+    }
+    // If other SAS schemes required - check here and use others
+    AlgorithmEnum* renderAlgo = &zrtpSasTypes.getByName((const char*)render);
+    uint8_t sasBytes[4];;
+    if (renderAlgo->isValid()) {
+        sasBytes[0] = newSasHash[0];
+        sasBytes[1] = newSasHash[1];
+        sasBytes[2] = newSasHash[2] & 0xf0;
+        sasBytes[3] = 0;
+    }
+    SAS = Base32(sasBytes, 20).getEncoded();
+    std::string cs(cipher->getReadable());
+    cs.append("/").append(pubKey->getName()).append("/MitM");
+
+    callback->srtpSecretsOn(cs, SAS, false);
+    return &zrtpRelayAck;
+}
+
+// TODO Implement GoClear handling
+ZrtpPacketClearAck* ZRtp::prepareClearAck(ZrtpPacketGoClear* gpkt) {
+    sendInfo(Warning, WarningGoClearReceived);
+    return &zrtpClearAck;
+}
+
+ZrtpPacketGoClear* ZRtp::prepareGoClear(uint32_t errMsg) {
+    ZrtpPacketGoClear* gclr = &zrtpGoClear;
+    gclr->clrClearHmac();
+    return gclr;
+}
+
+/*
+ * The next functions look up and return a prefered algorithm. These
+ * functions work as follows:
+ * - If the Hello packet does not contain an algorithm (number of algorithms
+*    is zero) then return the mandatory algorithm.
+ * - Build a list of algorithm names and ids from configuration data. If
+ *   the configuration data does not contain a mandatory algorithm append
+ *   the mandatory algorithm to the list and ids.
+ * - Build a list of algorithm names from the Hello message. If
+ *   the Hello message does not contain a mandatory algorithm append
+ *   the mandatory algorithm to the list.
+ * - Lookup a matching algorithm. The list built from Hello takes
+ *   precedence in the lookup (indexed by the outermost loop).
+ *
+ * This guarantees that we always return a supported alogrithm respecting
+ * the order of algorithms in the Hello message
+ *
+ * The mandatory algorithms are: (internal enums are our prefered algoritms)
+ * Hash:                S256 (SHA 256)             (internal enum Sha256)
+ * Symmetric Cipher:    AES1 (AES 128)             (internal enum Aes128)
+ * SRTP Authentication: HS32 and HS80 (32/80 bits) (internal enum AuthLen32)
+ * Key Agreement:       DH3k (3072 Diffie-Helman)  (internal enum Dh3072)
+ *
+ */
+AlgorithmEnum* ZRtp::findBestHash(ZrtpPacketHello *hello) {
+
+    int i;
+    int ii;
+    int numAlgosOffered;
+    AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1];
+
+    int numAlgosConf;
+    AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
+
+    bool mandatoryFound = false;
+
+    // If Hello does not contain any hash names return Sha256, its mandatory
+    int num = hello->getNumHashes();
+    if (num == 0) {
+        return &zrtpHashes.getByName(mandatoryHash);
+    }
+    // Build list of configured hash algorithm names, append mandatory algos
+    // if necessary.
+    numAlgosConf = configureAlgos.getNumConfiguredAlgos(HashAlgorithm);
+    for (i = 0; i < numAlgosConf; i++) {
+        algosConf[i] = &configureAlgos.getAlgoAt(HashAlgorithm, i);
+        if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryHash) {
+            mandatoryFound = true;
+        }
+    }
+    if (!mandatoryFound) {
+        algosConf[numAlgosConf++] = &zrtpHashes.getByName(mandatoryHash);
+    }
+
+    // Build list of offered known algos in Hello, append mandatory algos if necessary
+    mandatoryFound = false;
+    for (numAlgosOffered = 0, i = 0; i < num; i++) {
+        algosOffered[numAlgosOffered] = &zrtpHashes.getByName((const char*)hello->getHashType(i));
+        if (!algosOffered[numAlgosOffered]->isValid())
+            continue;
+        if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryHash) {
+            mandatoryFound = true;
+        }
+    }
+    if (!mandatoryFound) {
+        algosOffered[numAlgosOffered++] = &zrtpHashes.getByName(mandatoryHash);
+    }
+
+    // Lookup offered algos in configured algos. Because of appended
+    // mandatory algorithms at least one match will happen
+    for (i = 0; i < numAlgosOffered; i++) {
+        for (ii = 0; ii < numAlgosConf; ii++) {
+            if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
+                return algosConf[ii];
+            }
+        }
+    }
+    return &zrtpHashes.getByName(mandatoryHash);
+}
+
+AlgorithmEnum* ZRtp::findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk) {
+
+    int i;
+    int ii;
+    int numAlgosOffered;
+    AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1];
+
+    int numAlgosConf;
+    AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
+
+    bool mandatoryFound = false;
+
+    int num = hello->getNumCiphers();
+    if (num == 0 || (*(int32_t*)(pk->getName()) == *(int32_t*)dh2k)) {
+        return &zrtpSymCiphers.getByName(aes1);
+    }
+
+    // Build list of configured cipher algorithm names, append mandatory algos
+    // if necessary.
+    numAlgosConf = configureAlgos.getNumConfiguredAlgos(CipherAlgorithm);
+    for (i = 0; i < numAlgosConf; i++) {
+        algosConf[i] = &configureAlgos.getAlgoAt(CipherAlgorithm, i);
+        if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryCipher) {
+            mandatoryFound = true;
+        }
+    }
+    if (!mandatoryFound) {
+        algosConf[numAlgosConf++] = &zrtpSymCiphers.getByName(mandatoryCipher);
+    }
+
+    // Build list of offered known algos names in Hello, append mandatory algos if
+    // necessary
+    mandatoryFound = false;
+    for (numAlgosOffered = 0, i = 0; i < num; i++) {
+        algosOffered[numAlgosOffered] = &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
+        if (!algosOffered[numAlgosOffered]->isValid())
+            continue;
+        if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryCipher) {
+            mandatoryFound = true;
+        }
+    }
+
+    if (!mandatoryFound) {
+        algosOffered[numAlgosOffered++] = &zrtpSymCiphers.getByName(mandatoryCipher);
+    }
+
+    // Lookup offered algos in configured algos. Because of appended
+    // mandatory algorithms at least one match will happen
+    for (i = 0; i < numAlgosOffered; i++) {
+        for (ii = 0; ii < numAlgosConf; ii++) {
+            if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
+                return algosConf[ii];
+            }
+        }
+    }
+    return &zrtpSymCiphers.getByName(mandatoryCipher);
+}
+
+AlgorithmEnum* ZRtp::findBestPubkey(ZrtpPacketHello *hello) {
+
+    int i;
+    int ii;
+    int numAlgosOffered;
+    AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1];
+
+    int numAlgosConf;
+    AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
+
+    bool mandatoryFound = false;
+
+    int num = hello->getNumPubKeys();
+    if (num == 0) {
+        return &zrtpPubKeys.getByName(mandatoryPubKey);
+    }
+    // Build list of configured pubkey algorithm names, append mandatory algos
+    // if necessary.
+    // The list must include real public key algorithms only, so skip
+    // mult-stream mode, preshared and alike.
+    numAlgosConf = configureAlgos.getNumConfiguredAlgos(PubKeyAlgorithm);
+    for (i = 0, ii = 0; i < numAlgosConf; i++) {
+        algosConf[ii] = &configureAlgos.getAlgoAt(PubKeyAlgorithm, ii);
+        if (*(int32_t*)(algosConf[ii]->getName()) == *(int32_t*)mult) {
+            continue;                               // skip multi-stream mode
+        }
+        if (*(int32_t*)(algosConf[ii++]->getName()) == *(int32_t*)mandatoryPubKey) {
+            mandatoryFound = true;
+        }
+    }
+
+    numAlgosConf = ii;
+    if (!mandatoryFound) {
+        algosConf[numAlgosConf++] = &zrtpPubKeys.getByName(mandatoryPubKey);
+    }
+
+    // Build list of offered known algos in Hello, append mandatory algos if necessary
+    mandatoryFound = false;
+    for (numAlgosOffered = 0, i = 0; i < num; i++) {
+        algosOffered[numAlgosOffered] = &zrtpPubKeys.getByName((const char*)hello->getPubKeyType(i));
+        if (!algosOffered[numAlgosOffered]->isValid())
+            continue;
+        if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryPubKey) {
+            mandatoryFound = true;
+        }
+    }
+
+    if (!mandatoryFound) {
+        algosOffered[numAlgosOffered++] = &zrtpPubKeys.getByName(mandatoryPubKey);
+    }
+
+    // Lookup offered algos in configured algos. Because of appended
+    // mandatory algorithms at least one match will happen
+    for (i = 0; i < numAlgosOffered; i++) {
+        for (ii = 0; ii < numAlgosConf; ii++) {
+            if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
+                return algosConf[ii];
+            }
+        }
+    }
+    return &zrtpPubKeys.getByName(mandatoryPubKey);
+}
+
+AlgorithmEnum* ZRtp::findBestSASType(ZrtpPacketHello *hello) {
+
+    int  i;
+    int ii;
+    int numAlgosOffered;
+    AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1];
+
+    int numAlgosConf;
+    AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
+
+    bool mandatoryFound = false;
+
+    int num = hello->getNumSas();
+    if (num == 0) {
+        return &zrtpSasTypes.getByName(mandatorySasType);
+    }
+    // Buildlist of configured SAS algorithm names, append mandatory algos
+    // if necessary.
+    numAlgosConf = configureAlgos.getNumConfiguredAlgos(SasType);
+    for (i = 0; i < numAlgosConf; i++) {
+        algosConf[i] = &configureAlgos.getAlgoAt(SasType, i);
+        if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatorySasType) {
+            mandatoryFound = true;
+        }
+    }
+
+    if (!mandatoryFound) {
+        algosConf[numAlgosConf++] = &zrtpSasTypes.getByName(mandatorySasType);
+    }
+
+    // Build list of offered known algos in Hello, append mandatory algos if necessary
+    for (numAlgosOffered = 0, i = 0; i < num; i++) {
+        algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i));
+        if (!algosOffered[numAlgosOffered]->isValid())
+            continue;
+        if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatorySasType) {
+            mandatoryFound = true;
+        }
+    }
+
+    if (!mandatoryFound) {
+        algosOffered[numAlgosOffered++] = &zrtpSasTypes.getByName(mandatorySasType);
+    }
+
+    // Lookup offered algos in configured algos. Because of appended
+    // mandatory algorithms at least one match will happen
+    for (i = 0; i < numAlgosOffered; i++) {
+        for (ii = 0; ii < numAlgosConf; ii++) {
+            if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
+                return algosConf[ii];
+            }
+        }
+    }
+    return &zrtpSasTypes.getByName(mandatorySasType);
+}
+
+AlgorithmEnum* ZRtp::findBestAuthLen(ZrtpPacketHello *hello) {
+
+    int  i;
+    int ii;
+    int numAlgosOffered;
+    AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+2];
+
+    int numAlgosConf;
+    AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+2];
+
+    bool mandatoryFound_1 = false;
+    bool mandatoryFound_2 = false;
+
+    int num = hello->getNumAuth();
+    if (num == 0) {
+        return &zrtpAuthLengths.getByName(mandatoryAuthLen_1);
+    }
+
+    // Build list of configured SAS algorithm names, append mandatory algos
+    // if necessary.
+    numAlgosConf = configureAlgos.getNumConfiguredAlgos(AuthLength);
+    for (i = 0; i < numAlgosConf; i++) {
+        algosConf[i] = &configureAlgos.getAlgoAt(AuthLength, i);
+        if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryAuthLen_1) {
+            mandatoryFound_1 = true;
+        }
+        if (*(int32_t*)(algosConf[i]->getName()) == *(int32_t*)mandatoryAuthLen_2) {
+            mandatoryFound_2 = true;
+        }
+    }
+
+    if (!mandatoryFound_1) {
+        algosConf[numAlgosConf++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_1);
+    }
+
+    if (!mandatoryFound_2) {
+        algosConf[numAlgosConf++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_2);
+    }
+
+    // Build list of offered known algos in Hello, append mandatory algos if necessary
+    for (numAlgosOffered = 0, i = 0; i < num; i++) {
+        algosOffered[numAlgosOffered] = &zrtpAuthLengths.getByName((const char*)hello->getAuthLen(i));
+        if (!algosOffered[numAlgosOffered]->isValid())
+            continue;
+        if (*(int32_t*)(algosOffered[numAlgosOffered]->getName()) == *(int32_t*)mandatoryAuthLen_1) {
+            mandatoryFound_1 = true;
+        }
+        if (*(int32_t*)(algosOffered[numAlgosOffered++]->getName()) == *(int32_t*)mandatoryAuthLen_2) {
+            mandatoryFound_2 = true;
+        }
+    }
+    if (!mandatoryFound_1) {
+        algosOffered[numAlgosOffered++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_1);
+    }
+    if (!mandatoryFound_2) {
+        algosOffered[numAlgosOffered++] = &zrtpAuthLengths.getByName(mandatoryAuthLen_2);
+    }
+    // Lookup offered algos in configured algos. Because of appended
+    // mandatory algorithms at least one match will happen
+    for (i = 0; i < numAlgosOffered; i++) {
+        for (ii = 0; ii < numAlgosConf; ii++) {
+            if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
+                return algosConf[ii];
+            }
+        }
+    }
+    return &zrtpAuthLengths.getByName(mandatoryAuthLen_1);
+}
+
+bool ZRtp::checkMultiStream(ZrtpPacketHello *hello) {
+
+    int  i;
+    int num = hello->getNumPubKeys();
+
+    // Multi Stream mode is mandatory, thus if nothing is offered then it is supported :-)
+    if (num == 0) {
+        return true;
+    }
+    for (i = 0; i < num; i++) {
+        if (*(int32_t*)(hello->getPubKeyType(i)) == *(int32_t*)mult) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool ZRtp::verifyH2(ZrtpPacketCommit *commit) {
+    uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH];
+
+    sha256(commit->getH2(), HASH_IMAGE_SIZE, tmpH3);
+    if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) {
+        return false;
+    }
+    return true;
+}
+
+void ZRtp::computeHvi(ZrtpPacketDHPart* dh, ZrtpPacketHello *hello) {
+
+    unsigned char* data[3];
+    unsigned int length[3];
+    /*
+     * populate the vector to compute the HVI hash according to the
+     * ZRTP specification.
+     */
+    data[0] = (uint8_t*)dh->getHeaderBase();
+    length[0] = dh->getLength() * ZRTP_WORD_SIZE;
+
+    data[1] = (uint8_t*)hello->getHeaderBase();
+    length[1] = hello->getLength() * ZRTP_WORD_SIZE;
+
+    data[2] = NULL;            // terminate data chunks
+    hashListFunction(data, length, hvi);
+    return;
+}
+
+void ZRtp:: computeSharedSecretSet(ZIDRecord &zidRec) {
+
+    /*
+     * Compute the Initiator's and Reponder's retained shared secret Ids.
+     * Use negotiated HMAC.
+     */
+    uint8_t randBuf[RS_LENGTH];
+    uint32_t macLen;
+
+    if (!zidRec.isRs1Valid()) {
+        randomZRTP(randBuf, RS_LENGTH);
+        hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs1IDi, &macLen);
+        hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), rs1IDr, &macLen);
+    }
+    else {
+        rs1Valid = true;
+        hmacFunction((unsigned char*)zidRec.getRs1(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs1IDi, &macLen);
+        hmacFunction((unsigned char*)zidRec.getRs1(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs1IDr, &macLen);
+    }
+
+    if (!zidRec.isRs2Valid()) {
+        randomZRTP(randBuf, RS_LENGTH);
+        hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs2IDi, &macLen);
+        hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), rs2IDr, &macLen);
+    }
+    else {
+        rs2Valid = true;
+        hmacFunction((unsigned char*)zidRec.getRs2(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs2IDi, &macLen);
+        hmacFunction((unsigned char*)zidRec.getRs2(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs2IDr, &macLen);
+    }
+
+    /*
+    * For the time being we don't support this types of shared secrect. Could be
+    * easily done: somebody sets some data into our ZRtp object, check it here
+    * and use it. Otherwise use the random data.
+    */
+    randomZRTP(randBuf, RS_LENGTH);
+    hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), auxSecretIDi, &macLen);
+    hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), auxSecretIDr, &macLen);
+
+    if (!zidRec.isMITMKeyAvailable()) {
+        randomZRTP(randBuf, RS_LENGTH);
+        hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), pbxSecretIDi, &macLen);
+        hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen);
+    }
+    else {
+        hmacFunction((unsigned char*)zidRec.getMiTMData(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), pbxSecretIDi, &macLen);
+        hmacFunction((unsigned char*)zidRec.getMiTMData(), RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen);
+    }
+}
+
+/*
+ * The DH packet for this function is DHPart1 and contains the Responder's
+ * retained secret ids. Compare them with the expected secret ids (refer
+ * to chapter 5.3 in the specification).
+ * When using this method then we are in Initiator role.
+ */
+void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec) {
+    const uint8_t* setD[3];
+    int32_t rsFound = 0;
+
+    setD[0] = setD[1] = setD[2] = NULL;
+
+    /*
+     * Select the real secrets into setD. The dhPart is DHpart1 message
+     * received from responder. rs1IDr and rs2IDr are the expected ids using
+     * the initator's cached retained secrets.
+     */
+    int matchingSecrets = 0;
+    if (memcmp(rs1IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs1();
+        rsFound = 0x1;
+    }
+    else if (memcmp(rs1IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs1();
+        rsFound = 0x2;
+    }
+    else if (memcmp(rs2IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs2();
+        rsFound = 0x4;
+    }
+    else if (memcmp(rs2IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs2();
+        rsFound = 0x8;
+    }
+    /* *** Not yet supported
+    if (memcmp(auxSecretIDr, dhPart->getAuxSecretId(), 8) == 0) {
+    DEBUGOUT((fprintf(stdout, "%c: Match for aux secret found\n", zid[0])));
+        setD[matchingSecrets++] = auxSecret;
+    }
+    */
+    if (memcmp(pbxSecretIDr, dhPart->getPbxSecretId(), 8) == 0) {
+        DEBUGOUT((fprintf(stdout, "%c: Match for Other_secret found\n", zid[0])));
+        setD[matchingSecrets++] = zidRec.getMiTMData();
+    }
+    // Check if some retained secrets found
+    if (rsFound == 0) {                        // no RS matches found
+        if (rs1Valid || rs2Valid) {            // but valid RS records in cache
+            sendInfo(Warning, WarningNoExpectedRSMatch);
+            zidRec.resetSasVerified();
+        }
+        else {                                 // No valid RS record in cache
+            sendInfo(Warning, WarningNoRSMatch);
+        }
+    }
+    else {                                     // at least one RS matches
+        sendInfo(Info, InfoRSMatchFound);
+    }
+    /*
+     * Ready to generate s0 here.
+     * The formular to compute S0 (Refer to ZRTP specification 5.4.4):
+     *
+      s0 = hash( counter | DHResult | "ZRTP-HMAC-KDF" | ZIDi | ZIDr | \
+      total_hash | len(s1) | s1 | len(s2) | s2 | len(s3) | s3)
+     *
+     * Note: in this function we are Initiator, thus ZIDi is our zid
+     * (zid), ZIDr is the peer's zid (peerZid).
+     */
+
+    /*
+     * These arrays hold the pointers and lengths of the data that must be
+     * hashed to create S0.  According to the formula the max number of
+     * elements to hash is 12, add one for the terminating "NULL"
+     */
+    unsigned char* data[13];
+    unsigned int   length[13];
+    uint32_t pos = 0;                  // index into the array
+
+    // we need a number of length data items, so define them here
+    uint32_t counter, sLen[3];
+
+    //Very first element is a fixed counter, big endian
+    counter = 1;
+    counter = htonl(counter);
+    data[pos] = (unsigned char*)&counter;
+    length[pos++] = sizeof(uint32_t);
+
+    // Next is the DH result itself
+    data[pos] = DHss;
+    length[pos++] = dhContext->getDhSize();
+
+    // Next the fixed string "ZRTP-HMAC-KDF"
+    data[pos] = (unsigned char*)KDFString;
+    length[pos++] = strlen(KDFString);
+
+    // Next is Initiator's id (ZIDi), in this case as Initiator
+    // it is zid
+    data[pos] = zid;
+    length[pos++] = ZID_SIZE;
+
+    // Next is Responder's id (ZIDr), in this case our peer's id
+    data[pos] = peerZid;
+    length[pos++] = ZID_SIZE;
+
+    // Next ist total hash (messageHash) itself
+    data[pos] = messageHash;
+    length[pos++] = hashLength;
+
+    /*
+     * For each matching shared secret hash the length of
+     * the shared secret as 32 bit big-endian number followd by the
+     * shared secret itself. The length of a shared seceret is
+     * currently fixed to RS_LENGTH. If a shared
+     * secret is not used _only_ its length is hased as zero
+     * length. NOTE: if implementing auxSecret and/or pbxSecret -> check
+     * this length stuff again.
+     */
+    int secretHashLen = RS_LENGTH;
+    secretHashLen = htonl(secretHashLen);        // prepare 32 bit big-endian number
+
+    for (int32_t i = 0; i < 3; i++) {
+        if (setD[i] != NULL) {           // a matching secret, set length, then secret
+            sLen[i] = secretHashLen;
+            data[pos] = (unsigned char*)&sLen[i];
+            length[pos++] = sizeof(uint32_t);
+            data[pos] = (unsigned char*)setD[i];
+            length[pos++] = RS_LENGTH;
+        }
+        else {                           // no machting secret, set length 0, skip secret
+            sLen[i] = 0;
+            data[pos] = (unsigned char*)&sLen[i];
+            length[pos++] = sizeof(uint32_t);
+        }
+    }
+
+    data[pos] = NULL;
+    hashListFunction(data, length, s0);
+//  hexdump("S0 I", s0, hashLength);
+
+    memset(DHss, 0, dhContext->getDhSize());
+    delete[] DHss;
+    DHss = NULL;
+
+    computeSRTPKeys();
+    memset(s0, 0, MAX_DIGEST_LENGTH);
+}
+/*
+ * The DH packet for this function is DHPart2 and contains the Initiator's
+ * retained secret ids. Compare them with the expected secret ids (refer
+ * to chapter 5.3.1 in the specification).
+ */
+void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec) {
+    const uint8_t* setD[3];
+    int32_t rsFound = 0;
+
+    setD[0] = setD[1] = setD[2] = NULL;
+
+    /*
+     * Select the real secrets into setD
+     */
+    int matchingSecrets = 0;
+    if (memcmp(rs1IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs1();
+        rsFound = 0x1;
+    }
+    else if (memcmp(rs1IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs1();
+        rsFound = 0x2;
+    }
+    else if (memcmp(rs2IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs2();
+        rsFound |= 0x4;
+    }
+    else if (memcmp(rs2IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
+        setD[matchingSecrets++] = zidRec.getRs2();
+        rsFound |= 0x8;
+    }
+    /* ***** not yet supported
+    if (memcmp(auxSecretIDi, dhPart->getauxSecretId(), 8) == 0) {
+    DEBUGOUT((fprintf(stdout, "%c: Match for aux secret found\n", zid[0])));
+        setD[matchingSecrets++] = ;
+    }
+    */
+    if (memcmp(pbxSecretIDi, dhPart->getPbxSecretId(), 8) == 0) {
+        DEBUGOUT((fprintf(stdout, "%c: Match for PBX secret found\n", zid[0])));
+        setD[matchingSecrets++] = zidRec.getMiTMData();
+    }
+    // Check if some retained secrets found
+    if (rsFound == 0) {                        // no RS matches found
+        if (rs1Valid || rs2Valid) {            // but valid RS records in cache
+            sendInfo(Warning, WarningNoExpectedRSMatch);
+            zidRec.resetSasVerified();
+        }
+        else {                                 // No valid RS record in cache
+            sendInfo(Warning, WarningNoRSMatch);
+        }
+    }
+    else {                                     // at least one RS matches
+        sendInfo(Info, InfoRSMatchFound);
+    }
+
+    /*
+     * ready to generate s0 here.
+     * The formular to compute S0 (Refer to ZRTP specification 5.4.4):
+     *
+      s0 = hash( counter | DHResult | "ZRTP-HMAC-KDF" | ZIDi | ZIDr | \
+      total_hash | len(s1) | s1 | len(s2) | s2 | len(s3) | s3)
+     *
+     * Note: in this function we are Responder, thus ZIDi is the peer's zid
+     * (peerZid), ZIDr is our zid.
+     */
+
+    /*
+     * These arrays hold the pointers and lengths of the data that must be
+     * hashed to create S0.  According to the formula the max number of
+     * elements to hash is 12, add one for the terminating "NULL"
+     */
+    unsigned char* data[13];
+    unsigned int   length[13];
+    uint32_t pos = 0;                  // index into the array
+
+
+    // we need a number of length data items, so define them here
+    uint32_t counter, sLen[3];
+
+    //Very first element is a fixed counter, big endian
+    counter = 1;
+    counter = htonl(counter);
+    data[pos] = (unsigned char*)&counter;
+    length[pos++] = sizeof(uint32_t);
+
+    // Next is the DH result itself
+    data[pos] = DHss;
+    length[pos++] = dhContext->getDhSize();
+
+    // Next the fixed string "ZRTP-HMAC-KDF"
+    data[pos] = (unsigned char*)KDFString;
+    length[pos++] = strlen(KDFString);
+
+    // Next is Initiator's id (ZIDi), in this case as Responder
+    // it is peerZid
+    data[pos] = peerZid;
+    length[pos++] = ZID_SIZE;
+
+    // Next is Responder's id (ZIDr), in this case our own zid
+    data[pos] = zid;
+    length[pos++] = ZID_SIZE;
+
+    // Next ist total hash (messageHash) itself
+    data[pos] = messageHash;
+    length[pos++] = hashLength;
+
+    /*
+     * For each matching shared secret hash the length of
+     * the shared secret as 32 bit big-endian number followd by the
+     * shared secret itself. The length of a shared seceret is
+     * currently fixed to SHA256_DIGEST_LENGTH. If a shared
+     * secret is not used _only_ its length is hased as zero
+     * length. NOTE: if implementing auxSecret and/or pbxSecret -> check
+     * this length stuff again.
+     */
+    int secretHashLen = RS_LENGTH;
+    secretHashLen = htonl(secretHashLen);        // prepare 32 bit big-endian number
+
+    for (int32_t i = 0; i < 3; i++) {
+        if (setD[i] != NULL) {           // a matching secret, set length, then secret
+            sLen[i] = secretHashLen;
+            data[pos] = (unsigned char*)&sLen[i];
+            length[pos++] = sizeof(uint32_t);
+            data[pos] = (unsigned char*)setD[i];
+            length[pos++] = RS_LENGTH;
+        }
+        else {                           // no machting secret, set length 0, skip secret
+            sLen[i] = 0;
+            data[pos] = (unsigned char*)&sLen[i];
+            length[pos++] = sizeof(uint32_t);
+        }
+    }
+
+    data[pos] = NULL;
+    hashListFunction(data, length, s0);
+//  hexdump("S0 R", s0, hashLength);
+
+    memset(DHss, 0, dhContext->getDhSize());
+    delete[] DHss;
+    DHss = NULL;
+
+    computeSRTPKeys();
+    memset(s0, 0, MAX_DIGEST_LENGTH);
+}
+
+
+void ZRtp::KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLength,
+               uint8_t* context, int32_t contextLength, int32_t L, uint8_t* output) {
+
+    unsigned char* data[6];
+    uint32_t length[6];
+    uint32_t pos = 0;                  // index into the array
+    uint32_t maclen = 0;
+
+    // Very first element is a fixed counter, big endian
+    uint32_t counter = 1;
+    counter = htonl(counter);
+    data[pos] = (unsigned char*)&counter;
+    length[pos++] = sizeof(uint32_t);
+
+    // Next element is the label, null terminated, labelLength includes null byte.
+    data[pos] = label;
+    length[pos++] = labelLength;
+
+    // Next is the KDF context
+    data[pos] = context;
+    length[pos++] = contextLength;
+
+    // last element is HMAC length in bits, big endian
+    uint32_t len = htonl(L);
+    data[pos] = (unsigned char*)&len;
+    length[pos++] = sizeof(uint32_t);
+
+    data[pos] = NULL;
+
+    // Use negotiated hash.
+    hmacListFunction(key, keyLength, data, length, output, &maclen);
+}
+
+// Compute the Multi Stream mode s0
+void ZRtp::generateKeysMultiStream() {
+
+    // allocate the maximum size, compute real size to use
+    uint8_t KDFcontext[sizeof(peerZid)+sizeof(zid)+sizeof(messageHash)];
+    int32_t kdfSize = sizeof(peerZid)+sizeof(zid)+hashLength;
+
+    if (myRole == Responder) {
+        memcpy(KDFcontext, peerZid, sizeof(peerZid));
+        memcpy(KDFcontext+sizeof(peerZid), zid, sizeof(zid));
+    }
+    else {
+        memcpy(KDFcontext, zid, sizeof(zid));
+        memcpy(KDFcontext+sizeof(zid), peerZid, sizeof(peerZid));
+    }
+    memcpy(KDFcontext+sizeof(zid)+sizeof(peerZid), messageHash, hashLength);
+
+    KDF(zrtpSession, hashLength, (unsigned char*)zrtpMsk, strlen(zrtpMsk)+1, KDFcontext, kdfSize, hashLength*8, s0);
+
+    memset(KDFcontext, 0, sizeof(KDFcontext));
+
+    computeSRTPKeys();
+}
+
+void ZRtp::computePBXSecret() {
+    // Construct the KDF context as per ZRTP specification chap 7.3.1:
+    // ZIDi || ZIDr
+    uint8_t KDFcontext[sizeof(peerZid)+sizeof(zid)];
+    int32_t kdfSize = sizeof(peerZid)+sizeof(zid);
+
+    if (myRole == Responder) {
+        memcpy(KDFcontext, peerZid, sizeof(peerZid));
+        memcpy(KDFcontext+sizeof(peerZid), zid, sizeof(zid));
+    }
+    else {
+        memcpy(KDFcontext, zid, sizeof(zid));
+        memcpy(KDFcontext+sizeof(zid), peerZid, sizeof(peerZid));
+    }
+
+    KDF(zrtpSession, hashLength, (unsigned char*)zrtpTrustedMitm, strlen(zrtpTrustedMitm)+1, KDFcontext,
+        kdfSize, SHA256_DIGEST_LENGTH * 8, pbxSecretTmpBuffer);
+
+    pbxSecretTmp = pbxSecretTmpBuffer;  // set pointer to buffer, signal PBX secret was computed
+}
+
+
+void ZRtp::computeSRTPKeys() {
+
+    // allocate the maximum size, compute real size to use
+    uint8_t KDFcontext[sizeof(peerZid)+sizeof(zid)+sizeof(messageHash)];
+    int32_t kdfSize = sizeof(peerZid)+sizeof(zid)+hashLength;
+
+    int32_t keyLen = cipher->getKeylen() * 8;
+
+    if (myRole == Responder) {
+        memcpy(KDFcontext, peerZid, sizeof(peerZid));
+        memcpy(KDFcontext+sizeof(peerZid), zid, sizeof(zid));
+    }
+    else {
+        memcpy(KDFcontext, zid, sizeof(zid));
+        memcpy(KDFcontext+sizeof(zid), peerZid, sizeof(peerZid));
+    }
+    memcpy(KDFcontext+sizeof(zid)+sizeof(peerZid), messageHash, hashLength);
+
+    // Inititiator key and salt
+    KDF(s0, hashLength, (unsigned char*)iniMasterKey, strlen(iniMasterKey)+1, KDFcontext, kdfSize, keyLen, srtpKeyI);
+    KDF(s0, hashLength, (unsigned char*)iniMasterSalt, strlen(iniMasterSalt)+1, KDFcontext, kdfSize, 112, srtpSaltI);
+
+    // Responder key and salt
+    KDF(s0, hashLength, (unsigned char*)respMasterKey, strlen(respMasterKey)+1, KDFcontext, kdfSize, keyLen, srtpKeyR);
+    KDF(s0, hashLength, (unsigned char*)respMasterSalt, strlen(respMasterSalt)+1, KDFcontext, kdfSize, 112, srtpSaltR);
+
+    // The HMAC keys for GoClear
+    KDF(s0, hashLength, (unsigned char*)iniHmacKey, strlen(iniHmacKey)+1, KDFcontext, kdfSize, hashLength*8, hmacKeyI);
+
+    KDF(s0, hashLength, (unsigned char*)respHmacKey, strlen(respHmacKey)+1, KDFcontext, kdfSize, hashLength*8, hmacKeyR);
+
+    // The keys for Confirm messages
+    KDF(s0, hashLength, (unsigned char*)iniZrtpKey, strlen(iniZrtpKey)+1, KDFcontext, kdfSize, keyLen, zrtpKeyI);
+    KDF(s0, hashLength, (unsigned char*)respZrtpKey, strlen(respZrtpKey)+1, KDFcontext, kdfSize, keyLen, zrtpKeyR);
+
+    if (!multiStream) {
+        // Compute the new Retained Secret
+        KDF(s0, hashLength, (unsigned char*)retainedSec, strlen(retainedSec)+1, KDFcontext, kdfSize, SHA256_DIGEST_LENGTH*8, newRs1);
+
+        // Compute the ZRTP Session Key
+        KDF(s0, hashLength, (unsigned char*)zrtpSessionKey, strlen(zrtpSessionKey)+1, KDFcontext, kdfSize, hashLength*8, zrtpSession);
+
+        // perform SAS generation according to chapter 5.5 and 8.
+        // we don't need a speciai sasValue filed. sasValue are the first
+        // (leftmost) 32 bits (4 bytes) of sasHash
+        uint8_t sasBytes[4];
+        KDF(s0, hashLength, (unsigned char*)sasString, strlen(sasString)+1, KDFcontext, kdfSize, SHA256_DIGEST_LENGTH*8, sasHash);
+
+        // according to chapter 8 only the leftmost 20 bits of sasValue (aka
+        //  sasHash) are used to create the character SAS string of type SAS
+        // base 32 (5 bits per character)
+        sasBytes[0] = sasHash[0];
+        sasBytes[1] = sasHash[1];
+        sasBytes[2] = sasHash[2] & 0xf0;
+        sasBytes[3] = 0;
+        SAS = Base32(sasBytes, 20).getEncoded();
+        if (signSasSeen)
+            callback->signSAS(sasHash);
+    }
+    memset(KDFcontext, 0, sizeof(KDFcontext));
+}
+
+bool ZRtp::srtpSecretsReady(EnableSecurity part) {
+
+    SrtpSecret_t sec;
+
+    sec.symEncAlgorithm = cipher->getAlgoId();
+
+    sec.keyInitiator = srtpKeyI;
+    sec.initKeyLen = cipher->getKeylen() * 8;
+    sec.saltInitiator = srtpSaltI;
+    sec.initSaltLen = 112;
+
+    sec.keyResponder = srtpKeyR;
+    sec.respKeyLen = cipher->getKeylen() * 8;
+    sec.saltResponder = srtpSaltR;
+    sec.respSaltLen = 112;
+
+    sec.authAlgorithm = authLength->getAlgoId();
+    sec.srtpAuthTagLen = authLength->getKeylen();
+
+    sec.sas = SAS;
+    sec.role = myRole;
+
+    return callback->srtpSecretsReady(&sec, part);
+}
+
+
+void ZRtp::setNegotiatedHash(AlgorithmEnum* hash) {
+    switch (zrtpHashes.getOrdinal(*hash)) {
+    case 0:
+        hashLength = SHA256_DIGEST_LENGTH;
+        hashFunction = sha256;
+        hashListFunction = sha256;
+
+        hmacFunction = hmac_sha256;
+        hmacListFunction = hmac_sha256;
+
+        createHashCtx = createSha256Context;
+        closeHashCtx = closeSha256Context;
+        hashCtxFunction = sha256Ctx;
+        hashCtxListFunction = sha256Ctx;
+        break;
+
+    case 1:
+        hashLength = SHA384_DIGEST_LENGTH;
+        hashFunction = sha384;
+        hashListFunction = sha384;
+
+        hmacFunction = hmac_sha384;
+        hmacListFunction = hmac_sha384;
+
+        createHashCtx = createSha384Context;
+        closeHashCtx = closeSha384Context;
+        hashCtxFunction = sha384Ctx;
+        hashCtxListFunction = sha384Ctx;
+        break;
+    }
+}
+
+
+void ZRtp::srtpSecretsOff(EnableSecurity part) {
+    callback->srtpSecretsOff(part);
+}
+
+void ZRtp::SASVerified() {
+    if (paranoidMode)
+        return;
+
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+    ZIDFile *zid = ZIDFile::getInstance();
+
+    zid->getRecord(&zidRec);
+    zidRec.setSasVerified();
+    zid->saveRecord(&zidRec);
+}
+
+void ZRtp::resetSASVerified() {
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+    ZIDFile *zid = ZIDFile::getInstance();
+
+    zid->getRecord(&zidRec);
+    zidRec.resetSasVerified();
+    zid->saveRecord(&zidRec);
+}
+
+
+void ZRtp::sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) {
+
+    // We've reached secure state: overwrite the SRTP master key and master salt.
+    if (severity == Info && subCode == InfoSecureStateOn) {
+        memset(srtpKeyI, 0, cipher->getKeylen());
+        memset(srtpSaltI, 0, 112/8);
+        memset(srtpKeyR, 0, cipher->getKeylen());
+        memset(srtpSaltR, 0, 112/8);
+    }
+    callback->sendInfo(severity, subCode);
+}
+
+
+void ZRtp::zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) {
+    callback->zrtpNegotiationFailed(severity, subCode);
+}
+
+void ZRtp::zrtpNotSuppOther() {
+    callback->zrtpNotSuppOther();
+}
+
+void ZRtp::synchEnter() {
+    callback->synchEnter();
+}
+
+void ZRtp::synchLeave() {
+    callback->synchLeave();
+}
+
+int32_t ZRtp::sendPacketZRTP(ZrtpPacketBase *packet) {
+    return ((packet == NULL) ? 0 :
+            callback->sendDataZRTP(packet->getHeaderBase(), (packet->getLength() * 4) + 4));
+}
+
+int32_t ZRtp::activateTimer(int32_t tm) {
+    return (callback->activateTimer(tm));
+}
+
+int32_t ZRtp::cancelTimer() {
+    return (callback->cancelTimer());
+}
+
+void ZRtp::setAuxSecret(uint8_t* data, int32_t length) {
+    if (length > 0) {
+        auxSecret = new uint8_t[length];
+        auxSecretLength = length;
+        memcpy(auxSecret, data, length);
+    }
+}
+
+void ZRtp::setClientId(std::string id) {
+    if (id.size() < CLIENT_ID_SIZE) {
+        unsigned char tmp[CLIENT_ID_SIZE +1] = {' '};
+        memcpy(tmp, id.c_str(), id.size());
+        tmp[CLIENT_ID_SIZE] = 0;
+        zrtpHello.setClientId(tmp);
+    } else {
+        zrtpHello.setClientId((unsigned char*)id.c_str());
+    }
+
+    int32_t len = zrtpHello.getLength() * ZRTP_WORD_SIZE;
+
+    // Hello packet is ready now, compute its HMAC
+    // (excluding the HMAC field (2*ZTP_WORD_SIZE)) and store in Hello
+    // use the implicit hash function
+    uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+    hmacFunctionImpl(H2, HASH_IMAGE_SIZE, (uint8_t*)zrtpHello.getHeaderBase(), len-(2*ZRTP_WORD_SIZE), hmac, &macLen);
+    zrtpHello.setHMAC(hmac);
+
+    // calculate hash over the final Hello packet, refer to chap 9.1 how to
+    // use this hash in SIP/SDP.
+    hashFunctionImpl((uint8_t*)zrtpHello.getHeaderBase(), len, helloHash);
+}
+
+void ZRtp::storeMsgTemp(ZrtpPacketBase* pkt) {
+    uint32_t length = pkt->getLength() * ZRTP_WORD_SIZE;
+    length = (length > sizeof(tempMsgBuffer)) ? sizeof(tempMsgBuffer) : length; 
+    memset(tempMsgBuffer, 0, sizeof(tempMsgBuffer));
+    memcpy(tempMsgBuffer, (uint8_t*)pkt->getHeaderBase(), length);
+    lengthOfMsgData = length;
+}
+
+bool ZRtp::checkMsgHmac(uint8_t* key) {
+    uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+    int32_t len = lengthOfMsgData-(HMAC_SIZE);  // compute HMAC, but exlude the stored HMAC :-)
+
+    // Use the implicit hash function
+    hmacFunctionImpl(key, HASH_IMAGE_SIZE, tempMsgBuffer, len, hmac, &macLen);
+    return (memcmp(hmac, tempMsgBuffer+len, (HMAC_SIZE)) == 0 ? true : false);
+}
+
+std::string ZRtp::getHelloHash() {
+    std::ostringstream stm;
+
+    uint8_t* hp = helloHash;
+
+    stm << zrtpVersion;
+    stm << " ";
+    stm.fill('0');
+    stm << hex;
+    for (int i = 0; i < hashLengthImpl; i++) {
+        stm.width(2);
+        stm << static_cast<uint32_t>(*hp++);
+    }
+    return stm.str();
+}
+
+std::string ZRtp::getPeerHelloHash() {
+    std::ostringstream stm;
+
+    if (peerHelloVersion[0] == 0)
+        return std::string();
+
+    uint8_t* hp = peerHelloHash;
+
+    stm << peerHelloVersion;
+    stm << " ";
+    stm.fill('0');
+    stm << hex;
+    for (int i = 0; i < hashLengthImpl; i++) {
+        stm.width(2);
+        stm << static_cast<uint32_t>(*hp++);
+    }
+    return stm.str();
+}
+
+std::string ZRtp::getMultiStrParams() {
+
+    // the string will hold binary data - it's opaque to the application
+    std::string str("");
+    char tmp[MAX_DIGEST_LENGTH + 1 + 1 + 1]; // hash length + cipher + authLength + hash
+
+    if (inState(SecureState) && !multiStream) {
+        // construct array that holds zrtpSession, cipher type, auth-length, and hash type
+        tmp[0] = zrtpHashes.getOrdinal(*hash);
+        tmp[1] = zrtpAuthLengths.getOrdinal(*authLength);
+        tmp[2] = zrtpSymCiphers.getOrdinal(*cipher);
+        memcpy(tmp+3, zrtpSession, hashLength);
+        str.assign(tmp, hashLength + 1 + 1 + 1); // set chars (bytes) to the string
+    }
+    return str;
+}
+
+void ZRtp::setMultiStrParams(std::string parameters) {
+
+    char tmp[MAX_DIGEST_LENGTH + 1 + 1 + 1]; // max. hash length + cipher + authLength + hash
+
+    // First get negotiated hash from parameters, set algorithms and length
+    int i = parameters.at(0) & 0xff;
+    hash = &zrtpHashes.getByOrdinal(i);
+    setNegotiatedHash(hash);           // sets hashlength
+
+    // use string.copy(buffer, num, start=0) to retrieve chars (bytes) from the string
+    parameters.copy(tmp, hashLength + 1 + 1 + 1, 0);
+
+    i = tmp[1] & 0xff;
+    authLength = &zrtpAuthLengths.getByOrdinal(i);
+    i = tmp[2] & 0xff;
+    cipher = &zrtpSymCiphers.getByOrdinal(i);
+    memcpy(zrtpSession, tmp+3, hashLength);
+
+    // after setting zrtpSession, cipher, and auth-length set multi-stream to true
+    multiStream = true;
+    stateEngine->setMultiStream(true);
+}
+
+bool ZRtp::isMultiStream() {
+    return multiStream;
+}
+
+bool ZRtp::isMultiStreamAvailable() {
+    return multiStreamAvailable;
+}
+
+void ZRtp::acceptEnrollment(bool accepted) {
+    if (!accepted) {
+        callback->zrtpInformEnrollment(EnrollmentCanceled);
+        return;
+    }
+    // Get peer's zid record to store the pbx (MitM) secret
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+    ZIDFile* zid = ZIDFile::getInstance();
+    zid->getRecord(&zidRec);
+
+    if (pbxSecretTmp != NULL) {
+        zidRec.setMiTMData(pbxSecretTmp);
+        callback->zrtpInformEnrollment(EnrollmentOk);
+    }
+    else {
+        callback->zrtpInformEnrollment(EnrollmentFailed);
+        return;
+    }
+    zid->saveRecord(&zidRec);
+    return;
+}
+
+bool ZRtp::setSignatureData(uint8_t* data, int32_t length) {
+    if ((length % 4) != 0)
+        return false;
+
+    ZrtpPacketConfirm* cfrm = (myRole == Responder) ? &zrtpConfirm1 : &zrtpConfirm2;
+    cfrm->setSignatureLength(length / 4);
+    return cfrm->setSignatureData(data, length);
+}
+
+const uint8_t* ZRtp::getSignatureData() {
+    return signatureData;
+}
+
+int32_t ZRtp::getSignatureLength() {
+    return signatureLength * ZRTP_WORD_SIZE;
+}
+
+void ZRtp::conf2AckSecure() {
+    Event_t ev;
+
+    ev.type = ZrtpPacket;
+    ev.packet = (uint8_t*)&zrtpConf2Ack;
+
+    if (stateEngine != NULL) {
+        stateEngine->processEvent(&ev);
+    }
+}
+
+int32_t ZRtp::compareCommit(ZrtpPacketCommit *commit) {
+    // TODO: enhance to compare according to rules defined in chapter 4.2
+    int32_t len = 0;
+    len = !multiStream ? HVI_SIZE : (4 * ZRTP_WORD_SIZE);
+    return (memcmp(hvi, commit->getHvi(), len));
+}
+
+bool ZRtp::isEnrollmentMode() {
+    return enrollmentMode;
+}
+
+void ZRtp::setEnrollmentMode(bool enrollmentMode) {
+    this->enrollmentMode = enrollmentMode;
+}
+
+bool ZRtp::isPeerEnrolled() {
+    return peerIsEnrolled;
+}
+
+bool ZRtp::sendSASRelayPacket(uint8_t* sh, std::string render) {
+
+    uint8_t confMac[MAX_DIGEST_LENGTH];
+    uint32_t macLen;
+    uint8_t* hkey, *ekey;
+
+    // If we are responder then the PBX used it's Initiator keys
+    if (myRole == Responder) {
+        hkey = hmacKeyR;
+        ekey = zrtpKeyR;
+        // TODO: check signature length in zrtpConfirm1 and if not zero copy Signature data
+    }
+    else {
+        hkey = hmacKeyI;
+        ekey = zrtpKeyI;
+        // TODO: check signature length in zrtpConfirm2 and if not zero copy Signature data
+    }
+    // Prepare IV data that we will use during confirm packet encryption.
+    randomZRTP(randomIV, sizeof(randomIV));
+    zrtpSasRelay.setIv(randomIV);
+    zrtpSasRelay.setTrustedSas(sh);
+    zrtpSasRelay.setSas((uint8_t*)render.c_str());
+
+    // Encrypt and HMAC with Initiator's key - we are Initiator here
+    int16_t hmlen = (zrtpSasRelay.getLength() - 9) * ZRTP_WORD_SIZE;
+    cipher->getEncrypt()(ekey, cipher->getKeylen(), randomIV, (uint8_t*)zrtpSasRelay.getFiller(), hmlen);
+
+    // Use negotiated HMAC (hash)
+    hmacFunction(hkey, hashLength, (unsigned char*)zrtpSasRelay.getFiller(), hmlen, confMac, &macLen);
+
+    zrtpSasRelay.setHmac(confMac);
+
+    stateEngine->sendSASRelay(&zrtpSasRelay);
+    return true;
+}
+
+std::string ZRtp::getSasType() {
+    std::string sasT(sasType->getName());
+    return sasT;
+}
+
+uint8_t* ZRtp::getSasHash() {
+    return sasHash;
+}
+
+int32_t ZRtp::getPeerZid(uint8_t* data) {
+    memcpy(data, peerZid, IDENTIFIER_LEN);
+    return IDENTIFIER_LEN;
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
+
diff --git a/jni/libzrtp/src/ZrtpCWrapper.cpp b/jni/libzrtp/src/ZrtpCWrapper.cpp
new file mode 100644
index 0000000..1e1d2c8
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpCWrapper.cpp
@@ -0,0 +1,470 @@
+/*
+    This class maps the ZRTP C calls to ZRTP C++ methods.
+    Copyright (C) 2010  Werner Dittmann
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <libzrtpcpp/ZrtpCallback.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+#include <libzrtpcpp/ZIDFile.h>
+#include <libzrtpcpp/ZRtp.h>
+#include <libzrtpcpp/ZrtpCallbackWrapper.h>
+#include <libzrtpcpp/ZrtpCWrapper.h>
+#include <libzrtpcpp/ZrtpCrc32.h>
+
+static int32_t zrtp_initZidFile(const char* zidFilename);
+
+ZrtpContext* zrtp_CreateWrapper() 
+{
+    ZrtpContext* zc = new ZrtpContext;
+    zc->configure = 0;
+    zc->zrtpEngine = 0;
+    zc->zrtpCallback = 0;
+
+    return zc;
+}
+
+void zrtp_initializeZrtpEngine(ZrtpContext* zrtpContext, 
+                               zrtp_Callbacks *cb, const char* id,
+                               const char* zidFilename,
+                               void* userData,
+                               int32_t mitmMode)
+{
+    std::string clientIdString(id);
+
+    zrtpContext->zrtpCallback = new ZrtpCallbackWrapper(cb, zrtpContext);
+    zrtpContext->userData = userData;
+
+    if (zrtpContext->configure == 0) {
+        zrtpContext->configure = new ZrtpConfigure();
+        zrtpContext->configure->setStandardConfig();
+    }
+
+    // Initialize ZID file (cache) and get my own ZID
+    zrtp_initZidFile(zidFilename);
+    ZIDFile* zf = ZIDFile::getInstance();
+    const unsigned char* myZid = zf->getZid();
+
+    zrtpContext->zrtpEngine = new ZRtp((uint8_t*)myZid, zrtpContext->zrtpCallback,
+                              clientIdString, zrtpContext->configure, mitmMode == 0 ? false : true);
+}
+
+void zrtp_DestroyWrapper(ZrtpContext* zrtpContext) {
+
+    if (zrtpContext == NULL)
+        return;
+
+    delete zrtpContext->zrtpEngine;
+    zrtpContext->zrtpEngine = NULL;
+
+    delete zrtpContext->zrtpCallback;
+    zrtpContext->zrtpCallback = NULL;
+
+    delete zrtpContext->configure;
+    zrtpContext->configure = NULL;
+
+    delete zrtpContext;
+}
+
+static int32_t zrtp_initZidFile(const char* zidFilename) {
+    ZIDFile* zf = ZIDFile::getInstance();
+
+    if (!zf->isOpen()) {
+        std::string fname;
+        if (zidFilename == NULL) {
+            char *home = getenv("HOME");
+            std::string baseDir = (home != NULL) ? (std::string(home) + std::string("/."))
+                                  : std::string(".");
+            fname = baseDir + std::string("GNUccRTP.zid");
+            zidFilename = fname.c_str();
+        }
+        return zf->open((char *)zidFilename);
+    }
+    return 0;
+}
+
+int32_t zrtp_CheckCksum(uint8_t* buffer, uint16_t temp, uint32_t crc) 
+{
+    return zrtpCheckCksum(buffer, temp, crc);
+}
+
+uint32_t zrtp_GenerateCksum(uint8_t* buffer, uint16_t temp)
+{
+    return zrtpGenerateCksum(buffer, temp);
+}
+
+uint32_t zrtp_EndCksum(uint32_t crc)
+{
+    return zrtpEndCksum(crc);
+}
+
+/*
+ * Applications use the following methods to control ZRTP, for example
+ * to enable ZRTP, set flags etc.
+ */
+void zrtp_startZrtpEngine(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->startZrtpEngine();
+}
+
+void zrtp_stopZrtpEngine(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->stopZrtp();
+}
+
+void zrtp_processZrtpMessage(ZrtpContext* zrtpContext, uint8_t *extHeader, uint32_t peerSSRC) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->processZrtpMessage(extHeader, peerSSRC);
+}
+
+void zrtp_processTimeout(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->processTimeout();
+}
+
+//int32_t zrtp_handleGoClear(ZrtpContext* zrtpContext, uint8_t *extHeader)
+//{
+//    if (zrtpContext && zrtpContext->zrtpEngine)
+//        return zrtpContext->zrtpEngine->handleGoClear(extHeader) ? 1 : 0;
+//
+//    return 0;
+//}
+
+void zrtp_setAuxSecret(ZrtpContext* zrtpContext, uint8_t* data, int32_t length) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->setAuxSecret(data, length);
+}
+
+int32_t zrtp_inState(ZrtpContext* zrtpContext, int32_t state) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->inState(state) ? 1 : 0;
+
+    return 0;
+}
+
+void zrtp_SASVerified(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->SASVerified();
+}
+
+void zrtp_resetSASVerified(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->resetSASVerified();
+}
+
+char* zrtp_getHelloHash(ZrtpContext* zrtpContext) {
+    std::string ret;
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        ret = zrtpContext->zrtpEngine->getHelloHash();
+    else
+        return NULL;
+
+    if (ret.size() == 0)
+        return NULL;
+
+    char* retval = (char*)malloc(ret.size()+1);
+    strcpy(retval, ret.c_str());
+    return retval;
+}
+
+char* zrtp_getPeerHelloHash(ZrtpContext* zrtpContext) {
+    std::string ret;
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        ret = zrtpContext->zrtpEngine->getPeerHelloHash();
+    else
+        return NULL;
+
+    if (ret.size() == 0)
+        return NULL;
+
+    char* retval = (char*)malloc(ret.size()+1);
+    strcpy(retval, ret.c_str());
+    return retval;
+}
+
+char* zrtp_getMultiStrParams(ZrtpContext* zrtpContext, int32_t *length) {
+    std::string ret;
+
+    *length = 0;
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        ret = zrtpContext->zrtpEngine->getMultiStrParams();
+    else
+        return NULL;
+
+    if (ret.size() == 0)
+        return NULL;
+
+    *length = ret.size();
+    char* retval = (char*) malloc(ret.size());
+    ret.copy(retval, ret.size(), 0);
+    return retval;
+}
+
+void zrtp_setMultiStrParams(ZrtpContext* zrtpContext, char* parameters, int32_t length) {
+    if (!zrtpContext || !zrtpContext->zrtpEngine)
+        return;
+
+    if (parameters == NULL)
+        return;
+
+    std::string str("");
+    str.assign(parameters, length); // set chars (bytes) to the string
+
+    zrtpContext->zrtpEngine->setMultiStrParams(str);
+}
+
+int32_t zrtp_isMultiStream(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->isMultiStream() ? 1 : 0;
+
+    return 0;
+}
+
+int32_t zrtp_isMultiStreamAvailable(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->isMultiStreamAvailable() ? 1 : 0;
+
+    return 0;
+}
+
+void zrtp_acceptEnrollment(ZrtpContext* zrtpContext, int32_t accepted) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->acceptEnrollment(accepted == 0 ? false : true);
+}
+
+int32_t zrtp_isEnrollmentMode(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->isEnrollmentMode() ? 1 : 0;
+
+    return 0;
+}
+
+void zrtp_setEnrollmentMode(ZrtpContext* zrtpContext, int32_t enrollmentMode) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->setEnrollmentMode(enrollmentMode == 0 ? false : true);
+}
+
+int32_t isPeerEnrolled(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->isPeerEnrolled() ? 1 : 0;
+
+    return 0;
+}
+
+int32_t zrtp_sendSASRelayPacket(ZrtpContext* zrtpContext, uint8_t* sh, char* render) {
+    if (zrtpContext && zrtpContext->zrtpEngine) {
+        std::string rn(render);
+        return zrtpContext->zrtpEngine->sendSASRelayPacket(sh, rn) ? 1 : 0;
+    }
+    return 0;
+}
+
+
+const char* zrtp_getSasType(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine) {
+        std::string rn = zrtpContext->zrtpEngine->getSasType();
+        return rn.c_str();
+    }
+    return NULL;
+}
+
+
+uint8_t* zrtp_getSasHash(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->getSasHash();
+
+    return NULL;
+}
+
+int32_t zrtp_setSignatureData(ZrtpContext* zrtpContext, uint8_t* data, int32_t length) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->setSignatureData(data, length) ? 1 : 0;
+
+    return 0;
+}
+
+const uint8_t* zrtp_getSignatureData(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->getSignatureData();
+
+    return 0;
+}
+
+int32_t zrtp_getSignatureLength(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->getSignatureLength();
+
+    return 0;
+}
+
+void zrtp_conf2AckSecure(ZrtpContext* zrtpContext) {
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        zrtpContext->zrtpEngine->conf2AckSecure();
+}
+
+int32_t zrtp_getPeerZid(ZrtpContext* zrtpContext, uint8_t* data) {
+    if (data == NULL)
+        return 0;
+
+    if (zrtpContext && zrtpContext->zrtpEngine)
+        return zrtpContext->zrtpEngine->getPeerZid(data);
+
+    return 0;
+}
+
+/*
+ * The following methods wrap the ZRTP Configure functions
+ */
+int32_t zrtp_InitializeConfig (ZrtpContext* zrtpContext)
+{
+    zrtpContext->configure = new ZrtpConfigure();
+    return 1;
+}
+
+static EnumBase* getEnumBase(zrtp_AlgoTypes type)
+{
+        switch(type) {
+        case zrtp_HashAlgorithm:
+            return &zrtpHashes;
+            break;
+
+        case zrtp_CipherAlgorithm:
+            return &zrtpSymCiphers;
+            break;
+
+        case zrtp_PubKeyAlgorithm:
+            return &zrtpPubKeys;
+            break;
+
+        case zrtp_SasType:
+            return &zrtpSasTypes;
+            break;
+
+        case zrtp_AuthLength:
+            return &zrtpAuthLengths;
+            break;
+
+        default:
+            return NULL;
+    }
+}
+
+char** zrtp_getAlgorithmNames(ZrtpContext* zrtpContext, Zrtp_AlgoTypes type) 
+{
+    std::list<std::string>* names = NULL;
+    EnumBase* base = getEnumBase(type);
+
+    if (!base)
+        return NULL;
+    
+    names = base->getAllNames();
+    int size = base->getSize();
+    char** cNames = new char* [size+1];
+    cNames[size] = NULL;
+    
+    std::list<std::string >::iterator b = names->begin();
+    std::list<std::string >::iterator e = names->end();
+
+    for (int i = 0; b != e; b++, i++) {
+        cNames[i] = new char [(*b).size()+1];
+        strcpy(cNames[i], (*b).c_str());
+    }
+    return cNames;
+}
+
+void zrtp_freeAlgorithmNames(char** names)
+{
+    if (!names)
+        return;
+    
+    for (char** cp = names; *cp; cp++)
+        delete *cp;
+    
+    delete names;
+}
+
+void zrtp_setStandardConfig(ZrtpContext* zrtpContext)
+{
+    zrtpContext->configure->setStandardConfig();
+}
+
+void zrtp_setMandatoryOnly(ZrtpContext* zrtpContext)
+{
+    zrtpContext->configure->setMandatoryOnly();
+}
+
+int32_t zrtp_addAlgo(ZrtpContext* zrtpContext, zrtp_AlgoTypes algoType, const char* algo)
+{
+    EnumBase* base = getEnumBase(algoType);
+    AlgorithmEnum& a = base->getByName(algo);
+
+    return zrtpContext->configure->addAlgo((AlgoTypes)algoType, a);
+}
+
+int32_t zrtp_addAlgoAt(ZrtpContext* zrtpContext, zrtp_AlgoTypes algoType, const char* algo, int32_t index)
+{
+    EnumBase* base = getEnumBase(algoType);
+    AlgorithmEnum& a = base->getByName(algo);
+
+    return zrtpContext->configure->addAlgoAt((AlgoTypes)algoType, a, index);
+}
+
+int32_t zrtp_removeAlgo(ZrtpContext* zrtpContext, zrtp_AlgoTypes algoType, const char* algo)
+{
+    EnumBase* base = getEnumBase(algoType);
+    AlgorithmEnum& a = base->getByName(algo);
+
+    return zrtpContext->configure->removeAlgo((AlgoTypes)algoType, a);
+}
+
+int32_t zrtp_getNumConfiguredAlgos(ZrtpContext* zrtpContext, zrtp_AlgoTypes algoType)
+{
+    return zrtpContext->configure->getNumConfiguredAlgos((AlgoTypes)algoType);
+}
+
+const char* zrtp_getAlgoAt(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, int32_t index)
+{
+       AlgorithmEnum& a = zrtpContext->configure->getAlgoAt((AlgoTypes)algoType, index);
+       return a.getName();
+}
+
+int32_t zrtp_containsAlgo(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char*  algo)
+{
+    EnumBase* base = getEnumBase(algoType);
+    AlgorithmEnum& a = base->getByName(algo);
+
+    return zrtpContext->configure->containsAlgo((AlgoTypes)algoType, a) ? 1 : 0;
+}
+
+void zrtp_setTrustedMitM(ZrtpContext* zrtpContext, int32_t yesNo)
+{
+    zrtpContext->configure->setTrustedMitM(yesNo ? true : false);
+}
+
+int32_t zrtp_isTrustedMitM(ZrtpContext* zrtpContext)
+{
+    return zrtpContext->configure->isTrustedMitM() ? 1 : 0;
+}
+
+void zrtp_setSasSignature(ZrtpContext* zrtpContext, int32_t yesNo)
+{
+    zrtpContext->configure->setSasSignature(yesNo ? true : false);
+}
+
+int32_t zrtp_isSasSignature(ZrtpContext* zrtpContext)
+{
+    return zrtpContext->configure->isSasSignature() ? 1 : 0;
+}
diff --git a/jni/libzrtp/src/ZrtpCallbackWrapper.cpp b/jni/libzrtp/src/ZrtpCallbackWrapper.cpp
new file mode 100644
index 0000000..ca2dce6
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpCallbackWrapper.cpp
@@ -0,0 +1,151 @@
+/*
+    This class maps the ZRTP C++ callback methods to C callback methods.
+    Copyright (C) 2010  Werner Dittmann
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <libzrtpcpp/ZrtpCallbackWrapper.h>
+
+ZrtpCallbackWrapper::ZrtpCallbackWrapper(zrtp_Callbacks* cb, ZrtpContext* ctx) :
+        c_callbacks(cb), zrtpCtx(ctx)
+{
+    init();
+}
+
+void ZrtpCallbackWrapper::init()
+{
+}
+/*
+* The following methods implement the GNU ZRTP callback interface.
+* For detailed documentation refer to file ZrtpCallback.h
+*/
+int32_t ZrtpCallbackWrapper::sendDataZRTP(const unsigned char* data, int32_t length)
+{
+    return c_callbacks->zrtp_sendDataZRTP(zrtpCtx, data, length);
+}
+
+int32_t ZrtpCallbackWrapper::activateTimer (int32_t time)
+{
+    c_callbacks->zrtp_activateTimer(zrtpCtx, time);
+    return 1;
+}
+
+int32_t ZrtpCallbackWrapper::cancelTimer()
+{
+    c_callbacks->zrtp_cancelTimer(zrtpCtx);
+    return 0;
+}
+
+void ZrtpCallbackWrapper::sendInfo (GnuZrtpCodes::MessageSeverity severity, int32_t subCode)
+{
+    c_callbacks->zrtp_sendInfo(zrtpCtx, (int32_t)severity, subCode);
+}
+
+bool ZrtpCallbackWrapper::srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part)
+{
+    C_SrtpSecret_t* cs = new C_SrtpSecret_t;
+    cs->symEncAlgorithm = (zrtp_SrtpAlgorithms)secrets->symEncAlgorithm;
+    cs->initKeyLen = secrets->initKeyLen;
+    cs->initSaltLen = secrets->initSaltLen;
+    cs->keyInitiator = secrets->keyInitiator;
+    cs->keyResponder = secrets->keyResponder;
+    cs->respKeyLen = secrets->respKeyLen;
+    cs->respSaltLen = secrets->respSaltLen;
+    cs->role = (int32_t)secrets->role;
+    cs->saltInitiator = secrets->saltInitiator;
+    cs->saltResponder = secrets->saltResponder;
+    cs->sas = new char [secrets->sas.size()+1];
+    strcpy(cs->sas, secrets->sas.c_str());
+    cs->authAlgorithm = (zrtp_SrtpAlgorithms)secrets->authAlgorithm;
+    cs->srtpAuthTagLen = secrets->srtpAuthTagLen;
+
+    bool retval = (c_callbacks->zrtp_srtpSecretsReady(zrtpCtx, cs, (int32_t)part) == 0) ? false : true ;
+
+    delete[] cs->sas;
+    delete cs;
+
+    return retval;
+}
+
+void ZrtpCallbackWrapper::srtpSecretsOff (EnableSecurity part )
+{
+    c_callbacks->zrtp_srtpSecretsOff(zrtpCtx, (int32_t)part);
+}
+
+void ZrtpCallbackWrapper::srtpSecretsOn ( std::string c, std::string s, bool verified )
+{
+    char* cc = new char [c.size()+1];
+    char* cs = new char [s.size()+1];
+
+    strcpy(cc, c.c_str());
+    if(!s.empty()) 
+        strcpy(cs, s.c_str());
+    else
+        *cs = '\0';
+
+    c_callbacks->zrtp_rtpSecretsOn(zrtpCtx, cc, cs, verified?1:0);
+
+    delete[] cc;
+    delete[] cs;
+}
+
+void ZrtpCallbackWrapper::handleGoClear()
+{
+}
+
+void ZrtpCallbackWrapper::zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode)
+{
+    c_callbacks->zrtp_zrtpNegotiationFailed(zrtpCtx, (int32_t)severity, subCode);
+}
+
+void ZrtpCallbackWrapper::zrtpNotSuppOther()
+{
+    c_callbacks->zrtp_zrtpNotSuppOther(zrtpCtx);
+}
+
+void ZrtpCallbackWrapper::synchEnter()
+{
+    c_callbacks->zrtp_synchEnter(zrtpCtx);
+}
+
+
+void ZrtpCallbackWrapper::synchLeave()
+{
+    c_callbacks->zrtp_synchLeave(zrtpCtx);
+}
+
+void ZrtpCallbackWrapper::zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info)
+{
+    c_callbacks->zrtp_zrtpAskEnrollment(zrtpCtx, (zrtp_InfoEnrollment)info);
+}
+
+void ZrtpCallbackWrapper::zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info)
+{
+    c_callbacks->zrtp_zrtpInformEnrollment(zrtpCtx, (zrtp_InfoEnrollment)info);
+
+}
+
+void ZrtpCallbackWrapper::signSAS(uint8_t* sasHash)
+{
+    c_callbacks->zrtp_signSAS(zrtpCtx, sasHash);
+}
+
+bool ZrtpCallbackWrapper::checkSASSignature(uint8_t* sasHash)
+{
+    bool retval = (c_callbacks->zrtp_checkSASSignature(zrtpCtx, sasHash) == 0) ? false : true;
+
+    return retval;
+}
diff --git a/jni/libzrtp/src/ZrtpConfigure.cpp b/jni/libzrtp/src/ZrtpConfigure.cpp
new file mode 100644
index 0000000..560466f
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpConfigure.cpp
@@ -0,0 +1,496 @@
+#include <libzrtpcpp/crypto/aesCFB.h>

+#include <libzrtpcpp/crypto/twoCFB.h>

+#include <libzrtpcpp/ZrtpConfigure.h>

+#include <libzrtpcpp/ZrtpTextData.h>

+

+AlgorithmEnum::AlgorithmEnum(const AlgoTypes type, const char* name, 

+                             int32_t klen, const char* ra, encrypt_t en, 

+                             decrypt_t de, SrtpAlgorithms alId):

+    algoType(type) , algoName(name), keyLen(klen), readable(ra), encrypt(en),

+    decrypt(de), algoId(alId) {

+}

+

+AlgorithmEnum::~AlgorithmEnum()

+{

+}

+

+const char* AlgorithmEnum::getName() {

+    return algoName.c_str(); 

+}

+

+const char* AlgorithmEnum::getReadable() {

+    return readable.c_str();

+}

+    

+int AlgorithmEnum::getKeylen() {

+    return keyLen;

+}

+

+SrtpAlgorithms AlgorithmEnum::getAlgoId() {

+    return algoId;

+}

+

+encrypt_t AlgorithmEnum::getEncrypt() {

+    return encrypt;

+}

+

+decrypt_t AlgorithmEnum::getDecrypt() {

+    return decrypt;

+}

+

+AlgoTypes AlgorithmEnum::getAlgoType() { 

+    return algoType; 

+}

+

+bool AlgorithmEnum::isValid() {

+    return (algoType != Invalid); 

+}

+

+static AlgorithmEnum invalidAlgo(Invalid, "", 0, "", NULL, NULL, None);

+

+

+EnumBase::EnumBase(AlgoTypes a) : algoType(a) {

+}

+

+EnumBase::~EnumBase() {}

+

+void EnumBase::insert(const char* name) {

+    if (!name)

+        return;

+    AlgorithmEnum* e = new AlgorithmEnum(algoType, name, 0, "", NULL, NULL, None);

+    algos.push_back(e);

+}

+

+void EnumBase::insert(const char* name, int32_t klen, const char* ra,

+                      encrypt_t enc, decrypt_t dec, SrtpAlgorithms alId) {

+    if (!name)

+        return;

+    AlgorithmEnum* e = new AlgorithmEnum(algoType, name, klen, ra, enc, dec, alId);

+    algos.push_back(e);

+}

+

+int EnumBase::getSize() {

+    return algos.size(); 

+}

+

+AlgoTypes EnumBase::getAlgoType() {

+    return algoType;

+}

+

+AlgorithmEnum& EnumBase::getByName(const char* name) {

+    std::vector<AlgorithmEnum* >::iterator b = algos.begin();

+    std::vector<AlgorithmEnum* >::iterator e = algos.end();

+

+    for (; b != e; b++) {

+        if (strncmp((*b)->getName(), name, 4) == 0) {

+            return *(*b);

+        }

+    }

+    return invalidAlgo;

+}

+

+AlgorithmEnum& EnumBase::getByOrdinal(int ord) {

+    std::vector<AlgorithmEnum* >::iterator b = algos.begin();

+    std::vector<AlgorithmEnum* >::iterator e = algos.end();

+

+    for (int i = 0; b != e; ++b) {

+        if (i == ord) {

+            return *(*b);

+        }

+        i++;

+    }

+    return invalidAlgo;

+}

+

+int EnumBase::getOrdinal(AlgorithmEnum& algo) {

+    std::vector<AlgorithmEnum* >::iterator b = algos.begin();

+    std::vector<AlgorithmEnum* >::iterator e = algos.end();

+

+    for (int i = 0; b != e; ++b) {

+        if (strncmp((*b)->getName(), algo.getName(), 4) == 0) {

+            return i;

+        }

+        i++;

+    }

+    return -1;

+}

+

+std::list<std::string>* EnumBase::getAllNames() {

+    std::vector<AlgorithmEnum* >::iterator b = algos.begin();

+    std::vector<AlgorithmEnum* >::iterator e = algos.end();

+

+    std::list<std::string>* strg = new std::list<std::string>();

+

+    for (; b != e; b++) {

+        std::string s((*b)->getName());

+        strg->push_back(s);

+    }

+    return strg;

+}

+

+

+/**

+ * Set up the enumeration list for available hash algorithms

+ */

+HashEnum::HashEnum() : EnumBase(HashAlgorithm) {

+    insert(s256);

+    insert(s384);

+}

+

+HashEnum::~HashEnum() {}

+

+/**

+ * Set up the enumeration list for available symmetric cipher algorithms

+ */

+SymCipherEnum::SymCipherEnum() : EnumBase(CipherAlgorithm) {

+    insert(aes3, 32, "AES-CM-256", aesCfbEncrypt, aesCfbDecrypt, Aes);

+    insert(aes1, 16, "AES-CM-128", aesCfbEncrypt, aesCfbDecrypt, Aes);

+    insert(two3, 32, "TWO-CM-256", twoCfbEncrypt, twoCfbDecrypt, TwoFish);

+    insert(two1, 16, "TWO-CM-128", twoCfbEncrypt, twoCfbDecrypt, TwoFish);

+}

+

+SymCipherEnum::~SymCipherEnum() {}

+

+/**

+ * Set up the enumeration list for available public key algorithms

+ */

+PubKeyEnum::PubKeyEnum() : EnumBase(PubKeyAlgorithm) {

+    insert(dh2k);

+    insert(dh3k);

+    insert(mult);

+    insert(ec25);

+    insert(ec38);

+}

+

+PubKeyEnum::~PubKeyEnum() {}

+

+/**

+ * Set up the enumeration list for available SAS algorithms

+ */

+SasTypeEnum::SasTypeEnum() : EnumBase(SasType) {

+    insert(b32);

+}

+

+SasTypeEnum::~SasTypeEnum() {}

+

+/**

+ * Set up the enumeration list for available SRTP authentications

+ */

+AuthLengthEnum::AuthLengthEnum() : EnumBase(AuthLength) {

+    insert(hs32, 32, "", NULL, NULL, Sha1);

+    insert(hs80, 80, "", NULL, NULL, Sha1);

+    insert(sk32, 32, "", NULL, NULL, Skein);

+    insert(sk64, 64, "", NULL, NULL, Skein);

+}

+

+AuthLengthEnum::~AuthLengthEnum() {}

+

+/*

+ * Here the global accessible enumerations for all implemented algorithms.

+ */

+HashEnum zrtpHashes;

+SymCipherEnum zrtpSymCiphers;

+PubKeyEnum zrtpPubKeys;

+SasTypeEnum zrtpSasTypes;

+AuthLengthEnum zrtpAuthLengths;

+

+/*

+ * The public methods are mainly a facade to the private methods.

+ */

+ZrtpConfigure::ZrtpConfigure() : enableTrustedMitM(false), enableSasSignature(false), enableParanoidMode(false) {}

+

+ZrtpConfigure::~ZrtpConfigure() {}

+

+void ZrtpConfigure::setStandardConfig() {

+    clear();

+

+    addAlgo(HashAlgorithm, zrtpHashes.getByName(s384));

+    addAlgo(HashAlgorithm, zrtpHashes.getByName(s256));

+

+    addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(two3));

+    addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes3));

+    addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(two1));

+    addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes1));

+

+    addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(ec25));

+    addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh3k));

+    addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(ec38));

+    addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh2k));

+    addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(mult));

+

+    addAlgo(SasType, zrtpSasTypes.getByName(b32));

+

+    addAlgo(AuthLength, zrtpAuthLengths.getByName(sk32));

+    addAlgo(AuthLength, zrtpAuthLengths.getByName(sk64));

+    addAlgo(AuthLength, zrtpAuthLengths.getByName(hs32));

+    addAlgo(AuthLength, zrtpAuthLengths.getByName(hs80));

+}

+

+void ZrtpConfigure::setMandatoryOnly() {

+    clear();

+

+    addAlgo(HashAlgorithm, zrtpHashes.getByName(s256));

+

+    addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes1));

+

+    addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh3k));

+    addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(mult));

+

+    addAlgo(SasType, zrtpSasTypes.getByName(b32));

+

+    addAlgo(AuthLength, zrtpAuthLengths.getByName(hs32));

+    addAlgo(AuthLength, zrtpAuthLengths.getByName(hs80));

+

+}

+

+void ZrtpConfigure::clear() {

+    hashes.clear();

+    symCiphers.clear();

+    publicKeyAlgos.clear();

+    sasTypes.clear();

+    authLengths.clear();

+}

+

+int32_t ZrtpConfigure::addAlgo(AlgoTypes algoType, AlgorithmEnum& algo) {

+

+    return addAlgo(getEnum(algoType), algo);

+}

+

+int32_t ZrtpConfigure::addAlgoAt(AlgoTypes algoType, AlgorithmEnum& algo, int32_t index) {

+

+    return addAlgoAt(getEnum(algoType), algo, index);

+}

+

+AlgorithmEnum& ZrtpConfigure::getAlgoAt(AlgoTypes algoType, int32_t index) {

+

+    return getAlgoAt(getEnum(algoType), index);

+}

+

+int32_t ZrtpConfigure::removeAlgo(AlgoTypes algoType, AlgorithmEnum& algo) {

+

+    return removeAlgo(getEnum(algoType), algo);

+}

+

+int32_t ZrtpConfigure::getNumConfiguredAlgos(AlgoTypes algoType) {

+

+    return getNumConfiguredAlgos(getEnum(algoType));

+}

+

+bool ZrtpConfigure::containsAlgo(AlgoTypes algoType, AlgorithmEnum& algo) {

+

+    return containsAlgo(getEnum(algoType), algo);

+}

+

+void ZrtpConfigure::printConfiguredAlgos(AlgoTypes algoType) {

+

+    printConfiguredAlgos(getEnum(algoType));

+}

+

+/*

+ * The next methods are the private methods that implement the real

+ * details.

+ */

+AlgorithmEnum& ZrtpConfigure::getAlgoAt(std::vector<AlgorithmEnum* >& a, int32_t index) {

+

+    if (index >= (int)a.size())

+        return invalidAlgo;

+

+    std::vector<AlgorithmEnum* >::iterator b = a.begin();

+    std::vector<AlgorithmEnum* >::iterator e = a.end();

+

+    for (int i = 0; b != e; ++b) {

+        if (i == index) {

+            return *(*b);

+        }

+        i++;

+    }

+    return invalidAlgo;

+}

+

+int32_t ZrtpConfigure::addAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo) {

+    int size = (int)a.size();

+    if (size >= maxNoOfAlgos)

+        return -1;

+

+    if (!algo.isValid())

+        return -1;

+

+    if (containsAlgo(a, algo))

+        return (maxNoOfAlgos - size);

+

+    a.push_back(&algo);

+    return (maxNoOfAlgos - (int)a.size());

+}

+

+int32_t ZrtpConfigure::addAlgoAt(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo, int32_t index) {

+    if (index >= maxNoOfAlgos)

+        return -1;

+

+    int size = (int)a.size();

+

+    if (!algo.isValid())

+        return -1;

+

+//    a[index] = &algo;

+

+    if (index >= size) {

+        a.push_back(&algo);

+        return maxNoOfAlgos - (int)a.size();

+    }

+    std::vector<AlgorithmEnum* >::iterator b = a.begin();

+    std::vector<AlgorithmEnum* >::iterator e = a.end();

+

+    for (int i = 0; b != e; ++b) {

+        if (i == index) {

+            a.insert(b, &algo);

+            break;

+        }

+        i++;

+    }

+    return (maxNoOfAlgos - (int)a.size());

+}

+

+int32_t ZrtpConfigure::removeAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo) {

+

+    if ((int)a.size() == 0 || !algo.isValid())

+        return maxNoOfAlgos;

+

+    std::vector<AlgorithmEnum* >::iterator b = a.begin();

+    std::vector<AlgorithmEnum* >::iterator e = a.end();

+

+    for (; b != e; ++b) {

+        if (strcmp((*b)->getName(), algo.getName()) == 0) {

+            a.erase(b);

+            break;

+        }

+    }

+    return (maxNoOfAlgos - (int)a.size());

+}

+

+int32_t ZrtpConfigure::getNumConfiguredAlgos(std::vector<AlgorithmEnum* >& a) {

+    return (int32_t)a.size();

+}

+

+bool ZrtpConfigure::containsAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo) {

+

+    if ((int)a.size() == 0 || !algo.isValid())

+        return false;

+

+    std::vector<AlgorithmEnum* >::iterator b = a.begin();

+    std::vector<AlgorithmEnum* >::iterator e = a.end();

+

+    for (; b != e; ++b) {

+        if (strcmp((*b)->getName(), algo.getName()) == 0) {

+            return true;

+        }

+    }

+    return false;

+}

+

+void ZrtpConfigure::printConfiguredAlgos(std::vector<AlgorithmEnum* >& a) {

+

+    std::vector<AlgorithmEnum* >::iterator b = a.begin();

+    std::vector<AlgorithmEnum* >::iterator e = a.end();

+

+    for (; b != e; ++b) {

+        printf("print configured: name: %s\n", (*b)->getName());

+    }

+}

+

+std::vector<AlgorithmEnum* >& ZrtpConfigure::getEnum(AlgoTypes algoType) {

+

+    switch(algoType) {

+        case HashAlgorithm:

+            return hashes;

+            break;

+

+        case CipherAlgorithm:

+            return symCiphers;

+            break;

+

+        case PubKeyAlgorithm:

+            return publicKeyAlgos;

+            break;

+

+        case SasType:

+            return sasTypes;

+            break;

+

+        case AuthLength:

+            return authLengths;

+            break;

+

+        default:

+            break;

+    }

+    return hashes;

+}

+

+void ZrtpConfigure::setTrustedMitM(bool yesNo) {

+    enableTrustedMitM = yesNo;

+}

+

+bool ZrtpConfigure::isTrustedMitM() {

+    return enableTrustedMitM;

+}

+

+void ZrtpConfigure::setSasSignature(bool yesNo) {

+    enableSasSignature = yesNo;

+}

+

+bool ZrtpConfigure::isSasSignature() {

+    return enableSasSignature;

+}

+

+void ZrtpConfigure::setParanoidMode(bool yesNo) {

+    enableParanoidMode = yesNo;

+}

+

+bool ZrtpConfigure::isParanoidMode() {

+    return enableParanoidMode;

+}

+

+#if 0

+ZrtpConfigure config;

+

+main() {

+    printf("Start\n");

+    printf("size: %d\n", zrtpHashes.getSize());

+    AlgorithmEnum e = zrtpHashes.getByName("S256");

+    printf("algo name: %s\n", e.getName());

+    printf("algo type: %d\n", e.getAlgoType());

+

+    std::list<std::string>* names = zrtpHashes.getAllNames();

+    printf("size of name list: %d\n", names->size());

+    printf("first name: %s\n", names->front().c_str());

+    printf("last name: %s\n", names->back().c_str());

+

+    printf("free slots: %d (expected 6)\n", config.addAlgo(HashAlgorithm, e));

+

+    AlgorithmEnum e1(HashAlgorithm, "SHA384");

+    printf("free slots: %d (expected 5)\n", config.addAlgoAt(HashAlgorithm, e1, 0));

+    AlgorithmEnum e2 = config.getAlgoAt(HashAlgorithm, 0);

+    printf("algo name: %s (expected SHA384)\n", e2.getName());

+    printf("Num of configured algos: %d (expected 2)\n", config.getNumConfiguredAlgos(HashAlgorithm));

+    config.printConfiguredAlgos(HashAlgorithm);

+    printf("free slots: %d (expected 6)\n", config.removeAlgo(HashAlgorithm, e2));

+    e2 = config.getAlgoAt(HashAlgorithm, 0);

+    printf("algo name: %s (expected SHA256)\n", e2.getName());

+    

+    printf("clearing config\n");

+    config.clear();

+    printf("size: %d\n", zrtpHashes.getSize());

+    e = zrtpHashes.getByName("S256");

+    printf("algo name: %s\n", e.getName());

+    printf("algo type: %d\n", e.getAlgoType());

+

+}

+

+#endif

+/** EMACS **

+ * Local variables:

+ * mode: c++

+ * c-default-style: ellemtel

+ * c-basic-offset: 4

+ * End:

+ */

diff --git a/jni/libzrtp/src/ZrtpCrc32.cpp b/jni/libzrtp/src/ZrtpCrc32.cpp
new file mode 100644
index 0000000..c65b19a
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpCrc32.cpp
@@ -0,0 +1,223 @@
+/* SCTP kernel reference Implementation
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001-2003 International Business Machines, Corp.
+ *
+ * SCTP Checksum functions
+ *
+ * The SCTP reference implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * The SCTP reference implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ *                 ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ *    http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by:
+ *    Dinakaran Joseph
+ *    Jon Grimm <jgrimm@us.ibm.com>
+ *    Sridhar Samudrala <sri@us.ibm.com>
+ *
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+/* The following code has been taken directly from
+ * draft-ietf-tsvwg-sctpcsum-03.txt
+ *
+ * The code has now been modified by Werner.Dittmann@t-online.de for use 
+ * inside the ZRTP implementation.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <libzrtpcpp/ZrtpCrc32.h>
+
+#define CRC32C_POLY 0x1EDC6F41
+#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* Copyright 2001, D. Otis.  Use this program, code or tables    */
+/* extracted from it, as desired without restriction.            */
+/*                                                               */
+/* 32 Bit Reflected CRC table generation for SCTP.               */
+/* To accommodate serial byte data being shifted out least       */
+/* significant bit first, the table's 32 bit words are reflected */
+/* which flips both byte and bit MS and LS positions.  The CRC   */
+/* is calculated MS bits first from the perspective of the serial*/
+/* stream.  The x^32 term is implied and the x^0 term may also   */
+/* be shown as +1.  The polynomial code used is 0x1EDC6F41.      */
+/* Castagnoli93                                                  */
+/* x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+  */
+/* x^11+x^10+x^9+x^8+x^6+x^0                                     */
+/* Guy Castagnoli Stefan Braeuer and Martin Herrman              */
+/* "Optimization of Cyclic Redundancy-Check Codes                */
+/* with 24 and 32 Parity Bits",                                  */
+/* IEEE Transactions on Communications, Vol.41, No.6, June 1993  */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+static const uint32_t crc_c[256] = {
+    0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
+    0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
+    0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+    0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
+    0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
+    0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+    0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
+    0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
+    0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+    0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
+    0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
+    0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+    0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
+    0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
+    0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+    0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
+    0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
+    0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+    0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
+    0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
+    0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+    0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
+    0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
+    0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+    0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
+    0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
+    0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+    0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
+    0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
+    0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+    0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
+    0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
+    0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+    0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
+    0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
+    0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+    0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
+    0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
+    0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+    0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
+    0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
+    0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+    0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
+    0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
+    0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+    0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
+    0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
+    0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+    0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
+    0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
+    0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+    0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
+    0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
+    0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+    0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
+    0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
+    0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+    0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
+    0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
+    0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+    0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
+    0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
+    0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+    0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
+};
+
+
+bool zrtpCheckCksum(uint8_t *buffer, uint16_t length, uint32_t crc32)
+{
+    uint32_t chksum = zrtpGenerateCksum(buffer, length);
+    chksum = zrtpEndCksum(chksum);
+    // fprintf(stderr, "Received crc %x, computed crc: %x\n", crc32, chksum);
+    return (crc32 == chksum);
+}
+
+uint32_t zrtpGenerateCksum(uint8_t *buffer, uint16_t length)
+{
+    uint32_t crc32 = ~(uint32_t) 0;
+    uint32_t i;
+
+    // fprintf(stderr, "Buffer %xl, length: %d\n", buffer, length);
+    /* Calculate the CRC. */
+    for (i = 0; i < length ; i++)
+        CRC32C(crc32, buffer[i]);
+
+    return crc32;
+}
+
+uint32_t zrtpEndCksum(uint32_t crc32)
+{
+    uint32_t result;
+    uint8_t byte0, byte1, byte2, byte3;
+
+    result = ~crc32;
+
+    /*  result  now holds the negated polynomial remainder;
+     *  since the table and algorithm is "reflected" [williams95].
+     *  That is,  result has the same value as if we mapped the message
+     *  to a polyomial, computed the host-bit-order polynomial
+     *  remainder, performed final negation, then did an end-for-end
+     *  bit-reversal.
+     *  Note that a 32-bit bit-reversal is identical to four inplace
+     *  8-bit reversals followed by an end-for-end byteswap.
+     *  In other words, the bytes of each bit are in the right order,
+     *  but the bytes have been byteswapped.  So we now do an explicit
+     *  byteswap.  On a little-endian machine, this byteswap and
+     *  the final ntohl cancel out and could be elided.
+     */
+    byte0 = result & 0xff;
+    byte1 = (result>>8) & 0xff;
+    byte2 = (result>>16) & 0xff;
+    byte3 = (result>>24) & 0xff;
+
+    crc32 = ((byte0 << 24) |
+	     (byte1 << 16) |
+	     (byte2 << 8)  |
+	     byte3);
+    // fprintf(stderr, "Computed crc32: %x\n", crc32);
+    return crc32;
+}
+
+#ifdef UNIT_TEST
+uint8_t test_data[48] = {
+    0x01, 0xC0, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x01, 0xFE, 0x60, 0xAC,
+    0x00, 0x00, 0x00, 0x08,
+    0x00, 0x00, 0x00, 0x04,
+    0x00, 0x00, 0x00, 0x09,
+    0x25, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+};
+    
+int main( int argc, char * argv[] )
+{
+    crc32c =  sctp_update_cksum(test_data, 48);
+    printf("Hello World, expected result: 0x664f75eb\n");
+    printf("Result is: 0x%x\n", crc32c);
+}
+#endif
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/ZrtpPacketClearAck.cpp b/jni/libzrtp/src/ZrtpPacketClearAck.cpp
new file mode 100644
index 0000000..85f1484
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketClearAck.cpp
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketClearAck.h>
+
+ZrtpPacketClearAck::ZrtpPacketClearAck() {
+    DEBUGOUT((fprintf(stdout, "Creating ClearAck packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+
+    setZrtpId();
+    setLength((sizeof(ClearAckPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)ClearAckMsg);
+}
+
+ZrtpPacketClearAck::ZrtpPacketClearAck(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating Conf2Ack packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((ClearAckPacket_t*)data)->hdr;	// the standard header
+}
+
+ZrtpPacketClearAck::~ZrtpPacketClearAck() {
+    DEBUGOUT((fprintf(stdout, "Deleting ClearAck packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketCommit.cpp b/jni/libzrtp/src/ZrtpPacketCommit.cpp
new file mode 100644
index 0000000..97a162a
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketCommit.cpp
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketCommit.h>
+
+ZrtpPacketCommit::ZrtpPacketCommit() {
+    DEBUGOUT((fprintf(stdout, "Creating commit packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+    commitHeader = &data.commit;
+
+    setZrtpId();
+    setLength((sizeof (CommitPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)CommitMsg);
+}
+
+void ZrtpPacketCommit::setNonce(uint8_t* text) {
+    memcpy(commitHeader->hvi, text, sizeof(commitHeader->hvi) - 4 * ZRTP_WORD_SIZE);
+    uint16_t len = getLength();
+    len -= 4;
+    setLength(len);
+}
+
+ZrtpPacketCommit::ZrtpPacketCommit(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating commit packet from data\n")));
+    zrtpHeader = (zrtpPacketHeader_t *)&((CommitPacket_t *)data)->hdr;	// the standard header
+    commitHeader = (Commit_t *)&((CommitPacket_t *)data)->commit;
+}
+
+ZrtpPacketCommit::~ZrtpPacketCommit() {
+    DEBUGOUT((fprintf(stdout, "Deleting commit packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketConf2Ack.cpp b/jni/libzrtp/src/ZrtpPacketConf2Ack.cpp
new file mode 100644
index 0000000..f35dc82
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketConf2Ack.cpp
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketConf2Ack.h>
+
+ZrtpPacketConf2Ack::ZrtpPacketConf2Ack() {
+    DEBUGOUT((fprintf(stdout, "Creating Conf2Ack packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+
+    setZrtpId();
+    setLength((sizeof (Conf2AckPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)Conf2AckMsg);
+}
+
+ZrtpPacketConf2Ack::ZrtpPacketConf2Ack(char *data) {
+    DEBUGOUT((fprintf(stdout, "Creating Conf2Ack packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((Conf2AckPacket_t*)data)->hdr;	// the standard header
+}
+
+ZrtpPacketConf2Ack::~ZrtpPacketConf2Ack() {
+    DEBUGOUT((fprintf(stdout, "Deleting Conf2Ack packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketConfirm.cpp b/jni/libzrtp/src/ZrtpPacketConfirm.cpp
new file mode 100644
index 0000000..f558759
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketConfirm.cpp
@@ -0,0 +1,87 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketConfirm.h>
+
+ZrtpPacketConfirm::ZrtpPacketConfirm() {
+    DEBUGOUT((fprintf(stdout, "Creating Confirm packet without data, no sl data\n")));
+    initialize();
+    setSignatureLength(0);
+}
+
+ZrtpPacketConfirm::ZrtpPacketConfirm(uint32_t sl) {
+    DEBUGOUT((fprintf(stdout, "Creating Confirm packet without data\n")));
+    initialize();
+    setSignatureLength(sl);
+}
+
+void ZrtpPacketConfirm::initialize() {
+    void* allocated = &data;
+    memset(allocated, 0, sizeof(data));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((ConfirmPacket_t *)allocated)->hdr;	// the standard header
+    confirmHeader = (Confirm_t *)&((ConfirmPacket_t *)allocated)->confirm;
+
+    setZrtpId();
+}
+
+bool ZrtpPacketConfirm::setSignatureLength(uint32_t sl) {
+    if (sl > 512)
+        return false;
+
+    int32_t length = sizeof(ConfirmPacket_t) + (sl * ZRTP_WORD_SIZE);
+    confirmHeader->sigLength = sl;                                     // sigLength is a uint byte
+    if (sl & 0x100) {                                                  // check the 9th bit
+        confirmHeader->filler[1] = 1;                                  // and set it if necessary
+    }
+    setLength(length / 4);
+    return true;
+}
+
+bool ZrtpPacketConfirm::setSignatureData(uint8_t* data, int32_t length) {
+    int32_t l = getSignatureLength() * 4;
+    if (length > l || (length % 4) != 0)
+        return false;
+
+    uint8_t* p = ((uint8_t*)&confirmHeader->expTime) + 4;              // point to signature block
+    memcpy(p, data, length);
+    return true;
+}
+
+int32_t ZrtpPacketConfirm::getSignatureLength() {
+    int32_t sl = confirmHeader->sigLength & 0xff;
+    if (confirmHeader->filler[1] == 1) {                              // do we have a 9th bit
+        sl |= 0x100;
+    }
+    return sl;
+}
+
+ZrtpPacketConfirm::ZrtpPacketConfirm(uint8_t* data) {
+    DEBUGOUT((fprintf(stdout, "Creating Confirm packet from data\n")));
+
+    allocated = NULL;
+    zrtpHeader = (zrtpPacketHeader_t *)&((ConfirmPacket_t *)data)->hdr;	// the standard header
+    confirmHeader = (Confirm_t *)&((ConfirmPacket_t *)data)->confirm;
+}
+
+ZrtpPacketConfirm::~ZrtpPacketConfirm() {
+    DEBUGOUT((fprintf(stdout, "Deleting Confirm packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketDHPart.cpp b/jni/libzrtp/src/ZrtpPacketDHPart.cpp
new file mode 100644
index 0000000..8c59233
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketDHPart.cpp
@@ -0,0 +1,98 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketDHPart.h>
+
+ZrtpPacketDHPart::ZrtpPacketDHPart() {
+    DEBUGOUT((fprintf(stdout, "Creating DHPart packet without data and pkt type\n")));
+    initialize();
+}
+
+ZrtpPacketDHPart::ZrtpPacketDHPart(const char* pkt) {
+    DEBUGOUT((fprintf(stdout, "Creating DHPart packet without data\n")));
+    initialize();
+    setPubKeyType(pkt);
+}
+
+void ZrtpPacketDHPart::initialize() {
+
+    void* allocated = &data;
+    memset(allocated, 0, sizeof(data));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((DHPartPacket_t *)allocated)->hdr; // the standard header
+    DHPartHeader = (DHPart_t *)&((DHPartPacket_t *)allocated)->dhPart;
+    pv = ((uint8_t*)allocated) + sizeof(DHPartPacket_t);    // point to the public key value
+
+    setZrtpId();
+}
+
+// The fixed numbers below are taken from ZRTP specification, chap 5.1.5
+void ZrtpPacketDHPart::setPubKeyType(const char* pkt) {
+    // Well - the algo type is only 4 char thus cast to int32 and compare
+    if (*(int32_t*)pkt == *(int32_t*)dh2k) {
+        dhLength = 256;
+    }
+    else if (*(int32_t*)pkt == *(int32_t*)dh3k) {
+        dhLength = 384;
+    }
+    else if (*(int32_t*)pkt == *(int32_t*)ec25) {
+        dhLength = 64;
+    }
+    else if (*(int32_t*)pkt == *(int32_t*)ec38) {
+        dhLength = 96;
+    }
+    else
+        return;
+
+    int length = sizeof(DHPartPacket_t) + dhLength + (2 * ZRTP_WORD_SIZE); // HMAC field is 2*ZRTP_WORD_SIZE
+    setLength(length / ZRTP_WORD_SIZE);
+}
+
+ZrtpPacketDHPart::ZrtpPacketDHPart(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating DHPart packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((DHPartPacket_t *)data)->hdr;  // the standard header
+    DHPartHeader = (DHPart_t *)&((DHPartPacket_t *)data)->dhPart;
+
+    int16_t len = getLength();
+    DEBUGOUT((fprintf(stdout, "DHPart length: %d\n", len)));
+    if (len == 85) {
+        dhLength = 256;
+    }
+    else if (len == 117) {
+        dhLength = 384;
+    }
+    else if (len == 37) {
+        dhLength = 64;
+    }
+    else if (len == 45) {
+        dhLength = 96;
+    }
+    else {
+        pv = NULL;
+        return;
+    }
+    pv = data + sizeof(DHPartPacket_t);    // point to the public key value
+}
+
+ZrtpPacketDHPart::~ZrtpPacketDHPart() {
+    DEBUGOUT((fprintf(stdout, "Deleting DHPart packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketError.cpp b/jni/libzrtp/src/ZrtpPacketError.cpp
new file mode 100644
index 0000000..a9d881e
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketError.cpp
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Copyright (C) 2006
+ *
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketError.h>
+
+ZrtpPacketError::ZrtpPacketError() {
+    DEBUGOUT((fprintf(stdout, "Creating Error packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+    errorHeader = &data.error;
+
+    setZrtpId();
+    setLength((sizeof(ErrorPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)ErrorMsg);
+}
+
+ZrtpPacketError::ZrtpPacketError(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating Error packet from data\n")));
+
+    allocated = NULL;
+    zrtpHeader = (zrtpPacketHeader_t *)&((ErrorPacket_t *)data)->hdr;	// the standard header
+    errorHeader = (Error_t *)&((ErrorPacket_t *)data)->error;
+}
+
+ZrtpPacketError::~ZrtpPacketError() {
+    DEBUGOUT((fprintf(stdout, "Deleting Error packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketErrorAck.cpp b/jni/libzrtp/src/ZrtpPacketErrorAck.cpp
new file mode 100644
index 0000000..3a30977
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketErrorAck.cpp
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketErrorAck.h>
+
+ZrtpPacketErrorAck::ZrtpPacketErrorAck() {
+    DEBUGOUT((fprintf(stdout, "Creating ErrorAck packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+
+    setZrtpId();
+    setLength((sizeof (ErrorAckPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)ErrorAckMsg);
+}
+
+ZrtpPacketErrorAck::ZrtpPacketErrorAck(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating ErrorAck packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((ErrorAckPacket_t*)data)->hdr;	// the standard header
+}
+
+ZrtpPacketErrorAck::~ZrtpPacketErrorAck() {
+    DEBUGOUT((fprintf(stdout, "Deleting ErrorAck packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketGoClear.cpp b/jni/libzrtp/src/ZrtpPacketGoClear.cpp
new file mode 100644
index 0000000..247aec1
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketGoClear.cpp
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Copyright (C) 2006
+ *
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketGoClear.h>
+
+ZrtpPacketGoClear::ZrtpPacketGoClear() {
+    DEBUGOUT((fprintf(stdout, "Creating GoClear packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+    clearHeader = &data.goClear;
+
+    setZrtpId();
+    setLength((sizeof(GoClearPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)GoClearMsg);
+}
+
+ZrtpPacketGoClear::ZrtpPacketGoClear(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating GoClear packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((GoClearPacket_t *)data)->hdr;	// the standard header
+    clearHeader = (GoClear_t *)&((GoClearPacket_t *)data)->goClear;
+}
+
+ZrtpPacketGoClear::~ZrtpPacketGoClear() {
+    DEBUGOUT((fprintf(stdout, "Deleting GoClear packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketHello.cpp b/jni/libzrtp/src/ZrtpPacketHello.cpp
new file mode 100644
index 0000000..17a82d2
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketHello.cpp
@@ -0,0 +1,129 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketHello.h>
+
+
+ZrtpPacketHello::ZrtpPacketHello() {
+    DEBUGOUT((fprintf(stdout, "Creating Hello packet without data\n")));
+}
+
+void ZrtpPacketHello::configureHello(ZrtpConfigure* config) {
+    // The NumSupported* data is in ZrtpTextData.h 
+    nHash = config->getNumConfiguredAlgos(HashAlgorithm);
+    nCipher = config->getNumConfiguredAlgos(CipherAlgorithm);
+    nPubkey = config->getNumConfiguredAlgos(PubKeyAlgorithm);
+    nSas = config->getNumConfiguredAlgos(SasType);
+    nAuth = config->getNumConfiguredAlgos(AuthLength);
+
+    // length is fixed Header plus HMAC size (2*ZRTP_WORD_SIZE)
+    int32_t length = sizeof(HelloPacket_t) + (2 * ZRTP_WORD_SIZE);
+    length += nHash * ZRTP_WORD_SIZE;
+    length += nCipher * ZRTP_WORD_SIZE;
+    length += nPubkey * ZRTP_WORD_SIZE;
+    length += nSas * ZRTP_WORD_SIZE;
+    length += nAuth * ZRTP_WORD_SIZE;
+
+    // Don't change order of this sequence
+    oHash = sizeof(Hello_t);
+    oCipher = oHash + (nHash * ZRTP_WORD_SIZE);
+    oAuth = oCipher + (nCipher * ZRTP_WORD_SIZE);
+    oPubkey = oAuth + (nAuth * ZRTP_WORD_SIZE);
+    oSas = oPubkey + (nPubkey * ZRTP_WORD_SIZE);
+    oHmac = oSas + (nSas * ZRTP_WORD_SIZE);         // offset to HMAC
+
+    void* allocated = &data;
+    memset(allocated, 0, sizeof(data));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((HelloPacket_t *)allocated)->hdr;	// the standard header
+    helloHeader = (Hello_t *)&((HelloPacket_t *)allocated)->hello;
+
+    setZrtpId();
+
+    // minus 1 for CRC size 
+    setLength(length / ZRTP_WORD_SIZE);
+    setMessageType((uint8_t*)HelloMsg);
+
+    setVersion((uint8_t*)zrtpVersion);
+
+    uint32_t lenField = nHash << 16;
+    for (int32_t i = 0; i < nHash; i++) {
+        AlgorithmEnum& hash = config->getAlgoAt(HashAlgorithm, i);
+        setHashType(i, (int8_t*)hash.getName());
+    }
+
+    lenField |= nCipher << 12;
+    for (int32_t i = 0; i < nCipher; i++) {
+        AlgorithmEnum& cipher = config->getAlgoAt(CipherAlgorithm, i);
+        setCipherType(i, (int8_t*)cipher.getName());
+    }
+
+    lenField |= nAuth << 8;
+    for (int32_t i = 0; i < nAuth; i++) {
+        AlgorithmEnum& length = config->getAlgoAt(AuthLength, i);
+        setAuthLen(i, (int8_t*)length.getName());
+    }
+
+    lenField |= nPubkey << 4;
+    for (int32_t i = 0; i < nPubkey; i++) {
+        AlgorithmEnum& pubKey = config->getAlgoAt(PubKeyAlgorithm, i);
+        setPubKeyType(i, (int8_t*)pubKey.getName());
+    }
+
+    lenField |= nSas;
+    for (int32_t i = 0; i < nSas; i++) {
+        AlgorithmEnum& sas = config->getAlgoAt(SasType, i);
+        setSasType(i, (int8_t*)sas.getName());
+    }
+    *((uint32_t*)&helloHeader->flags) = htonl(lenField);
+}
+
+ZrtpPacketHello::ZrtpPacketHello(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating Hello packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((HelloPacket_t *)data)->hdr;	// the standard header
+    helloHeader = (Hello_t *)&((HelloPacket_t *)data)->hello;
+
+    uint32_t t = *((uint32_t*)&helloHeader->flags);
+    uint32_t temp = ntohl(t);
+
+    nHash = (temp & (0xf << 16)) >> 16;
+    nHash &= 0x7;                              // restrict to max 7 algorithms 
+    nCipher = (temp & (0xf << 12)) >> 12;
+    nCipher &= 0x7; 
+    nAuth = (temp & (0xf << 8)) >> 8;
+    nAuth &= 0x7; 
+    nPubkey = (temp & (0xf << 4)) >> 4;
+    nPubkey &= 0x7; 
+    nSas = temp & 0xf;
+    nSas &= 0x7; 
+
+    oHash = sizeof(Hello_t);
+    oCipher = oHash + (nHash * ZRTP_WORD_SIZE);
+    oAuth = oCipher + (nCipher * ZRTP_WORD_SIZE);
+    oPubkey = oAuth + (nAuth * ZRTP_WORD_SIZE);
+    oSas = oPubkey + (nPubkey * ZRTP_WORD_SIZE);
+    oHmac = oSas + (nSas * ZRTP_WORD_SIZE);         // offset to HMAC
+}
+
+ZrtpPacketHello::~ZrtpPacketHello() {
+    DEBUGOUT((fprintf(stdout, "Deleting Hello packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketHelloAck.cpp b/jni/libzrtp/src/ZrtpPacketHelloAck.cpp
new file mode 100644
index 0000000..2d752b7
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketHelloAck.cpp
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketHelloAck.h>
+
+ZrtpPacketHelloAck::ZrtpPacketHelloAck() {
+    DEBUGOUT((fprintf(stdout, "Creating HelloAck packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+
+    setZrtpId();
+    setLength((sizeof(HelloAckPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)HelloAckMsg);
+}
+
+ZrtpPacketHelloAck::ZrtpPacketHelloAck(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating HelloAck packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((HelloAckPacket_t *)data)->hdr;	// the standard header
+
+}
+
+ZrtpPacketHelloAck::~ZrtpPacketHelloAck() {
+    DEBUGOUT((fprintf(stdout, "Deleting HelloAck packet: alloc: %x\n", allocated)));
+}
+
diff --git a/jni/libzrtp/src/ZrtpPacketPing.cpp b/jni/libzrtp/src/ZrtpPacketPing.cpp
new file mode 100644
index 0000000..9a1f90f
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketPing.cpp
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketPing.h>
+
+ZrtpPacketPing::ZrtpPacketPing() {
+    DEBUGOUT((fprintf(stdout, "Creating Ping packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+    pingHeader = &data.ping;
+
+    setZrtpId();
+    setLength((sizeof(PingPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)PingMsg);
+    setVersion((uint8_t*)zrtpVersion);
+}
+
+ZrtpPacketPing::ZrtpPacketPing(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating Ping packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((PingPacket_t*)data)->hdr;	// the standard header
+    pingHeader = (Ping_t *)&((PingPacket_t *)data)->ping;
+}
+
+ZrtpPacketPing::~ZrtpPacketPing() {
+    DEBUGOUT((fprintf(stdout, "Deleting Ping packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketPingAck.cpp b/jni/libzrtp/src/ZrtpPacketPingAck.cpp
new file mode 100644
index 0000000..2331640
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketPingAck.cpp
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketPingAck.h>
+
+ZrtpPacketPingAck::ZrtpPacketPingAck() {
+    DEBUGOUT((fprintf(stdout, "Creating PingAck packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+    pingAckHeader = &data.pingAck;
+
+    setZrtpId();
+    setLength((sizeof(PingAckPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)PingAckMsg);
+    setVersion((uint8_t*)zrtpVersion);
+}
+
+ZrtpPacketPingAck::ZrtpPacketPingAck(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating PingAck packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((PingAckPacket_t*)data)->hdr; // the standard header
+    pingAckHeader = (PingAck_t *)&((PingAckPacket_t *)data)->pingAck;
+}
+
+ZrtpPacketPingAck::~ZrtpPacketPingAck() {
+    DEBUGOUT((fprintf(stdout, "Deleting PingAck packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketRelayAck.cpp b/jni/libzrtp/src/ZrtpPacketRelayAck.cpp
new file mode 100644
index 0000000..6ff0c7a
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketRelayAck.cpp
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2006-20011 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketRelayAck.h>
+
+ZrtpPacketRelayAck::ZrtpPacketRelayAck() {
+    DEBUGOUT((fprintf(stdout, "Creating RelayAck packet without data\n")));
+
+    zrtpHeader = &data.hdr;	// the standard header
+
+    setZrtpId();
+    setLength((sizeof (RelayAckPacket_t) / ZRTP_WORD_SIZE) - 1);
+    setMessageType((uint8_t*)RelayAckMsg);
+}
+
+ZrtpPacketRelayAck::ZrtpPacketRelayAck(uint8_t *data) {
+    DEBUGOUT((fprintf(stdout, "Creating RelayAck packet from data\n")));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((RelayAckPacket_t*)data)->hdr;	// the standard header
+}
+
+ZrtpPacketRelayAck::~ZrtpPacketRelayAck() {
+    DEBUGOUT((fprintf(stdout, "Deleting RelayAck packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpPacketSASrelay.cpp b/jni/libzrtp/src/ZrtpPacketSASrelay.cpp
new file mode 100644
index 0000000..d132e28
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpPacketSASrelay.cpp
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <libzrtpcpp/ZrtpPacketSASrelay.h>
+
+ZrtpPacketSASrelay::ZrtpPacketSASrelay() {
+    DEBUGOUT((fprintf(stdout, "Creating SASrelay packet without data, no sl data\n")));
+    initialize();
+    setSignatureLength(0);
+}
+
+ZrtpPacketSASrelay::ZrtpPacketSASrelay(uint32_t sl) {
+    DEBUGOUT((fprintf(stdout, "Creating SASrelay packet without data\n")));
+    initialize();
+    setSignatureLength(sl);
+}
+
+void ZrtpPacketSASrelay::initialize() {
+    void* allocated = &data;
+    memset(allocated, 0, sizeof(data));
+
+    zrtpHeader = (zrtpPacketHeader_t *)&((SASrelayPacket_t *)allocated)->hdr;	// the standard header
+    sasRelayHeader = (SASrelay_t *)&((SASrelayPacket_t *)allocated)->sasrelay;
+
+    setZrtpId();
+    setMessageType((uint8_t*)SasRelayMsg);
+}
+
+void ZrtpPacketSASrelay::setSignatureLength(uint32_t sl) {
+    sl &= 0x1ff;                                                       // make sure it is max 9 bits
+    int32_t length = sizeof(ConfirmPacket_t) + (sl * ZRTP_WORD_SIZE);
+    sasRelayHeader->sigLength = sl;                                     // sigLength is a uint byte
+    if (sl & 0x100) {                                                  // check the 9th bit
+        sasRelayHeader->filler[1] = 1;                                  // and set it if necessary
+    }
+    setLength(length / 4);
+}
+
+uint32_t ZrtpPacketSASrelay::getSignatureLength() {
+    uint32_t sl = sasRelayHeader->sigLength;
+    if (sasRelayHeader->filler[1] == 1) {                              // do we have a 9th bit
+        sl |= 0x100;
+    }
+    return sl;
+}
+
+ZrtpPacketSASrelay::ZrtpPacketSASrelay(uint8_t* data) {
+    DEBUGOUT((fprintf(stdout, "Creating SASrelay packet from data\n")));
+
+    allocated = NULL;
+    zrtpHeader = (zrtpPacketHeader_t *)&((SASrelayPacket_t *)data)->hdr;	// the standard header
+    sasRelayHeader = (SASrelay_t *)&((SASrelayPacket_t *)data)->sasrelay;
+}
+
+ZrtpPacketSASrelay::~ZrtpPacketSASrelay() {
+    DEBUGOUT((fprintf(stdout, "Deleting SASrelay packet: alloc: %x\n", allocated)));
+}
diff --git a/jni/libzrtp/src/ZrtpQueue.cpp b/jni/libzrtp/src/ZrtpQueue.cpp
new file mode 100644
index 0000000..c9cd0e2
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpQueue.cpp
@@ -0,0 +1,847 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <string>
+#include <stdio.h>
+
+#include <libzrtpcpp/ZrtpQueue.h>
+#include <libzrtpcpp/ZIDFile.h>
+#include <libzrtpcpp/ZRtp.h>
+#include <libzrtpcpp/ZrtpStateClass.h>
+#include <libzrtpcpp/ZrtpUserCallback.h>
+
+static TimeoutProvider<std::string, ost::ZrtpQueue*>* staticTimeoutProvider = NULL;
+
+NAMESPACE_COMMONCPP
+using namespace GnuZrtpCodes;
+
+ZrtpQueue::ZrtpQueue(uint32 size, RTPApplication& app) :
+        AVPQueue(size,app)
+{
+    init();
+}
+
+ZrtpQueue::ZrtpQueue(uint32 ssrc, uint32 size, RTPApplication& app) :
+        AVPQueue(ssrc,size,app)
+{
+    init();
+}
+
+void ZrtpQueue::init()
+{
+    zrtpUserCallback = NULL;
+    enableZrtp = false;
+    started = false;
+    mitmMode = false;
+    enableParanoidMode = false;
+    zrtpEngine = NULL;
+    senderZrtpSeqNo = 1;
+
+    clientIdString = clientId;
+    peerSSRC = 0;
+}
+
+ZrtpQueue::~ZrtpQueue() {
+
+    endQueue();
+    stopZrtp();
+
+    if (zrtpUserCallback != NULL) {
+        delete zrtpUserCallback;
+        zrtpUserCallback = NULL;
+    }
+}
+
+int32_t
+ZrtpQueue::initialize(const char *zidFilename, bool autoEnable, ZrtpConfigure* config)
+{
+    int32_t ret = 1;
+
+    synchEnter();
+
+    ZrtpConfigure* configOwn = NULL;
+    if (config == NULL) {
+        config = configOwn = new ZrtpConfigure();
+        config->setStandardConfig();
+    }
+    enableZrtp = autoEnable;
+
+    config->setParanoidMode(enableParanoidMode);
+
+    if (staticTimeoutProvider == NULL) {
+        staticTimeoutProvider = new TimeoutProvider<std::string, ZrtpQueue*>();
+        staticTimeoutProvider->start();
+    }
+    ZIDFile* zf = ZIDFile::getInstance();
+    if (!zf->isOpen()) {
+        std::string fname;
+        if (zidFilename == NULL) {
+            char *home = getenv("HOME");
+            std::string baseDir = (home != NULL) ? (std::string(home) + std::string("/."))
+                                                    : std::string(".");
+            fname = baseDir + std::string("GNUZRTP.zid");
+            zidFilename = fname.c_str();
+        }
+        if (zf->open((char *)zidFilename) < 0) {
+            enableZrtp = false;
+            ret = -1;
+        }
+    }
+    if (ret > 0) {
+        const uint8_t* ownZid = zf->getZid();
+        zrtpEngine = new ZRtp((uint8_t*)ownZid, (ZrtpCallback*)this, clientIdString, config, mitmMode, signSas);
+    }
+    if (configOwn != NULL) {
+        delete configOwn;
+    }
+    synchLeave();
+    return ret;
+}
+
+void ZrtpQueue::startZrtp() {
+    if (zrtpEngine != NULL) {
+        zrtpEngine->startZrtpEngine();
+        started = true;
+    }
+}
+
+void ZrtpQueue::stopZrtp() {
+    if (zrtpEngine != NULL) {
+        delete zrtpEngine;
+        zrtpEngine = NULL;
+        started = false;
+    }
+}
+
+/*
+ * The takeInDataPacket implementation for ZRTPQueue.
+ */
+size_t
+ZrtpQueue::takeInDataPacket(void)
+{
+    InetHostAddress network_address;
+    tpport_t transport_port;
+
+    uint32 nextSize = (uint32)getNextDataPacketSize();
+    unsigned char* buffer = new unsigned char[nextSize];
+    int32 rtn = (int32)recvData(buffer, nextSize, network_address, transport_port);
+    if ( (rtn < 0) || ((uint32)rtn > getMaxRecvPacketSize()) ){
+        delete buffer;
+        return 0;
+    }
+
+    IncomingZRTPPkt* packet = NULL;
+    // check if this could be a real RTP/SRTP packet.
+    if ((*buffer & 0xf0) != 0x10) {
+        return (rtpDataPacket(buffer, rtn, network_address, transport_port));
+    }
+
+    // We assume all other packets are ZRTP packets here. Process
+    // if ZRTP processing is enabled. Because valid RTP packets are
+    // already handled we delete any packets here after processing.
+    if (enableZrtp && zrtpEngine != NULL) {
+        // Fixed header length + smallest ZRTP packet (includes CRC)
+        if ((unsigned)rtn < (12 + sizeof(HelloAckPacket_t))) // data too small, dismiss
+            return 0;
+
+        // Get CRC value into crc (see above how to compute the offset)
+        uint16_t temp = rtn - CRC_SIZE;
+        uint32_t crc = *(uint32_t*)(buffer + temp);
+        crc = ntohl(crc);
+
+        if (!zrtpCheckCksum(buffer, temp, crc)) {
+            delete buffer;
+            if (zrtpUserCallback != NULL)
+                zrtpUserCallback->showMessage(Warning, WarningCRCmismatch);
+            return 0;
+        }
+
+        packet = new IncomingZRTPPkt(buffer,rtn);
+
+        uint32 magic = packet->getZrtpMagic();
+
+        // Check if it is really a ZRTP packet, if not delete it and return 0
+        if (magic != ZRTP_MAGIC || zrtpEngine == NULL) {
+            delete packet;
+            return 0;
+        }
+        // cover the case if the other party sends _only_ ZRTP packets at the
+        // beginning of a session. Start ZRTP in this case as well.
+        if (!started) {
+            startZrtp();
+         }
+        // this now points beyond the undefined and length field.
+        // We need them, thus adjust
+        unsigned char* extHeader =
+                const_cast<unsigned char*>(packet->getHdrExtContent());
+        extHeader -= 4;
+
+        // store peer's SSRC, used when creating the CryptoContext
+        peerSSRC = packet->getSSRC();
+        zrtpEngine->processZrtpMessage(extHeader, peerSSRC);
+    }
+    delete packet;
+    return 0;
+}
+
+size_t
+ZrtpQueue::rtpDataPacket(unsigned char* buffer, int32 rtn, InetHostAddress network_address, tpport_t transport_port)
+{
+     // Special handling of padding to take care of encrypted content.
+    // In case of SRTP the padding length field is also encrypted, thus
+    // it gives a wrong length. Check and clear padding bit before
+    // creating the RTPPacket. Will be set and re-computed after a possible
+    // SRTP decryption.
+    uint8 padSet = (*buffer & 0x20);
+    if (padSet) {
+        *buffer = *buffer & ~0x20;          // clear padding bit
+    }
+    //  build a packet. It will link itself to its source
+    IncomingRTPPkt* packet =
+        new IncomingRTPPkt(buffer,rtn);
+
+    // Generic header validity check.
+    if ( !packet->isHeaderValid() ) {
+        delete packet;
+        return 0;
+    }
+
+    // Look for a CryptoContext for this packet's SSRC
+    CryptoContext* pcc = getInQueueCryptoContext(packet->getSSRC());
+
+    // If no crypto context is available for this SSRC but we are already in
+    // Secure state then create a CryptoContext for this SSRC.
+    // Assumption: every SSRC stream sent via this connection is secured
+    // _and_ uses the same crypto parameters.
+    if (pcc == NULL) {
+        pcc = getInQueueCryptoContext(0);
+        if (pcc != NULL) {
+            pcc = pcc->newCryptoContextForSSRC(packet->getSSRC(), 0, 0L);
+            if (pcc != NULL) {
+                pcc->deriveSrtpKeys(0);
+                setInQueueCryptoContext(pcc);
+            }
+        }
+    }
+    // If no crypto context: then either ZRTP is off or in early state
+    // If crypto context is available then unprotect data here. If an error
+    // occurs report the error and discard the packet.
+    if (pcc != NULL) {
+        int32 ret;
+        if ((ret = packet->unprotect(pcc)) < 0) {
+            if (!onSRTPPacketError(*packet, ret)) {
+                delete packet;
+                return 0;
+            }
+        }
+        if (started && zrtpEngine->inState(WaitConfAck)) {
+            zrtpEngine->conf2AckSecure();
+        }
+    }
+
+    // virtual for profile-specific validation and processing.
+    if (!onRTPPacketRecv(*packet) ) {
+        delete packet;
+        return 0;
+    }
+    if (padSet) {
+        packet->reComputePayLength(true);
+    }
+    // get time of arrival
+    struct timeval recvtime;
+    gettimeofday(&recvtime,NULL);
+
+    bool source_created;
+    SyncSourceLink* sourceLink =
+            getSourceBySSRC(packet->getSSRC(),source_created);
+    SyncSource* s = sourceLink->getSource();
+    if ( source_created ) {
+        // Set data transport address.
+        setDataTransportPort(*s,transport_port);
+        // Network address is assumed to be the same as the control one
+        setNetworkAddress(*s,network_address);
+        sourceLink->initStats();
+        // First packet arrival time.
+        sourceLink->setInitialDataTime(recvtime);
+        sourceLink->setProbation(getMinValidPacketSequence());
+        if ( sourceLink->getHello() )
+            onNewSyncSource(*s);
+    }
+    else if ( 0 == s->getDataTransportPort() ) {
+        // Test if RTCP packets had been received but this is the
+        // first data packet from this source.
+        setDataTransportPort(*s,transport_port);
+    }
+
+    // Before inserting in the queue,
+    // 1) check for collisions and loops. If the packet cannot be
+    //    assigned to a source, it will be rejected.
+    // 2) check the source is a sufficiently well known source
+    // TODO: also check CSRC identifiers.
+    if (checkSSRCInIncomingRTPPkt(*sourceLink, source_created,
+        network_address, transport_port) &&
+        recordReception(*sourceLink,*packet,recvtime) ) {
+        // now the packet link is linked in the queues
+        IncomingRTPPktLink* packetLink = new IncomingRTPPktLink(packet, sourceLink, recvtime,
+                                       packet->getTimestamp() - sourceLink->getInitialDataTimestamp(),
+                                       NULL,NULL,NULL,NULL);
+        insertRecvPacket(packetLink);
+    } else {
+        // must be discarded due to collision or loop or
+        // invalid source
+        delete packet;
+        return 0;
+    }
+    // Start the ZRTP engine after we got a at least one RTP packet and
+    // sent some as well or we are in multi-stream mode.
+    if (!started && enableZrtp) {
+        startZrtp();
+    }
+    return rtn;
+}
+
+bool
+ZrtpQueue::onSRTPPacketError(IncomingRTPPkt& pkt, int32 errorCode)
+{
+    if (errorCode == -1) {
+        sendInfo(Warning, WarningSRTPauthError);
+    }
+    else {
+        sendInfo(Warning, WarningSRTPreplayError);
+    }
+    return false;
+}
+
+
+void
+ZrtpQueue::putData(uint32 stamp, const unsigned char* data, size_t len)
+{
+    OutgoingDataQueue::putData(stamp, data, len);
+}
+
+
+void
+ZrtpQueue::sendImmediate(uint32 stamp, const unsigned char* data, size_t len)
+{
+    OutgoingDataQueue::sendImmediate(stamp, data, len);
+}
+
+
+/*
+ * Here the callback methods required by the ZRTP implementation
+ */
+int32_t ZrtpQueue::sendDataZRTP(const unsigned char *data, int32_t length) {
+
+    OutgoingZRTPPkt* packet = new OutgoingZRTPPkt(data, length);
+
+    packet->setSSRC(getLocalSSRC());
+
+    packet->setSeqNum(senderZrtpSeqNo++);
+
+    /*
+     * Compute the ZRTP CRC over the full ZRTP packet. Thus include
+     * the fixed packet header into the calculation.
+     */
+    uint16_t temp = packet->getRawPacketSize() - CRC_SIZE;
+    uint8_t* pt = (uint8_t*)packet->getRawPacket();
+    uint32_t crc = zrtpGenerateCksum(pt, temp);
+    // convert and store CRC in crc field of ZRTP packet.
+    crc = zrtpEndCksum(crc);
+
+    // advance pointer to CRC storage
+    pt += temp;
+    *(uint32_t*)pt = htonl(crc);
+
+    dispatchImmediate(packet);
+    delete packet;
+
+    return 1;
+}
+
+bool ZrtpQueue::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;
+
+    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,
+                    0,
+                    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,
+                  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,
+                    0,
+                    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,
+                  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;
+        }
+        // Insert the Crypto templates (SSRC == 0) into the queue. When we send
+        // the first RTP or RTCP packet the real crypto context will be created.
+        // Refer to putData(), sendImmediate() in ccrtp's outqueue.cpp and
+        // takeinControlPacket() in ccrtp's control.cpp.
+        //
+         setOutQueueCryptoContext(senderCryptoContext);
+         setOutQueueCryptoContextCtrl(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,
+                    0,
+                    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,
+                  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,
+                    0,
+                    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,
+                  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;
+        }
+        // Insert the Crypto templates (SSRC == 0) into the queue. When we receive
+        // the first RTP or RTCP packet the real crypto context will be created.
+        // Refer to rtpDataPacket() above and takeinControlPacket in ccrtp's control.cpp.
+        //
+        setInQueueCryptoContext(recvCryptoContext);
+        setInQueueCryptoContextCtrl(recvCryptoContextCtrl);
+    }
+    return true;
+}
+
+void ZrtpQueue::srtpSecretsOn(std::string c, std::string s, bool verified)
+{
+
+  if (zrtpUserCallback != NULL) {
+    zrtpUserCallback->secureOn(c);
+    if (!s.empty()) {
+        zrtpUserCallback->showSAS(s, verified);
+    }
+  }
+}
+
+void ZrtpQueue::srtpSecretsOff(EnableSecurity part) {
+    if (part == ForSender) {
+        removeOutQueueCryptoContext(NULL);
+        removeOutQueueCryptoContextCtrl(NULL);
+    }
+    if (part == ForReceiver) {
+        removeInQueueCryptoContext(NULL);
+        removeInQueueCryptoContextCtrl(NULL);
+    }
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->secureOff();
+    }
+}
+
+int32_t ZrtpQueue::activateTimer(int32_t time) {
+    std::string s("ZRTP");
+    if (staticTimeoutProvider != NULL) {
+        staticTimeoutProvider->requestTimeout(time, this, s);
+    }
+    return 1;
+}
+
+int32_t ZrtpQueue::cancelTimer() {
+    std::string s("ZRTP");
+    if (staticTimeoutProvider != NULL) {
+        staticTimeoutProvider->cancelRequest(this, s);
+    }
+    return 1;
+}
+
+void ZrtpQueue::handleTimeout(const std::string &c) {
+    if (zrtpEngine != NULL) {
+        zrtpEngine->processTimeout();
+    }
+}
+
+void ZrtpQueue::handleGoClear()
+{
+    fprintf(stderr, "Need to process a GoClear message!");
+}
+
+void ZrtpQueue::sendInfo(MessageSeverity severity, int32_t subCode) {
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->showMessage(severity, subCode);
+    }
+}
+
+void ZrtpQueue::zrtpNegotiationFailed(MessageSeverity severity, int32_t subCode) {
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->zrtpNegotiationFailed(severity, subCode);
+    }
+}
+
+void ZrtpQueue::zrtpNotSuppOther() {
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->zrtpNotSuppOther();
+    }
+}
+
+void ZrtpQueue::synchEnter() {
+    synchLock.enter();
+}
+
+void ZrtpQueue::synchLeave() {
+    synchLock.leave();
+}
+
+void ZrtpQueue::zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment  info) {
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->zrtpAskEnrollment(info);
+    }
+}
+
+void ZrtpQueue::zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment  info) {
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->zrtpInformEnrollment(info);
+    }
+}
+
+void ZrtpQueue::signSAS(uint8_t* sasHash) {
+    if (zrtpUserCallback != NULL) {
+        zrtpUserCallback->signSAS(sasHash);
+    }
+}
+
+bool ZrtpQueue::checkSASSignature(uint8_t* sasHash) {
+    if (zrtpUserCallback != NULL) {
+        return zrtpUserCallback->checkSASSignature(sasHash);
+    }
+    return false;
+}
+
+void ZrtpQueue::setEnableZrtp(bool onOff)   {
+    enableZrtp = onOff;
+}
+
+bool ZrtpQueue::isEnableZrtp() {
+    return enableZrtp;
+}
+
+void ZrtpQueue::SASVerified() {
+    if (zrtpEngine != NULL)
+        zrtpEngine->SASVerified();
+}
+
+void ZrtpQueue::resetSASVerified() {
+    if (zrtpEngine != NULL)
+        zrtpEngine->resetSASVerified();
+}
+
+void ZrtpQueue::goClearOk()    {  }
+
+void ZrtpQueue::requestGoClear()  { }
+
+void ZrtpQueue::setAuxSecret(uint8* data, int32_t length)  {
+    if (zrtpEngine != NULL)
+        zrtpEngine->setAuxSecret(data, length);
+}
+
+void ZrtpQueue::setUserCallback(ZrtpUserCallback* ucb) {
+    zrtpUserCallback = ucb;
+}
+
+void ZrtpQueue::setClientId(std::string id) {
+    clientIdString = id;
+}
+
+std::string ZrtpQueue::getHelloHash()  {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getHelloHash();
+    else
+        return std::string();
+}
+
+std::string ZrtpQueue::getPeerHelloHash()  {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getPeerHelloHash();
+    else
+        return std::string();
+}
+
+std::string ZrtpQueue::getMultiStrParams()  {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getMultiStrParams();
+    else
+        return std::string();
+}
+
+void ZrtpQueue::setMultiStrParams(std::string parameters)  {
+    if (zrtpEngine != NULL)
+        zrtpEngine->setMultiStrParams(parameters);
+}
+
+bool ZrtpQueue::isMultiStream()  {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->isMultiStream();
+    return false;
+}
+
+bool ZrtpQueue::isMultiStreamAvailable()  {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->isMultiStreamAvailable();
+    return false;
+}
+
+void ZrtpQueue::acceptEnrollment(bool accepted) {
+    if (zrtpEngine != NULL)
+        zrtpEngine->acceptEnrollment(accepted);
+}
+
+std::string ZrtpQueue::getSasType() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getSasType();
+    else
+        return NULL;
+}
+
+uint8_t* ZrtpQueue::getSasHash() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getSasHash();
+    else
+        return NULL;
+}
+
+bool ZrtpQueue::sendSASRelayPacket(uint8_t* sh, std::string render) {
+
+    if (zrtpEngine != NULL)
+        return zrtpEngine->sendSASRelayPacket(sh, render);
+    else
+        return false;
+}
+
+bool ZrtpQueue::isMitmMode() {
+    return mitmMode;
+}
+
+void ZrtpQueue::setMitmMode(bool mitmMode) {
+    this->mitmMode = mitmMode;
+}
+
+bool ZrtpQueue::isEnrollmentMode() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->isEnrollmentMode();
+    else
+        return false;
+}
+
+void ZrtpQueue::setEnrollmentMode(bool enrollmentMode) {
+    if (zrtpEngine != NULL)
+        zrtpEngine->setEnrollmentMode(enrollmentMode);
+}
+
+void ZrtpQueue::setParanoidMode(bool yesNo) {
+        enableParanoidMode = yesNo;
+}
+
+bool ZrtpQueue::isParanoidMode() {
+        return enableParanoidMode;
+}
+
+bool ZrtpQueue::isPeerEnrolled() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->isPeerEnrolled();
+    else
+        return false;
+}
+
+void ZrtpQueue::setSignSas(bool sasSignMode) {
+    signSas = sasSignMode;
+}
+
+bool ZrtpQueue::setSignatureData(uint8* data, int32 length) {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->setSignatureData(data, length);
+    return 0;
+}
+
+const uint8* ZrtpQueue::getSignatureData() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getSignatureData();
+    return 0;
+}
+
+int32 ZrtpQueue::getSignatureLength() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getSignatureLength();
+    return 0;
+}
+
+int32 ZrtpQueue::getPeerZid(uint8* data) {
+    if (data == NULL)
+        return 0;
+
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getPeerZid(data);
+
+    return 0;
+}
+
+IncomingZRTPPkt::IncomingZRTPPkt(const unsigned char* const block, size_t len) :
+        IncomingRTPPkt(block,len) {
+}
+
+uint32 IncomingZRTPPkt::getZrtpMagic() const {
+     return ntohl(getHeader()->timestamp);
+}
+
+uint32 IncomingZRTPPkt::getSSRC() const {
+     return ntohl(getHeader()->sources[0]);
+}
+
+OutgoingZRTPPkt::OutgoingZRTPPkt(
+    const unsigned char* const hdrext, uint32 hdrextlen) :
+        OutgoingRTPPkt(NULL, 0, hdrext, hdrextlen, NULL ,0, 0, NULL)
+{
+    getHeader()->version = 0;
+    getHeader()->timestamp = htonl(ZRTP_MAGIC);
+}
+
+END_NAMESPACE
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
+
diff --git a/jni/libzrtp/src/ZrtpStateClass.cpp b/jni/libzrtp/src/ZrtpStateClass.cpp
new file mode 100644
index 0000000..cff9c6e
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpStateClass.cpp
@@ -0,0 +1,1473 @@
+/*
+  Copyright (C) 2006-2008 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <ctype.h>
+
+#include <libzrtpcpp/ZRtp.h>
+#include <libzrtpcpp/ZrtpStateClass.h>
+
+using namespace std;
+using namespace GnuZrtpCodes;
+
+state_t states[numberOfStates] = {
+    {Initial,      &ZrtpStateClass::evInitial },
+    {Detect,       &ZrtpStateClass::evDetect },
+    {AckDetected,  &ZrtpStateClass::evAckDetected },
+    {AckSent,      &ZrtpStateClass::evAckSent },
+    {WaitCommit,   &ZrtpStateClass::evWaitCommit },
+    {CommitSent,   &ZrtpStateClass::evCommitSent },
+    {WaitDHPart2,  &ZrtpStateClass::evWaitDHPart2 },
+    {WaitConfirm1, &ZrtpStateClass::evWaitConfirm1 },
+    {WaitConfirm2, &ZrtpStateClass::evWaitConfirm2 },
+    {WaitConfAck,  &ZrtpStateClass::evWaitConfAck },
+    {WaitClearAck, &ZrtpStateClass::evWaitClearAck },
+    {SecureState,  &ZrtpStateClass::evSecureState },
+    {WaitErrorAck, &ZrtpStateClass::evWaitErrorAck }
+};
+
+
+ZrtpStateClass::ZrtpStateClass(ZRtp *p) {
+    parent = p;
+    secSubstate = Normal;
+    engine = new ZrtpStates(states, numberOfStates, Initial);
+
+    commitPkt = NULL;
+    multiStream = false;
+
+    // Set up timers according to ZRTP spec
+    T1.start = 50;
+    T1.maxResend = 20;
+    T1.capping = 200;
+
+    T2.start = 150;
+    T2.maxResend = 10;
+    T2.capping = 600;
+}
+
+ZrtpStateClass::~ZrtpStateClass(void) {
+
+    // If not in Initial state: close the protocol engine
+    // before destroying it. This will free pending packets
+    // if necessary.
+    if (!inState(Initial)) {
+        Event_t ev;
+
+        cancelTimer();
+        ev.type = ZrtpClose;
+        event = &ev;
+        engine->processEvent(*this);
+    }
+    delete engine;
+}
+
+void ZrtpStateClass::processEvent(Event_t *ev) {
+
+    event = ev;
+    char *msg, first, middle, last;
+    uint8_t *pkt;
+
+    parent->synchEnter();
+
+    if (event->type == ZrtpPacket) {
+	pkt = event->packet;
+	msg = (char *)pkt + 4;
+	first = tolower(*msg);
+	middle = tolower(*(msg+4));
+        last = tolower(*(msg+7));
+
+        // Check if this is an Error packet.
+	if (first == 'e' && middle =='r' && last == ' ') {
+            /*
+             * Process a received Error packet.
+             *
+             * In any case stop timer to prevent resending packets.
+             * Use callback method to prepare and get an ErrorAck packet.
+             * Modify event type to "ErrorPkt" and hand it over to current
+             * state for further processing.
+             */
+            cancelTimer();
+            ZrtpPacketError epkt(pkt);
+            ZrtpPacketErrorAck* eapkt = parent->prepareErrorAck(&epkt);
+            parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(eapkt));
+            event->type = ErrorPkt;
+        }
+        else if (first == 'p' && middle == ' ' && last == ' ') {
+            ZrtpPacketPing ppkt(pkt);
+            ZrtpPacketPingAck* ppktAck = parent->preparePingAck(&ppkt);
+            if (ppktAck != NULL) {          // ACK only to valid PING packet, otherwise ignore it 
+                parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck));
+            }
+            parent->synchLeave();
+            return;
+        }
+        else if (first == 's' && last == 'y') {
+            uint32_t errorCode = 0;
+            ZrtpPacketSASrelay* srly = new ZrtpPacketSASrelay(pkt);
+            ZrtpPacketRelayAck* rapkt = parent->prepareRelayAck(srly, &errorCode);
+            parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(rapkt));
+            parent->synchLeave();
+            return;
+        }
+
+    }
+    /*
+     * Shut down protocol state engine: cancel outstanding timer, further
+     * processing in current state.
+     */
+    else if (event->type == ZrtpClose) {
+        cancelTimer();
+    }
+    engine->processEvent(*this);
+    parent->synchLeave();
+}
+
+
+void ZrtpStateClass::evInitial(void) {
+    DEBUGOUT((cout << "Checking for match in Initial.\n"));
+
+    if (event->type == ZrtpInitial) {
+	ZrtpPacketHello* hello = parent->prepareHello();
+
+	// remember packet for easy resend in case timer triggers
+	sentPacket = static_cast<ZrtpPacketBase *>(hello);
+
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed();                 // returns to state Initial
+            return;
+        }
+        if (startTimer(&T1) <= 0) {
+            timerFailed(SevereNoTimer);      // returns to state Initial
+            return;
+        }
+	nextState(Detect);
+    }
+}
+
+/*
+ * Detect state.
+ *
+ * When in this state the protocol engine sent an initial Hello packet
+ * to the peer.
+ *
+ * When entering this state transition function then:
+ * - Assume Initiator mode, mode may change later on peer reaction
+ * - Instance variable sentPacket contains the sent Hello packet
+ * - Hello timer T1 may be active. This is the case if the other peer
+ *   has prepared its RTP session and answers our Hello packets nearly 
+ *   immediately, i.e. before the Hello timeout counter expires. If the
+ *   other peer does not send a Hello during this time the state engine
+ *   reports "other peer does not support ZRTP" but stays
+ *   in state Detect with no active timer (passiv mode). Staying in state 
+ *   Detect allows another peer to start its detect phase any time later.
+ *
+ *   This restart capability is the reason why we use "startTimer(&T1)" in 
+ *   case we received a Hello packet from another peer. This effectively 
+ *   restarts the Hello timeout counter.
+ *
+ *   In this state we also handle ZrtpInitialize event. This forces a
+ *   restart of ZRTP discovery if an application calls ZrtpQueue#startZrtp
+ *   again. This may happen after a previous discovery phase were not 
+ *   successful.
+ *
+ *   Usually applications use some sort of signaling protocol, for example
+ *   SIP, to negotiate the RTP parameters. Thus the RTP sessions setup is
+ *   fairly sychronized and thus also the ZRTP detection phase. Applications
+ *   that use some other ways to setup the RTP sessions this restart capability
+ *   comes in handy because no RTP setup sychronization is necessary.
+ * 
+ * Possible events in this state are:
+ * - timeout for sent Hello packet: causes a resend check and 
+ *   repeat sending of Hello packet
+ * - received a HelloAck: stop active timer, prepare and send Hello packet,
+ *   switch to state AckDeteced.
+ * - received a Hello: stop active timer, send HelloAck, prepare Commit 
+ *   packet, switch to state AckSent.
+ *
+ */
+void ZrtpStateClass::evDetect(void) {
+
+    DEBUGOUT((cout << "Checking for match in Detect.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    /*
+     * First check the general event type, then discrimnate
+     * the real event.
+     */
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+        /*
+         * HelloAck:
+         * - our peer acknowledged our Hello packet, we have not seen the peer's Hello yet
+         * - cancel timer T1 to stop resending Hello
+         * - switch to state AckDetected, wait for peer's Hello (F3)
+         */
+        if (first == 'h' && last =='k') {
+            cancelTimer();
+            sentPacket = NULL;
+            nextState(AckDetected);
+            return;
+        }
+        /*
+         * Hello:
+         * - send HelloAck packet to acknowledge the received Hello packet 
+         * - use received Hello packet to prepare own Commit packet. We need to
+         *   do it at this point because we need the hash value computed from
+         *   peer's Hello packet. Follwing states my use the prepared Commit.
+         * - switch to new state AckSent which sends own Hello packet until 
+         *   peer acknowledges this
+         * - Don't clear sentPacket, points to Hello
+         */
+        if (first == 'h' && last ==' ') {
+            cancelTimer();
+            ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck();
+
+            if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
+                parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
+                return;
+            }
+            // Use peer's Hello packet to create my commit packet, store it 
+            // for possible later usage in state AckSent
+            ZrtpPacketHello hpkt(pkt);
+            commitPkt = parent->prepareCommit(&hpkt, &errorCode);
+
+            nextState(AckSent);
+            if (commitPkt == NULL) {
+                sendErrorPacket(errorCode);    // switches to Error state
+                return;
+            }
+            if (startTimer(&T1) <= 0) {        // restart own Hello timer/counter
+                timerFailed(SevereNoTimer);    // returns to state Initial
+            }
+            T1.maxResend = 60;                 // more retries to extend time, see chap. 6
+        }
+        return;      // unknown packet for this state - Just ignore it
+    }
+    // Timer event triggered - this is Timer T1 to resend Hello
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed();       // returns to state Initial
+            return;
+        }
+        if (nextTimer(&T1) <= 0) {
+            commitPkt = NULL;
+            parent->zrtpNotSuppOther();
+            nextState(Detect);
+        }
+    }
+    // If application call zrtpStart() to restart discovery
+    else if (event->type == ZrtpInitial) {
+        cancelTimer();
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed();                 // returns to state Initial
+            return;
+        }
+        if (startTimer(&T1) <= 0) {
+            timerFailed(SevereNoTimer);   // returns to state Initial
+        }
+    }
+    else { // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+
+/*
+ * AckSent state.
+ *
+ * The protocol engine got a Hello packet from peer and answered with a
+ * HelloAck response.  According to the protocol we must also send a 
+ * Hello after HelloAck (refer to figure 1 in ZRTP RFC xxxx, message 
+ * HelloACK (F2) must be followed by Hello (F3)). We use the timeout in 
+ * this state to send the required Hello (F3).
+ *
+ * Our peer must acknowledge the Hello with HelloAck. In earlier versions 
+ * also a Commit was a valid packet thus the code covers this.
+ * Figure 1 in the RFC shows the HelloAck, chapter 7 states that a Commit 
+ * may be send to acknowledge Hello. There is one constraint when using a Commit to
+ * acknowledge Hello: refer to chapter 4.1 that requires that both parties
+ * have completed the Hello/HelloAck discovery handshake. This implies that 
+ * only message F4 may be replaced by a Commit. This constraint guarantees
+ * that both peers have seen at least one Hello.
+ *
+ * When entering this transition function:
+ * - The instance variabe sentPacket contains own Hello packet
+ * - The instance variabe commitPkt points to prepared Commit packet 
+ * - Timer T1 is active
+ *
+ * Possible events in this state are:
+ * - timeout for sent Hello packet: causes a resend check and repeat sending
+ *   of Hello packet
+ * - HelloAck: The peer answered with HelloAck to own HelloAck/Hello. Send
+ *   prepared Commit packet and try Initiator mode.
+ * - Commit: The peer answered with Commit to HelloAck/Hello, thus switch to
+ *   responder mode.
+ * - Hello: If the protcol engine receives another Hello it repeats the 
+ *   HelloAck/Hello response until Timer T1 exceeds its maximum. This may 
+ *   happen if the other peer sends Hello only (maybe due to network problems)
+ */
+void ZrtpStateClass::evAckSent(void) {
+
+    DEBUGOUT((cout << "Checking for match in AckSent.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    /*
+     * First check the general event type, then discrimnate
+     * the real event.
+     */
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+	msg = (char *)pkt + 4;
+
+	first = tolower(*msg);
+	last = tolower(*(msg+7));
+
+	/*
+         * HelloAck:
+         * The peer answers with HelloAck to own HelloAck/Hello. Send Commit
+         * and try Initiator mode. The requirement defined in chapter 4.1 to
+         * have a complete Hello/HelloAck is fulfilled.
+	 * - stop Hello timer T1
+	 * - send own Commit message
+	 * - switch state to CommitSent, start Commit timer, assume Initiator
+	 */
+	if (first == 'h' && last =='k') {
+	    cancelTimer();
+
+            // remember packet for easy resend in case timer triggers
+            // Timer trigger received in new state CommitSend
+            sentPacket = static_cast<ZrtpPacketBase *>(commitPkt);
+            commitPkt = NULL;                    // now stored in sentPacket
+	    nextState(CommitSent);
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();             // returns to state Initial
+                return;
+            }
+            if (startTimer(&T2) <= 0) {
+                timerFailed(SevereNoTimer);  // returns to state Initial
+	    }
+	    return;
+        }
+        /*
+         * Hello:
+         * - peer didn't receive our HelloAck
+         * - repeat HelloAck/Hello response:
+         *  -- get HelloAck packet, send it
+         *  -- The timeout trigger of T1 sends our Hello packet
+         *  -- stay in state AckSent
+         *
+         * Similar to Detect state: just acknowledge the Hello, the next
+         * timeout sends the following Hello.
+         */
+
+        if (first == 'h' && last ==' ') {
+            ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck();
+
+            if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
+                nextState(Detect);
+                parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
+            }
+            return;
+        }
+        /*
+         * Commit:
+         * The peer answers with Commit to HelloAck/Hello, thus switch to
+         * responder mode.
+         * - stop timer T1
+         * - prepare and send our DHPart1
+         * - switch to state WaitDHPart2 and wait for peer's DHPart2
+         * - don't start timer, we are responder
+         */
+        if (first == 'c') {
+            cancelTimer();
+            ZrtpPacketCommit cpkt(pkt);
+
+            if (!multiStream) {
+                ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&cpkt, &errorCode);
+
+                // Something went wrong during processing of the Commit packet
+                if (dhPart1 == NULL) {
+                    if (errorCode != IgnorePacket) {
+                        sendErrorPacket(errorCode);
+                    }
+                    return;
+                }
+                commitPkt = NULL;
+                sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
+                nextState(WaitDHPart2);
+            }
+            else {
+                ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&cpkt, &errorCode);
+
+                // Something went wrong during processing of the Commit packet
+                if (confirm == NULL) {
+                    if (errorCode != IgnorePacket) {
+                        sendErrorPacket(errorCode);
+                    }
+                    return;
+                }
+                sentPacket = static_cast<ZrtpPacketBase *>(confirm);
+                nextState(WaitConfirm2);
+            }
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();      // returns to state Initial
+            }
+        }
+    }
+    /*
+     * Timer:
+     * - resend Hello packet, stay in state, restart timer until repeat 
+     *   counter triggers
+     * - if repeat counter triggers switch to state Detect, con't clear
+     *   sentPacket, Detect requires it to point to own Hello message
+     */
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            return sendFailed();      // returns to state Initial
+        }
+        if (nextTimer(&T1) <= 0) {
+            parent->zrtpNotSuppOther();
+            commitPkt = NULL;
+            // Stay in state Detect to be prepared get an hello from
+            // other peer any time later
+            nextState(Detect);
+        }
+    }
+    else {   // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        commitPkt = NULL;
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+/*
+ * AckDetected state.
+ *
+ * The protocol engine received a HelloAck in state Detect, thus the peer 
+ * acknowledged our the Hello. According to ZRT RFC xxxx our peer must send
+ * its Hello until our protocol engine sees it (refer also to comment for
+ * state AckSent). This protocol sequence gurantees that both peers got at
+ * least one Hello. 
+ *
+ * When entering this transition function
+ * - instance variable sentPacket is NULL, Hello timer stopped
+ *
+ * Possible events in this state are:
+ * Hello: we have to choices
+ *  1) we can acknowledge the peer's Hello with a HelloAck
+ *  2) we can acknowledge the peer's Hello with a Commit
+ *  Both choices are implemented and may be enabled by setting a compile
+ *  time #if (see code below). Currently we use choice 1) here because
+ *  it's more aligned to the ZRTP specification
+ */
+void ZrtpStateClass::evAckDetected(void) {
+
+    DEBUGOUT((cout << "Checking for match in AckDetected.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+
+#if 1
+        /*
+         * Implementation for choice 1)
+         * Hello:
+         * - Acknowledge peers Hello, sending HelloACK (F4)
+         * - switch to state WaitCommit, wait for peer's Commit
+         * - we are going to be in the Responder role
+         */
+
+        if (first == 'h' && last ==' ') {
+            // Parse Hello packet and build an own Commit packet even if the
+            // Commit is not send to the peer. We need to do this to check the
+            // Hello packet and prepare the shared secret stuff.
+            ZrtpPacketHello hpkt(pkt);
+            ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode);
+
+            // Something went wrong during processing of the Hello packet, for
+            // example wrong version, duplicate ZID.
+            if (commit == NULL) {
+                sendErrorPacket(errorCode);
+                return;
+            }
+            ZrtpPacketHelloAck *helloAck = parent->prepareHelloAck();
+            nextState(WaitCommit);
+
+            // remember packet for easy resend
+            sentPacket = static_cast<ZrtpPacketBase *>(helloAck);
+            if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
+                sendFailed();
+            }
+        }
+#else
+        /*
+         * Implementation for choice 2)
+         * Hello:
+         * - Acknowledge peers Hello by sending Commit (F5)
+         *   instead of HelloAck (F4)
+         * - switch to state CommitSent
+         * - Initiator role, thus start timer T2 to monitor timeout for Commit
+         */
+
+        if (first == 'h') {
+            // Parse peer's packet data into a Hello packet
+            ZrtpPacketHello hpkt(pkt);
+            ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode);
+            // Something went wrong during processing of the Hello packet  
+            if (commit == NULL) {
+                sendErrorPacket(errorCode);
+                return;
+            }
+            nextState(CommitSent);
+
+            // remember packet for easy resend in case timer triggers
+            // Timer trigger received in new state CommitSend
+            sentPacket = static_cast<ZrtpPacketBase *>(commit);
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();
+                return;
+            }
+            if (startTimer(&T2) <= 0) {
+                timerFailed(SevereNoTimer);
+            }
+        }
+#endif
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        nextState(Initial);
+    }
+}
+
+/*
+ * WaitCommit state.
+ *
+ * This state is only used if we use choice 1) in AckDetected.
+ *
+ * When entering this transition function
+ * - instance variable sentPacket contains a HelloAck packet
+ * 
+ * Possible events in this state are:
+ * - Hello: just resend our HelloAck
+ * - Commit: prepare and send our DHPart1 message to start first
+ *   half of DH key agreement. Switch to state WaitDHPart2, don't
+ *   start any timer, we a Responder.
+ */
+void ZrtpStateClass::evWaitCommit(void) {
+
+    DEBUGOUT((cout << "Checking for match in WaitCommit.\n"));
+
+    char *msg, first;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        /*
+         * Hello:
+         * - resend HelloAck
+         * - stay in WaitCommit
+         */
+        if (first == 'h') {
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();       // returns to state Initial
+            }
+            return;
+        }
+        /*
+         * Commit:
+         * - prepare DH1Part packet or Confirm1 if multi stream mode
+         * - send it to peer
+         * - switch state to WaitDHPart2 or WaitConfirm2 if multi stream mode
+         * - don't start timer, we are responder
+         */
+        if (first == 'c') {
+            ZrtpPacketCommit cpkt(pkt);
+
+            if (!multiStream) {
+                ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&cpkt, &errorCode);
+
+                // Something went wrong during processing of the Commit packet
+                if (dhPart1 == NULL) {
+                    if (errorCode != IgnorePacket) {
+                        sendErrorPacket(errorCode);
+                    }
+                    return;
+                }
+                sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
+                nextState(WaitDHPart2);
+            }
+            else {
+                ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&cpkt, &errorCode);
+
+                // Something went wrong during processing of the Commit packet
+                if (confirm == NULL) {
+                    if (errorCode != IgnorePacket) {
+                        sendErrorPacket(errorCode);
+                    }
+                    return;
+                }
+                sentPacket = static_cast<ZrtpPacketBase *>(confirm);
+                nextState(WaitConfirm2);
+            }
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();       // returns to state Initial
+            }
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+
+/*
+ * CommitSent state.
+ *
+ * This state either handles a DH1Part1 message to start the first
+ * half of DH key agreement or it handles a Commit clash. If handling a
+ * Commit clash it may happen that we change our role from Initiator to
+ * Responder.
+ *
+ * When entering this transition function
+ * - assume Initiator mode, may change if we reveice a Commit here
+ * - sentPacket contains Commit packet
+ * - Commit timer (T2) active
+ *
+ * Possible events in this state are:
+ * - timeout for sent Commit packet: causes a resend check and repeat sending
+ *   of Commit packet
+ * - Commit: This is a Commit clash. Break the tie accroding to chapter 5.2
+ * - DHPart1: start first half of DH key agreement. Perpare and send own DHPart2
+ *   and switch to state WaitConfirm1.
+ */
+
+void ZrtpStateClass::evCommitSent(void) {
+
+    DEBUGOUT((cout << "Checking for match in CommitSend.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+
+        /*
+         * HelloAck or Hello:
+         * - delayed "HelloAck" or "Hello", maybe due to network latency, just 
+         *   ignore it
+         * - no switch in state, leave timer as it is
+         */
+        if (first == 'h' && (last =='k' || last == ' ')) {
+            return;
+        }
+
+        /*
+         * Commit:
+         * We have a "Commit" clash. Resolve it.
+         *
+         * - switch off resending Commit
+         * - compare my hvi with peer's hvi
+         * - if my hvi is greater
+         *   - we are Initiator, stay in state, wait for peer's DHPart1 packet
+         * - else
+         *   - we are Responder, stop timer
+         *   - prepare and send DH1Packt,
+         *   - switch to state WaitDHPart2, implies Responder path
+         */
+        if (first == 'c' && last == ' ') {
+            ZrtpPacketCommit zpCo(pkt);
+
+            if (!parent->verifyH2(&zpCo)) {
+                return;
+            }
+            cancelTimer();         // this cancels the Commit timer T2
+
+            // if our hvi is less than peer's hvi: switch to Responder mode and
+            // send DHPart1 or Confirm1 packet. Peer (as Initiator) will retrigger if
+            // necessary
+            //
+            if (parent->compareCommit(&zpCo) < 0) {
+                if (!multiStream) {
+                    ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&zpCo, &errorCode);
+
+                    // Something went wrong during processing of the Commit packet
+                    if (dhPart1 == NULL) {
+                        if (errorCode != IgnorePacket) {
+                            sendErrorPacket(errorCode);
+                        }
+                        return;
+                    }
+                    nextState(WaitDHPart2);
+                    sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
+                }
+                else {
+                    ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&zpCo, &errorCode);
+
+                    // Something went wrong during processing of the Commit packet
+                    if (confirm == NULL) {
+                        if (errorCode != IgnorePacket) {
+                            sendErrorPacket(errorCode);
+                        }
+                        return;
+                    }
+                    nextState(WaitConfirm2);
+                    sentPacket = static_cast<ZrtpPacketBase *>(confirm);
+                }
+                if (!parent->sendPacketZRTP(sentPacket)) {
+                    sendFailed();       // returns to state Initial
+                }
+            }
+            // Stay in state, we are Initiator, wait for DHPart1 of Confirm1 packet from peer.
+            // Resend Commit after timeout until we get a DHPart1 or Confirm1
+            else {
+                if (startTimer(&T2) <= 0) { // restart the Commit timer, gives peer more time to react
+                    timerFailed(SevereNoTimer);    // returns to state Initial
+                }
+            }
+            return;
+        }
+
+        /*
+         * DHPart1:
+         * - switch off resending Commit
+         * - Prepare and send DHPart2
+         * - switch to WaitConfirm1
+         * - start timer to resend DHPart2 if necessary, we are Initiator
+         */
+        if (first == 'd') {
+            cancelTimer();
+            sentPacket = NULL;
+            ZrtpPacketDHPart dpkt(pkt);
+            ZrtpPacketDHPart* dhPart2 = parent->prepareDHPart2(&dpkt, &errorCode);
+
+            // Something went wrong during processing of the DHPart1 packet
+            if (dhPart2 == NULL) {
+                if (errorCode != IgnorePacket) {
+                    sendErrorPacket(errorCode);
+                }
+                else {
+                    if (startTimer(&T2) <= 0) {
+                        timerFailed(SevereNoTimer);       // switches to state Initial
+                    }
+                }
+
+                return;
+            }
+            sentPacket = static_cast<ZrtpPacketBase *>(dhPart2);
+            nextState(WaitConfirm1);
+
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();       // returns to state Initial
+                return;
+            }
+            if (startTimer(&T2) <= 0) {
+                timerFailed(SevereNoTimer);       // switches to state Initial
+            }
+            return;
+        }
+
+        if (multiStream && (first == 'c' && last == '1')) {
+            cancelTimer();
+            ZrtpPacketConfirm cpkt(pkt);
+
+            ZrtpPacketConfirm* confirm = parent->prepareConfirm2MultiStream(&cpkt, &errorCode);
+
+            // Something went wrong during processing of the Confirm1 packet
+            if (confirm == NULL) {
+                sendErrorPacket(errorCode);
+                return;
+            }
+            nextState(WaitConfAck);
+            sentPacket = static_cast<ZrtpPacketBase *>(confirm);
+
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();         // returns to state Initial
+                return;
+            }
+            if (startTimer(&T2) <= 0) {
+                timerFailed(SevereNoTimer);  // returns to state Initial
+                return;
+            }
+            // according to chap 5.6: after sending Confirm2 the Initiator must
+            // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck
+            // state.
+            if (!parent->srtpSecretsReady(ForReceiver)) {
+                parent->sendInfo(Severe, CriticalSWError);
+                sendErrorPacket(CriticalSWError);
+                return;
+            }
+        }
+    }
+    // Timer event triggered, resend the Commit packet
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();       // returns to state Initial
+                return;
+        }
+        if (nextTimer(&T2) <= 0) {
+            timerFailed(SevereTooMuchRetries);       // returns to state Initial
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+
+/*
+ * WaitDHPart2 state.
+ *
+ * This state handles the second part of SH key agreement. Only the Resonder
+ * can enter this state.
+ *
+ * When entering this transition function
+ * - sentPacket contains DHPart1 packet, no timer active
+ *
+ * Possible events in this state are:
+ * - Commit: Our peer didn't receive out DHPart1 thus the peer sends Commit again.
+ *   Just repeat our DHPart1.
+ * - DHPart2: start second half of DH key agreement. Perpare and send own Confirm1
+ *   and switch to state WaitConfirm2.
+ */
+void ZrtpStateClass::evWaitDHPart2(void) {
+
+    DEBUGOUT((cout << "Checking for match in DHPart2.\n"));
+
+    char *msg, first;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        /*
+         * Commit:
+         * - resend DHPart1
+         * - stay in state
+         */
+        if (first == 'c') {
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                return sendFailed();       // returns to state Initial
+            }
+            return;
+        }
+        /*
+         * DHPart2:
+         * - prepare Confirm1 packet
+         * - switch to WaitConfirm2
+         * - No timer, we are responder
+         */
+        if (first == 'd') {
+            ZrtpPacketDHPart dpkt(pkt);
+            ZrtpPacketConfirm* confirm = parent->prepareConfirm1(&dpkt, &errorCode);
+
+            if (confirm == NULL) {
+                if (errorCode != IgnorePacket) {
+                    sendErrorPacket(errorCode);
+                }
+                return;
+            }
+            nextState(WaitConfirm2);
+            sentPacket = static_cast<ZrtpPacketBase *>(confirm);
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();       // returns to state Initial
+            }
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+
+/*
+ * WaitConirm1 state.
+ *
+ * This state handles a received Confirm1 message and only the Initiator
+ * can enter this state.
+ *
+ * When entering this transition function in DH mode:
+ * - Initiator mode
+ * - sentPacket contains DHPart2 packet, DHPart2 timer active
+ *
+ * When entering this transition function in Multi stream mode via AckSent:
+ * - Initiator mode
+ * - sentPacket contains my Commit packet, Commit timer active
+ * 
+* Possible events in this state are:
+ * - timeout for sent DHPart2 packet: causes a resend check and repeat sending
+ *   of DHPart2 packet.
+ * - Confirm1: Check Confirm1 message. If it is ok then prepare and send own
+ *   Confirm2 packet and switch to state WaitConfAck.
+ */
+void ZrtpStateClass::evWaitConfirm1(void) {
+
+    DEBUGOUT((cout << "Checking for match in WaitConfirm1.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+
+        /*
+         * Confirm1:
+         * - Switch off resending DHPart2
+         * - prepare a Confirm2 packet
+         * - switch to state WaitConfAck
+         * - set timer to monitor Confirm2 packet, we are initiator
+         */
+        if (first == 'c' && last == '1') {
+            cancelTimer();
+            ZrtpPacketConfirm cpkt(pkt);
+
+            ZrtpPacketConfirm* confirm = parent->prepareConfirm2(&cpkt, &errorCode);
+
+            // Something went wrong during processing of the Confirm1 packet
+            if (confirm == NULL) {
+                sendErrorPacket(errorCode);
+                return;
+            }
+            nextState(WaitConfAck);
+            sentPacket = static_cast<ZrtpPacketBase *>(confirm);
+
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();         // returns to state Initial
+                return;
+            }
+            if (startTimer(&T2) <= 0) {
+                timerFailed(SevereNoTimer);  // returns to state Initial TODO check for return following this line
+            }
+            // according to chap 5.8: after sending Confirm2 the Initiator must
+            // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck
+            // state.
+            if (!parent->srtpSecretsReady(ForReceiver)) {
+                parent->sendInfo(Severe, CriticalSWError);
+                sendErrorPacket(CriticalSWError);
+                return;
+            }
+        }
+    }
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed();             // returns to state Initial
+            return;
+        }
+        if (nextTimer(&T2) <= 0) {
+            timerFailed(SevereTooMuchRetries);     // returns to state Initial
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+
+/*
+ * WaitConfirm2 state.
+ *
+ * Handles the Confirm2 message that closes the key agreement handshake. Only
+ * the Responder can enter this state. If the Confirm2 message is ok send a 
+ * Conf2Ack to our peer. Switch to secure mode after sending Conf2Ack, our 
+ * peer switches to secure mode after receiving Conf2Ack.
+ *
+ * TODO - revise documentation comments
+ * 
+ * When entering this transition function
+ * - Responder mode
+ * - sentPacket contains Confirm1 packet, no timer active
+ *
+ * Possible events in this state are:
+ * - DHPart2: Our peer didn't receive our Confirm1 thus sends DHPart2 again.
+ *   Just repeat our Confirm1.
+ * - Confirm2: close DH key agreement. Perpare and send own Conf2Ack
+ *   and switch to state SecureState.
+ */
+void ZrtpStateClass::evWaitConfirm2(void) {
+
+    DEBUGOUT((cout << "Checking for match in WaitConfirm2.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+    uint32_t errorCode = 0;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+
+        /*
+         * DHPart2 or Commit in multi stream mode:
+         * - resend Confirm1 packet
+         * - stay in state
+         */
+        if (first == 'd' || (multiStream && (first == 'c' && last == ' '))) {
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();             // returns to state Initial
+            }
+            return;
+        }
+        /*
+         * Confirm2:
+         * - prepare ConfAck
+         * - switch on security (SRTP)
+         * - switch to SecureState
+         */
+        if (first == 'c' && last == '2') {
+            ZrtpPacketConfirm cpkt(pkt);
+            ZrtpPacketConf2Ack* confack = parent->prepareConf2Ack(&cpkt, &errorCode);
+
+            // Something went wrong during processing of the confirm2 packet
+            if (confack == NULL) {
+                sendErrorPacket(errorCode);
+                return;
+            }
+            sentPacket = static_cast<ZrtpPacketBase *>(confack);
+
+            if (!parent->sendPacketZRTP(sentPacket)) {
+                sendFailed();             // returns to state Initial
+                return;
+            }
+            if (!parent->srtpSecretsReady(ForSender) ||
+                !parent->srtpSecretsReady(ForReceiver)) {
+                parent->sendInfo(Severe, CriticalSWError);
+                sendErrorPacket(CriticalSWError);
+                return;
+            }
+            nextState(SecureState);
+            parent->sendInfo(Info, InfoSecureStateOn);
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+
+/*
+ * WaitConf2Ack state.
+ *
+ * This state handles the Conf2Ack message that acknowledges the successfull
+ * processing of Confirm2. Only the Initiator can enter this state. Switch on
+ * secure mode and switch to state SecureState.
+ *
+ * When entering this transition function
+ * - Initiator mode
+ * - sentPacket contains Confirm2 packet, Confirm2 timer active
+ * - receiver security switched on
+ *
+ * Possible events in this state are:
+ * - timeout for sent Confirm2 packet: causes a resend check and repeat sending
+ *   of Confirm2 packet
+ * - Conf2Ack: Key agreement was successfull, switch to secure mode.
+ */
+void ZrtpStateClass::evWaitConfAck(void) {
+
+    DEBUGOUT((cout << "Checking for match in WaitConfAck.\n"));
+
+    char *msg, first;
+    uint8_t *pkt;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+         /*
+         * ConfAck:
+         * - Switch off resending Confirm2
+         * - switch to SecureState
+         */
+        if (first == 'c') {
+            cancelTimer();
+            sentPacket = NULL;
+            // Receiver was already enabled after sending Confirm2 packet
+            // see previous states.
+            if (!parent->srtpSecretsReady(ForSender)) {
+                parent->sendInfo(Severe, CriticalSWError);
+                sendErrorPacket(CriticalSWError);
+                return;
+            }
+            nextState(SecureState);
+            // TODO: call parent to clear signature data at initiator
+            parent->sendInfo(Info, InfoSecureStateOn);
+        }
+    }
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed();             // returns to state Initial
+            parent->srtpSecretsOff(ForReceiver);
+            return;
+        }
+        if (nextTimer(&T2) <= 0) {
+            timerFailed(SevereTooMuchRetries); // returns to state Initial
+            parent->srtpSecretsOff(ForReceiver);
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+        parent->srtpSecretsOff(ForReceiver);
+    }
+}
+
+/*
+ * When entering this transition function
+ * - sentPacket contains GoClear packet, GoClear timer active
+ */
+
+void ZrtpStateClass::evWaitClearAck(void) {
+    DEBUGOUT((cout << "Checking for match in ClearAck.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+
+    if (event->type == ZrtpPacket) {
+	pkt = event->packet;
+	msg = (char *)pkt + 4;
+
+	first = tolower(*msg);
+	last = tolower(*(msg+7));
+
+	/*
+	 * ClearAck:
+	 * - stop resending GoClear,
+	 * - switch to state AckDetected, wait for peer's Hello
+	 */
+	if (first == 'c' && last =='k') {
+	    cancelTimer();
+	    sentPacket = NULL;
+	    nextState(Initial);
+	}
+    }
+    // Timer event triggered - this is Timer T2 to resend GoClear w/o HMAC
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed();                 // returns to state Initial
+            return;
+        }
+        if (nextTimer(&T2) <= 0) {
+            timerFailed(SevereTooMuchRetries);     // returns to state Initial
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+	sentPacket = NULL;
+	nextState(Initial);
+    }
+}
+
+
+/*
+ * WaitErrorAck state.
+ *
+ * This state belongs to the "error handling state overlay" and handle
+ * ErrorAck message. Most of the ZRTP states can send Error message for
+ * example if they detect wrong packets. After sending an Error message
+ * the protocol engine switches to WaitErrorAck state. Receiving an
+ * ErrorAck message completes the ZRTP error handling.
+ *
+ * When entering this transition function
+ * - sentPacket contains Error packet, Error timer active
+ *
+ * Possible events in this state are:
+ * - timeout for sent Error packet: causes a resend check and repeat sending
+ *   of Error packet
+ * - ErrorAck: Stop timer and switch to state Initial.
+ */
+
+void ZrtpStateClass::evWaitErrorAck(void) {
+    DEBUGOUT((cout << "Checking for match in ErrorAck.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+
+        /*
+         * Errorck:
+         * - stop resending Error,
+         * - switch to state Initial
+         */
+        if (first == 'e' && last =='k') {
+            cancelTimer();
+            sentPacket = NULL;
+            nextState(Initial);
+        }
+    }
+    // Timer event triggered - this is Timer T2 to resend Error.
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed();                 // returns to state Initial
+            return;
+        }
+        if (nextTimer(&T2) <= 0) {
+            timerFailed(SevereTooMuchRetries);     // returns to state Initial
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        sentPacket = NULL;
+        nextState(Initial);
+    }
+}
+
+void ZrtpStateClass::evSecureState(void) {
+
+    DEBUGOUT((cout << "Checking for match in SecureState.\n"));
+
+    char *msg, first, last;
+    uint8_t *pkt;
+
+    /*
+     * Handle a possible substate. If substate handling was ok just return.
+     */
+    if (secSubstate == WaitSasRelayAck) {
+        if (subEvWaitRelayAck())
+            return; 
+    }
+
+    if (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+
+        /*
+         * Confirm2:
+         * - resend Conf2Ack packet
+         * - stay in state
+         */
+        if (first == 'c' && last == '2') {
+            if (sentPacket != NULL && !parent->sendPacketZRTP(sentPacket)) {
+                sentPacket = NULL;
+                nextState(Initial);
+                parent->srtpSecretsOff(ForSender);
+                parent->srtpSecretsOff(ForReceiver);
+                parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
+            }
+            return;
+        }
+        /*
+         * GoClear received, handle it. TODO fix go clear handling
+         */
+        if (first == 'g' && last == 'r') {
+            ZrtpPacketGoClear gpkt(pkt);
+            ZrtpPacketClearAck* clearAck = parent->prepareClearAck(&gpkt);
+
+            if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(clearAck))) {
+                return;
+            }
+        // TODO Timeout to resend clear ack until user user confirmation
+        }
+    }
+    else {  // unknown Event type for this state (covers Error and ZrtpClose)
+        sentPacket = NULL;
+        parent->srtpSecretsOff(ForSender);
+        parent->srtpSecretsOff(ForReceiver);
+        nextState(Initial);
+        if (event->type != ZrtpClose) {
+            parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
+        }
+        parent->sendInfo(Info, InfoSecureStateOff);
+    }
+}
+
+bool ZrtpStateClass::subEvWaitRelayAck() {
+    char *msg, first, last;
+    uint8_t* pkt;
+
+    /*
+     * First check the general event type, then discrimnate the real event.
+     */
+    if  (event->type == ZrtpPacket) {
+        pkt = event->packet;
+        msg = (char *)pkt + 4;
+
+        first = tolower(*msg);
+        last = tolower(*(msg+7));
+
+        /*
+         * SAS relayAck:
+         * - stop resending SASRelay,
+         * - switch to secure substate Normal
+         */
+        if (first == 'r' && last =='k') {
+            cancelTimer();
+            secSubstate = Normal;
+            sentPacket = NULL;
+        }
+        return true;
+    }
+    // Timer event triggered - this is Timer T2 to resend Error.
+    else if (event->type == Timer) {
+        if (!parent->sendPacketZRTP(sentPacket)) {
+            sendFailed(); // returns to state Initial
+            return false;
+        }
+        if (nextTimer(&T2) <= 0) {
+            // returns to state initial
+            // timerFailed(ZrtpCodes.SevereCodes.SevereTooMuchRetries);
+            return false;
+        }
+        return true;
+    }
+    return false;
+}
+
+int32_t ZrtpStateClass::startTimer(zrtpTimer_t *t) {
+
+    t->time = t->start;
+    t->counter = 0;
+    return parent->activateTimer(t->time);
+}
+
+int32_t ZrtpStateClass::nextTimer(zrtpTimer_t *t) {
+
+    t->time += t->time;
+    t->time = (t->time > t->capping)? t->capping : t->time;
+    t->counter++;
+    if (t->counter > t->maxResend) {
+        return -1;
+    }
+    return parent->activateTimer(t->time);
+}
+
+void ZrtpStateClass::sendErrorPacket(uint32_t errorCode) {
+    cancelTimer();
+
+    ZrtpPacketError* err = parent->prepareError(errorCode);
+    parent->zrtpNegotiationFailed(ZrtpError, errorCode);
+
+    sentPacket =  static_cast<ZrtpPacketBase *>(err);
+    nextState(WaitErrorAck);
+    if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(err)) || (startTimer(&T2) <= 0)) {
+        sendFailed();
+    }
+}
+
+void ZrtpStateClass::sendSASRelay(ZrtpPacketSASrelay* relay) {
+    cancelTimer();
+    sentPacket = static_cast<ZrtpPacketBase *>(relay);
+    secSubstate = WaitSasRelayAck;
+    if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(relay)) || (startTimer(&T2) <= 0)) {
+        sendFailed();
+    }
+}
+
+void ZrtpStateClass::sendFailed() {
+    sentPacket = NULL;
+    nextState(Initial);
+    parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
+}
+
+void ZrtpStateClass::timerFailed(int32_t subCode) {
+    sentPacket = NULL;
+    nextState(Initial);
+    parent->zrtpNegotiationFailed(Severe, subCode);
+}
+
+void ZrtpStateClass::setMultiStream(bool multi) {
+    multiStream = multi;
+}
+
+bool ZrtpStateClass::isMultiStream() {
+    return multiStream;
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/ZrtpTextData.cpp b/jni/libzrtp/src/ZrtpTextData.cpp
new file mode 100644
index 0000000..5861099
--- /dev/null
+++ b/jni/libzrtp/src/ZrtpTextData.cpp
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2006-2008 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+#include <stdint.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+//                             1
+//                    1234567890123456
+char clientId[] =    "GNU ZRTP 2.1.0  "; // 16 chars max.
+char zrtpVersion[] = "1.10";             // must be 4 chars
+/**
+ *
+ */
+char HelloMsg[]    = "Hello   ";
+char HelloAckMsg[] = "HelloACK";
+char CommitMsg[]   = "Commit  ";
+char DHPart1Msg[]  = "DHPart1 ";
+char DHPart2Msg[]  = "DHPart2 ";
+char Confirm1Msg[] = "Confirm1";
+char Confirm2Msg[] = "Confirm2";
+char Conf2AckMsg[] = "Conf2ACK";
+char ErrorMsg[]    = "Error   ";
+char ErrorAckMsg[] = "ErrorACK";
+char GoClearMsg[]  = "GoClear ";
+char ClearAckMsg[] = "ClearACK";
+char PingMsg[]     = "Ping    ";
+char PingAckMsg[]  = "PingACK ";
+char SasRelayMsg[] = "SASrelay";
+char RelayAckMsg[] = "RelayACK";
+
+char responder[]      = "Responder";
+char initiator[]      = "Initiator";
+char iniMasterKey[]   = "Initiator SRTP master key";
+char iniMasterSalt[]  = "Initiator SRTP master salt";
+char respMasterKey[]  = "Responder SRTP master key";
+char respMasterSalt[] = "Responder SRTP master salt";
+
+char iniHmacKey[]  = "Initiator HMAC key";
+char respHmacKey[] = "Responder HMAC key";
+char retainedSec[] = "retained secret";
+
+char iniZrtpKey[]  = "Initiator ZRTP key";
+char respZrtpKey[] = "Responder ZRTP key";
+
+char sasString[] = "SAS";
+
+char KDFString[] = "ZRTP-HMAC-KDF";
+
+char zrtpSessionKey[] = "ZRTP Session Key";
+
+char zrtpMsk[] = "ZRTP MSK";
+char zrtpTrustedMitm[] = "Trusted MiTM key";
+
+char s256[] = "S256";
+char s384[] = "S384";
+const char* mandatoryHash = s256;
+
+char aes3[] = "AES3";
+char aes2[] = "AES2";
+char aes1[] = "AES1";
+char two3[] = "2FS3";
+char two2[] = "2FS2";
+char two1[] = "2FS1";
+const char* mandatoryCipher = aes1;
+
+char dh2k[] = "DH2k";
+char ec25[] = "EC25";
+char dh3k[] = "DH3k";
+char ec38[] = "EC38";
+char mult[] = "Mult";
+const char* mandatoryPubKey = dh3k;
+
+char b32[] = "B32 ";
+const char* mandatorySasType = b32;
+
+char hs32[] = "HS32";
+char hs80[] = "HS80";
+char sk32[] = "SK32";
+char sk64[] = "SK64";
+const char* mandatoryAuthLen_1 = hs32;
+const char* mandatoryAuthLen_2 = hs80;
diff --git a/jni/libzrtp/src/libzrtpcpp/Base32.h b/jni/libzrtp/src/libzrtpcpp/Base32.h
new file mode 100644
index 0000000..fbe2983
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/Base32.h
@@ -0,0 +1,228 @@
+#ifndef BASE32_H
+#define BASE32_H
+
+/*
+ *
+ * Copyright (c) 2002 Bryce "Zooko" Wilcox-O'Hearn Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software to
+ * deal in this software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of this software, and to permit persons to whom this software
+ * is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THIS SOFTWARE.
+ *
+ * Converted to C++ by:
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+/**
+ * @file Base32.h
+ * @brief C++ implmentation of the Base32 encoding and decoding
+ * 
+ * ZRTP uses the base 32 encoding and decoding to generate the Short 
+ * Authentication String (SAS).
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <iostream>
+#include <cstdlib>
+
+#include <string.h>
+#include <assert.h>
+#include <stddef.h>
+
+using namespace std;
+
+extern int divceil(int a, int b);
+
+class Base32 {
+
+ public:
+
+    /**
+     * A Constructor that decodes from base32 into binary.
+     *
+     * The constructor decodes the base32 encoded data back into binary
+     * data. Use <code>getDecoded(...)</code> to get the binary data.
+     *
+     * @param encoded
+     *     The string that contains the base32 encoded data.
+     */
+    Base32(const string encoded);
+
+    /**
+     * A Constructor that decodes from base32 into binary.
+     *
+     * This constructor decodes the base32 encoded data back into
+     * binary data. Only the specified number of bits are decoded
+     * (should be a multiple of 5).  Use
+     * <code>getDecoded(...)</code> to get the binary data.
+     *
+     * @param encoded
+     *     The string that contains the base32 encoded data.
+     * @param noOfBits
+     *     How many bits to decode into binary data.
+     */
+    Base32(const string encoded, int noOfBits);
+
+    /**
+     * A Constructor that encodes binary data.
+     *
+     * The constructor converts the first specified number of bits of
+     * the binary data into a base32 presentation. Use
+     * <code>getEncoded</code> to get the encoded data.
+     *
+     * @param data
+     *    A pointer to the first bits (byte) of binary data
+     * @param noOfBits
+     *    How many bits to use for encoding. Should be a
+     *    multiple of 5.
+     */
+    Base32(const unsigned char* data, int noOfBits);
+
+    ~Base32();
+
+    /**
+     * Get the decoded binary data and its length.
+     *
+     * The method returns the decoded binary data if the appropriate
+     * Constructor was used. Otherwise we return <code>NULL</code>
+     * pointer and length zero.
+     *
+     * <em>Note:</em> This method returns a pointer to the decoded
+     * binary data. The Base32 object manages this pointer, thus you
+     * may need to copy the data to a save place before deleting this
+     * object. If the object is deleted this pointer is no longer
+     * valid.
+     *
+     * @param length
+     *     A reference to an integer.
+     * @return
+     *     A pointer to the decoded binary data.
+     */
+    const unsigned char* getDecoded(int &length);
+
+    /**
+     * Get the encoded base32 string.
+     *
+     * The method returns a string that contains the base32 encoded
+     * data if the appropriate constructor was used. Otherwise we
+     * return an empty string.
+     *
+     * @return
+     *     The string containing the base32 encoded data.
+     */
+    const string getEncoded() { return encoded; };
+
+    /**
+     * Compute the number of base32 encoded characters given the
+     * number of bits.
+     *
+     * @param lengthInBits
+     *      The length of the data in bits
+     * @return
+     *      The length of the base-32 encoding of the data in characters
+     */
+    static size_t const b2alen(const size_t lengthInBits) {
+	return divceil(lengthInBits, 5); };
+
+ private:
+
+    /**
+     * Decodes a string with base32 presentation into binary data.
+     *
+     * a2b_l() will return a result big enough to hold lengthinbits bits.  So
+     * for example if cs is 4 characters long (encoding at least 15 and up to
+     * 20 bits) and lengthinbits is 16, then a2b_l() will return a string of
+     * length 2 (since 2 bytes is sufficient to store 16 bits).  If cs is 4
+     * characters long and lengthinbits is 20, then a2b_l() will return a
+     * string of length 3 (since 3 bytes is sufficient to store 20 bits). Note
+     * that `b2a_l()' does not mask off unused least-significant bits, so for
+     * example if cs is 4 characters long and lengthinbits is 17, then you
+     * must ensure that all three of the unused least-significant bits of cs
+     * are zero bits or you will get the wrong result. This precondition is
+     * tested by assertions if assertions are enabled. (Generally you just
+     * require the encoder to ensure this consistency property between the
+     * least significant zero bits and value of `lengthinbits', and reject
+     * strings that have a length-in-bits which isn't a multiple of 8 and yet
+     * don't have trailing zero bits, as improperly encoded.)
+     *
+     * @param cs
+     *    The data to be decoded
+     * @param size
+     *    The length of the input data buffer. Usually divceil(length in bits, 5).
+     * @param lengthinbits
+     *    The number of bits of data in <code>cs</code> to be decoded
+     */
+    void a2b_l(const string cs, size_t size, const size_t lengthinbits);
+
+    /**
+     * Encodes binary to to base32 presentation.
+     *
+     * b2a_l() will generate a base-32 encoded string big enough to encode
+     * lengthinbits bits.  So for example if os is 2 bytes long and
+     * lengthinbits is 15, then b2a_l() will generate a 3-character- long
+     * base-32 encoded string (since 3 quintets is sufficient to encode 15
+     * bits). If os is 2 bytes long and lengthinbits is 16 (or None), then
+     * b2a_l() will generate a 4-character string.  Note that `b2a_l()' does
+     * not mask off unused least-significant bits, so for example if os is 2
+     * bytes long and lengthinbits is 15, then you must ensure that the unused
+     * least-significant bit of os is a zero bit or you will get the wrong
+     * result.  This precondition is tested by assertions if assertions are
+     * enabled.
+     *
+     * Warning: if you generate a base-32 encoded string with `b2a_l()', and
+     * then someone else tries to decode it by calling `a2b()' instead of
+     * `a2b_l()', then they will (probably) get a different string than the
+     * one you encoded!  So only use `b2a_l()' when you are sure that the
+     * encoding and decoding sides know exactly which `lengthinbits' to use.
+     * If you do not have a way for the encoder and the decoder to agree upon
+     * the lengthinbits, then it is best to use `b2a()' and `a2b()'.  The only
+     * drawback to using `b2a()' over `b2a_l()' is that when you have a number
+     * of bits to encode that is not a multiple of 8, `b2a()' can sometimes
+     * generate a base-32 encoded string that is one or two characters longer
+     * than necessary.
+     *
+     * @param cs
+     *     Pointer to binary data.
+     * @param len
+     *     Length of the binary data buffer. Usually (noOfBits+7)/8.
+     * @param noOfBits
+     *    The number of bits of data in encoded into `cs'
+     */
+    void b2a_l(const unsigned char* cs, int len, const size_t noOfBits);
+
+    /**
+     * Holds the pointer to decoded binary data
+     */
+    unsigned char *binaryResult;
+
+    /**
+     * Length of decoding result
+     */
+    int resultLength;
+
+    /**
+     * The string containing the base32 encoded data.
+     */
+    string encoded;
+
+    unsigned char smallBuffer[128];
+};
+
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/CMakeLists.txt b/jni/libzrtp/src/libzrtpcpp/CMakeLists.txt
new file mode 100755
index 0000000..099a233
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/CMakeLists.txt
@@ -0,0 +1,9 @@
+
+if(enable_ccrtp)
+  set(ccrtp_inst ZrtpQueue.h zrtpccrtp.h ZrtpUserCallback.h TimeoutProvider.h)
+endif()
+
+install(FILES 
+    ZrtpCodes.h ZrtpConfigure.h ZrtpCallback.h ZrtpCWrapper.h 
+    ${ccrtp_inst} DESTINATION include/libzrtpcpp)
+
diff --git a/jni/libzrtp/src/libzrtpcpp/TimeoutProvider.h b/jni/libzrtp/src/libzrtpcpp/TimeoutProvider.h
new file mode 100644
index 0000000..d24c7fc
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/TimeoutProvider.h
@@ -0,0 +1,303 @@
+/*
+  Copyright (C) 2006, 2005, 2004 Erik Eliasson, Johan Bilien, Werner Dittmann
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifndef TIMEOUTPROVIDER_H
+#define TIMEOUTPROVIDER_H
+
+/**
+ * Provides a way to request timeouts after a number of milli seconds.
+ *
+ * A command is associated to each timeout.
+ *
+ * Modified to use the common c++ library functions and the STL
+ * list by Werner Dittmann.
+ *
+ * @author Erik Eliasson, eliasson@it.kth.se, 2003
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <list>
+#include <sys/time.h>
+
+#include <config.h>
+#include <cc++/thread.h>
+
+/**
+ * Represents a request of a "timeout" (delivery of a command to a
+ * "timeout receiver" after at least a specified time period).
+ *
+ * Slightly modified to use gettimeofday directly.
+ *
+ * NOTE: This class is only used internaly.
+ * @author Erik Eliasson
+ * @author Werner Dittmann
+ */
+template <class TOCommand, class TOSubscriber>
+class TPRequest
+{
+
+public:
+
+    TPRequest( TOSubscriber tsi, int timeoutMs, const TOCommand &command):
+    subscriber(tsi)
+    {
+        struct timeval tv;
+        gettimeofday(&tv, NULL );
+
+        when_ms = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000;
+    when_ms += timeoutMs;
+    this->command = command;
+    }
+
+    /**
+     * @param t  ms since Epoch
+     */
+    bool happensBefore(uint64 t)
+    {
+    if (when_ms < t) {
+        return true;
+    }
+    if (when_ms > t) {
+        return false;
+    }
+    return false; // if equal it does not "happens_before"
+
+    }
+
+    bool happensBefore(const TPRequest *req){
+    return happensBefore(req->when_ms);
+    }
+
+    /**
+     * Number of milli seconds until timeout from when this method is
+     * called
+     */
+    int getMsToTimeout ()
+    {
+        struct timeval tv;
+        gettimeofday(&tv, NULL );
+
+        uint64 now = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000;
+
+    if (happensBefore(now)) {
+        return 0;
+    }
+    else {
+        return (int)(when_ms - now);
+    }
+    }
+
+    TOCommand getCommand()
+    {
+    return command;
+    }
+
+    TOSubscriber getSubscriber()
+    {
+    return subscriber;
+    }
+
+    /**
+     * Two timeout requests are considered equeal if they have
+     * the same subscriber AND command AND time when they
+     * occur. If one of the time is zero then this is a
+     * wildcard and matches always.
+     */
+    bool operator==(const TPRequest<TOCommand, TOSubscriber> &req)
+    {
+    if (req.subscriber == subscriber &&
+               req.command == command &&
+               req.when_ms == when_ms) {
+            return true;
+        }
+        return false;
+    }
+
+private:
+    TOSubscriber subscriber;
+    uint64 when_ms;     // Time since Epoch in ms when the timeout
+                // will happen
+
+    TOCommand command;      // Command that will be delivered to the
+                // receiver (subscriber) of the timeout.
+};
+
+/**
+ * Class to generate objects giving timeout functionality.
+ *
+ * @author Erik Eliasson
+ * @author Werner Dittmann
+ */
+template<class TOCommand, class TOSubscriber>
+        class TimeoutProvider : public ost::Thread, ost::Event {
+
+public:
+
+    /**
+     * Timeout Provide Constructor
+     */
+    TimeoutProvider(): requests(), synchLock(), stop(false)  { }
+
+    /**
+     * Destructor also terminates the Timeout thread.
+     */
+    ~TimeoutProvider() {
+    terminate();
+    }
+
+    /**
+     * Terminates the Timeout provider thread.
+     */
+    void stopThread(){
+    stop = true;
+    signal();       // signal event to waiting thread
+    }
+
+    /**
+     * Request a timeout trigger.
+     *
+     * @param time_ms   Number of milli-seconds until the timeout is
+     *          wanted. Note that a small additional period of time is
+     *          added that depends on execution speed.
+     * @param subscriber The receiver of the callback when the command has timed
+     *          out. This argument must not be NULL.
+     * @param command   Specifies the String command to be passed back in the
+     *          callback.
+     */
+    void requestTimeout(int32_t time_ms, TOSubscriber subscriber, const TOCommand &command)
+    {
+        TPRequest<TOCommand, TOSubscriber>* request =
+                new TPRequest<TOCommand, TOSubscriber>(subscriber, time_ms, command);
+
+        synchLock.enter();
+
+    if (requests.size()==0) {
+        requests.push_front(request);
+        signal();
+        synchLock.leave();
+        return;
+    }
+        if (request->happensBefore(requests.front())) {
+        requests.push_front(request);
+        signal();
+            synchLock.leave();
+        return;
+    }
+        if (requests.back()->happensBefore(request)){
+        requests.push_back(request);
+        signal();
+            synchLock.leave();
+        return;
+    }
+
+        typename std::list<TPRequest<TOCommand, TOSubscriber>* >::iterator i;
+        for(i = requests.begin(); i != requests.end(); i++ ) {
+            if( request->happensBefore(*i)) {
+                requests.insert(i, request);
+                break;
+            }
+        }
+    signal();
+    synchLock.leave();
+    }
+
+    /**
+     * Removes timeout requests that belong to a subscriber and command.
+     *
+     * @see requestTimeout
+     */
+    void cancelRequest(TOSubscriber subscriber, const TOCommand &command)
+    {
+        synchLock.enter();
+        typename std::list<TPRequest<TOCommand, TOSubscriber>* >::iterator i;
+        for(i = requests.begin(); i != requests.end(); ) {
+            if( (*i)->getCommand() == command &&
+                (*i)->getSubscriber() == subscriber) {
+                i = requests.erase(i);
+                continue;
+            }
+            i++;
+        }
+    synchLock.leave();
+    }
+
+protected:
+
+    void run()
+    {
+    do {
+        synchLock.enter();
+        int32_t time = 3600000;
+        int32_t size = 0;
+        if ((size = requests.size()) > 0) {
+                time = requests.front()->getMsToTimeout();
+            }
+        if (time == 0 && size > 0) {
+        if (stop){  // This must be checked so that we will
+                // stop even if we have timeouts to deliver.
+                    synchLock.leave();
+            return;
+        }
+                TPRequest<TOCommand, TOSubscriber>* req = requests.front();
+        TOSubscriber subs = req->getSubscriber();
+        TOCommand command = req->getCommand();
+
+                requests.pop_front();
+
+        synchLock.leave(); // call the command with free Mutex
+        subs->handleTimeout(command);
+        continue;
+        }
+        synchLock.leave();
+        if (stop) {     // If we were told to stop while delivering
+                                // a timeout we will exit here
+        return;
+        }
+        reset();        // ready to receive triggers again
+            wait(time);
+        if (stop) {     // If we are told to exit while waiting we
+                                // will exit
+        return;
+        }
+    } while(true);
+    }
+
+private:
+
+    // The timeouts are ordered in the order of which they
+    // will expire. Nearest in future is first in list.
+    std::list<TPRequest<TOCommand, TOSubscriber> *> requests;
+
+    ost::Mutex synchLock;   // Protects the internal data structures
+
+    bool stop;      // Flag to tell the worker thread
+                        // to terminate. Set to true and
+                        // wake the worker thread to
+                        // terminate it.
+};
+
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/ZIDFile.h b/jni/libzrtp/src/libzrtpcpp/ZIDFile.h
new file mode 100644
index 0000000..0637c27
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZIDFile.h
@@ -0,0 +1,157 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+
+#include <libzrtpcpp/ZIDRecord.h>
+
+#ifndef _ZIDFILE_H_
+#define _ZIDFILE_H_
+/**
+ * @file ZIDFile.h
+ * @brief ZID file management
+ *
+ * A ZID file stores (caches) some data that helps ZRTP to achives its
+ * key continuity feature. See @c ZIDRecord for further info which data
+ * the ZID file contains.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+/**
+ * This class implements a ZID (ZRTP Identifiers) file.
+ *
+ * The ZID file holds information about peers.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZIDFile {
+
+private:
+
+    FILE* zidFile;
+    unsigned char associatedZid[IDENTIFIER_LEN];
+    /**
+     * The private ZID file constructor.
+     *
+     */
+    ZIDFile(): zidFile(NULL) {};
+    ~ZIDFile();
+    void createZIDFile(char* name);
+    void checkDoMigration(char* name);
+
+public:
+
+    /**
+     * Get the an instance of ZIDFile.
+     *
+     * This method just creates an instance an store a pointer to it
+     * in a static variable. The ZIDFile is a singleton, thus only
+     * <em>one</em> ZID file can be open at one time.
+     *
+     * @return
+     *    A pointer to the global ZIDFile singleton instance.
+     */
+    static ZIDFile* getInstance();
+    /**
+     * Open the named ZID file and return a ZID file class.
+     *
+     * This static function either opens an existing ZID file or
+     * creates a new ZID file with the given name. The ZIDFile is a
+     * singleton, thus only <em>one</em> ZID file can be open at one
+     * time.
+     *
+     * To open another ZID file you must close the active ZID file
+     * first.
+     *
+     * @param name
+     *    The name of the ZID file to open or create
+     * @return
+     *    1 if file could be opened/created, 0 if the ZID instance
+     *    already has an open file, -1 if open/creation of file failed.
+     */
+    int open(char *name);
+
+    /**
+     * Check if ZIDFile has an active (open) file.
+     *
+     * @return
+     *    True if ZIDFile has an active file, false otherwise
+     */
+    bool isOpen() { return (zidFile != NULL); };
+
+     /**
+     * Close the ZID file.
+     * Closes the ZID file, and prepares to open a new ZID file.
+     */
+    void close();
+
+    /**
+     * Get a ZID record from the active ZID file.
+     *
+     * The method get the identifier data from the ZID record parameter,
+     * locates the record in the ZID file and fills in the RS1, RS2, and
+     * other data.
+     *
+     * If no matching record exists in the ZID file the method creates
+     * it and fills it with default values.
+     *
+     * @param zidRecord
+     *    The ZID record that contains the identifier data. The method
+     *    fills in data .
+     * @return
+     *    Currently always 1 to indicate sucess
+     */
+    unsigned int getRecord(ZIDRecord* zidRecord);
+
+    /**
+     * Save a ZID record into the active ZID file.
+     *
+     * This method saves the content of a ZID record into the ZID file. Before
+     * you can save the ZID record you must have performed a getRecord()
+     * first.
+     *
+     * @param zidRecord
+     *    The ZID record to save.
+     * @return
+     *    1 on success
+     */
+    unsigned int saveRecord(ZIDRecord *zidRecord);
+
+    /**
+     * Get the ZID associated with this ZID file.
+     *
+     * @return
+     *    Pointer to the ZID
+     */
+    const unsigned char* getZid() { return associatedZid; };
+};
+
+/**
+ * @}
+ */
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/ZIDRecord.h b/jni/libzrtp/src/libzrtpcpp/ZIDRecord.h
new file mode 100644
index 0000000..eb2d190
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZIDRecord.h
@@ -0,0 +1,307 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZIDRECORD_H_
+#define _ZIDRECORD_H_
+
+
+/**
+ * @file ZIDRecord.h
+ * @brief ZID record management
+ *
+ * A ZID record stores (caches) ZID (ZRTP ID) specific data that helps ZRTP
+ * to achives its key continuity feature. Please refer to the ZRTP
+ * specification to get detailed information about the ZID.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+#define IDENTIFIER_LEN  12
+#define RS_LENGTH       32
+#define TIME_LENGTH      8      // 64 bit, can hold time on 64 bit systems
+
+/**
+ * This is the recod structure of version 1 ZID records.
+ *
+ * This is not longer in use - only during migration.
+ */
+typedef struct zidrecord1 {
+    char recValid;  //!< if 1 record is valid, if 0: invalid
+    char ownZid;    //!< if >1 record contains own ZID, usually 1st record
+    char rs1Valid;  //!< if 1 RS1 contains valid data
+    char rs2Valid;  //!< if 1 RS2 contains valid data
+    unsigned char identifier[IDENTIFIER_LEN]; ///< the peer's ZID or own ZID
+    unsigned char rs1Data[RS_LENGTH], rs2Data[RS_LENGTH]; ///< the peer's RS data
+} zidrecord1_t;
+
+/**
+ * This is the recod structure of version 2 ZID records.
+ */
+typedef struct zidrecord2 {
+    char version;   ///< version number of file format, this is #2
+    char flags;     ///< bit field holding various flags, see below
+    char filler1;   ///< round up to next 32 bit
+    char filler2;   ///< round up to next 32 bit
+    unsigned char identifier[IDENTIFIER_LEN]; ///< the peer's ZID or own ZID
+    unsigned char rs1Interval[TIME_LENGTH];   ///< expiration time of RS1; -1 means indefinite
+    unsigned char rs1Data[RS_LENGTH];         ///< the peer's RS2 data
+    unsigned char rs2Interval[TIME_LENGTH];   ///< expiration time of RS2; -1 means indefinite
+    unsigned char rs2Data[RS_LENGTH];         ///< the peer's RS2 data
+    unsigned char mitmKey[RS_LENGTH];         ///< MiTM key if available
+} zidrecord2_t;
+
+
+#ifndef __EXPORT
+  #if __GNUC__ >= 4
+    #define __EXPORT    __attribute__ ((visibility("default")))
+    #define __LOCAL     __attribute__ ((visibility("hidden")))
+  #elif defined _WIN32 || defined __CYGWIN__
+    #define __EXPORT    __declspec(dllimport)
+    #define __LOCAL
+  #else
+    #define __EXPORT
+    #define __LOCAL
+  #endif
+#endif
+
+static const int Valid            = 0x1;
+static const int SASVerified      = 0x2;
+static const int RS1Valid         = 0x4;
+static const int RS2Valid         = 0x8;
+static const int MITMKeyAvailable = 0x10;
+static const int OwnZIDRecord     = 0x20;
+
+/**
+ * This class implements the ZID record.
+ *
+ * The ZID record holds data about a peer. According to ZRTP specification
+ * we use a ZID to identify a peer. ZRTP uses the RS (Retained Secret) data
+ * to construct shared secrets.
+ * <p>
+ * NOTE: ZIDRecord has ZIDFile as friend. ZIDFile knows about the private
+ *   data of ZIDRecord - please keep both classes synchronized.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZIDRecord {
+    friend class ZIDFile;
+
+private:
+    zidrecord2_t record;
+    unsigned long position;
+
+    /*
+     * The default constructor is private
+     */
+    ZIDRecord() {
+    record.version = 2;
+    }
+
+    /**
+     * Functions for I/O availabe for ZID file handling
+     *
+     * These functions are private, thus only friends may use it.
+     */
+    void setPosition(long pos) {position = pos;}
+    long getPosition()         {return position; }
+
+    zidrecord2_t* getRecordData() {return &record; }
+    int getRecordLength()         {return sizeof(zidrecord2_t); }
+
+    bool isValid()    { return ((record.flags & Valid) == Valid); }
+    void setValid()   { record.flags |= Valid; }
+
+public:
+    /**
+     * Create a ZID Record with given ZID data
+     *
+     * The method creates a new ZID record and initializes its ZID
+     * data field. All other fields are set to null.
+     *
+     * An application can use this pre-initialized record to look
+     * up the associated record in the ZID file. If the record is
+     * available, the ZID record fields are filled with the stored
+     * data.
+     *
+     * @param idData
+     *     Pointer to the fixed length ZID data
+     * @see ZIDFile::getRecord
+     */
+    ZIDRecord(const unsigned char *idData) {
+    memset(&record, 0, sizeof(zidrecord2_t));
+    memcpy(record.identifier, idData, IDENTIFIER_LEN);
+    record.version = 2;
+    }
+
+    /**
+     * Set @c valid flag in RS1
+     */
+    void setRs1Valid()   { record.flags |= RS1Valid; }
+
+    /**
+     * reset @c valid flag in RS1
+     */
+    void resetRs1Valid() { record.flags &= ~RS1Valid; }
+
+    /**
+     * Check @c valid flag in RS1
+     */
+    bool isRs1Valid()    { return ((record.flags & RS1Valid) == RS1Valid); }
+
+    /**
+     * Set @c valid flag in RS2
+     */
+    void setRs2Valid()   { record.flags |= RS2Valid; }
+
+    /**
+     * Reset @c valid flag in RS2
+     */
+    void resetRs2Valid() { record.flags &= ~RS2Valid; }
+
+    /**
+     * Check @c valid flag in RS2
+     */
+    bool isRs2Valid()    { return ((record.flags & RS2Valid) == RS2Valid); }
+
+    /**
+     * Set MITM key available
+     */
+    void setMITMKeyAvailable()    { record.flags |= MITMKeyAvailable; }
+
+    /**
+     * Reset MITM key available
+     */
+    void resetMITMKeyAvailable()  { record.flags &= ~MITMKeyAvailable; }
+
+    /**
+     * Check MITM key available is set
+     */
+    bool isMITMKeyAvailable()     { return ((record.flags & MITMKeyAvailable) == MITMKeyAvailable); }
+
+    /**
+     * Mark this as own ZID record
+     */
+    void setOwnZIDRecord()  { record.flags = OwnZIDRecord; }
+    /**
+     * Reset own ZID record marker
+     */
+    void resetOwnZIDRecord(){ record.flags = 0; }
+
+    /**
+     * Check own ZID record marker
+     */
+    bool isOwnZIDRecord()   { return (record.flags == OwnZIDRecord); }  // no other flag allowed if own ZID
+
+    /**
+     * Set SAS for this ZID as verified
+     */
+    void setSasVerified()   { record.flags |= SASVerified; }
+    /**
+     * Reset SAS for this ZID as verified
+     */
+    void resetSasVerified() { record.flags &= ~SASVerified; }
+
+    /**
+     * Check if SAS for this ZID was verified
+     */
+    bool isSasVerified()    { return ((record.flags & SASVerified) == SASVerified); }
+
+    /**
+     * Return the ZID for this record
+     */
+    const uint8_t* getIdentifier() {return record.identifier; }
+
+    /**
+     * Check if RS1 is still valid
+     *
+     * Returns true if RS1 is still valid, false otherwise.
+     *
+     * @return
+     *    Returns true is RS1 is not expired (valid), false otherwise.
+     */
+    const bool isRs1NotExpired();
+
+    /**
+     * Returns pointer to RS1 data.
+     */
+    const unsigned char* getRs1() { return record.rs1Data; }
+
+    /**
+     * Check if RS2 is still valid
+     *
+     * Returns true if RS2 is still valid, false otherwise.
+     *
+     * @return
+     *    Returns true is RS2 is not expired (valid), false otherwise.
+     */
+    const bool isRs2NotExpired();
+
+    /**
+     * Returns pointer to RS1 data.
+     */
+    const unsigned char* getRs2() { return record.rs2Data; }
+
+    /**
+     * Sets new RS1 data and associated expiration value.
+     *
+     * If the expiration value is >0 or -1 the method stores the new
+     * RS1. Before it stores the new RS1 it shifts the exiting RS1
+     * into RS2 (together with its expiration time). Then it computes
+     * the expiration time of the and stores the result together with
+     * the new RS1.
+     *
+     * If the expiration value is -1 then this RS will never expire.
+     *
+     * If the expiration value is 0 then the expiration value of a
+     * stored RS1 is cleared and no new RS1 value is stored. Also RS2
+     * is left unchanged.
+     *
+     * @param data
+     *    Points to the new RS1 data.
+     * @param expire
+     *    The expiration interval in seconds. Default is -1.
+     *
+     */
+    void setNewRs1(const unsigned char* data, int32_t expire =-1);
+
+    /**
+     * Set MiTM key data.
+     *
+     */
+    void setMiTMData(const unsigned char* data);
+
+    /**
+     * Get MiTM key data.
+     *
+     */
+    const unsigned char* getMiTMData() {return record.mitmKey; }
+};
+
+#endif // ZIDRECORD
+
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/ZRtp.h b/jni/libzrtp/src/libzrtpcpp/ZRtp.h
new file mode 100644
index 0000000..4e03f28
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZRtp.h
@@ -0,0 +1,1292 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTP_H_
+#define _ZRTP_H_
+/**
+ * @file ZRtp.h
+ * @brief The ZRTP main engine
+ * @defgroup GNU_ZRTP The GNU ZRTP C++ implementation
+ * @{
+ */
+
+#include <cstdlib>
+
+#include <libzrtpcpp/ZrtpPacketHello.h>
+#include <libzrtpcpp/ZrtpPacketHelloAck.h>
+#include <libzrtpcpp/ZrtpPacketCommit.h>
+#include <libzrtpcpp/ZrtpPacketDHPart.h>
+#include <libzrtpcpp/ZrtpPacketConfirm.h>
+#include <libzrtpcpp/ZrtpPacketConf2Ack.h>
+#include <libzrtpcpp/ZrtpPacketGoClear.h>
+#include <libzrtpcpp/ZrtpPacketClearAck.h>
+#include <libzrtpcpp/ZrtpPacketError.h>
+#include <libzrtpcpp/ZrtpPacketErrorAck.h>
+#include <libzrtpcpp/ZrtpPacketPing.h>
+#include <libzrtpcpp/ZrtpPacketPingAck.h>
+#include <libzrtpcpp/ZrtpPacketSASrelay.h>
+#include <libzrtpcpp/ZrtpPacketRelayAck.h>
+#include <libzrtpcpp/ZrtpCallback.h>
+#include <libzrtpcpp/ZIDRecord.h>
+
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
+// Prepare to support digest algorithms up to 512 bit (64 bytes)
+#define MAX_DIGEST_LENGTH       64
+#define IMPL_MAX_DIGEST_LENGTH  64
+
+class __EXPORT ZrtpStateClass;
+class ZrtpDH;
+
+/**
+ * The main ZRTP class.
+ *
+ * This is the main class of the RTP/SRTP independent part of the GNU
+ * ZRTP. It handles the ZRTP HMAC, DH, and other data management. The
+ * user of this class needs to know only a few methods and needs to
+ * provide only a few external functions to connect to a Timer
+ * mechanism and to send data via RTP and SRTP. Refer to the
+ * ZrtpCallback class to get detailed information regading the
+ * callback methods required by GNU RTP.
+ *
+ * The class ZrtpQueue is the GNU ccRTP specific implementation that
+ * extends standard ccRTP RTP provide ZRTP support. Refer to the
+ * documentation of ZrtpQueue to get more information about the usage
+ * of ZRtp and associated classes.
+ *
+ * The main entry into the ZRTP class is the processExtensionHeader()
+ * method.
+ *
+ * This class does not directly handle the protocol states, timers,
+ * and packet resend. The protocol state engine is responsible for
+ * these actions.
+ *
+ * Example how to use ZRtp:
+ *<pre>
+ *    zrtpEngine = new ZRtp((uint8_t*)ownZid, (ZrtpCallback*)this, idString);
+ *    zrtpEngine->startZrtpEngine();
+ *</pre>
+ * @see ZrtpCallback
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZRtp {
+
+    public:
+
+    /**
+     * Constructor intializes all relevant data but does not start the
+     * engine.
+     */
+    ZRtp(uint8_t* myZid, ZrtpCallback* cb, std::string id,
+         ZrtpConfigure* config, bool mitmm= false, bool sasSignSupport= false);
+
+    /**
+     * Destructor cleans up.
+     */
+    ~ZRtp();
+
+    /**
+     * Kick off the ZRTP protocol engine.
+     *
+     * This method calls the ZrtpStateClass#evInitial() state of the state
+     * engine. After this call we are able to process ZRTP packets
+     * from our peer and to process them.
+     */
+    void startZrtpEngine();
+
+    /**
+     * Stop ZRTP security.
+     *
+     */
+    void stopZrtp();
+
+    /**
+     * Process RTP extension header.
+     *
+     * This method expects to get a pointer to the extension header of
+     * a RTP packet. The method checks if this is really a ZRTP
+     * packet. If this check fails the method returns 0 (false) in
+     * case this is not a ZRTP packet. We return a 1 if we processed
+     * the ZRTP extension header and the caller may process RTP data
+     * after the extension header as usual.  The method return -1 the
+     * call shall dismiss the packet and shall not forward it to
+     * further RTP processing.
+     *
+     * @param extHeader
+     *    A pointer to the first byte of the extension header. Refer to
+     *    RFC3550.
+     * @param peerSSRC
+     *    The peer's SSRC.
+     * @return
+     *    Code indicating further packet handling, see description above.
+     */
+    void processZrtpMessage(uint8_t *extHeader, uint32_t peerSSRC);
+
+    /**
+     * Process a timeout event.
+     *
+     * We got a timeout from the timeout provider. Forward it to the
+     * protocol state engine.
+     *
+     */
+    void processTimeout();
+
+    /**
+     * Check for and handle GoClear ZRTP packet header.
+     *
+     * This method checks if this is a GoClear packet. If not, just return
+     * false. Otherwise handle it according to the specification.
+     *
+     * @param extHeader
+     *    A pointer to the first byte of the extension header. Refer to
+     *    RFC3550.
+     * @return
+     *    False if not a GoClear, true otherwise.
+     */
+    bool handleGoClear(uint8_t *extHeader);
+
+    /**
+     * Set the auxilliary secret.
+     *
+     * Use this method to set the auxilliary secret data. Refer to ZRTP
+     * specification, chapter 4.3 ff
+     *
+     * @param data
+     *     Points to the secret data.
+     * @param length
+     *     Length of the auxilliary secrect in bytes
+     */
+    void setAuxSecret(uint8_t* data, int32_t length);
+
+    /**
+     * Check current state of the ZRTP state engine
+     *
+     * @param state
+     *    The state to check.
+     * @return
+     *    Returns true id ZRTP engine is in the given state, false otherwise.
+     */
+    bool inState(int32_t state);
+
+    /**
+     * Set SAS as verified.
+     *
+     * Call this method if the user confirmed (verfied) the SAS. ZRTP
+     * remembers this together with the retained secrets data.
+     */
+    void SASVerified();
+
+    /**
+     * Reset the SAS verfied flag for the current active user's retained secrets.
+     *
+     */
+    void resetSASVerified();
+
+    /**
+     * Get the ZRTP Hello Hash data.
+     *
+     * Use this method to get the ZRTP Hello Hash data. The method
+     * returns the data as a string containing the ZRTP protocol version and
+     * hex-digits.
+     *
+     * Refer to ZRTP specification, chapter 8.
+     *
+     * @return
+     *    a std:string containing the Hello hash value as hex-digits. The
+     *    hello hash is available immediately after class instantiation.
+     */
+    std::string getHelloHash();
+
+    /**
+     * Get the peer's ZRTP Hello Hash data.
+     *
+     * Use this method to get the peer's ZRTP Hello Hash data. The method
+     * returns the data as a string containing the ZRTP protocol version and
+     * hex-digits.
+     *
+     * The peer's hello hash is available only after ZRTP received a hello. If
+     * no data is available the function returns an empty string.
+     *
+     * Refer to ZRTP specification, chapter 8.
+     *
+     * @return
+     *    a std:string containing the Hello version and the hello hash as hex digits.
+     */
+    std::string getPeerHelloHash();
+
+    /**
+     * Get Multi-stream parameters.
+     *
+     * Use this method to get the Multi-stream that were computed during
+     * the ZRTP handshake. An application may use these parameters to
+     * enable multi-stream processing for an associated SRTP session.
+     *
+     * Refer to chapter 4.4.2 in the ZRTP specification for further details
+     * and restriction how and when to use multi-stream mode.
+     *
+     * @return
+     *    a string that contains the multi-stream parameters. The application
+     *    must not modify the contents of this string, it is opaque data. The
+     *    application may hand over this string to a new ZrtpQueue instance
+     *    to enable multi-stream processing for this ZrtpQueue.
+     *    If ZRTP was not started or ZRTP is not yet in secure state the method
+     *    returns an empty string.
+     */
+    std::string getMultiStrParams();
+
+    /**
+     * Set Multi-stream parameters.
+     *
+     * Use this method to set the parameters required to enable Multi-stream
+     * processing of ZRTP. The multi-stream parameters must be set before the
+     * application starts the ZRTP protocol engine.
+     *
+     * Refer to chapter 4.4.2 in the ZRTP specification for further details
+     * of multi-stream mode.
+     *
+     * @param parameters
+     *     A string that contains the multi-stream parameters that this
+     *     new ZrtpQueue instanace shall use. See also
+     *     <code>getMultiStrParams()</code>
+     */
+    void setMultiStrParams(std::string parameters);
+
+    /**
+     * Check if this ZRTP session is a Multi-stream session.
+     *
+     * Use this method to check if this ZRTP instance uses multi-stream.
+     * Refer to chapters 4.2 and 4.4.2 in the ZRTP.
+     *
+     * @return
+     *     True if multi-stream is used, false otherwise.
+     */
+    bool isMultiStream();
+
+    /**
+     * Check if the other ZRTP client supports Multi-stream.
+     *
+     * Use this method to check if the other ZRTP client supports
+     * Multi-stream mode.
+     *
+     * @return
+     *     True if multi-stream is available, false otherwise.
+     */
+    bool isMultiStreamAvailable();
+
+    /**
+     * Accept a PBX enrollment request.
+     *
+     * If a PBX service asks to enroll the PBX trusted MitM key and the user
+     * accepts this request, for example by pressing an OK button, the client
+     * application shall call this method and set the parameter
+     * <code>accepted</code> to true. If the user does not accept the request
+     * set the parameter to false.
+     *
+     * @param accepted
+     *     True if the enrollment request is accepted, false otherwise.
+     */
+    void acceptEnrollment(bool accepted);
+
+    /**
+     * Check the state of the enrollment mode.
+     * 
+     * If true then we will set the enrollment flag (E) in the confirm
+     * packets and perform the enrollment actions. A MitM (PBX) enrollment service
+     * started this ZRTP session. Can be set to true only if mitmMode is also true.
+     * 
+     * @return status of the enrollmentMode flag.
+     */
+    bool isEnrollmentMode();
+
+    /**
+     * Set the state of the enrollment mode.
+     * 
+     * If true then we will set the enrollment flag (E) in the confirm
+     * packets and perform the enrollment actions. A MitM (PBX) enrollment 
+     * service must sets this mode to true. 
+     * 
+     * Can be set to true only if mitmMode is also true. 
+     * 
+     * @param enrollmentMode defines the new state of the enrollmentMode flag
+     */
+    void setEnrollmentMode(bool enrollmentMode);
+
+    /**
+     * Check if a peer's cache entry has a vaild MitM key.
+     *
+     * If true then the other peer ha a valid MtiM key, i.e. the peer has performed
+     * the enrollment procedure. A PBX ZRTP Back-2-Back application can use this function
+     * to check which of the peers is enrolled.
+     *
+     * @return True if the other peer has a valid Mitm key (is enrolled).
+     */
+    bool isPeerEnrolled();
+
+    /**
+     * Send the SAS relay packet.
+     * 
+     * The method creates and sends a SAS relay packet according to the ZRTP
+     * specifications. Usually only a MitM capable user agent (PBX) uses this
+     * function.
+     * 
+     * @param sh the full SAS hash value, 32 bytes
+     * @param render the SAS rendering algorithm
+     */
+    bool sendSASRelayPacket(uint8_t* sh, std::string render);
+
+    /**
+     * Get the commited SAS rendering algorithm for this ZRTP session.
+     * 
+     * @return the commited SAS rendering algorithm
+     */
+    std::string getSasType();
+ 
+    /**
+     * Get the computed SAS hash for this ZRTP session.
+     *
+     * A PBX ZRTP back-to-Back function uses this function to get the SAS
+     * hash of an enrolled client to construct the SAS relay packet for
+     * the other client.
+     *
+     * @return a pointer to the byte array that contains the full
+     *         SAS hash.
+     */
+    uint8_t* getSasHash();
+
+    /**
+     * Set signature data.
+     *
+     * This functions stores signature data and transmitts it during ZRTP
+     * processing to the other party as part of the Confirm packets. Refer to
+     * chapters 5.7 and 7.2.
+     *
+     * The signature data must be set before ZRTP the application calls
+     * <code>start()</code>.
+     *
+     * @param data
+     *    The signature data including the signature type block. The method
+     *    copies this data into the Confirm packet at signature type block.
+     * @param length
+     *    The length of the signature data in bytes. This length must be
+     *    multiple of 4.
+     * @return
+     *    True if the method stored the data, false otherwise.
+     */
+    bool setSignatureData(uint8_t* data, int32_t length);
+
+    /**
+     * Get signature data.
+     *
+     * This functions returns a pointer to the signature data that was receivied
+     * during ZRTP processing. Refer to chapters 5.7 and 7.2.
+     *
+     * The returned pointer points to volatile data that is valid only during the
+     * <code>checkSASSignature()</code> callback funtion. The application must copy
+     * the signature data if it will be used after the callback function returns.
+     *
+     * The signature data can be retrieved after ZRTP enters secure state.
+     * <code>start()</code>.
+     *
+     * @return
+     *    Pointer to signature data.
+     */
+    const uint8_t* getSignatureData();
+
+    /**
+     * Get length of signature data in number of bytes.
+     *
+     * This functions returns the length of signature data that was receivied
+     * during ZRTP processing. Refer to chapters 5.7 and 7.2.
+     *
+     * @return
+     *    Length in bytes of the received signature data. The method returns
+     *    zero if no signature data is avilable.
+     */
+    int32_t getSignatureLength();
+
+    /**
+     * Emulate a Conf2Ack packet.
+     *
+     * This method emulates a Conf2Ack packet. According to ZRTP specification
+     * the first valid SRTP packet that the Initiator receives must switch
+     * on secure mode. Refer to chapter 4 in the specificaton
+     *
+     */
+    void conf2AckSecure();
+
+     /**
+      * Get other party's ZID (ZRTP Identifier) data
+      *
+      * This functions returns the other party's ZID that was receivied
+      * during ZRTP processing.
+      *
+      * The ZID data can be retrieved after ZRTP receive the first Hello
+      * packet from the other party. The application may call this method
+      * for example during SAS processing in showSAS(...) user callback
+      * method.
+      *
+      * @param data
+      *    Pointer to a data buffer. This buffer must have a size of
+      *    at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
+      * @return
+      *    Number of bytes copied into the data buffer - must be equivalent
+      *    to 96 bit, usually 12 bytes.
+      */
+     int32_t getPeerZid(uint8_t* data);
+
+private:
+     friend class ZrtpStateClass;
+
+    /**
+     * The state engine takes care of protocol processing.
+     */
+    ZrtpStateClass* stateEngine;
+
+    /**
+     * This is my ZID that I send to the peer.
+     */
+    uint8_t zid[IDENTIFIER_LEN];
+
+    /**
+     * The peer's ZID
+     */
+    uint8_t peerZid[IDENTIFIER_LEN];
+
+    /**
+     * The callback class provides me with the interface to send
+     * data and to deal with timer management of the hosting system.
+     */
+    ZrtpCallback* callback;
+
+    /**
+     * My active Diffie-Helman context
+     */
+    ZrtpDH* dhContext;
+
+    /**
+     * The computed DH shared secret
+     */
+    uint8_t* DHss;
+
+    /**
+     * My computed public key
+     */
+    uint8_t pubKeyBytes[400];
+    /**
+     * Length off public key
+     */
+//    int32_t pubKeyLen;
+    /**
+     * My Role in the game
+     */
+    Role myRole;
+
+    /**
+     * The human readable SAS value
+     */
+    std::string SAS;
+
+    /**
+     * The SAS hash for signaling and alike. Refer to chapters
+     * 4.5 and 7 how sasHash, sasValue and the SAS string are derived.
+     */
+    uint8_t sasHash[MAX_DIGEST_LENGTH];
+    /**
+     * The ids for the retained and other shared secrets
+     */
+    uint8_t rs1IDr[MAX_DIGEST_LENGTH];
+    uint8_t rs2IDr[MAX_DIGEST_LENGTH];
+    uint8_t auxSecretIDr[MAX_DIGEST_LENGTH];
+    uint8_t pbxSecretIDr[MAX_DIGEST_LENGTH];
+
+    uint8_t rs1IDi[MAX_DIGEST_LENGTH];
+    uint8_t rs2IDi[MAX_DIGEST_LENGTH];
+    uint8_t auxSecretIDi[MAX_DIGEST_LENGTH];
+    uint8_t pbxSecretIDi[MAX_DIGEST_LENGTH];
+
+    /**
+     * pointers to aux secret storage and length of aux secret
+     */
+    uint8_t* auxSecret;
+    int32_t auxSecretLength;
+
+    /**
+     * Record if valid rs1 and/or rs1 were found in the
+     * retaind secret cache.
+     */
+    bool rs1Valid;
+    bool rs2Valid;
+    /**
+     * My hvi
+     */
+    uint8_t hvi[MAX_DIGEST_LENGTH];
+
+    /**
+     * The peer's hvi
+     */
+    uint8_t peerHvi[8*ZRTP_WORD_SIZE];
+
+    /**
+     * Context to compute the SHA256 hash of selected messages.
+     * Used to compute the s0, refer to chapter 4.4.1.4
+     */
+    void* msgShaContext;
+    /**
+     * Commited Hash, Cipher, and public key algorithms
+     */
+    AlgorithmEnum* hash;
+    AlgorithmEnum* cipher;
+    AlgorithmEnum* pubKey;
+    /**
+     * The selected SAS type.
+     */
+    AlgorithmEnum* sasType;
+
+    /**
+     * The selected SAS type.
+     */
+    AlgorithmEnum* authLength;
+
+    /**
+     * The Hash images as defined in chapter 5.1.1 (H0 is a random value,
+     * not stored here). Need full SHA 256 lenght to store hash value but
+     * only the leftmost 128 bits are used in computations and comparisons.
+     */
+    uint8_t H0[IMPL_MAX_DIGEST_LENGTH];
+    uint8_t H1[IMPL_MAX_DIGEST_LENGTH];
+    uint8_t H2[IMPL_MAX_DIGEST_LENGTH];
+    uint8_t H3[IMPL_MAX_DIGEST_LENGTH];
+    uint8_t helloHash[IMPL_MAX_DIGEST_LENGTH];
+
+    uint8_t peerHelloHash[IMPL_MAX_DIGEST_LENGTH];
+    uint8_t peerHelloVersion[ZRTP_WORD_SIZE + 1];   // +1 for nul byte
+
+    // We get the peer's H? from the message where length is defined as 8 words
+    uint8_t peerH0[8*ZRTP_WORD_SIZE];
+    uint8_t peerH1[8*ZRTP_WORD_SIZE];
+    uint8_t peerH2[8*ZRTP_WORD_SIZE];
+    uint8_t peerH3[8*ZRTP_WORD_SIZE];
+
+    /**
+     * The SHA256 hash over selected messages
+     */
+    uint8_t messageHash[MAX_DIGEST_LENGTH];
+
+    /**
+     * The s0
+     */
+    uint8_t s0[MAX_DIGEST_LENGTH];
+
+    /**
+     * The new Retained Secret
+     */
+    uint8_t newRs1[MAX_DIGEST_LENGTH];
+
+    /**
+     * The GoClear HMAC keys and confirm HMAC key
+     */
+    uint8_t hmacKeyI[MAX_DIGEST_LENGTH];
+    uint8_t hmacKeyR[MAX_DIGEST_LENGTH];
+
+    /**
+     * The Initiator's srtp key and salt
+     */
+    uint8_t srtpKeyI[MAX_DIGEST_LENGTH];
+    uint8_t srtpSaltI[MAX_DIGEST_LENGTH];
+
+    /**
+     * The Responder's srtp key and salt
+     */
+    uint8_t srtpKeyR[MAX_DIGEST_LENGTH];
+    uint8_t srtpSaltR[MAX_DIGEST_LENGTH];
+
+    /**
+     * The keys used to encrypt/decrypt the confirm message
+     */
+    uint8_t zrtpKeyI[MAX_DIGEST_LENGTH];
+    uint8_t zrtpKeyR[MAX_DIGEST_LENGTH];
+
+    /**
+     * Pointers to negotiated hash and HMAC functions
+     */
+    void (*hashFunction)(unsigned char *data,
+            unsigned int data_length,
+            unsigned char *digest);
+
+    void (*hashListFunction)(unsigned char *data[],
+            unsigned int data_length[],
+            unsigned char *digest);
+
+    void (*hmacFunction)(uint8_t* key, uint32_t key_length,
+                uint8_t* data, int32_t data_length,
+                uint8_t* mac, uint32_t* mac_length);
+
+    void (*hmacListFunction)( uint8_t* key, uint32_t key_length,
+                           uint8_t* data[], uint32_t data_length[],
+                           uint8_t* mac, uint32_t* mac_length );
+
+    void* (*createHashCtx)();
+
+    void (*closeHashCtx)(void* ctx, unsigned char* digest);
+
+    void (*hashCtxFunction)(void* ctx, unsigned char* data,
+           unsigned int dataLength);
+
+    void (*hashCtxListFunction)(void* ctx, unsigned char* dataChunks[],
+           unsigned int dataChunkLength[]);
+
+    int32_t hashLength;
+
+    // Funtion pointers to implicit hash and hmac functions
+    void (*hashFunctionImpl)(unsigned char *data,
+            unsigned int data_length,
+            unsigned char *digest);
+
+    void (*hashListFunctionImpl)(unsigned char *data[],
+            unsigned int data_length[],
+            unsigned char *digest);
+
+    void (*hmacFunctionImpl)(uint8_t* key, uint32_t key_length,
+                uint8_t* data, int32_t data_length,
+                uint8_t* mac, uint32_t* mac_length);
+
+    void (*hmacListFunctionImpl)( uint8_t* key, uint32_t key_length,
+                           uint8_t* data[], uint32_t data_length[],
+                           uint8_t* mac, uint32_t* mac_length );
+
+    int32_t hashLengthImpl;
+
+    /**
+     * The ZRTP Session Key
+     * Refer to chapter 5.4.1.4
+     */
+    uint8_t zrtpSession[MAX_DIGEST_LENGTH];
+
+    /**
+     * True if this ZRTP instance uses multi-stream mode.
+     */
+    bool multiStream;
+
+        /**
+     * True if the other ZRTP client supports multi-stream mode.
+     */
+    bool multiStreamAvailable;
+
+    /**
+     * Enable MitM (PBX) enrollment
+     * 
+     * If set to true then ZRTP honors the PBX enrollment flag in
+     * Commit packets and calls the appropriate user callback
+     * methods. If the parameter is set to false ZRTP ignores the PBX
+     * enrollment flags.
+     */
+    bool enableMitmEnrollment;
+
+    /**
+     * True if a valid trusted MitM key of the other peer is available, i.e. enrolled.
+     */
+    bool peerIsEnrolled;
+
+    /**
+     * Set to true if the Hello packet contained the M-flag (MitM flag).
+     * We use this later to check some stuff for SAS Relay processing
+     */
+    bool mitmSeen;
+
+    /**
+     * Temporarily store computed pbxSecret, if user accepts enrollment then
+     * it will copied to our ZID record of the PBX (MitM)  
+     */
+    uint8_t* pbxSecretTmp;
+    uint8_t  pbxSecretTmpBuffer[MAX_DIGEST_LENGTH];
+
+    /**
+     * If true then we will set the enrollment flag (E) in the confirm
+     * packets. Set to true if the PBX enrollment service started this ZRTP 
+     * session. Can be set to true only if mitmMode is also true. 
+     */
+    bool enrollmentMode;
+
+    /**
+     * Configuration data which algorithms to use.
+     */
+    ZrtpConfigure configureAlgos;
+    /**
+     * Pre-initialized packets.
+     */
+    ZrtpPacketHello    zrtpHello;
+    ZrtpPacketHelloAck zrtpHelloAck;
+    ZrtpPacketConf2Ack zrtpConf2Ack;
+    ZrtpPacketClearAck zrtpClearAck;
+    ZrtpPacketGoClear  zrtpGoClear;
+    ZrtpPacketError    zrtpError;
+    ZrtpPacketErrorAck zrtpErrorAck;
+    ZrtpPacketDHPart   zrtpDH1;
+    ZrtpPacketDHPart   zrtpDH2;
+    ZrtpPacketCommit   zrtpCommit;
+    ZrtpPacketConfirm  zrtpConfirm1;
+    ZrtpPacketConfirm  zrtpConfirm2;
+    ZrtpPacketPingAck  zrtpPingAck;
+    ZrtpPacketSASrelay zrtpSasRelay;
+    ZrtpPacketRelayAck zrtpRelayAck;
+
+    /**
+     * Random IV data to encrypt the confirm data, 128 bit for AES
+     */
+    uint8_t randomIV[16];
+
+    uint8_t tempMsgBuffer[1024];
+    int32_t lengthOfMsgData;
+
+    /**
+     * Variables to store signature data. Includes the signature type block
+     */
+    const uint8_t* signatureData;       // will be set when needed
+    int32_t  signatureLength;     // overall length in bytes
+
+    /**
+     * Is true if the other peer signaled SAS signature support in its Hello packet.
+     */
+    bool signSasSeen;
+
+    uint32_t peerSSRC;            // peer's SSRC, required to setup PingAck packet
+
+    /**
+     * Enable or disable paranoid mode.
+     *
+     * The Paranoid mode controls the behaviour and handling of the SAS verify flag. If
+     * Panaoid mode is set to flase then ZRtp applies the normal handling. If Paranoid
+     * mode is set to true then the handling is:
+     *
+     * <ul>
+     * <li> Force the SAS verify flag to be false at srtpSecretsOn() callback. This gives
+     *      the user interface (UI) the indication to handle the SAS as <b>not verified</b>.
+     *      See implementation note below.</li>
+     * <li> Don't set the SAS verify flag in the <code>Confirm</code> packets, thus the other
+     *      also must report the SAS as <b>not verified</b>.</li>
+     * <li> ignore the <code>SASVerified()</code> function, thus do not set the SAS to verified
+     *      in the ZRTP cache. </li>
+     * <li> Disable the <b>Trusted PBX MitM</b> feature. Just send the <code>SASRelay</code> packet
+     *      but do not process the relayed data. This protects the user from a malicious
+     *      "trusted PBX".</li>
+     * </ul>
+     * ZRtp performs alls other steps during the ZRTP negotiations as usual, in particular it
+     * computes, compares, uses, and stores the retained secrets. This avoids unnecessary warning
+     * messages. The user may enable or disable the Paranoid mode on a call-by-call basis without
+     * breaking the key continuity data.
+     *
+     * <b>Implementation note:</b></br>
+     * An application shall always display the SAS code if the SAS verify flag is <code>false</code>.
+     * The application shall also use mechanisms to remind the user to compare the SAS code, for
+     * example useing larger fonts, different colours and other display features.
+     */
+    bool paranoidMode;
+
+    /**
+     * Find the best Hash algorithm that is offered in Hello.
+     *
+     * Find the best, that is the strongest, Hash algorithm that our peer
+     * offers in its Hello packet.
+     *
+     * @param hello
+     *    The Hello packet.
+     * @return
+     *    The Enum that identifies the best offered Hash algortihm. Return
+     *    <code>NumSupportedHashes</code> to signal that no matching Hash algorithm
+     *     was found at all.
+    */
+    AlgorithmEnum* findBestHash(ZrtpPacketHello *hello);
+
+    /**
+     * Find the best symmetric cipher algorithm that is offered in Hello.
+     *
+     * Find the best, that is the strongest, cipher algorithm that our peer
+     * offers in its Hello packet.
+     *
+     * @param hello
+     *    The Hello packet.
+     * @param pk
+     *    The id of the selected public key algorithm
+     * @return
+     *    The Enum that identifies the best offered Cipher algortihm. Return
+     *    <code>NumSupportedSymCiphers</code> to signal that no matching Cipher algorithm
+     *    was found at all.
+     */
+    AlgorithmEnum* findBestCipher(ZrtpPacketHello *hello,  AlgorithmEnum* pk);
+
+    /**
+     * Find the best Public Key algorithm that is offered in Hello.
+     *
+     * Find the best, that is the strongest, public key algorithm that our peer
+     * offers in its Hello packet.
+     *
+     * @param hello
+     *    The Hello packet.
+     * @return
+     *    The Enum that identifies the best offered Public Key algortihm. Return
+     *    <code>NumSupportedPubKeys</code> to signal that no matching Public Key algorithm
+     *    was found at all.
+     */
+    AlgorithmEnum* findBestPubkey(ZrtpPacketHello *hello);
+
+    /**
+     * Find the best SAS algorithm that is offered in Hello.
+     *
+     * Find the best, that is the strongest, SAS algorithm that our peer
+     * offers in its Hello packet.
+     *
+     * @param hello
+     *    The Hello packet.
+     * @return
+     *    The Enum that identifies the best offered SAS algortihm. Return
+     *    <code>NumSupportedSASTypes</code> to signal that no matching SAS algorithm
+     *    was found at all.
+     */
+    AlgorithmEnum* findBestSASType(ZrtpPacketHello* hello);
+
+    /**
+     * Find the best authentication length that is offered in Hello.
+     *
+     * Find the best, that is the strongest, authentication length that our peer
+     * offers in its Hello packet.
+     *
+     * @param hello
+     *    The Hello packet.
+     * @return
+     *    The Enum that identifies the best offered authentication length. Return
+     *    <code>NumSupportedAuthLenghts</code> to signal that no matching length
+     *    was found at all.
+     */
+    AlgorithmEnum* findBestAuthLen(ZrtpPacketHello* hello);
+
+    /**
+     * Check if MultiStream mode is offered in Hello.
+     *
+     * Find the best, that is the strongest, authentication length that our peer
+     * offers in its Hello packet.
+     *
+     * @param hello
+     *    The Hello packet.
+     * @return
+     *    True if multi stream mode is available, false otherwise.
+     */
+    bool checkMultiStream(ZrtpPacketHello* hello);
+
+    /**
+     * Save the computed MitM secret to the ZID record of the peer
+     */
+    void writeEnrollmentPBX();
+
+    /**
+     * Compute my hvi value according to ZRTP specification.
+     */
+    void computeHvi(ZrtpPacketDHPart* dh, ZrtpPacketHello *hello);
+
+    void computeSharedSecretSet(ZIDRecord& zidRec);
+
+    void computeSRTPKeys();
+
+    void KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLength,
+               uint8_t* context, int32_t contextLength, int32_t L, uint8_t* output);
+
+    void generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec);
+
+    void generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec);
+
+    void generateKeysMultiStream();
+
+    void computePBXSecret();
+
+    void setNegotiatedHash(AlgorithmEnum* hash);
+
+    /*
+     * The following methods are helper functions for ZrtpStateClass.
+     * ZrtpStateClass calls them to prepare packets, send data, report
+     * problems, etc.
+     */
+    /**
+     * Send a ZRTP packet.
+     *
+     * The state engines calls this method to send a packet via the RTP
+     * stack.
+     *
+     * @param packet
+     *    Points to the ZRTP packet.
+     * @return
+     *    zero if sending failed, one if packet was send
+     */
+    int32_t sendPacketZRTP(ZrtpPacketBase *packet);
+
+    /**
+     * Activate a Timer using the host callback.
+     *
+     * @param tm
+     *    The time in milliseconds.
+     * @return
+     *    zero if activation failed, one if timer was activated
+     */
+    int32_t activateTimer(int32_t tm);
+
+    /**
+     * Cancel the active Timer using the host callback.
+     *
+     * @return
+     *    zero if activation failed, one if timer was activated
+     */
+    int32_t cancelTimer();
+
+    /**
+     * Prepare a Hello packet.
+     *
+     * Just take the preinitialized Hello packet and return it. No
+     * further processing required.
+     *
+     * @return
+     *    A pointer to the initialized Hello packet.
+     */
+    ZrtpPacketHello* prepareHello();
+
+    /**
+     * Prepare a HelloAck packet.
+     *
+     * Just take the preinitialized HelloAck packet and return it. No
+     * further processing required.
+     *
+     * @return
+     *    A pointer to the initialized HelloAck packet.
+     */
+    ZrtpPacketHelloAck* prepareHelloAck();
+
+    /**
+     * Prepare a Commit packet.
+     *
+     * We have received a Hello packet from our peer. Check the offers
+     * it makes to us and select the most appropriate. Using the
+     * selected values prepare a Commit packet and return it to protocol
+     * state engine.
+     *
+     * @param hello
+     *    Points to the received Hello packet
+     * @param errMsg
+     *    Points to an integer that can hold a ZRTP error code.
+     * @return
+     *    A pointer to the prepared Commit packet
+     */
+    ZrtpPacketCommit* prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg);
+
+    /**
+     * Prepare a Commit packet for Multi Stream mode.
+     *
+     * Using the selected values prepare a Commit packet and return it to protocol
+     * state engine.
+     *
+     * @param hello
+     *    Points to the received Hello packet
+     * @return
+     *    A pointer to the prepared Commit packet for multi stream mode
+     */
+    ZrtpPacketCommit* prepareCommitMultiStream(ZrtpPacketHello *hello);
+
+    /**
+     * Prepare the DHPart1 packet.
+     *
+     * This method prepares a DHPart1 packet. The input to the method is always
+     * a Commit packet received from the peer. Also we a in the role of the
+     * Responder.
+     *
+     * When we receive a Commit packet we get the selected ciphers, hashes, etc
+     * and cross-check if this is ok. Then we need to initialize a set of DH
+     * keys according to the selected cipher. Using this data we prepare our DHPart1
+     * packet.
+     */
+    ZrtpPacketDHPart* prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMsg);
+
+    /**
+     * Prepare the DHPart2 packet.
+     *
+     * This method prepares a DHPart2 packet. The input to the method is always
+     * a DHPart1 packet received from the peer. Our peer sends the DH1Part as
+     * response to our Commit packet. Thus we are in the role of the
+     * Initiator.
+     *
+     */
+    ZrtpPacketDHPart* prepareDHPart2(ZrtpPacketDHPart* dhPart1, uint32_t* errMsg);
+
+    /**
+     * Prepare the Confirm1 packet.
+     *
+     * This method prepare the Confirm1 packet. The input to this method is the
+     * DHPart2 packect received from our peer. The peer sends the DHPart2 packet
+     * as response of our DHPart1. Here we are in the role of the Responder
+     *
+     */
+    ZrtpPacketConfirm* prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* errMsg);
+
+    /**
+     * Prepare the Confirm1 packet in multi stream mode.
+     *
+     * This method prepares the Confirm1 packet. The state engine call this method
+     * if multi stream mode is selected and a Commit packet was received. The input to
+     * this method is the Commit.
+     * Here we are in the role of the Responder
+     *
+     */
+    ZrtpPacketConfirm* prepareConfirm1MultiStream(ZrtpPacketCommit* commit, uint32_t* errMsg);
+
+    /**
+     * Prepare the Confirm2 packet.
+     *
+     * This method prepare the Confirm2 packet. The input to this method is the
+     * Confirm1 packet received from our peer. The peer sends the Confirm1 packet
+     * as response of our DHPart2. Here we are in the role of the Initiator
+     */
+    ZrtpPacketConfirm* prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* errMsg);
+
+    /**
+     * Prepare the Confirm2 packet in multi stream mode.
+     *
+     * This method prepares the Confirm2 packet. The state engine call this method if
+     * multi stream mode is active and in state CommitSent. The input to this method is
+     * the Confirm1 packet received from our peer. The peer sends the Confirm1 packet
+     * as response of our Commit packet in multi stream mode.
+     * Here we are in the role of the Initiator
+     */
+    ZrtpPacketConfirm* prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, uint32_t* errMsg);
+
+    /**
+     * Prepare the Conf2Ack packet.
+     *
+     * This method prepare the Conf2Ack packet. The input to this method is the
+     * Confirm2 packet received from our peer. The peer sends the Confirm2 packet
+     * as response of our Confirm1. Here we are in the role of the Initiator
+     */
+    ZrtpPacketConf2Ack* prepareConf2Ack(ZrtpPacketConfirm* confirm2, uint32_t* errMsg);
+
+    /**
+     * Prepare the ErrorAck packet.
+     *
+     * This method prepares the ErrorAck packet. The input to this method is the
+     * Error packet received from the peer.
+     */
+    ZrtpPacketErrorAck* prepareErrorAck(ZrtpPacketError* epkt);
+
+    /**
+     * Prepare the Error packet.
+     *
+     * This method prepares the Error packet. The input to this method is the
+     * error code to be included into the message.
+     */
+    ZrtpPacketError* prepareError(uint32_t errMsg);
+
+    /**
+     * Prepare a ClearAck packet.
+     *
+     * This method checks if the GoClear message is valid. If yes then switch
+     * off SRTP processing, stop sending of RTP packets (pause transmit) and
+     * inform the user about the fact. Only if user confirms the GoClear message
+     * normal RTP processing is resumed.
+     *
+     * @return
+     *     NULL if GoClear could not be authenticated, a ClearAck packet
+     *     otherwise.
+     */
+    ZrtpPacketClearAck* prepareClearAck(ZrtpPacketGoClear* gpkt);
+
+    /**
+     * Prepare the ErrorAck packet.
+     *
+     * This method prepares the ErrorAck packet. The input to this method is the
+     * Error packet received from the peer.
+     */
+    ZrtpPacketPingAck* preparePingAck(ZrtpPacketPing* ppkt);
+
+    /**
+     * Prepare the RelayAck packet.
+     *
+     * This method prepares the RelayAck packet. The input to this method is the
+     * SASrelay packet received from the peer.
+     */
+    ZrtpPacketRelayAck* prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* errMsg);
+    
+    /**
+     * Prepare a GoClearAck packet w/o HMAC
+     *
+     * Prepare a GoCLear packet without a HMAC but with a short error message.
+     * This type of GoClear is used if something went wrong during the ZRTP
+     * negotiation phase.
+     *
+     * @return
+     *     A goClear packet without HMAC
+     */
+    ZrtpPacketGoClear* prepareGoClear(uint32_t errMsg = 0);
+
+    /**
+     * Compare the hvi values.
+     *
+     * Compare a received Commit packet with our Commit packet and returns
+     * which Commit packt is "more important". See chapter 5.2 to get further
+     * information how to compare Commit packets.
+     *
+     * @param commit
+     *    Pointer to the peer's commit packet we just received.
+     * @return
+     *    <0 if our Commit packet is "less important"
+     *    >0 if our Commit is "more important"
+     *     0 shouldn't happen because we compare crypto hashes
+     */
+    int32_t compareCommit(ZrtpPacketCommit *commit);
+
+    /**
+     * Verify the H2 hash image.
+     *
+     * Verifies the H2 hash contained in a received commit message.
+     * This functions just verifies H2 but does not store it.
+     *
+     * @param commit
+     *    Pointer to the peer's commit packet we just received.
+     * @return
+     *    true if H2 is ok and verified
+     *    false if H2 could not be verified
+     */
+    bool verifyH2(ZrtpPacketCommit *commit);
+
+    /**
+     * Send information messages to the hosting environment.
+     *
+     * The ZRTP implementation uses this method to send information messages
+     * to the host. Along with the message ZRTP provides a severity indicator
+     * that defines: Info, Warning, Error, Alert. Refer to the MessageSeverity
+     * enum in the ZrtpCallback class.
+     *
+     * @param severity
+     *     This defines the message's severity
+     * @param subCode
+     *     The subcode identifying the reason.
+     * @see ZrtpCodes#MessageSeverity
+     */
+    void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+    /**
+     * ZRTP state engine calls this if the negotiation failed.
+     *
+     * ZRTP calls this method in case ZRTP negotiation failed. The parameters
+     * show the severity as well as some explanatory text.
+     *
+     * @param severity
+     *     This defines the message's severity
+     * @param subCode
+     *     The subcode identifying the reason.
+     * @see ZrtpCodes#MessageSeverity
+     */
+    void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+    /**
+     * ZRTP state engine calls this method if the other side does not support ZRTP.
+     *
+     * If the other side does not answer the ZRTP <em>Hello</em> packets then
+     * ZRTP calls this method,
+     *
+     */
+    void zrtpNotSuppOther();
+
+    /**
+     * Signal SRTP secrets are ready.
+     *
+     * This method calls a callback method to inform the host that the SRTP
+     * secrets are ready.
+     *
+     * @param part
+     *    Defines for which part (sender or receiver) to switch on security
+     * @return
+     *    Returns false if something went wrong during initialization of SRTP
+     *    context. Propagate error back to state engine.
+     */
+    bool srtpSecretsReady(EnableSecurity part);
+
+    /**
+     * Switch off SRTP secrets.
+     *
+     * This method calls a callback method to inform the host that the SRTP
+     * secrets shall be cleared.
+     *
+     * @param part
+     *    Defines for which part (sender or receiver) to clear
+     */
+    void srtpSecretsOff(EnableSecurity part);
+
+    /**
+     * ZRTP state engine calls these methods to enter or leave its
+     * synchronization mutex.
+     */
+    void synchEnter();
+
+    void synchLeave();
+
+    /**
+     * Helper function to store ZRTP message data in a temporary buffer
+     *
+     * This functions first clears the temporary buffer, then stores
+     * the packet's data to it. We use this to check the packet's HMAC
+     * after we received the HMAC key in to following packet.
+     *
+     * @param data
+     *    Pointer to the packet's ZRTP message
+    */
+     void storeMsgTemp(ZrtpPacketBase* pkt);
+
+     /**
+      * Helper function to check a ZRTP message HMAC
+      *
+      * This function gets a HMAC key and uses it to compute a HMAC
+      * with this key and the stored data of a previous received ZRTP
+      * message. It compares the computed HMAC and the HMAC stored in
+      * the received message and returns the result.
+      *
+      * @param key
+      *    Pointer to the HMAC key.
+      * @return
+      *    Returns true if the computed HMAC and the stored HMAC match,
+      *    false otherwise.
+      */
+     bool checkMsgHmac(uint8_t* key);
+
+     /**
+      * Set the client ID for ZRTP Hello message.
+      *
+      * The user of ZRTP must set its id to identify itself in the
+      * ZRTP HELLO message. The maximum length is 16 characters. Shorter
+      * id string are allowed, they will be filled with blanks. A longer id
+      * is truncated to 16 characters.
+      *
+      * The identifier is set in the Hello packet of ZRTP. Thus only after
+      * setting the identifier ZRTP can compute the HMAC and the final
+      * helloHash.
+      *
+      * @param id
+      *     The client's id
+      */
+     void setClientId(std::string id);
+};
+
+/**
+ * @}
+ */
+#endif // ZRTP
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpCWrapper.h b/jni/libzrtp/src/libzrtpcpp/ZrtpCWrapper.h
new file mode 100644
index 0000000..0126545
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpCWrapper.h
@@ -0,0 +1,1339 @@
+/*
+    This file defines the GNU ZRTP C-to-C++ wrapper.
+    Copyright (C) 2010  Werner Dittmann
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef ZRTPCWRAPPER_H
+#define ZRTPCWRAPPER_H
+
+/**
+ *
+ * @file ZrtpCWrapper.h
+ * @brief The GNU ZRTP C-to-C++ wrapper.
+ *
+ * To avoid any include of C++ header files some structure, defines, and
+ * enumerations are repeated in this file. Refer to the inline comments if
+ * you modify the file.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ *
+ * @see ZRtp
+ */
+
+#include <stdint.h>
+
+/**
+ * Defines to specify the role a ZRTP peer has.
+ *
+ * According to the ZRTP specification the role determines which keys to
+ * use to encrypt or decrypt SRTP data.
+ *
+ * <ul>
+ * <li> The Initiator encrypts SRTP data using the <em>keyInitiator</em> and the
+ *      <em>saltInitiator</em> data, the Responder uses these data to decrypt.
+ * </li>
+ * <li> The Responder encrypts SRTP data using the <em>keyResponder</em> and the
+ *      <em>saltResponder</em> data, the Initiator uses these data to decrypt.
+ * </li>
+ * </ul>
+ */
+/*
+ * Keep the following defines in sync with Role enumeration in ZrtpCallback.h
+ */
+#define Responder 1             /*!< This client is in ZRTP Responder mode */
+#define Initiator 2             /*!< This client is in ZRTP Initiator mode */
+
+#define CRC_SIZE  4             /*!< Size of CRC code of a ZRTP packet */
+#define ZRTP_MAGIC 0x5a525450   /*!< The magic code that identifies a ZRTP packet */
+#define MAX_ZRTP_SIZE 3072      /*!< The biggest ZRTP packet ever possible */
+
+/*
+ * IMPORTANT: keep the following enums in synch with ZrtpCodes. We copy them here
+ * to avoid any C++ header includes and defines. The protocol states are located
+ * ZrtpStateClass.h .
+ */
+/**
+ * This enum defines the information message severity.
+ *
+ * The ZRTP implementation issues information messages to inform the user
+ * about ongoing processing, unusual behavior, or alerts in case of severe
+ * problems. Each main severity code a number of sub-codes exist that
+ * specify the exact nature of the problem.
+ *
+ * An application gets message severity codes and the associated sub-codes
+ * via the ZrtpUserCallback#showMessage method.
+ *
+ * The severity levels and their meaning are:
+ *
+ * <dl>
+ * <dt>Info</dt> <dd>keeps the user informed about ongoing processing and
+ *     security setup. The enumeration InfoCodes defines the subcodes.
+ * </dd>
+ * <dt>Warning</dt> <dd>is an information about some security issues, e.g. if
+ *     an AES 256 encryption is request but only DH 3072 as public key scheme
+ *     is supported. ZRTP will establish a secure session (SRTP). The
+ *     enumeration WarningCodes defines the sub-codes.
+ * </dd>
+ * <dt>Severe</dt> <dd>is used if an error occured during ZRTP protocol usage.
+ *     In case of <em>Severe</em> ZRTP will <b>not</b> establish a secure session.
+ *     The enumeration SevereCodes defines the sub-codes.
+ * </dd>
+ * <dt>Zrtp</dt> <dd>shows a ZRTP security problem. Refer to the enumeration
+ *     ZrtpErrorCodes for sub-codes. GNU ZRTP of course will <b>not</b>
+ *     establish a secure session.
+ * </dd>
+ * </dl>
+ *
+ */
+enum zrtp_MessageSeverity {
+    zrtp_Info = 1,                      /*!< Just an info message */
+    zrtp_Warning,                       /*!< A Warning message - security can be established */
+    zrtp_Severe,                        /*!< Severe error, security will not be established */
+    zrtp_ZrtpError                      /*!< ZRTP error, security will not be established  */
+};
+
+/**
+ * Sub-codes for Info
+ */
+enum zrtp_InfoCodes {
+    zrtp_InfoHelloReceived = 1,          /*!< Hello received, preparing a Commit */
+    zrtp_InfoCommitDHGenerated,          /*!< Commit: Generated a public DH key */
+    zrtp_InfoRespCommitReceived,         /*!< Responder: Commit received, preparing DHPart1 */
+    zrtp_InfoDH1DHGenerated,             /*!< DH1Part: Generated a public DH key */
+    zrtp_InfoInitDH1Received,            /*!< Initiator: DHPart1 received, preparing DHPart2 */
+    zrtp_InfoRespDH2Received,            /*!< Responder: DHPart2 received, preparing Confirm1 */
+    zrtp_InfoInitConf1Received,          /*!< Initiator: Confirm1 received, preparing Confirm2 */
+    zrtp_InfoRespConf2Received,          /*!< Responder: Confirm2 received, preparing Conf2Ack */
+    zrtp_InfoRSMatchFound,               /*!< At least one retained secrets matches - security OK */
+    zrtp_InfoSecureStateOn,              /*!< Entered secure state */
+    zrtp_InfoSecureStateOff              /*!< No more security for this session */
+};
+
+/**
+ * Sub-codes for Warning
+ */
+enum zrtp_WarningCodes {
+    zrtp_WarningDHAESmismatch = 1,       /*!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096 */
+    zrtp_WarningGoClearReceived,         /*!< Received a GoClear message */
+    zrtp_WarningDHShort,                 /*!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096 */
+    zrtp_WarningNoRSMatch,               /*!< No retained shared secrets available - must verify SAS */
+    zrtp_WarningCRCmismatch,             /*!< Internal ZRTP packet checksum mismatch - packet dropped */
+    zrtp_WarningSRTPauthError,           /*!< Dropping packet because SRTP authentication failed! */
+    zrtp_WarningSRTPreplayError,         /*!< Dropping packet because SRTP replay check failed! */
+    zrtp_WarningNoExpectedRSMatch        /*!< Valid retained shared secrets availabe but no matches found - must verify SAS */
+};
+
+/**
+ * Sub-codes for Severe
+ */
+enum zrtp_SevereCodes {
+    zrtp_SevereHelloHMACFailed = 1,      /*!< Hash HMAC check of Hello failed! */
+    zrtp_SevereCommitHMACFailed,         /*!< Hash HMAC check of Commit failed! */
+    zrtp_SevereDH1HMACFailed,            /*!< Hash HMAC check of DHPart1 failed! */
+    zrtp_SevereDH2HMACFailed,            /*!< Hash HMAC check of DHPart2 failed! */
+    zrtp_SevereCannotSend,               /*!< Cannot send data - connection or peer down? */
+    zrtp_SevereProtocolError,            /*!< Internal protocol error occured! */
+    zrtp_SevereNoTimer,                  /*!< Cannot start a timer - internal resources exhausted? */
+    zrtp_SevereTooMuchRetries            /*!< Too much retries during ZRTP negotiation - connection or peer down? */
+};
+
+/**
+  * Error codes according to the ZRTP specification chapter 6.9
+  *
+  * GNU ZRTP uses these error codes in two ways: to fill the appropriate
+  * field ing the ZRTP Error packet and as sub-code in
+  * ZrtpUserCallback#showMessage(). GNU ZRTP uses thes error codes also
+  * to report received Error packts, in this case the sub-codes are their
+  * negative values.
+  *
+  * The enumeration member comments are copied from the ZRTP specification.
+  */
+enum zrtp_ZrtpErrorCodes {
+    zrtp_MalformedPacket =   0x10,    /*!< Malformed packet (CRC OK, but wrong structure) */
+    zrtp_CriticalSWError =   0x20,    /*!< Critical software error */
+    zrtp_UnsuppZRTPVersion = 0x30,    /*!< Unsupported ZRTP version */
+    zrtp_HelloCompMismatch = 0x40,    /*!< Hello components mismatch */
+    zrtp_UnsuppHashType =    0x51,    /*!< Hash type not supported */
+    zrtp_UnsuppCiphertype =  0x52,    /*!< Cipher type not supported */
+    zrtp_UnsuppPKExchange =  0x53,    /*!< Public key exchange not supported */
+    zrtp_UnsuppSRTPAuthTag = 0x54,    /*!< SRTP auth. tag not supported */
+    zrtp_UnsuppSASScheme =   0x55,    /*!< SAS scheme not supported */
+    zrtp_NoSharedSecret =    0x56,    /*!< No shared secret available, DH mode required */
+    zrtp_DHErrorWrongPV =    0x61,    /*!< DH Error: bad pvi or pvr ( == 1, 0, or p-1) */
+    zrtp_DHErrorWrongHVI =   0x62,    /*!< DH Error: hvi != hashed data */
+    zrtp_SASuntrustedMiTM =  0x63,    /*!< Received relayed SAS from untrusted MiTM */
+    zrtp_ConfirmHMACWrong =  0x70,    /*!< Auth. Error: Bad Confirm pkt HMAC */
+    zrtp_NonceReused =       0x80,    /*!< Nonce reuse */
+    zrtp_EqualZIDHello =     0x90,    /*!< Equal ZIDs in Hello */
+    zrtp_GoCleatNotAllowed = 0x100,   /*!< GoClear packet received, but not allowed */
+    zrtp_IgnorePacket =      0x7fffffff /*!< Internal state, not reported */
+};
+
+/**
+ * Information codes for the Enrollment user callbacks.
+ */
+enum zrtp_InfoEnrollment {
+    zrtp_EnrollmentRequest,              //!< Aks user to confirm or deny an Enrollemnt request
+    zrtp_EnrollmentCanceled,             //!< User did not confirm the PBX enrollement
+    zrtp_EnrollmentFailed,               //!< Enrollment process failed, no PBX secret available
+    zrtp_EnrollmentOk                    //!< Enrollment process for this PBX was ok
+};
+
+/* The ZRTP protocol states */
+enum zrtpStates {
+    Initial,            /*!< Initial state after starting the state engine */
+    Detect,             /*!< State sending Hello, try to detect answer message */
+    AckDetected,        /*!< HelloAck received */
+    AckSent,            /*!< HelloAck sent after Hello received */
+    WaitCommit,         /*!< Wait for a Commit message */
+    CommitSent,         /*!< Commit message sent */
+    WaitDHPart2,        /*!< Wait for a DHPart2 message */
+    WaitConfirm1,       /*!< Wait for a Confirm1 message */
+    WaitConfirm2,       /*!< Wait for a confirm2 message */
+    WaitConfAck,        /*!< Wait for Conf2Ack */
+    WaitClearAck,       /*!< Wait for clearAck - not used */
+    SecureState,        /*!< This is the secure state - SRTP active */
+    WaitErrorAck,       /*!< Wait for ErrorAck message */
+    numberOfStates      /*!< Gives total number of protocol states */
+};
+
+/*! The algorihms that we support in SRTP and that ZRTP can negotiate. */
+typedef enum {
+    zrtp_Aes = 1,        /*!< Use AES as symmetrical cipher algorithm */
+    zrtp_TwoFish,        /*!< Use TwoFish as symmetrical cipher algorithm */
+    zrtp_Sha1,           /*!< Use Sha1 as authentication algorithm */
+    zrtp_Skein           /*!< Use Skein as authentication algorithm */
+} zrtp_SrtpAlgorithms;
+
+/**
+ * This structure contains pointers to the SRTP secrets and the role info.
+ *
+ * About the role and what the meaning of the role is refer to the
+ * of the enum Role. The pointers to the secrets are valid as long as
+ * the ZRtp object is active. To use these data after the ZRtp object's
+ * lifetime you may copy the data into a save place.
+ */
+typedef struct c_srtpSecrets
+{
+    zrtp_SrtpAlgorithms symEncAlgorithm;/*!< symmetrical cipher algorithm */
+    const uint8_t* keyInitiator;        /*!< Initiator's key */
+    int32_t initKeyLen;                 /*!< Initiator's key length */
+    const uint8_t* saltInitiator;       /*!< Initiator's salt */
+    int32_t initSaltLen;                /*!< Initiator's salt length */
+    const uint8_t* keyResponder;        /*!< Responder's key */
+    int32_t respKeyLen;                 /*!< Responder's key length */
+    const uint8_t* saltResponder;       /*!< Responder's salt */
+    int32_t respSaltLen;                /*!< Responder's salt length */
+    zrtp_SrtpAlgorithms authAlgorithm;  /*!< SRTP authentication algorithm */
+    int32_t srtpAuthTagLen;             /*!< SRTP authentication length */
+    char* sas;                          /*!< The SAS string */
+    int32_t  role;                      /*!< ZRTP role of this client */
+} C_SrtpSecret_t;
+
+/*
+ * Keep the following defines in sync with enum EnableSecurity in ZrtpCallback.h
+ */
+#define ForReceiver 1       /*!< Enable security for SRTP receiver */
+#define ForSender   2       /*!< Enable security for SRTP sender */
+
+#ifdef __cplusplus
+#pragma GCC visibility push(default)
+extern "C"
+{
+#endif
+
+    typedef struct ZRtp ZRtp;
+    typedef struct ZrtpCallbackWrapper ZrtpCallbackWrapper;
+    typedef struct ZrtpConfigure ZrtpConfigure;
+
+
+    typedef struct zrtpContext
+    {
+        ZRtp* zrtpEngine;                   /*!< Holds the real ZRTP engine */
+        ZrtpCallbackWrapper* zrtpCallback;  /*!< Help class Callback wrapper */
+        ZrtpConfigure* configure;           /*!< Optional configuration data */
+        void* userData;                     /*!< User data, set by application */
+    } ZrtpContext;
+
+    /**
+    * This structure defines the callback functions required by GNU ZRTP.
+    *
+    * The RTP stack specific part must implement the callback methods.
+    * The generic part of GNU ZRTP uses these mehtods
+    * to communicate with the specific part, for example to send data
+    * via the RTP/SRTP stack, to set timers and cancel timer and so on.
+    *
+    * The generiy part of GNU ZRTP needs only a few callback methods to
+    * be implemented by the specific part.
+    *
+    * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+    */
+
+    /**
+     * The following methods define the GNU ZRTP callback interface.
+     * For detailed documentation refer to file ZrtpCallback.h, each C
+     * method has "zrtp_" prepended to the C++ name.
+     *
+     * @see ZrtpCallback
+     */
+    typedef struct zrtp_Callbacks
+    {
+        /**
+        * Send a ZRTP packet via RTP.
+        *
+        * ZRTP calls this method to send a ZRTP packet via the RTP session.
+        * The ZRTP packet will have to be created using the provided ZRTP message.
+        *
+        * @param ctx
+        *    Pointer to the opaque ZrtpContext structure.
+        * @param data
+        *    Points to ZRTP message to send.
+        * @param length
+        *    The length in bytes of the data
+        * @return
+        *    zero if sending failed, one if packet was sent
+        */
+        int32_t (*zrtp_sendDataZRTP) (ZrtpContext* ctx, const uint8_t* data, int32_t length ) ;
+
+        /**
+        * Activate timer.
+        *
+        * @param ctx
+        *    Pointer to the opaque ZrtpContext structure.
+        * @param time
+        *    The time in ms for the timer
+        * @return
+        *    zero if activation failed, one if timer was activated
+        */
+        int32_t (*zrtp_activateTimer) (ZrtpContext* ctx, int32_t time ) ;
+
+        /**
+        * Cancel the active timer.
+        *
+        * @param ctx
+        *    Pointer to the opaque ZrtpContext structure.
+        * @return
+        *    zero if cancel action failed, one if timer was canceled
+        */
+        int32_t (*zrtp_cancelTimer)(ZrtpContext* ctx) ;
+
+        /**
+        * Send information messages to the hosting environment.
+        *
+        * The ZRTP implementation uses this method to send information
+        * messages to the host. Along with the message ZRTP provides a
+        * severity indicator that defines: Info, Warning, Error,
+        * Alert. Refer to the <code>MessageSeverity</code> enum above.
+        *
+        * @param ctx
+        *    Pointer to the opaque ZrtpContext structure.
+        * @param severity
+        *     This defines the message's severity
+        * @param subCode
+        *     The subcode identifying the reason.
+        * @see ZrtpCodes#MessageSeverity
+        */
+        void (*zrtp_sendInfo) (ZrtpContext* ctx, int32_t severity, int32_t subCode ) ;
+
+        /**
+         * SRTP crypto data ready for the sender or receiver.
+         *
+         * The ZRTP implementation calls this method right after all SRTP
+         * secrets are computed and ready to be used. The parameter points
+         * to a structure that contains pointers to the SRTP secrets and a
+         * <code>enum Role</code>. The called method (the implementation
+         * of this abstract method) must either copy the pointers to the SRTP
+         * data or the SRTP data itself to a save place. The SrtpSecret_t
+         * structure is destroyed after the callback method returns to the
+         * ZRTP implementation.
+         *
+         * The SRTP data themselves are obtained in the ZRtp object and are
+         * valid as long as the ZRtp object is active. TheZRtp's
+         * destructor clears the secrets. Thus the called method needs to
+         * save the pointers only, ZRtp takes care of the data.
+         *
+         * The implementing class may enable SRTP processing in this
+         * method or delay it to srtpSecertsOn().
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param secrets A pointer to a SrtpSecret_t structure that
+         *     contains all necessary data.
+         *
+         * @param part for which part (Sender or Receiver) this data is
+         *     valid.
+         *
+         * @return Returns false if something went wrong during
+         *    initialization of SRTP context, for example memory shortage.
+         */
+        int32_t (*zrtp_srtpSecretsReady) (ZrtpContext* ctx, C_SrtpSecret_t* secrets, int32_t part ) ;
+
+        /**
+         * Switch off the security for the defined part.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param part Defines for which part (sender or receiver) to
+         *    switch on security
+         */
+        void (*zrtp_srtpSecretsOff) (ZrtpContext* ctx, int32_t part ) ;
+
+        /**
+         * Switch on the security.
+         *
+         * ZRTP calls this method after it has computed the SAS and check
+         * if it is verified or not. In addition ZRTP provides information
+         * about the cipher algorithm and key length for the SRTP session.
+         *
+         * This method must enable SRTP processing if it was not enabled
+         * during sertSecretsReady().
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param c The name of the used cipher algorithm and mode, or
+         *    NULL
+         *
+         * @param s The SAS string
+         *
+         * @param verified if <code>verified</code> is true then SAS was
+         *    verified by both parties during a previous call.
+         */
+        void (*zrtp_rtpSecretsOn) (ZrtpContext* ctx, char* c, char* s, int32_t verified ) ;
+
+        /**
+         * This method handles GoClear requests.
+         *
+         * According to the ZRTP specification the user must be informed about
+         * a GoClear request because the ZRTP implementation switches off security
+         * if it could authenticate the GoClear packet.
+         *
+         * <b>Note:</b> GoClear is not yet implemented in GNU ZRTP.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         */
+        void (*zrtp_handleGoClear)(ZrtpContext* ctx) ;
+
+        /**
+         * Handle ZRTP negotiation failed.
+         *
+         * ZRTP calls this method in case ZRTP negotiation failed. The
+         * parameters show the severity as well as the reason.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param severity
+         *     This defines the message's severity
+         * @param subCode
+         *     The subcode identifying the reason.
+         * @see ZrtpCodes#MessageSeverity
+         */
+        void (*zrtp_zrtpNegotiationFailed) (ZrtpContext* ctx, int32_t severity, int32_t subCode ) ;
+
+        /**
+         * ZRTP calls this method if the other side does not support ZRTP.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * If the other side does not answer the ZRTP <em>Hello</em> packets then
+         * ZRTP calls this method,
+         *
+         */
+        void (*zrtp_zrtpNotSuppOther)(ZrtpContext* ctx) ;
+
+        /**
+         * Enter synchronization mutex.
+         *
+         * GNU ZRTP requires one mutex to synchronize its
+         * processing. Because mutex implementations depend on the
+         * underlying infrastructure, for example operating system or
+         * thread implementation, GNU ZRTP delegates mutex handling to the
+         * specific part of its implementation.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         */
+        void (*zrtp_synchEnter)(ZrtpContext* ctx) ;
+
+        /**
+         * Leave synchronization mutex.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         */
+        void (*zrtp_synchLeave)(ZrtpContext* ctx) ;
+
+        /**
+         * Inform about a PBX enrollment request.
+         *
+         * Please refer to chapter 8.3 ff to get more details about PBX
+         * enrollment and SAS relay.
+         *
+         * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+         * ZRTP.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param info Give some information to the user about the PBX
+         *    requesting an enrollment.
+         */
+        void (*zrtp_zrtpAskEnrollment) (ZrtpContext* ctx, int32_t info) ;
+
+        /**
+         * Inform about PBX enrollment result.
+         *
+         * Informs the use about the acceptance or denial of an PBX enrollment
+         * request
+         *
+         * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+         * ZRTP.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param info Give some information to the user about the result
+         *    of an enrollment.
+         */
+        void (*zrtp_zrtpInformEnrollment) (ZrtpContext* ctx, int32_t info ) ;
+
+        /**
+         * Request a SAS signature.
+         *
+         * After ZRTP was able to compute the Short Authentication String
+         * (SAS) it calls this method. The client may now use an
+         * approriate method to sign the SAS. The client may use
+         * ZrtpQueue#setSignatureData() to store the signature data and
+         * enable signature transmission to the other peer. Refer to
+         * chapter 8.2 of ZRTP specification.
+         *
+         * <b>Note:</b> SAS signing is not yet fully supported by GNU
+         * ZRTP.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param sas
+         *    Pointer to the 32 byte SAS hash to sign.
+         *
+         */
+        void (*zrtp_signSAS)(ZrtpContext* ctx, uint8_t* sas) ;
+
+        /**
+         * ZRTPQueue calls this method to request a SAS signature check.
+         *
+         * After ZRTP received a SAS signature in one of the Confirm packets it
+         * call this method. The client may use <code>getSignatureLength()</code>
+         * and <code>getSignatureData()</code>of ZrtpQueue to get the signature
+         * data and perform the signature check. Refer to chapter 8.2 of ZRTP
+         * specification.
+         *
+         * If the signature check fails the client may return false to ZRTP. In
+         * this case ZRTP signals an error to the other peer and terminates
+         * the ZRTP handshake.
+         *
+         * <b>Note:</b> SAS signing is not yet fully supported by GNU
+         * ZRTP.
+         *
+         * @param ctx
+         *    Pointer to the opaque ZrtpContext structure.
+         * @param sas
+         *    Pointer to the 32 byte SAS hash that was signed by the other peer.
+         * @return
+         *    true if the signature was ok, false otherwise.
+         *
+         */
+        int32_t (*zrtp_checkSASSignature) (ZrtpContext* ctx, uint8_t* sas ) ;
+    } zrtp_Callbacks;
+
+    /**
+     * Create the GNU ZRTP C wrapper.
+     *
+     * This wrapper implements the C interface to the C++ based GNU ZRTP.
+     * @returns
+     *      Pointer to the ZrtpContext
+     */
+    ZrtpContext* zrtp_CreateWrapper();
+
+    /**
+     * Initialize the ZRTP protocol engine.
+     *
+     * This method initialized the GNU ZRTP protocol engine. An application
+     * calls this method to actually create the ZRTP protocol engine and
+     * initialize its configuration data. This method does not start the
+     * protocol engine.
+     *
+     * If an application requires a specific algorithm configuration then it
+     * must set the algorithm configuration data before it initializes the
+     * ZRTP protocol engine.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param cb
+     *     The callback structure that holds the addresses of the callback
+     *     methods.
+     * @param id
+     *     A C string that holds the ZRTP client id, only the first 16 chars
+     *     are used.
+     * @param zidFilename
+     *     The name of the ZID file. This file holds some parameters and
+     *     other data like additional shared secrets.
+     * @param userData
+     *     A pointer to user data. The wrapper just stores this pointer in
+     *     the ZrtpContext and the application may use it for its purposes.
+     * @param mitmMode
+     *     A trusted Mitm (PBX) must set this to true. The ZRTP engine sets
+     *     the M Flag in the Hello packet to announce a trusted MitM.
+     * @returns
+     *      Pointer to the ZrtpContext
+     *
+     * @see zrtp_InitializeConfig
+     */
+    void zrtp_initializeZrtpEngine(ZrtpContext* zrtpContext,
+                                   zrtp_Callbacks *cb,
+                                   const char* id,
+                                   const char* zidFilename,
+                                   void* userData,
+                                   int32_t mitmMode);
+
+    /**
+     * Destroy the ZRTP wrapper and its underlying objects.
+     */
+    void zrtp_DestroyWrapper (ZrtpContext* zrtpContext);
+
+    /**
+     * Computes the ZRTP checksum over a received ZRTP packet buffer and
+     * compares the result with received checksum.
+     *
+     * @param buffer
+     *    Pointer to ZRTP packet buffer
+     * @param length
+     *    Length of the packet buffer excluding received CRC data
+     * @param crc
+     *    The received CRC data.
+     * @returns
+     *    True if CRC matches, false otherwise.
+     */
+    int32_t zrtp_CheckCksum(uint8_t* buffer, uint16_t length, uint32_t crc);
+
+    /**
+     * Computes the ZRTP checksum over a newly created ZRTP packet buffer.
+     *
+     * @param buffer
+     *    Pointer to the created ZRTP packet buffer
+     * @param length
+     *    Length of the packet buffer
+     * @returns
+     *    The computed CRC.
+     */
+    uint32_t zrtp_GenerateCksum(uint8_t* buffer, uint16_t length);
+
+    /**
+     * Prepares the ZRTP checksum for appending to ZRTP packet.
+     * @param crc
+     *    The computed CRC data.
+     * @returns
+     *    Prepared CRC data in host order
+     */
+    uint32_t zrtp_EndCksum(uint32_t crc);
+
+    /**
+     * Kick off the ZRTP protocol engine.
+     *
+     * This method calls the ZrtpStateClass#evInitial() state of the state
+     * engine. After this call we are able to process ZRTP packets
+     * from our peer and to process them.
+     *
+     * <b>NOTE: application shall never call this method directly but use the
+     * appropriate method provided by the RTP implementation. </b>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_startZrtpEngine(ZrtpContext* zrtpContext);
+
+    /**
+     * Stop ZRTP security.
+     *
+     * <b>NOTE: An application shall never call this method directly but use the
+     * appropriate method provided by the RTP implementation. </b>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_stopZrtpEngine(ZrtpContext* zrtpContext);
+
+    /**
+     * Process RTP extension header.
+     *
+     * This method expects to get a pointer to the message part of
+     * a ZRTP packet.
+     *
+     * <b>NOTE: An application shall never call this method directly. Only
+     * the module that implements the RTP binding shall use this method</b>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param extHeader
+     *    A pointer to the first byte of the ZRTP message part.
+     * @param peerSSRC
+     *    The peer's SSRC.
+     * @return
+     *    Code indicating further packet handling, see description above.
+     */
+    void zrtp_processZrtpMessage(ZrtpContext* zrtpContext, uint8_t *extHeader, uint32_t peerSSRC);
+
+    /**
+     * Process a timeout event.
+     *
+     * We got a timeout from the timeout provider. Forward it to the
+     * protocol state engine.
+     *
+     * <b>NOTE: application shall never call this method directly. Only
+     * the module that implements the RTP binding shall use this method</b>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_processTimeout(ZrtpContext* zrtpContext);
+
+    /*
+     * Check for and handle GoClear ZRTP packet header.
+     *
+     * This method checks if this is a GoClear packet. If not, just return
+     * false. Otherwise handle it according to the specification.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param extHeader
+     *    A pointer to the first byte of the extension header. Refer to
+     *    RFC3550.
+     * @return
+     *    False if not a GoClear, true otherwise.
+     *
+    int32_t zrtp_handleGoClear(ZrtpContext* zrtpContext, uint8_t *extHeader);
+    */
+    
+    /**
+     * Set the auxilliary secret.
+     *
+     * Use this method to set the auxilliary secret data. Refer to ZRTP
+     * specification, chapter 4.3 ff
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param data
+     *     Points to the secret data.
+     * @param length
+     *     Length of the auxilliary secrect in bytes
+     */
+    void zrtp_setAuxSecret(ZrtpContext* zrtpContext, uint8_t* data, int32_t length);
+
+    /**
+     * Check current state of the ZRTP state engine
+     *
+     * <b>NOTE: application usually don't call this method. Only
+     * the m-odule that implements the RTP binding shall use this method</b>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param state
+     *    The state to check.
+     * @return
+     *    Returns true if ZRTP engine is in the given state, false otherwise.
+     */
+    int32_t zrtp_inState(ZrtpContext* zrtpContext, int32_t state);
+
+    /**
+     * Set SAS as verified.
+     *
+     * Call this method if the user confirmed (verfied) the SAS. ZRTP
+     * remembers this together with the retained secrets data.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_SASVerified(ZrtpContext* zrtpContext);
+
+    /**
+     * Reset the SAS verfied flag for the current active user's retained secrets.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_resetSASVerified(ZrtpContext* zrtpContext);
+
+    /**
+     * Get the ZRTP Hello Hash data.
+     *
+     * Use this method to get the ZRTP Hello Hash data. The method
+     * returns the data as a string containing the ZRTP protocol version and
+     * hex-digits. Refer to ZRTP specification, chapter 8.
+     *
+     * <b>NOTE: An application may call this method if it needs this information.
+     * Usually it is not necessary.</b>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return
+     *    a pointer to a C-string that contains the Hello hash value as
+     *    hex-digits. The hello hash is available immediately after
+     *    @c zrtp_CreateWrapper .
+     *    The caller must @c free() if it does not use the
+     *    hello hash C-string anymore.
+     */
+    char* zrtp_getHelloHash(ZrtpContext* zrtpContext);
+
+    /**
+     * Get the peer's ZRTP Hello Hash data.
+     *
+     * Use this method to get the peer's ZRTP Hello Hash data. The method
+     * returns the data as a string containing the ZRTP protocol version and
+     * hex-digits.
+     *
+     * The peer's hello hash is available only after ZRTP received a hello. If
+     * no data is available the function returns an empty string.
+     *
+     * Refer to ZRTP specification, chapter 8.
+     *
+     * @return
+     *    a std:string containing the Hello version and the hello hash as hex digits.
+     */
+    char* zrtp_getPeerHelloHash(ZrtpContext* zrtpContext);
+
+    /**
+     * Get Multi-stream parameters.
+     *
+     * Use this method to get the Multi-stream parameters that were computed
+     * during the ZRTP handshake. An application may use these parameters to
+     * enable multi-stream processing for an associated SRTP session.
+     *
+     * The application must not modify the contents of returned char array, it
+     * is opaque data. The application may hand over this string to a new ZRTP
+     * instance to enable multi-stream processing for this new session.
+     *
+     * Refer to chapter 4.4.2 in the ZRTP specification for further details
+     * and restriction how and when to use multi-stream mode.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param length
+     *    Pointer to an integer that receives the length of the char array
+     * @return
+     *    a char array that contains the multi-stream parameters.
+     *    If ZRTP was not started or ZRTP is not yet in secure state the method
+     *    returns NULL and a length of 0.
+     */
+    char* zrtp_getMultiStrParams(ZrtpContext* zrtpContext, int32_t *length);
+
+    /**
+     * Set Multi-stream parameters.
+     *
+     * Use this method to set the parameters required to enable Multi-stream
+     * processing of ZRTP. The multi-stream parameters must be set before the
+     * application starts the ZRTP protocol engine.
+     *
+     * Refer to chapter 4.4.2 in the ZRTP specification for further details
+     * of multi-stream mode.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param length
+     *    The integer that contains the length of the char array
+     * @param parameters
+     *     A char array that contains the multi-stream parameters that this
+     *     new ZRTP instance shall use. See also
+     *     <code>getMultiStrParams()</code>
+     */
+    void zrtp_setMultiStrParams(ZrtpContext* zrtpContext, char* parameters, int32_t length);
+
+    /**
+     * Check if this ZRTP session is a Multi-stream session.
+     *
+     * Use this method to check if this ZRTP instance uses multi-stream.
+     * Refer to chapters 4.2 and 4.4.2 in the ZRTP.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return
+     *     True if multi-stream is used, false otherwise.
+     */
+    int32_t zrtp_isMultiStream(ZrtpContext* zrtpContext);
+
+    /**
+     * Check if the other ZRTP client supports Multi-stream.
+     *
+     * Use this method to check if the other ZRTP client supports
+     * Multi-stream mode.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return
+     *     True if multi-stream is available, false otherwise.
+     */
+    int32_t zrtp_isMultiStreamAvailable(ZrtpContext* zrtpContext);
+
+    /**
+     * Accept a PBX enrollment request.
+     *
+     * If a PBX service asks to enroll the PBX trusted MitM key and the user
+     * accepts this request, for example by pressing an OK button, the client
+     * application shall call this method and set the parameter
+     * <code>accepted</code> to true. If the user does not accept the request
+     * set the parameter to false.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param accepted
+     *     True if the enrollment request is accepted, false otherwise.
+     */
+    void zrtp_acceptEnrollment(ZrtpContext* zrtpContext, int32_t accepted);
+
+    /**
+     * Check the state of the enrollment mode.
+     * 
+     * If true then we will set the enrollment flag (E) in the confirm
+     * packets and performs the enrollment actions. A MitM (PBX) enrollment service 
+     * started this ZRTP session. Can be set to true only if mitmMode is also true.
+     * 
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return status of the enrollmentMode flag.
+     */
+    int32_t zrtp_isEnrollmentMode(ZrtpContext* zrtpContext);
+
+    /**
+     * Check the state of the enrollment mode.
+     * 
+     * If true then we will set the enrollment flag (E) in the confirm
+     * packets and perform the enrollment actions. A MitM (PBX) enrollment 
+     * service must sets this mode to true. 
+     * 
+     * Can be set to true only if mitmMode is also true. 
+     * 
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param enrollmentMode defines the new state of the enrollmentMode flag
+     */
+    void zrtp_setEnrollmentMode(ZrtpContext* zrtpContext, int32_t enrollmentMode);
+
+    /**
+     * Check if a peer's cache entry has a vaild MitM key.
+     *
+     * If true then the other peer ha a valid MtiM key, i.e. the peer has performed
+     * the enrollment procedure. A PBX ZRTP Back-2-Back application can use this function
+     * to check which of the peers is enrolled.
+     *
+     * @return True if the other peer has a valid Mitm key (is enrolled).
+     */
+    int32_t isPeerEnrolled(ZrtpContext* zrtpContext);
+
+    /**
+     * Send the SAS relay packet.
+     * 
+     * The method creates and sends a SAS relay packet according to the ZRTP
+     * specifications. Usually only a MitM capable user agent (PBX) uses this
+     * function.
+     * 
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param sh the full SAS hash value
+     * @param render the SAS rendering algorithm
+     */
+    int32_t zrtp_sendSASRelayPacket(ZrtpContext* zrtpContext, uint8_t* sh, char* render);
+
+    /**
+     * Get the commited SAS rendering algorithm for this ZRTP session.
+     * 
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return the commited SAS rendering algorithm
+     */
+    const char* zrtp_getSasType(ZrtpContext* zrtpContext);
+ 
+    /**
+     * Get the computed SAS hash for this ZRTP session.
+     * 
+     * A PBX ZRTP back-to-Back function uses this function to get the SAS
+     * hash of an enrolled client to construct the SAS relay packet for
+     * the other client.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return a pointer to the byte array that contains the full 
+     *         SAS hash.
+     */
+    uint8_t* zrtp_getSasHash(ZrtpContext* zrtpContext);
+
+    /**
+     * Set signature data
+     *
+     * This functions stores signature data and transmitts it during ZRTP
+     * processing to the other party as part of the Confirm packets. Refer to
+     * chapters 5.7 and 7.2.
+     *
+     * The signature data must be set before ZRTP the application calls
+     * <code>start()</code>.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param data
+     *    The signature data including the signature type block. The method
+     *    copies this data into the Confirm packet at signature type block.
+     * @param length
+     *    The length of the signature data in bytes. This length must be
+     *    multiple of 4.
+     * @return
+     *    True if the method stored the data, false otherwise.
+     */
+    int32_t zrtp_setSignatureData(ZrtpContext* zrtpContext, uint8_t* data, int32_t length);
+
+    /**
+     * Get signature data
+     *
+     * This functions returns signature data that was receivied during ZRTP
+     * processing. Refer to chapters 5.7 and 7.2.
+     *
+     * The signature data can be retrieved after ZRTP enters secure state.
+     * <code>start()</code>.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return
+     *    Number of bytes copied into the data buffer
+     */
+    const uint8_t* zrtp_getSignatureData(ZrtpContext* zrtpContext);
+
+    /**
+     * Get length of signature data
+     *
+     * This functions returns the length of signature data that was receivied
+     * during ZRTP processing. Refer to chapters 5.7 and 7.2.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return
+     *    Length in bytes of the received signature data. The method returns
+     *    zero if no signature data avilable.
+     */
+    int32_t zrtp_getSignatureLength(ZrtpContext* zrtpContext);
+
+    /**
+     * Emulate a Conf2Ack packet.
+     *
+     * This method emulates a Conf2Ack packet. According to ZRTP specification
+     * the first valid SRTP packet that the Initiator receives must switch
+     * on secure mode. Refer to chapter 4 in the specificaton
+     *
+     * <b>NOTE: application shall never call this method directly. Only
+     * the module that implements the RTP binding shall use this method</b>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_conf2AckSecure(ZrtpContext* zrtpContext);
+
+    /**
+     * Get other party's ZID (ZRTP Identifier) data
+     *
+     * This functions returns the other party's ZID that was receivied
+     * during ZRTP processing.
+     *
+     * The ZID data can be retrieved after ZRTP receive the first Hello
+     * packet from the other party. The application may call this method
+     * for example during SAS processing in showSAS(...) user callback
+     * method.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param data
+     *    Pointer to a data buffer. This buffer must have a size of
+     *    at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
+     * @return
+     *    Number of bytes copied into the data buffer - must be equivalent
+     *    to 12 bytes.
+     */
+    int32_t zrtp_getPeerZid(ZrtpContext* zrtpContext, uint8_t* data);
+
+
+    /**
+     * This enumerations list all configurable algorithm types.
+     */
+
+    /* Keep in synch with enumeration in ZrtpConfigure.h */
+
+    typedef enum zrtp_AlgoTypes {
+        zrtp_HashAlgorithm = 1, zrtp_CipherAlgorithm, zrtp_PubKeyAlgorithm, zrtp_SasType, zrtp_AuthLength
+    } Zrtp_AlgoTypes;
+
+    /**
+     * Initialize the GNU ZRTP Configure data.
+     *
+     * Initializing and setting a ZRTP configuration is optional. GNU ZRTP
+     * uses a sensible default if an application does not define its own
+     * ZRTP configuration.
+     *
+     * If an application initialize th configure data it must set the
+     * configuration data.
+     *
+     * The ZRTP specification, chapters 5.1.2 through 5.1.6 defines the
+     * algorithm names and their meaning.
+     *
+     * The current ZRTP implementation implements all mandatory algorithms
+     * plus a set of the optional algorithms. An application shall use
+     * @c zrtp_getAlgorithmNames to get the names of the available algorithms.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @returns
+     *      Pointer to the ZrtpConfCtx
+     *
+     * @see zrtp_getAlgorithmNames
+     */
+    int32_t zrtp_InitializeConfig (ZrtpContext* zrtpContext);
+
+    /**
+     * Get names of all available algorithmes of a given algorithm type.
+     *
+     * The algorithm names are as specified in the ZRTP specification, chapters
+     * 5.1.2 through 5.1.6 .
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param type
+     *    The algorithm type.
+     * @returns
+     *    A NULL terminated array of character pointers.
+     */
+    char** zrtp_getAlgorithmNames(ZrtpContext* zrtpContext, Zrtp_AlgoTypes type);
+
+    /**
+     * Free storage used to store the algorithm names.
+     *
+     * If an application does not longer require the algoritm names it should
+     * free the space.
+     *
+     * @param names
+     *    The NULL terminated array of character pointers.
+     */
+    void zrtp_freeAlgorithmNames(char** names);
+
+    /**
+    * Convenience function that sets a pre-defined standard configuration.
+    *
+    * The standard configuration consists of the following algorithms:
+    * <ul>
+    * <li> Hash: SHA256 </li>
+    * <li> Symmetric Cipher: AES 128, AES 256 </li>
+    * <li> Public Key Algorithm: DH2048, DH3027, MultiStream </li>
+    * <li> SAS type: libase 32 </li>
+    * <li> SRTP Authentication lengths: 32, 80 </li>
+    *</ul>
+    *
+    * @param zrtpContext
+    *    Pointer to the opaque ZrtpContext structure.
+    */
+    void zrtp_setStandardConfig(ZrtpContext* zrtpContext);
+
+    /**
+     * Convenience function that sets the mandatory algorithms only.
+     *
+     * Mandatory algorithms are:
+     * <ul>
+     * <li> Hash: SHA256 </li>
+     * <li> Symmetric Cipher: AES 128 </li>
+     * <li> Public Key Algorithm: DH3027, MultiStream </li>
+     * <li> SAS type: libase 32 </li>
+     * <li> SRTP Authentication lengths: 32, 80 </li>
+     *</ul>
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_setMandatoryOnly(ZrtpContext* zrtpContext);
+
+    /**
+     * Clear all configuration data.
+     *
+     * The functions clears all configuration data.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     */
+    void zrtp_confClear(ZrtpContext* zrtpContext);
+
+    /**
+     * Add an algorithm to configuration data.
+     *
+     * Adds the specified algorithm to the configuration data.
+     * If no free configuration data slot is available the
+     * function does not add the algorithm and returns -1. The
+     * methods appends the algorithm to the existing algorithms.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The name of the algorithm to add.
+     * @return
+     *    Number of free configuration data slots or -1 on error
+     */
+    int32_t zrtp_addAlgo(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char* algo);
+
+    /**
+     * Add an algorithm to configuration data at given index
+     *
+     * Adds the specified algorithm to the configuration data vector
+     * at a given index. If the index is larger than the actual size
+     * of the configuration vector the method just appends the algorithm.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The name of the algorithm to add.
+     * @param index
+     *    The index where to add the algorihm
+     * @return
+     *    Number of free configuration data slots or -1 on error
+     */
+    int32_t zrtp_addAlgoAt(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char* algo, int32_t index);
+
+    /**
+     * Remove a algorithm from configuration data.
+     *
+     * Removes the specified algorithm from configuration data. If
+     * the algorithm was not configured previously the function does
+     * not modify the configuration data and returns the number of
+     * free configuration data slots.
+     *
+     * If an application removes all algorithms then ZRTP does not
+     * include any algorithm into the hello message and falls back
+     * to a predefined mandatory algorithm.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The name of the algorithm to remove.
+     * @return
+     *    Number of free configuration slots.
+     */
+    int32_t zrtp_removeAlgo(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char* algo);
+
+    /**
+     * Returns the number of configured algorithms.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @return
+     *    The number of configured algorithms (used configuration
+     *    data slots)
+     */
+    int32_t zrtp_getNumConfiguredAlgos(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType);
+
+    /**
+     * Returns the identifier of the algorithm at index.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param index
+     *    The index in the list of the algorihm type
+     * @return
+     *    A pointer to the algorithm name. If the index
+     *    does not point to a configured slot then the function
+     *    returns NULL.
+     *
+     */
+    const char* zrtp_getAlgoAt(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, int32_t index);
+
+    /**
+     * Checks if the configuration data of the algorihm type already contains
+     * a specific algorithms.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The name of the algorithm to check
+     * @return
+     *    True if the algorithm was found, false otherwise.
+     *
+     */
+    int32_t zrtp_containsAlgo(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char*  algo);
+
+    /**
+     * Enables or disables trusted MitM processing.
+     *
+     * For further details of trusted MitM processing refer to ZRTP
+     * specification, chapter 7.3
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param yesNo
+     *    If set to true then trusted MitM processing is enabled.
+     */
+    void zrtp_setTrustedMitM(ZrtpContext* zrtpContext, int32_t yesNo);
+
+    /**
+     * Check status of trusted MitM processing.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return
+     *    Returns true if trusted MitM processing is enabled.
+     */
+    int32_t zrtp_isTrustedMitM(ZrtpContext* zrtpContext);
+
+    /**
+     * Enables or disables SAS signature processing.
+     *
+     * For further details of trusted MitM processing refer to ZRTP
+     * specification, chapter 7.2
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @param yesNo
+     *    If true then certificate processing is enabled.
+     */
+    void zrtp_setSasSignature(ZrtpContext* zrtpContext, int32_t yesNo);
+
+    /**
+     * Check status of SAS signature processing.
+     *
+     * @param zrtpContext
+     *    Pointer to the opaque ZrtpContext structure.
+     * @return
+     *    Returns true if certificate processing is enabled.
+     */
+    int32_t zrtp_isSasSignature(ZrtpContext* zrtpContext);
+
+#ifdef __cplusplus
+}
+#pragma GCC visibility pop
+#endif
+
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpCallback.h b/jni/libzrtp/src/libzrtpcpp/ZrtpCallback.h
new file mode 100644
index 0000000..957c4dd
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpCallback.h
@@ -0,0 +1,367 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCALLBACK_H_
+#define _ZRTPCALLBACK_H_
+
+/**
+ * @file ZrtpCallback.h
+ * @brief Callback interface between ZRTP and the RTP stack implementation
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <string>
+#include <stdint.h>
+#include <libzrtpcpp/ZrtpCodes.h>
+
+#ifndef __EXPORT
+  #if __GNUC__ >= 4
+    #define __EXPORT    __attribute__ ((visibility("default")))
+    #define __LOCAL     __attribute__ ((visibility("hidden")))
+  #elif defined _WIN32 || defined __CYGWIN__
+    #define __EXPORT    __declspec(dllimport)
+    #define __LOCAL
+  #else
+    #define __EXPORT
+    #define __LOCAL
+  #endif
+#endif
+
+/**
+ * This enum defines which role a ZRTP peer has.
+ *
+ * According to the ZRTP specification the role determines which keys to
+ * use to encrypt or decrypt SRTP data.
+ *
+ * <ul>
+ * <li> The Initiator encrypts SRTP data using the <em>keyInitiator</em> and the
+ *      <em>saltInitiator</em> data, the Responder uses these data to decrypt.
+ * </li>
+ * <li> The Responder encrypts SRTP data using the <em>keyResponder</em> and the
+ *      <em>saltResponder</em> data, the Initiator uses these data to decrypt.
+ * </li>
+ * </ul>
+ */
+typedef enum  {
+    Responder = 1,  ///< This client is in ZRTP Responder mode
+    Initiator       ///< This client is in ZRTP Initiator mode
+} Role;
+
+/// The algorihms that we support in SRTP and that ZRTP can negotiate.
+typedef enum {
+    None,
+    Aes = 1,        ///< Use AES as symmetrical cipher algorithm
+    TwoFish,        ///< Use TwoFish as symmetrical cipher algorithm
+    Sha1,           ///< Use Sha1 as authentication algorithm
+    Skein           ///< Use Skein as authentication algorithm
+} SrtpAlgorithms;
+
+/**
+ * This structure contains pointers to the SRTP secrets and the role info.
+ *
+ * About the role and what the meaning of the role is refer to the
+ * of the enum Role. The pointers to the secrets are valid as long as
+ * the ZRtp object is active. To use these data after the ZRtp object's
+ * lifetime you may copy the data into a save place. The destructor
+ * of ZRtp clears the data.
+ */
+typedef struct srtpSecrets {
+    SrtpAlgorithms symEncAlgorithm;     ///< symmetrical cipher algorithm
+    const uint8_t* keyInitiator;        ///< Initiator's key
+    int32_t initKeyLen;                 ///< Initiator's key length
+    const uint8_t* saltInitiator;       ///< Initiator's salt
+    int32_t initSaltLen;                ///< Initiator's salt length
+    const uint8_t* keyResponder;        ///< Responder's key
+    int32_t respKeyLen;                 ///< Responder's key length
+    const uint8_t* saltResponder;       ///< Responder's salt
+    int32_t respSaltLen;                ///< Responder's salt length
+    SrtpAlgorithms authAlgorithm;       ///< SRTP authentication algorithm
+    int32_t srtpAuthTagLen;             ///< SRTP authentication length
+    std::string sas;                    ///< The SAS string
+    Role  role;                         ///< ZRTP role of this client
+} SrtpSecret_t;
+
+enum EnableSecurity {
+    ForReceiver = 1,        ///< Enable security for SRTP receiver
+    ForSender   = 2         ///< Enable security for SRTP sender
+};
+
+/**
+ * This abstract class defines the callback functions required by GNU ZRTP.
+ *
+ * This class is a pure abstract class, aka Interface in Java, that
+ * defines the callback interface that the specific part of a GNU ZRTP
+ * must implement. The generic part of GNU ZRTP uses these mehtods
+ * to communicate with the specific part, for example to send data
+ * via the RTP/SRTP stack, to set timers and cancel timer and so on.
+ *
+ * The generiy part of GNU ZRTP needs only a few callback methods to
+ * be implemented by the specific part.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpCallback {
+
+protected:
+    friend class ZRtp;
+
+    virtual ~ZrtpCallback() {};
+
+    /**
+     * Send a ZRTP packet via RTP.
+     *
+     * ZRTP calls this method to send a ZRTP packet via the RTP session.
+     *
+     * @param data
+     *    Points to ZRTP packet to send.
+     * @param length
+     *    The length in bytes of the data
+     * @return
+     *    zero if sending failed, one if packet was send
+     */
+    virtual int32_t sendDataZRTP(const uint8_t* data, int32_t length) =0;
+
+    /**
+     * Activate timer.
+     *
+     * @param time
+     *    The time in ms for the timer
+     * @return
+     *    zero if activation failed, one if timer was activated
+     */
+    virtual int32_t activateTimer(int32_t time) =0;
+
+    /**
+     * Cancel the active timer.
+     *
+     * @return
+     *    zero if cancel action failed, one if timer was canceled
+     */
+    virtual int32_t cancelTimer() =0;
+
+    /**
+     * Send information messages to the hosting environment.
+     *
+     * The ZRTP implementation uses this method to send information
+     * messages to the host. Along with the message ZRTP provides a
+     * severity indicator that defines: Info, Warning, Error,
+     * Alert. Refer to the <code>MessageSeverity</code> enum above.
+     *
+     * @param severity
+     *     This defines the message's severity
+     * @param subCode
+     *     The subcode identifying the reason.
+     * @see ZrtpCodes#MessageSeverity
+     */
+    virtual void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) =0;
+
+    /**
+     * SRTP crypto data ready for the sender or receiver.
+     *
+     * The ZRTP implementation calls this method right after all SRTP
+     * secrets are computed and ready to be used. The parameter points
+     * to a structure that contains pointers to the SRTP secrets and a
+     * <code>enum Role</code>. The called method (the implementation
+     * of this abstract method) must either copy the pointers to the SRTP
+     * data or the SRTP data itself to a save place. The SrtpSecret_t
+     * structure is destroyed after the callback method returns to the
+     * ZRTP implementation.
+     *
+     * The SRTP data themselfs are ontained in the ZRtp object and are
+     * valid as long as the ZRtp object is active. TheZRtp's
+     * destructor clears the secrets. Thus the called method needs to
+     * save the pointers only, ZRtp takes care of the data.
+     *
+     * The implementing class may enable SRTP processing in this
+     * method or delay it to srtpSecertsOn().
+     *
+     * @param secrets A pointer to a SrtpSecret_t structure that
+     *     contains all necessary data.
+     *
+     * @param part for which part (Sender or Receiver) this data is
+     *     valid.
+     *
+     * @return Returns false if something went wrong during
+     *    initialization of SRTP context, for example memory shortage.
+     */
+    virtual bool srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part) =0;
+
+    /**
+     * Switch off the security for the defined part.
+     *
+     * @param part Defines for which part (sender or receiver) to
+     *    switch on security
+     */
+    virtual void srtpSecretsOff(EnableSecurity part) =0;
+
+    /**
+     * Switch on the security.
+     *
+     * ZRTP calls this method after it has computed the SAS and check
+     * if it is verified or not. In addition ZRTP provides information
+     * about the cipher algorithm and key length for the SRTP session.
+     *
+     * This method must enable SRTP processing if it was not enabled
+     * during sertSecretsReady().
+     *
+     * @param c The name of the used cipher algorithm and mode, or
+     *    NULL
+     *
+     * @param s The SAS string
+     *
+     * @param verified if <code>verified</code> is true then SAS was
+     *    verified by both parties during a previous call.
+     */
+    virtual void srtpSecretsOn(std::string c, std::string s, bool verified) =0;
+
+    /**
+     * This method handles GoClear requests.
+     *
+     * According to the ZRTP specification the user must be informed about
+     * a GoClear request because the ZRTP implementation switches off security
+     * if it could authenticate the GoClear packet.
+     *
+     * <b>Note:</b> GoClear is not yet implemented in GNU ZRTP.
+     *
+     */
+    virtual void handleGoClear() =0;
+
+    /**
+     * Handle ZRTP negotiation failed.
+     *
+     * ZRTP calls this method in case ZRTP negotiation failed. The
+     * parameters show the severity as well as the reason.
+     *
+     * @param severity
+     *     This defines the message's severity
+     * @param subCode
+     *     The subcode identifying the reason.
+     * @see ZrtpCodes#MessageSeverity
+     */
+    virtual void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) =0;
+
+    /**
+     * ZRTP calls this method if the other side does not support ZRTP.
+     *
+     * If the other side does not answer the ZRTP <em>Hello</em> packets then
+     * ZRTP calls this method,
+     *
+     */
+    virtual void zrtpNotSuppOther() =0;
+
+    /**
+     * Enter synchronization mutex.
+     *
+     * GNU ZRTP requires one mutes to synchronize its
+     * processing. Because mutex implementations depend on the
+     * underlying infrastructure, for example operating system or
+     * thread implementation, GNU ZRTP delegates mutex handling to the
+     * spcific part of its implementation.
+     */
+    virtual void synchEnter() =0;
+
+    /**
+     * Leave synchronization mutex.
+     */
+    virtual void synchLeave() =0;
+
+    /**
+     * Inform about a PBX enrollment request.
+     *
+     * Please refer to chapter 8.3 ff to get more details about PBX
+     * enrollment and SAS relay.
+     *
+     * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+     * ZRTP.
+     *
+     * @param info Give some information to the user about the PBX
+     *    requesting an enrollment.
+     */
+    virtual void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info) =0;
+
+    /**
+     * Inform about PBX enrollment result.
+     *
+     * Informs the use about the acceptance or denial of an PBX enrollment
+     * request
+     *
+     * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+     * ZRTP.
+     *
+     * @param info information to the user about the result
+     *    of an enrollment.
+     */
+    virtual void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info) =0;
+
+    /**
+     * Request a SAS signature.
+     *
+     * After ZRTP was able to compute the Short Authentication String
+     * (SAS) it calls this method. The client may now use an
+     * approriate method to sign the SAS. The client may use
+     * ZrtpQueue#setSignatureData() to store the signature data an
+     * enable signature transmission to the other peer. Refer to
+     * chapter 8.2 of ZRTP specification.
+     *
+     * <b>Note:</b> SAS signing is not yet fully supported by GNU
+     * ZRTP.
+     *
+     * @param sasHash
+     *    The SAS hash to sign.
+     *
+     */
+    virtual void signSAS(uint8_t* sasHash) =0;
+
+    /**
+     * ZRTPQueue calls this method to request a SAS signature check.
+     *
+     * After ZRTP received a SAS signature in one of the Confirm packets it
+     * call this method. The client may use <code>getSignatureLength()</code>
+     * and <code>getSignatureData()</code>of ZrtpQueue to get the signature
+     * data and perform the signature check. Refer to chapter 8.2 of ZRTP
+     * specification.
+     *
+     * If the signature check fails the client may return false to ZRTP. In
+     * this case ZRTP signals an error to the other peer and terminates
+     * the ZRTP handshake.
+     *
+     * <b>Note:</b> SAS signing is not yet fully supported by GNU
+     * ZRTP.
+     *
+     * @param sasHash
+     *    The SAS hash that was signed by the other peer.
+     * @return
+     *    true if the signature was ok, false otherwise.
+     *
+     */
+    virtual bool checkSASSignature(uint8_t* sasHash) =0;
+};
+
+#endif // ZRTPCALLBACK
+
+/**
+ * @}
+ */
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpCallbackWrapper.h b/jni/libzrtp/src/libzrtpcpp/ZrtpCallbackWrapper.h
new file mode 100644
index 0000000..dd739e0
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpCallbackWrapper.h
@@ -0,0 +1,101 @@
+/*
+    This class maps the ZRTP C++ callback methods to C callback methods.
+    Copyright (C) 2010 Werner Dittmann
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef ZRTPCALLBACKWRAPPER_H
+#define ZRTPCALLBACKWRAPPER_H
+
+#include <stdlib.h>
+
+#include <libzrtpcpp/ZrtpCallback.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+#include <libzrtpcpp/ZrtpCWrapper.h>
+
+/**
+ *
+ * @file ZrtpCallbackWrapper.h
+ * @brief C-Wrapper helper
+ *
+ * This is a helper class for for the C wrapper and implements
+ * the GNU ZRTP callback interface. For detailed documentation about
+ * the callback method refer to file <code>ZrtpCallback</code>
+ * @ingroup GNU_ZRTP
+ * @{
+ *
+ * @see ZrtpCallback
+ * @see ZrtpCWrapper
+ */
+class __EXPORT ZrtpCallbackWrapper : public ZrtpCallback
+{
+public:
+    /**
+     * Construct a class that implements ZrtpCallback and uses a C structure
+     * to call C functions that implement the callbacks.
+     *
+     * @param cb
+     *    The C callback structure that hold the addresses of the C methods
+     *    that implement the actual callback functions.
+     * @param ctx
+     *    Pointer to the ZrtpContext
+     */
+    ZrtpCallbackWrapper(zrtp_Callbacks* cb, ZrtpContext* ctx);
+
+    int32_t sendDataZRTP ( const unsigned char* data, int32_t length );
+
+    int32_t activateTimer ( int32_t time );
+
+    int32_t cancelTimer();
+
+    void sendInfo ( GnuZrtpCodes::MessageSeverity severity, int32_t subCode );
+
+    bool srtpSecretsReady ( SrtpSecret_t* secrets, EnableSecurity part );
+
+    void srtpSecretsOff ( EnableSecurity part );
+
+    void srtpSecretsOn ( std::string c, std::string s, bool verified );
+
+    void handleGoClear();
+
+    void zrtpNegotiationFailed ( GnuZrtpCodes::MessageSeverity severity, int32_t subCode );
+
+    void zrtpNotSuppOther();
+
+    void synchEnter();
+
+    void synchLeave();
+
+    void zrtpAskEnrollment (GnuZrtpCodes::InfoEnrollment info );
+
+    void zrtpInformEnrollment (GnuZrtpCodes::InfoEnrollment info );
+
+    void signSAS (uint8_t* sasHash );
+
+    bool checkSASSignature (uint8_t* sasHash );
+
+private:
+    void init();
+    zrtp_Callbacks *c_callbacks;
+    ZrtpContext* zrtpCtx;
+
+};
+
+/**
+ * @}
+ */
+
+#endif // ZRTPCALLBACKWRAPPER_H
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpCodes.h b/jni/libzrtp/src/libzrtpcpp/ZrtpCodes.h
new file mode 100755
index 0000000..a1bb6fc
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpCodes.h
@@ -0,0 +1,164 @@
+/** @file ZrtpCodes.h
+ */
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCODES_H_
+#define _ZRTPCODES_H_
+/**
+ * @file ZrtpCodes.h
+ * @brief The ZRTP info, warning, and error codes
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+namespace GnuZrtpCodes {
+/**
+ * \namespace GnuZrtpCodes
+ * 
+ * This enum defines the information message severity.
+ *
+ * The ZRTP implementation issues information messages to inform the user
+ * about ongoing processing, unusual behavior, or alerts in case of severe
+ * problems. Each main severity code a number of sub-codes exist that
+ * specify the exact nature of the problem. 
+ *
+ * An application gets message severity codes and the associated sub-codes
+ * via the ZrtpUserCallback#showMessage method.
+ * 
+ * The severity levels and their meaning are:
+ *
+ * <dl>
+ * <dt>Info</dt> <dd>keeps the user informed about ongoing processing and
+ *     security setup. The enumeration InfoCodes defines the subcodes.
+ * </dd>
+ * <dt>Warning</dt> <dd>is an information about some security issues, e.g. if
+ *     an AES 256 encryption is request but only DH 3072 as public key scheme
+ *     is supported. ZRTP will establish a secure session (SRTP). The
+ *     enumeration WarningCodes defines the sub-codes.
+ * </dd>
+ * <dt>Severe</dt> <dd>is used if an error occured during ZRTP protocol usage.
+ *     In case of <em>Severe</em> ZRTP will <b>not</b> establish a secure session.
+ *     The enumeration SevereCodes defines the sub-codes.
+ * </dd>
+ * <dt>Zrtp</dt> <dd>shows a ZRTP security problem. Refer to the enumeration
+ *     ZrtpErrorCodes for sub-codes. GNU ZRTP of course will <b>not</b> 
+ *     establish a secure session.
+ * </dd>
+ * </dl>
+ *
+ */
+enum MessageSeverity {
+    Info = 1,
+    Warning,
+    Severe,
+    ZrtpError
+};
+
+/**
+ * Sub-codes for Info
+ */
+enum InfoCodes {
+    InfoHelloReceived = 1,          //!< Hello received, preparing a Commit
+    InfoCommitDHGenerated,          //!< Commit: Generated a public DH key
+    InfoRespCommitReceived,         //!< Responder: Commit received, preparing DHPart1
+    InfoDH1DHGenerated,             //!< DH1Part: Generated a public DH key
+    InfoInitDH1Received,            //!< Initiator: DHPart1 received, preparing DHPart2
+    InfoRespDH2Received,            //!< Responder: DHPart2 received, preparing Confirm1
+    InfoInitConf1Received,          //!< Initiator: Confirm1 received, preparing Confirm2
+    InfoRespConf2Received,          //!< Responder: Confirm2 received, preparing Conf2Ack
+    InfoRSMatchFound,               //!< At least one retained secrets matches - security OK
+    InfoSecureStateOn,              //!< Entered secure state
+    InfoSecureStateOff              //!< No more security for this session
+};
+
+/**
+ * Sub-codes for Warning
+ */
+enum WarningCodes {
+    WarningDHAESmismatch = 1,       //!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096
+    WarningGoClearReceived,         //!< Received a GoClear message
+    WarningDHShort,                 //!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096
+    WarningNoRSMatch,               //!< No retained shared secrets available - must verify SAS
+    WarningCRCmismatch,             //!< Internal ZRTP packet checksum mismatch - packet dropped
+    WarningSRTPauthError,           //!< Dropping packet because SRTP authentication failed!
+    WarningSRTPreplayError,         //!< Dropping packet because SRTP replay check failed!
+    WarningNoExpectedRSMatch        //!< Valid retained shared secrets availabe but no matches found - must verify SAS
+};
+
+/**
+ * Sub-codes for Severe
+ */
+enum SevereCodes {
+    SevereHelloHMACFailed = 1,      //!< Hash HMAC check of Hello failed!
+    SevereCommitHMACFailed,         //!< Hash HMAC check of Commit failed!
+    SevereDH1HMACFailed,            //!< Hash HMAC check of DHPart1 failed!
+    SevereDH2HMACFailed,            //!< Hash HMAC check of DHPart2 failed!
+    SevereCannotSend,               //!< Cannot send data - connection or peer down?
+    SevereProtocolError,            //!< Internal protocol error occured!
+    SevereNoTimer,                  //!< Cannot start a timer - internal resources exhausted?
+    SevereTooMuchRetries            //!< Too much retries during ZRTP negotiation - connection or peer down?
+};
+
+/**
+  * Error codes according to the ZRTP specification chapter 6.9
+  *
+  * GNU ZRTP uses these error codes in two ways: to fill the appropriate
+  * field ing the ZRTP Error packet and as sub-code in 
+  * ZrtpUserCallback#showMessage(). GNU ZRTP uses thes error codes also
+  * to report received Error packts, in this case the sub-codes are their
+  * negative values.
+  *
+  * The enumeration member comments are copied from the ZRTP specification.
+  */
+enum ZrtpErrorCodes {
+    MalformedPacket =   0x10,    //!< Malformed packet (CRC OK, but wrong structure)
+    CriticalSWError =   0x20,    //!< Critical software error
+    UnsuppZRTPVersion = 0x30,    //!< Unsupported ZRTP version
+    HelloCompMismatch = 0x40,    //!< Hello components mismatch
+    UnsuppHashType =    0x51,    //!< Hash type not supported
+    UnsuppCiphertype =  0x52,    //!< Cipher type not supported
+    UnsuppPKExchange =  0x53,    //!< Public key exchange not supported
+    UnsuppSRTPAuthTag = 0x54,    //!< SRTP auth. tag not supported
+    UnsuppSASScheme =   0x55,    //!< SAS scheme not supported
+    NoSharedSecret =    0x56,    //!< No shared secret available, DH mode required
+    DHErrorWrongPV =    0x61,    //!< DH Error: bad pvi or pvr ( == 1, 0, or p-1)
+    DHErrorWrongHVI =   0x62,    //!< DH Error: hvi != hashed data
+    SASuntrustedMiTM =  0x63,    //!< Received relayed SAS from untrusted MiTM
+    ConfirmHMACWrong =  0x70,    //!< Auth. Error: Bad Confirm pkt HMAC
+    NonceReused =       0x80,    //!< Nonce reuse
+    EqualZIDHello =     0x90,    //!< Equal ZIDs in Hello
+    GoCleatNotAllowed = 0x100,   //!< GoClear packet received, but not allowed
+    IgnorePacket =      0x7fffffff
+};
+
+/**
+ * Information codes for the Enrollment user callbacks.
+ */
+enum InfoEnrollment {
+    EnrollmentRequest,              //!< Aks user to confirm or deny an Enrollemnt request
+    EnrollmentCanceled,             //!< User did not confirm the PBX enrollement
+    EnrollmentFailed,               //!< Enrollment process failed, no PBX secret available
+    EnrollmentOk                    //!< Enrollment process for this PBX was ok
+};
+
+}
+
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpConfigure.h b/jni/libzrtp/src/libzrtpcpp/ZrtpConfigure.h
new file mode 100644
index 0000000..33a824f
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpConfigure.h
@@ -0,0 +1,551 @@
+/*
+  Copyright (C) 2009 - 2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPCONFIGURE_H_
+#define _ZRTPCONFIGURE_H_
+
+/**
+ * @file ZrtpConfigure.h
+ * @brief The ZRTP configure functions
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <list>
+#include <string>
+#include <vector>
+#include <string.h>
+
+#include <libzrtpcpp/ZrtpCallback.h>
+
+/**
+ * This enumerations list all configurable algorithm types.
+ */
+
+enum AlgoTypes {
+    Invalid = 0, HashAlgorithm = 1, CipherAlgorithm, PubKeyAlgorithm, SasType, AuthLength
+};
+
+typedef void(*encrypt_t)(uint8_t*, int32_t, uint8_t*, uint8_t*, int32_t);
+typedef void(*decrypt_t)(uint8_t*, int32_t, const uint8_t*, uint8_t*, int32_t);
+
+/**
+ * The algorithm enumration class.
+ *
+ * This simple class is just a container of an algorithm's name and
+ * its associated algorithm type. We use this class together with the
+ * EnumBase class to implement a Java-like enum class functionality
+ * (not fully, but OK for our use case).
+ *
+ * An application shall use the get / check methods to retrieve information.
+ */
+class AlgorithmEnum {
+public:
+    /**
+     * Create an AlgorithmEnum object.
+     *
+     * @param type
+     *    Defines the algorithm type
+     * @param name
+     *    Set the names of the algorithm. The name is copied
+     *    and the call may reuse the space.
+     * @param klen
+     *    The key length for this algorihm in byte, for example 16 or 32
+     * @param ra
+     *    A human readable short string that describes the algorihm.
+     * @param en
+     *    Pointer to the encryption function of this algorithn
+     * @param de
+     *    Pointer to the decryption funtions of this algorithm.
+     * @param alId
+     *    The algorithm id used by SRTP to identify an algorithm type, for
+     *    example Skein, Sha1, Aes, ...
+     *
+     * @see AlgoTypes
+     */
+    AlgorithmEnum(const AlgoTypes type, const char* name, int32_t klen,
+                  const char* ra, encrypt_t en, decrypt_t de, SrtpAlgorithms alId);
+
+    /**
+     * AlgorithmEnum destructor
+     */
+    ~AlgorithmEnum();
+
+    /**
+     * Get the algorihm's name
+     *
+     * @returns
+     *    Algorithm's name as null terminated C-string. The
+     *    application must not free this memory.
+     */
+    const char* getName();
+
+    /**
+     * Get the algorihm's readable name
+     *
+     * @returns
+     *    Algorithm's readable name as null terminated C-string. The
+     *    application must not free this memory.
+     */
+    const char* getReadable();
+
+    /**
+     * Get the algorihm's key length.
+     *
+     * @returns
+     *    An integer definig the key length in bytes.
+     */
+    int getKeylen();
+
+    /**
+     * Get the algorihm's integer id.
+     *
+     * @returns
+     *    An integer that defines the algorithm.
+     */
+    SrtpAlgorithms getAlgoId();
+    /**
+     * Get the algorihm's key length.
+     *
+     * @returns
+     *    An integer definig the key length in bytes.
+     */
+    encrypt_t getEncrypt();
+
+    /**
+     * Get the algorihm's key length.
+     *
+     * @returns
+     *    An integer definig the key length in bytes.
+     */
+    decrypt_t getDecrypt();
+
+    /**
+     * Get the algorithm type of this AlgorithmEnum object.
+     *
+     * @returns
+     *     The algorithm type.
+     *
+     * @see AlgoTypes
+     */
+    AlgoTypes getAlgoType();
+
+    /**
+     * Check if this AlgorithmEnum object is valid
+     *
+     * @returns
+     *    @c true if the object is valid, @c false otherwise
+     */
+    bool isValid();
+
+private:
+    AlgoTypes algoType;
+    std::string algoName;
+    int32_t   keyLen;
+    std::string readable;
+    encrypt_t encrypt;
+    decrypt_t decrypt;
+    SrtpAlgorithms   algoId;
+};
+
+/**
+ * EnumBase provides methods to store and access algorithm enumerations of
+ * a specific algorithm type.
+ *
+ * An application shall use the get / check methods to retrieve information
+ * from the preset Algorithm Enumerations.
+ *
+ * @see AlgoTypes
+ * @see zrtpHashes
+ * @see zrtpSymCiphers
+ * @see zrtpPubKeys
+ * @see zrtpSasTypes
+ * @see zrtpAuthLengths
+ */
+class EnumBase {
+public:
+    /**
+     * Get an AlgorithmEnum by its name
+     *
+     * @param name
+     *    The name of the AlgorithmEnum to search.
+     * @returns
+     *    The AlgorithmEnum if found or an invalid AlgorithmEnum if the name
+     *    was not found
+     */
+    AlgorithmEnum& getByName(const char* name);
+
+    /**
+     * Return all names of all currently stored AlgorithmEnums
+     *
+     * @return
+     *    A C++ std::list of C++ std::strings that contain the names.
+     */
+    std::list<std::string>* getAllNames();
+
+    /**
+     * Get the number of currently stored AlgorithmEnums
+     *
+     * @return
+     *    The number of currently stored AlgorithmEnums
+     */
+    int getSize();
+
+    /**
+     * Get the AlgoTypes to which this EnumBase belongs.
+     *
+     * @return
+     *     The AlgoTypes of this EnumBase.
+     * @see AlgoTypes.
+     */
+    AlgoTypes getAlgoType();
+
+    /**
+     * Return the AlgorithmEnum by its ordinal number
+     *
+     * @param ord
+     *     The ordinal number of the AlgorithmEnum.
+     * @return
+     *     The AlgorithmEnum if found, an invalid Algorithm otherwise.
+     */
+    AlgorithmEnum& getByOrdinal(int ord);
+
+    /**
+     * Get the ordinal number of an AlgorithmEnum
+     *
+     * @param algo
+     *     Return toe ordinal numer of this AlgorithmEnum.
+     *
+     * @return
+     *    Return the ordinal number of this AlgorithmEnum if found,
+     *    -1 otherwise.
+     */
+    int getOrdinal(AlgorithmEnum& algo);
+
+protected:
+    EnumBase(AlgoTypes algo);
+    ~EnumBase();
+    void insert(const char* name);
+    void insert(const char* name, int32_t klen,
+                const char* ra, encrypt_t en, decrypt_t de, SrtpAlgorithms alId);
+
+private:
+    AlgoTypes algoType;
+    std::vector <AlgorithmEnum* > algos;
+};
+
+/**
+ * The enumaration subclasses that contain the supported algorithm enumerations.
+ */
+class HashEnum : public EnumBase {
+public:
+    HashEnum();
+    ~HashEnum();
+};
+
+class SymCipherEnum : public EnumBase {
+public:
+    SymCipherEnum();
+    ~SymCipherEnum();
+};
+
+class PubKeyEnum : public EnumBase {
+public:
+    PubKeyEnum();
+    ~PubKeyEnum();
+};
+
+class SasTypeEnum : public EnumBase {
+public:
+    SasTypeEnum();
+    ~SasTypeEnum();
+};
+
+class AuthLengthEnum : public EnumBase {
+public:
+    AuthLengthEnum();
+    ~AuthLengthEnum();
+};
+
+extern HashEnum zrtpHashes;
+extern SymCipherEnum zrtpSymCiphers;
+extern PubKeyEnum zrtpPubKeys;
+extern SasTypeEnum zrtpSasTypes;
+extern AuthLengthEnum zrtpAuthLengths;
+
+/**
+ * ZRTP configuration data.
+ *
+ * This class contains data and functions to set ZRTP configuration data.
+ * An application may use this class to set configuration information for
+ * ZRTP. ZRTP uses this configuration information to announce various
+ * algorithms via its Hello message. An application may use this class to
+ * restrict or allow use of algorithms.
+ *
+ * The constructor does not set any algorithms, thus it is an empty
+ * configuration. An application may use this empty configuration and
+ * hand it over to ZRTP. In this case ZRTP does not announce any algorithms
+ * in its Hello message and uses mandatory algorithms only.
+ *
+ * An application can configure implemented algorithms only.
+ */
+class __EXPORT ZrtpConfigure {
+public:
+    ZrtpConfigure();         /* Creates Configuration data */
+    ~ZrtpConfigure();
+
+    /**
+     * Set the maximum number of algorithms per algorithm type that an application can
+     * configure.
+     */
+    static const int maxNoOfAlgos = 7;
+    /**
+     * Convenience function that sets a pre-defined standard configuration.
+     *
+     * The standard configuration consists of the following algorithms:
+     * <ul>
+     * <li> Hash: SHA256 </li>
+     * <li> Symmetric Cipher: AES 128, AES 256 </li>
+     * <li> Public Key Algorithm: DH2048, DH3027, MultiStream </li>
+     * <li> SAS type: libase 32 </li>
+     * <li> SRTP Authentication lengths: 32, 80 </li>
+     *</ul>
+     */
+    void setStandardConfig();
+
+    /**
+     * Convenience function that sets the mandatory algorithms only.
+     *
+     * Mandatory algorithms are:
+     * <ul>
+     * <li> Hash: SHA256 </li>
+     * <li> Symmetric Cipher: AES 128 </li>
+     * <li> Public Key Algorithm: DH3027, MultiStream </li>
+     * <li> SAS type: libase 32 </li>
+     * <li> SRTP Authentication lengths: 32, 80 </li>
+     *</ul>
+     */
+    void setMandatoryOnly();
+
+    /**
+     * Clear all configuration data.
+     *
+     * The functions clears all configuration data.
+     */
+    void clear();
+
+    /**
+     * Add an algorithm to configuration data.
+     *
+     * Adds the specified algorithm to the configuration data.
+     * If no free configuration data slot is available the
+     * function does not add the algorithm and returns -1. The
+     * methods appends the algorithm to the existing algorithms.
+     *
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The enumeration of the algorithm to add.
+     * @return
+     *    Number of free configuration data slots or -1 on error
+     */
+    int32_t addAlgo(AlgoTypes algoType, AlgorithmEnum& algo);
+
+    /**
+     * Add an algorithm to configuration data at given index.
+     *
+     * Adds the specified algorithm to the configuration data vector
+     * at a given index. If the index is larger than the actual size
+     * of the configuration vector the method just appends the algorithm.
+     *
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The enumeration of the algorithm to add.
+     * @param index
+     *    The index where to add the algorihm
+     * @return
+     *    Number of free configuration data slots or -1 on error
+     */
+    int32_t addAlgoAt(AlgoTypes algoType, AlgorithmEnum& algo, int32_t index);
+
+    /**
+     * Remove a algorithm from configuration data.
+     *
+     * Removes the specified algorithm from configuration data. If
+     * the algorithm was not configured previously the function does
+     * not modify the configuration data and returns the number of
+     * free configuration data slots.
+     *
+     * If an application removes all algorithms then ZRTP does not
+     * include any algorithm into the hello message and falls back
+     * to a predefined mandatory algorithm.
+     *
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The enumeration of the algorithm to remove.
+     * @return
+     *    Number of free configuration slots.
+     */
+    int32_t removeAlgo(AlgoTypes algoType, AlgorithmEnum& algo);
+
+    /**
+     * Returns the number of configured algorithms.
+     *
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @return
+     *    The number of configured algorithms (used configuration
+     *    data slots)
+     */
+    int32_t getNumConfiguredAlgos(AlgoTypes algoType);
+
+    /**
+     * Returns the identifier of the algorithm at index.
+     *
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param index
+     *    The index in the list of the algorihm type
+     * @return
+     *    A pointer the the algorithm enumeration. If the index
+     *    does not point to a configured slot then the function
+     *    returns NULL.
+     *
+     */
+    AlgorithmEnum& getAlgoAt(AlgoTypes algoType, int32_t index);
+
+    /**
+     * Checks if the configuration data of the algorihm type already contains
+     * a specific algorithms.
+     *
+     * @param algoType
+     *    Specifies which algorithm type to select
+     * @param algo
+     *    The algorithm to check
+     * @return
+     *    True if the algorithm was found, false otherwise.
+     *
+     */
+    bool containsAlgo(AlgoTypes algoType, AlgorithmEnum& algo);
+
+    /**
+     * Enables or disables trusted MitM processing.
+     *
+     * For further details of trusted MitM processing refer to ZRTP
+     * specification, chapter 7.3
+     *
+     * @param yesNo
+     *    If set to true then trusted MitM processing is enabled.
+     */
+    void setTrustedMitM(bool yesNo);
+
+    /**
+     * Check status of trusted MitM processing.
+     *
+     * @return
+     *    Returns true if trusted MitM processing is enabled.
+     */
+    bool isTrustedMitM();
+
+    /**
+     * Enables or disables SAS signature processing.
+     *
+     * For further details of trusted MitM processing refer to ZRTP
+     * specification, chapter 7.2
+     *
+     * @param yesNo
+     *    If set to true then certificate processing is enabled.
+     */
+    void setSasSignature(bool yesNo);
+
+    /**
+     * Check status of SAS signature processing.
+     *
+     * @return
+     *    Returns true if certificate processing is enabled.
+     */
+    bool isSasSignature();
+
+    /**
+     * Enables or disables paranoid mode.
+     *
+     * For further explanation of paranoid mode refer to the documentation
+     * of ZRtp class.
+     *
+     * @param yesNo
+     *    If set to true then paranoid mode is enabled.
+     */
+    void setParanoidMode(bool yesNo);
+
+    /**
+     * Check status of paranoid mode.
+     *
+     * @return
+     *    Returns true if paranoid mode is enabled.
+     */
+    bool isParanoidMode();
+
+    /// Helper function to print some internal data
+    void printConfiguredAlgos(AlgoTypes algoTyp);
+
+  private:
+    std::vector<AlgorithmEnum* > hashes;
+    std::vector<AlgorithmEnum* > symCiphers;
+    std::vector<AlgorithmEnum* > publicKeyAlgos;
+    std::vector<AlgorithmEnum* > sasTypes;
+    std::vector<AlgorithmEnum* > authLengths;
+
+    bool enableTrustedMitM;
+    bool enableSasSignature;
+    bool enableParanoidMode;
+
+
+    AlgorithmEnum& getAlgoAt(std::vector<AlgorithmEnum* >& a, int32_t index);
+    int32_t addAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo);
+    int32_t addAlgoAt(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo, int32_t index);
+    int32_t removeAlgo(std::vector<AlgorithmEnum* >& a,  AlgorithmEnum& algo);
+    int32_t getNumConfiguredAlgos(std::vector<AlgorithmEnum* >& a);
+    bool containsAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo);
+    std::vector<AlgorithmEnum* >& getEnum(AlgoTypes algoType);
+
+    void printConfiguredAlgos(std::vector<AlgorithmEnum* >& a);
+
+  protected:
+
+  public:
+};
+
+/**
+ * @}
+ */
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpCrc32.h b/jni/libzrtp/src/libzrtpcpp/ZrtpCrc32.h
new file mode 100755
index 0000000..ad57edd
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpCrc32.h
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCRC32_H_
+#define _ZRTPCRC32_H_
+
+/**
+ *
+ * @file ZrtpCrc32.h
+ * @brief Methods to compute the CRC32 checksum for ZRTP packets
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ * 
+ * @see ZrtpCallback
+ */
+
+/**
+ * Check if a buffer matches a given CRC32 checksum.
+ * 
+ * @param buffer
+ *     Pointer to the data buffer.
+ * @param length
+ *     Length in bytes of the data buffer.
+ * @param crc32
+ *     The CRC32 checksum.
+ * 
+ * @return
+ *    @c true if the CRC32 checksum matches the computed checksum of the
+ *    buffer, @c false otherwise.
+ */
+bool zrtpCheckCksum(uint8_t *buffer, uint16_t length, uint32_t crc32);
+
+/**
+ * Generate a CRC32 checksum of a data buffer
+ * 
+ * @param buffer
+ *    Pointer to the buffer.
+ * @param length
+ *     Lenght of the buffer in bytes.
+ * 
+ * @return
+ *    A preliminary CRC32 checksum
+ */
+uint32_t zrtpGenerateCksum(uint8_t *buffer, uint16_t length);
+
+/**
+ * Close CRC32 computation.
+ * 
+ * @param crc32
+ *    A preliminary CRC32 checksum.
+ * 
+ * @return
+ *    The ready to use CRC32 checksum in host order.
+ */
+uint32_t zrtpEndCksum(uint32_t crc32);
+
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketBase.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketBase.h
new file mode 100644
index 0000000..f0d2944
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketBase.h
@@ -0,0 +1,147 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPPACKETBASE_H_
+#define _ZRTPPACKETBASE_H_
+
+/**
+ * @file ZrtpPacketBase.h
+ * @brief The ZRTP message header class
+ *
+ * This class defines the ZRTP message header and provides access and
+ * check methods.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+#include <libzrtpcpp/zrtpPacket.h>
+#include <libzrtpcpp/ZrtpTextData.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+#include <libzrtpcpp/ZrtpCrc32.h>
+
+// #define DEBUGOUT(deb)   deb
+#define DEBUGOUT(deb)
+
+/*
+ * This is the unique ZRTP ID in network order (PZ)
+ */
+const uint16_t zrtpId = 0x505a;
+
+/**
+ * This is the base class for all ZRTP packets
+ *
+ * All other ZRTP packet classes inherit from this class. It does not have
+ * an implementation of its own.
+ *
+ * The standard constructors of the subclasses usually initialize the @c allocate
+ * field with their fixed data array which is large enough to hold all message
+ * data. If an implementation needs to change this to use dynamic memory
+ * allocation only that line in the subclasses must be changed and the destructors
+ * should take care of memory management.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketBase {
+
+  private:
+
+  protected:
+      void* allocated;                  ///< Pointer to ZRTP message data
+      zrtpPacketHeader_t* zrtpHeader;   ///< points to the fixed ZRTP header structure
+
+  public:
+    /**
+     * Destructor is empty
+     */
+    virtual ~ZrtpPacketBase() {};
+
+    /**
+     * Get pointer to ZRTP header
+     *
+     * @return
+     *     Pointer to ZRTP header structure.
+     */
+    const uint8_t* getHeaderBase() { return (const uint8_t*)zrtpHeader; };
+
+    /**
+     * Check is this is a ZRTP message
+     *
+     * @return
+     *     @c true if check was ok
+     */
+    bool isZrtpPacket()            { return (ntohs(zrtpHeader->zrtpId) == zrtpId); };
+
+    /**
+     * Get the length in words of the ZRTP message
+     *
+     * @return
+     *     The length in words
+     */
+    uint16_t getLength()           { return ntohs(zrtpHeader->length); };
+
+    /**
+     * Return pointer to fixed length message type ASCII data
+     *
+     * @return
+     *     Pointer to ASCII character array
+     */
+    uint8_t* getMessageType()      { return zrtpHeader->messageType; };
+
+    /**
+     * Set the lenght field in the ZRTP header
+     *
+     * @param len
+     *     The length of the ZRTP message in words, host order
+     */
+    void setLength(uint16_t len)  { zrtpHeader->length = htons(len); };
+
+    /**
+     * Copy the message type ASCII data to ZRTP message type field
+     *
+     * @param msg
+     *     Pointer to message type ASCII character array
+     */
+    void setMessageType(uint8_t *msg)
+        { memcpy(zrtpHeader->messageType, msg, sizeof(zrtpHeader->messageType)); };
+
+    /**
+     * Initializes the ZRTP Id field
+     */
+    void setZrtpId()              { zrtpHeader->zrtpId = htons(zrtpId); }
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETBASE
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketClearAck.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketClearAck.h
new file mode 100644
index 0000000..992f6d8
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketClearAck.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETCLEARACK_H_
+#define _ZRTPPACKETCLEARACK_H_
+
+/**
+ * @file ZrtpPacketClearAck.h
+ * @brief The ZRTP ClearAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the ClearAck packet - Currently not used
+ *
+ * The ZRTP simple message ClearAck. The implementation sends this
+ * after switching to clear mode (non-SRTP mode).
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketClearAck : public ZrtpPacketBase {
+
+ public:
+    ZrtpPacketClearAck();       /// Creates a ClearAck packet with default data
+    ZrtpPacketClearAck(uint8_t* data);  /// Creates a ClearAck packet from received data
+    virtual ~ZrtpPacketClearAck();
+
+ private:
+     ClearAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCLEARACK
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketCommit.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketCommit.h
new file mode 100644
index 0000000..b23b23d
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketCommit.h
@@ -0,0 +1,134 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+#ifndef _ZRTPPACKETCOMMIT_H_
+#define _ZRTPPACKETCOMMIT_H_
+
+/**
+ * @file ZrtpPacketCommit.h
+ * @brief The ZRTP Commit message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Commit packet.
+ *
+ * The ZRTP message Commit. The ZRTP implementation sends or receives
+ * this message to commit the crypto parameters offered during a Hello
+ * message.
+ *
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketCommit : public ZrtpPacketBase {
+
+ protected:
+    Commit_t* commitHeader;     ///< Points to Commit message part
+
+ public:
+    /// Creates a Commit packet with default data
+    ZrtpPacketCommit();
+
+    /// Creates a Commit packet from received data
+    ZrtpPacketCommit(uint8_t* data);
+
+    /// Normal destructor
+    virtual ~ZrtpPacketCommit();
+
+    /// Get pointer to hash algorithm type field, a fixed length character array
+    uint8_t* getHashType()    { return commitHeader->hash; };
+
+    /// Get pointer to cipher algorithm type field, a fixed length character array
+    uint8_t* getCipherType()  { return commitHeader->cipher; };
+
+    /// Get pointer to SRTP authentication algorithm type field, a fixed length character array
+    uint8_t* getAuthLen()     { return commitHeader->authlengths; };
+
+    /// Get pointer to key agreement algorithm type field, a fixed length character array
+    uint8_t* getPubKeysType() { return commitHeader->pubkey; };
+
+    /// Get pointer to SAS algorithm type field, a fixed length character array
+    uint8_t* getSasType()     { return commitHeader->sas; };
+
+    /// Get pointer to ZID field, a fixed length byte array
+    uint8_t* getZid()         { return commitHeader->zid; };
+
+    /// Get pointer to HVI field, a fixed length byte array
+    uint8_t* getHvi()         { return commitHeader->hvi; };
+
+    /// Get pointer to NONCE field, a fixed length byte array, overlaps HVI field
+    uint8_t* getNonce()       { return commitHeader->hvi; };
+
+    /// Get pointer to hashH2 field, a fixed length byte array
+    uint8_t* getH2()          { return commitHeader->hashH2; };
+
+    /// Get pointer to MAC field, a fixed length byte array
+    uint8_t* getHMAC()        { return commitHeader->hmac; };
+
+    /// Get pointer to MAC field during multi-stream mode, a fixed length byte array
+    uint8_t* getHMACMulti()   { return commitHeader->hmac-4*ZRTP_WORD_SIZE; };
+
+    /// Set hash algorithm type field, fixed length character field
+    void setHashType(uint8_t* text)    { memcpy(commitHeader->hash, text, ZRTP_WORD_SIZE); };
+
+    /// Set cipher algorithm type field, fixed length character field
+    void setCipherType(uint8_t* text)  { memcpy(commitHeader->cipher, text, ZRTP_WORD_SIZE); };
+
+    /// Set SRTP authentication algorithm algorithm type field, fixed length character field
+    void setAuthLen(uint8_t* text)     { memcpy(commitHeader->authlengths, text, ZRTP_WORD_SIZE); };
+
+    /// Set key agreement algorithm type field, fixed length character field
+    void setPubKeyType(uint8_t* text)  { memcpy(commitHeader->pubkey, text, ZRTP_WORD_SIZE); };
+
+    /// Set SAS algorithm type field, fixed length character field
+    void setSasType(uint8_t* text)     { memcpy(commitHeader->sas, text, ZRTP_WORD_SIZE); };
+
+    /// Set ZID field, a fixed length byte array
+    void setZid(uint8_t* text)         { memcpy(commitHeader->zid, text, sizeof(commitHeader->zid)); };
+
+    /// Set HVI field, a fixed length byte array
+    void setHvi(uint8_t* text)         { memcpy(commitHeader->hvi, text, sizeof(commitHeader->hvi)); };
+
+    /// Set conce field, a fixed length byte array, overlapping HVI field
+    void setNonce(uint8_t* text);
+
+    /// Set hashH2 field, a fixed length byte array
+    void setH2(uint8_t* hash)          { memcpy(commitHeader->hashH2, hash, sizeof(commitHeader->hashH2)); };
+
+    /// Set MAC field, a fixed length byte array
+    void setHMAC(uint8_t* hash)        { memcpy(commitHeader->hmac, hash, sizeof(commitHeader->hmac)); };
+
+    /// Set MAC field during multi-stream mode, a fixed length byte array
+    void setHMACMulti(uint8_t* hash)   { memcpy(commitHeader->hmac-4*ZRTP_WORD_SIZE, hash, sizeof(commitHeader->hmac)); };
+
+ private:
+     CommitPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCOMMIT
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketConf2Ack.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketConf2Ack.h
new file mode 100644
index 0000000..a7c2567
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketConf2Ack.h
@@ -0,0 +1,60 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETCON2FACK_H_
+#define _ZRTPPACKETCON2FACK_H_
+
+/**
+ * @file ZrtpPacketConf2Ack.h
+ * @brief The ZRTP Conf2Ack message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Conf2Ack packet.
+ *
+ * The ZRTP simple message Conf2Ack. The implementation sends this
+ * after receiving and checking the Confirm2 message.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketConf2Ack : public ZrtpPacketBase {
+
+ public:
+    /// Creates a Conf2Ack packet with default data
+    ZrtpPacketConf2Ack();
+
+    ///Creates a Conf2Ack packet from received data
+    ZrtpPacketConf2Ack(char* data);
+
+    /// Normal destructor
+    virtual ~ZrtpPacketConf2Ack();
+
+ private:
+     Conf2AckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCONF2ACK
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketConfirm.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketConfirm.h
new file mode 100644
index 0000000..b2dfbf4
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketConfirm.h
@@ -0,0 +1,125 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETCONFIRM_H_
+#define _ZRTPPACKETCONFIRM_H_
+
+/**
+ * @file ZrtpPacketConfirm.h
+ * @brief The ZRTP Confirm message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Confirm packet.
+ *
+ * The ZRTP message Confirm. The implementation sends this
+ * to confirm the switch to SRTP (encrypted) mode. The contents of
+ * the Confirm message are encrypted, thus the implementation
+ * can check if the secret keys work.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketConfirm : public ZrtpPacketBase {
+
+    private:
+        Confirm_t* confirmHeader;   ///< Point to the Confirm message part
+
+    public:
+        /// Creates a Confirm packet with default data
+        ZrtpPacketConfirm();
+
+        /// Creates a Confirm packet with default data and a given signature length
+        ZrtpPacketConfirm(uint32_t sl);
+
+        /// Creates a Confirm packet from received data
+        ZrtpPacketConfirm(uint8_t* d);
+
+        /// Normal destructor
+        virtual ~ZrtpPacketConfirm();
+
+        /// Check if SAS verify flag is set
+        const bool isSASFlag()            { return confirmHeader->flags & 0x4; }
+
+        /// Check if PBXEnrollment flag is set
+        const bool isPBXEnrollment()      { return confirmHeader->flags & 0x8; }
+
+        /// Get pointer to filler bytes (contains one bit of signature length)
+        const uint8_t* getFiller()        { return confirmHeader->filler; }
+
+        /// Get pointer to IV data, fixed byte array
+        const uint8_t* getIv()            { return confirmHeader->iv; }
+
+        /// Get pointer to MAC data, fixed byte array
+        const uint8_t* getHmac()          { return confirmHeader->hmac; }
+
+        /// Get Expiration time data
+        const uint32_t getExpTime()       { return ntohl(confirmHeader->expTime); }
+
+        /// Get pointer to initial hash chain (H0) data, fixed byte array
+        uint8_t* getHashH0()              { return confirmHeader->hashH0; }
+
+        /// Get pointer to signature data, variable length, refer to getSignatureLength()
+        const uint8_t* getSignatureData() { return ((uint8_t*)&confirmHeader->expTime) + 4; }
+
+        /// get the signature length in words
+        int32_t getSignatureLength();
+
+        /// set SAS verified flag
+        void setSASFlag()            { confirmHeader->flags |= 0x4; }
+
+        /// set setPBXEnrollment flag
+        void setPBXEnrollment()      { confirmHeader->flags |= 0x8; }
+
+        /// Set MAC data, fixed length byte array
+        void setHmac(uint8_t* text)  { memcpy(confirmHeader->hmac, text, sizeof(confirmHeader->hmac)); }
+
+        /// Set IV data, fixed length byte array
+        void setIv(uint8_t* text)    { memcpy(confirmHeader->iv, text, sizeof(confirmHeader->iv)); }
+
+        /// Set expiration time data
+        void setExpTime(uint32_t t)  { confirmHeader->expTime = htonl(t); }
+
+        /// Set initial hash chain (H0) data, fixed length byte array
+        void setHashH0(uint8_t* t)   { memcpy(confirmHeader->hashH0, t, sizeof(confirmHeader->hashH0)); }
+
+        /// Set signature data, length of the signature data in bytes and must be a multiple of 4.
+        bool setSignatureData(uint8_t* data, int32_t length);
+
+        /// Set signature length in words
+        bool setSignatureLength(uint32_t sl);
+
+    private:
+        void initialize();
+     // Confirm packet is of variable length. It maximum size is 524 words:
+     // - 11 words fixed size
+     // - up to 513 words variable part, depending if signature is present and its length.
+     // This leads to a maximum of 4*524=2096 bytes.
+        uint8_t data[2100];       // large enough to hold a full blown Confirm packet
+
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCONFIRM
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketDHPart.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketDHPart.h
new file mode 100644
index 0000000..d0ea4ba
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketDHPart.h
@@ -0,0 +1,120 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETDHPART_H_
+#define _ZRTPPACKETDHPART_H_
+
+/**
+ * @file ZrtpPacketDHPart.h
+ * @brief The ZRTP DHPart message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the DHPart packet.
+ *
+ * The ZRTP message DHPart. The implementation sends this
+ * to exchange the Diffie-Helman public keys and the shared
+ * secrets between the two parties.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketDHPart : public ZrtpPacketBase {
+
+ protected:
+    uint8_t *pv;                ///< points to public key value inside DH message
+    DHPart_t* DHPartHeader;     ///< points to DH message structure
+    int32_t dhLength;           ///< length of DH message, DH message has variable length
+
+ public:
+    /// Creates a DHPart packet no data, must use setPubKeyType(...)
+    ZrtpPacketDHPart();
+
+    /// Creates a DHPart packet with default data and a give public key type
+    ZrtpPacketDHPart(const char* pkt);
+
+    /// Creates a DHPart packet from received data
+    ZrtpPacketDHPart(uint8_t* data);
+
+    /// Standard destructor
+    virtual ~ZrtpPacketDHPart();
+
+    /// Get pointer to public key value, variable length byte array
+    uint8_t* getPv()             { return pv; }
+
+    /// Get pointer to first retained secretd id, fixed length byte array
+    uint8_t* getRs1Id()          { return DHPartHeader->rs1Id; };
+
+    /// Get pointer to second retained secretd id, fixed length byte array
+    uint8_t* getRs2Id()          { return DHPartHeader->rs2Id; };
+
+    /// Get pointer to additional retained secretd id, fixed length byte array
+    uint8_t* getAuxSecretId()    { return DHPartHeader->auxSecretId; };
+
+    /// Get pointer to PBX retained secretd id, fixed length byte array
+    uint8_t* getPbxSecretId()    { return DHPartHeader->pbxSecretId; };
+
+    /// Get pointer to first hash (H1) for hash chain, fixed length byte array
+    uint8_t* getH1()             { return DHPartHeader->hashH1; };
+
+    /// Get pointer to HMAC, fixed length byte array
+    uint8_t* getHMAC()           { return pv+dhLength; };
+
+    /// Setpublic key value, variable length byte array
+    void setPv(uint8_t* text)         { memcpy(pv, text, dhLength); };
+
+    /// Set first retained secretd id, fixed length byte array
+    void setRs1Id(uint8_t* text)      { memcpy(DHPartHeader->rs1Id, text, sizeof(DHPartHeader->rs1Id)); };
+
+    /// Set second retained secretd id, fixed length byte array
+    void setRs2Id(uint8_t* text)      { memcpy(DHPartHeader->rs2Id, text, sizeof(DHPartHeader->rs2Id)); };
+
+    /// Set additional retained secretd id, fixed length byte array
+    void setAuxSecretId(uint8_t* t)   { memcpy(DHPartHeader->auxSecretId, t, sizeof(DHPartHeader->auxSecretId)); };
+
+    /// Set PBX retained secretd id, fixed length byte array
+    void setPbxSecretId(uint8_t* t)   { memcpy(DHPartHeader->pbxSecretId,t, sizeof(DHPartHeader->pbxSecretId)); };
+
+    /// Set first hash (H1) of hash chain, fixed length byte array
+    void setH1(uint8_t* t)            { memcpy(DHPartHeader->hashH1, t, sizeof(DHPartHeader->hashH1)); };
+
+    /// Set key agreement type, fixed size character array
+    void setPubKeyType(const char* pkt);
+
+    /// Set first MAC, fixed length byte array
+    void setHMAC(uint8_t* t)          { memcpy(pv+dhLength, t, 2*ZRTP_WORD_SIZE); };
+
+ private:
+    void initialize();
+    // SupportedPubKeys pktype;
+     // DHPart packet is of variable length. It maximum size is 141 words:
+     // - 13 words fixed sizze
+     // - up to 128 words variable part, depending on DH algorithm
+     //   leads to a maximum of 4*141=564 bytes.
+     uint8_t data[768];       // large enough to hold a full blown DHPart packet
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETDHPART
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketError.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketError.h
new file mode 100644
index 0000000..d775801
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketError.h
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETERROR_H_
+#define _ZRTPPACKETERROR_H_
+
+/**
+ * @file ZrtpPacketError.h
+ * @brief The ZRTP Error message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Error packet.
+ *
+ * The ZRTP simple message Error. The implementation sends this
+ * after detecting an error.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketError : public ZrtpPacketBase {
+
+ protected:
+    Error_t* errorHeader;   ///< Points to Error message
+
+ public:
+    /// Creates a Error packet with default data
+    ZrtpPacketError();
+
+    /// Creates a Error packet from received data
+    ZrtpPacketError(uint8_t* data);
+
+    virtual ~ZrtpPacketError();
+
+    /// Get the error code from Error message
+    uint32_t getErrorCode() { return ntohl(errorHeader->errorCode); };
+
+    /// Set error code in Error message
+    void setErrorCode(uint32_t code) {errorHeader->errorCode = htonl(code); };
+
+ private:
+     ErrorPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETERROR
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketErrorAck.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketErrorAck.h
new file mode 100644
index 0000000..e64c8a6
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketErrorAck.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2007 - 2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETERRORACK_H_
+#define _ZRTPPACKETERRORACK_H_
+
+/**
+ * @file ZrtpPacketErrorAck.h
+ * @brief The ZRTP ErrorAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the ErrorAck packet.
+ *
+ * The ZRTP simple message ErrorAck. The implementation sends this
+ * after receiving and checking the Error message.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketErrorAck : public ZrtpPacketBase {
+
+ public:
+    /// Creates a ErrorAck packet with default data
+    ZrtpPacketErrorAck();
+
+    /// Creates a ErrorAck packet from received data
+    ZrtpPacketErrorAck(uint8_t* data);
+    virtual ~ZrtpPacketErrorAck();
+
+ private:
+     ErrorAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif  // _ZRTPPACKETERRORACK_H_
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketGoClear.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketGoClear.h
new file mode 100644
index 0000000..10c3be6
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketGoClear.h
@@ -0,0 +1,72 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETGOCLEAR_H_
+#define _ZRTPPACKETGOCLEAR_H_
+
+/**
+ * @file ZrtpPacketGoClear.h
+ * @brief The ZRTP GoClear message
+ *
+ * GNU ZRTP does not implement GoClear feature
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the GoClear packet.
+ *
+ * The ZRTP message GoClear. The implementation sends this
+ * to order the peer to switch to clear mode (non-SRTP mode).
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketGoClear : public ZrtpPacketBase {
+
+ protected:
+    GoClear_t* clearHeader;
+
+ public:
+    /// Creates a GoCLear packet with default data
+    ZrtpPacketGoClear();
+
+    /// Creates a GoClear packet from received data
+    ZrtpPacketGoClear(uint8_t* data);
+
+    virtual ~ZrtpPacketGoClear();
+
+    /// Not used
+    const uint8_t* getClearHmac() { return clearHeader->clearHmac; };
+
+    /// Not used
+    void setClearHmac(uint8_t *text) { memcpy(clearHeader->clearHmac, text, 32); };
+
+    /// Not used
+    void clrClearHmac()              { memset(clearHeader->clearHmac, 0, 32); };
+
+ private:
+     GoClearPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETGOCLEAR
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketHello.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketHello.h
new file mode 100644
index 0000000..0cc7403
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketHello.h
@@ -0,0 +1,191 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETHELLO_H_
+#define _ZRTPPACKETHELLO_H_
+
+/**
+ * @file ZrtpPacketHello.h
+ * @brief The ZRTP Hello message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Hello packet.
+ *
+ * The ZRTP Hello message. The implementation sends this
+ * to start the ZRTP negotiation sequence. The Hello message
+ * offers crypto methods and parameters to the other party. The
+ * other party selects methods and parameters it can support
+ * and uses the Commit message to commit these.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketHello : public ZrtpPacketBase {
+
+ protected:
+    Hello_t* helloHeader;   ///< Point to the Hello message part
+
+    int32_t nHash,          ///< number of hash algorithms offered
+    nCipher,                ///< number of cipher algorithms offered
+    nPubkey,                ///< number of key agreement algorithms offered
+    nSas,                   ///< number of SAS algorithms offered
+    nAuth;                  ///< number of SRTP authentication algorithms offered
+
+    int32_t oHash,          ///< offsets in bytes to hash algorithm names
+    oCipher,                ///< offsets in bytes to cipher algorithm names
+    oPubkey,                ///< offsets in bytes to key agreement algorithm names
+    oSas,                   ///< offsets in bytes to SAS algorithm names
+    oAuth,                  ///< offsets in bytes to SRTP authentication algorithm names
+    oHmac;                  ///< offsets in bytes to MAC of Hello message
+
+ public:
+    /// Creates a Hello packet with default data
+    ZrtpPacketHello();
+
+    /// Creates a Hello packet from received data
+    ZrtpPacketHello(uint8_t *data);
+
+    virtual ~ZrtpPacketHello();
+
+    /**
+     * Set configure data and populate Hello message data.
+     *
+     * Fill in the offered Algorithm names and compute all offset to
+     * names and MAC. An application must call this method on Hello message
+     * objects created with the standard constructor (with default data)
+     * before the application can use most of the getter and setter methods.
+     *
+     * @param config
+     *    Pointer to ZrtpConfigure data.
+     */
+    void configureHello(ZrtpConfigure* config);
+
+    /// Get version number from Hello message, fixed ASCII character array
+    uint8_t* getVersion()  { return helloHeader->version; };
+
+    /// Get client id from Hello message, fixed ASCII character array
+    uint8_t* getClientId() { return helloHeader->clientId; };
+
+    /// Get H3 hash from Hello message, fixed byte array
+    uint8_t* getH3()       { return helloHeader->hashH3; };
+
+    /// Get client ZID from Hello message, fixed bytes array
+    uint8_t* getZid()      { return helloHeader->zid; };
+
+    /// Set version sting in Hello message, fixed ASCII character array
+    void setVersion(uint8_t *text)     { memcpy(helloHeader->version, text,ZRTP_WORD_SIZE ); }
+
+    /// Set client id in Hello message, fixed ASCII character array
+    void setClientId(const uint8_t *t) { memcpy(helloHeader->clientId, t, sizeof(helloHeader->clientId)); }
+
+    /// Set H3 hash in Hello message, fixed byte array
+    void setH3(uint8_t *hash)          { memcpy(helloHeader->hashH3, hash, sizeof(helloHeader->hashH3)); }
+
+    /// Set client ZID in Hello message, fixed bytes array
+    void setZid(uint8_t *text)         { memcpy(helloHeader->zid, text, sizeof(helloHeader->zid)); }
+
+    /// Check passive mode (mode not implemented)
+    bool isPassive()       { return helloHeader->flags & 0x10; };
+
+    /// Check if MitM flag is set
+    bool isMitmMode()       { return helloHeader->flags & 0x20; };
+
+    /// Check if SAS sign flag is set
+    bool isSasSign()       { return helloHeader->flags & 0x40; };
+
+    /// Get hash algorithm name at position n, fixed ASCII character array
+    uint8_t* getHashType(int32_t n)   { return ((uint8_t*)helloHeader)+oHash+(n*ZRTP_WORD_SIZE); }
+
+    /// Get ciper algorithm name at position n, fixed ASCII character array
+    uint8_t* getCipherType(int32_t n) { return ((uint8_t*)helloHeader)+oCipher+(n*ZRTP_WORD_SIZE); }
+
+    /// Get SRTP authentication algorithm name at position n, fixed ASCII character array
+    uint8_t* getAuthLen(int32_t n)    { return ((uint8_t*)helloHeader)+oAuth+(n*ZRTP_WORD_SIZE); }
+
+    /// Get key agreement algorithm name at position n, fixed ASCII character array
+    uint8_t* getPubKeyType(int32_t n) { return ((uint8_t*)helloHeader)+oPubkey+(n*ZRTP_WORD_SIZE); }
+
+    /// Get SAS algorithm name at position n, fixed ASCII character array
+    uint8_t* getSasType(int32_t n)    { return ((uint8_t*)helloHeader)+oSas+(n*ZRTP_WORD_SIZE); }
+
+    /// Get Hello MAC, fixed byte array
+    uint8_t* getHMAC()                { return ((uint8_t*)helloHeader)+oHmac; }
+
+    /// Set hash algorithm name at position n, fixed ASCII character array
+    void setHashType(int32_t n, int8_t* t)
+        { memcpy(((uint8_t*)helloHeader)+oHash+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+    /// Set ciper algorithm name at position n, fixed ASCII character array
+    void setCipherType(int32_t n, int8_t* t)
+        { memcpy(((uint8_t*)helloHeader)+oCipher+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+    /// Set SRTP authentication algorithm name at position n, fixed ASCII character array
+    void setAuthLen(int32_t n, int8_t* t)
+        { memcpy(((uint8_t*)helloHeader)+oAuth+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+    /// Set key agreement algorithm name at position n, fixed ASCII character array
+    void setPubKeyType(int32_t n, int8_t* t)
+        { memcpy(((uint8_t*)helloHeader)+oPubkey+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+    /// Set SAS algorithm name at position n, fixed ASCII character array
+    void setSasType(int32_t n, int8_t* t)
+        { memcpy(((uint8_t*)helloHeader)+oSas+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+    /// Set Hello MAC, fixed byte array
+    void setHMAC(uint8_t* t)
+        { memcpy(((uint8_t*)helloHeader)+oHmac, t, 2*ZRTP_WORD_SIZE); }
+
+    /// Get number of offered hash algorithms
+    int32_t getNumHashes()   {return nHash; }
+
+    /// Get number of offered cipher algorithms
+    int32_t getNumCiphers()  {return nCipher; }
+
+    /// Get number of offered key agreement algorithms
+    int32_t getNumPubKeys()  {return nPubkey; }
+
+    /// Get number of offered SAS algorithms
+    int32_t getNumSas()      {return nSas; }
+
+    /// Get number of offered SRTP authentication algorithms
+    int32_t getNumAuth()     {return nAuth; }
+
+    /// set MitM flag
+    void setMitmMode()            { helloHeader->flags |= 0x20; }
+
+    /// set SAS sign flag
+    void setSasSign()            { helloHeader->flags |= 0x40; }
+
+ private:
+     // Hello packet is of variable length. It maximum size is 46 words:
+     // - 11 words fixed sizze
+     // - up to 35 words variable part, depending on number of algorithms
+     // leads to a maximum of 4*46=184 bytes.
+     uint8_t data[256];       // large enough to hold a full blown Hello packet
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETHELLO
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketHelloAck.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketHelloAck.h
new file mode 100644
index 0000000..345a071
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketHelloAck.h
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETHELLOACK_H_
+#define _ZRTPPACKETHELLOACK_H_
+
+/**
+ * @file ZrtpPacketHelloAck.h
+ * @brief The ZRTP HelloAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the HelloAck packet.
+ *
+ * The ZRTP simple message HelloAck. The implementation sends this
+ * after receiving a Hello packet.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketHelloAck : public ZrtpPacketBase {
+
+ public:
+    /// Creates a HelloAck packet with default data
+    ZrtpPacketHelloAck();
+
+    /// Creates a HelloAck packet from received data
+    ZrtpPacketHelloAck(uint8_t* data);
+
+    virtual ~ZrtpPacketHelloAck();
+
+ private:
+     HelloAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETHELLOACK
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketPing.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketPing.h
new file mode 100644
index 0000000..840df62
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketPing.h
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETPING_H_
+#define _ZRTPPACKETPING_H_
+
+/**
+ * @file ZrtpPacketPing.h
+ * @brief The ZRTP Ping message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the PingAck packet.
+ *
+ * The ZRTP simple message PingAck.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketPing : public ZrtpPacketBase {
+
+ protected:
+    Ping_t* pingHeader;     ///< Point the the Ping message
+
+ public:
+    /// Creates a Ping message with default data
+    ZrtpPacketPing();
+
+    /// Creates a Ping message from received data
+    ZrtpPacketPing(uint8_t* data);
+
+    virtual ~ZrtpPacketPing();
+
+    /// Set ZRTP protocol version field, fixed ASCII character array
+    void setVersion(uint8_t *text)     { memcpy(pingHeader->version, text,ZRTP_WORD_SIZE ); }
+
+    /// Get the endpoit hash, fixed byte array
+    uint8_t* getEpHash()               { return pingHeader->epHash; }
+
+ private:
+     PingPacket_t data;
+};
+
+/**
+ * @}
+ */
+
+#endif // ZRTPPACKETCLEARACK
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketPingAck.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketPingAck.h
new file mode 100644
index 0000000..51ad8c8
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketPingAck.h
@@ -0,0 +1,74 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETPINGACK_H_
+#define _ZRTPPACKETPINGACK_H_
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+/**
+ * @file ZrtpPacketPingAck.h
+ * @brief The ZRTP PingAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+/**
+ * Implement the PingAck packet.
+ *
+ * The ZRTP simple message PingAck.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketPingAck : public ZrtpPacketBase {
+
+ protected:
+    PingAck_t* pingAckHeader;   ///< Points to PingAck message
+
+ public:
+    /// Creates a PingAck message with default data
+    ZrtpPacketPingAck();
+
+    /// Creates a PingAck message from received data
+    ZrtpPacketPingAck(uint8_t* data);
+
+    virtual ~ZrtpPacketPingAck();
+
+    /// Get SSRC from PingAck message
+    uint32_t getSSRC() { return ntohl(pingAckHeader->ssrc); };
+
+    /// Set ZRTP protocol version field, fixed ASCII character array
+    void setVersion(uint8_t *text)      { memcpy(pingAckHeader->version, text, ZRTP_WORD_SIZE ); }
+
+    /// Set SSRC in PingAck message
+    void setSSRC(uint32_t data)         {pingAckHeader->ssrc = htonl(data); };
+
+    /// Set remote endpoint hash, fixed byte array
+    void setRemoteEpHash(uint8_t *hash) { memcpy(pingAckHeader->remoteEpHash, hash, sizeof(pingAckHeader->remoteEpHash)); }
+
+    /// Set local endpoint hash, fixed byte array
+    void setLocalEpHash(uint8_t *hash)  { memcpy(pingAckHeader->localEpHash, hash, sizeof(pingAckHeader->localEpHash)); }
+
+ private:
+     PingAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCLEARACK
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketRelayAck.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketRelayAck.h
new file mode 100644
index 0000000..93437e6
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketRelayAck.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2007 - 2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETRELAYACK_H_
+#define _ZRTPPACKETRELAYACK_H_
+
+/**
+ * @file ZrtpPacketRelayAck.h
+ * @brief The ZRTP RelayAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the RelayAck packet.
+ *
+ * The ZRTP simple message RelayAck. The implementation sends this
+ * after receiving and checking the SASrelay message.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketRelayAck : public ZrtpPacketBase {
+
+ public:
+    /// Creates a RelayAck packet with default data
+    ZrtpPacketRelayAck();
+
+    /// Creates a RelayAck packet from received data
+    ZrtpPacketRelayAck(uint8_t* data);
+    virtual ~ZrtpPacketRelayAck();
+
+ private:
+     RelayAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif  // _ZRTPPACKETRELAYACK_H_
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpPacketSASrelay.h b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketSASrelay.h
new file mode 100644
index 0000000..427ac28
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpPacketSASrelay.h
@@ -0,0 +1,113 @@
+/*
+  Copyright (C) 2006-2011 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETSASRELAY_H_
+#define _ZRTPPACKETSASRELAY_H_
+
+/**
+ * @file ZrtpPacketSASrelay.h
+ * @brief The ZRTP SAS Relay message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Confirm packet.
+ *
+ * The ZRTP message Confirm. The implementation sends this
+ * to confirm the switch to SRTP (encrypted) mode. The contents of
+ * the Confirm message are encrypted, thus the implementation
+ * can check if the secret keys work.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketSASrelay : public ZrtpPacketBase {
+
+    private:
+        SASrelay_t* sasRelayHeader;   ///< Point to the Confirm message part
+
+    public:
+        /// Creates a Confirm packet with default data
+        ZrtpPacketSASrelay();
+
+        /// Creates a Confirm packet with default data and a given signature length
+        ZrtpPacketSASrelay(uint32_t sl);
+
+        /// Creates a Confirm packet from received data
+        ZrtpPacketSASrelay(uint8_t* d);
+
+        /// Normal destructor
+        virtual ~ZrtpPacketSASrelay();
+
+        /// Check is SAS verify flag is set
+        const bool isSASFlag()            { return sasRelayHeader->flags & 0x4; }
+
+        /// Get pointer to filler bytes (contains one bit of signature length)
+        const uint8_t* getFiller()        { return sasRelayHeader->filler; }
+
+        /// Get pointer to IV data, fixed byte array
+        const uint8_t* getIv()            { return sasRelayHeader->iv; }
+
+        /// Get pointer to MAC data, fixed byte array
+        const uint8_t* getHmac()          { return sasRelayHeader->hmac; }
+
+        /// Get pointer to new SAS rendering algorithm, fixed byte array
+        const uint8_t* getSas() {return sasRelayHeader->sas; }
+
+        /// Get pointer to new SAS hash data, fixed byte array
+        const uint8_t* getTrustedSas() { return sasRelayHeader->trustedSasHash; }
+
+        /// get the signature length in words
+        uint32_t getSignatureLength();
+
+        /// set SAS verified flag
+        void setSASFlag()            { sasRelayHeader->flags |= 0x4; }
+
+        /// Set MAC data, fixed length byte array
+        void setHmac(uint8_t* text)  { memcpy(sasRelayHeader->hmac, text, sizeof(sasRelayHeader->hmac)); }
+
+        /// Set IV data, fixed length byte array
+        void setIv(uint8_t* text)    { memcpy(sasRelayHeader->iv, text, sizeof(sasRelayHeader->iv)); }
+
+        /// Set SAS rendering algorithm, fixed length byte array
+        void setSas(uint8_t* text)    { memcpy(sasRelayHeader->sas, text, sizeof(sasRelayHeader->sas)); }
+
+        /// Set SAS hash data, fixed length byte array
+        void setTrustedSas(uint8_t* text)    { memcpy(sasRelayHeader->trustedSasHash, text, sizeof(sasRelayHeader->trustedSasHash)); }
+
+        /// Set signature length in words
+        void setSignatureLength(uint32_t sl);
+
+    private:
+        void initialize();
+     // Confirm packet is of variable length. It maximum size is 524 words:
+     // - 11 words fixed size
+     // - up to 513 words variable part, depending if signature is present and its length.
+     // This leads to a maximum of 4*524=2096 bytes.
+        uint8_t data[2100];       // large enough to hold a full blown Confirm packet
+
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETSASRELAY
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpQueue.h b/jni/libzrtp/src/libzrtpcpp/ZrtpQueue.h
new file mode 100644
index 0000000..0454771
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpQueue.h
@@ -0,0 +1,917 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPQUEUE_H_
+#define _ZRTPQUEUE_H_
+
+#include <ccrtp/cqueue.h>
+#include <ccrtp/rtppkt.h>
+#include <libzrtpcpp/ZrtpCallback.h>
+#include <libzrtpcpp/TimeoutProvider.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+
+class __EXPORT ZrtpUserCallback;
+class __EXPORT ZRtp;
+
+NAMESPACE_COMMONCPP
+
+/**
+ * GNU ccRTP extension to support GNU ZRTP.
+ *
+ * ZRTP was developed by Phil Zimmermann and provides functions to
+ * negotiate keys and other necessary data (crypto data) to set-up
+ * the Secure RTP (SRTP) crypto context. Refer to Phil's ZRTP
+ * specification at his <a href="http://zfoneproject.com/">Zfone
+ * project</a> site to get more detailed imformation about the
+ * capabilities of ZRTP.
+ *
+ * <b>Short overview of the ZRTP implementation</b>
+ *
+ * ZRTP is a specific protocol to negotiate encryption algorithms
+ * and the required key material. ZRTP uses a RTP session to
+ * exchange its protocol messages.
+ *
+ * A complete GNU ZRTP implementation consists of two parts, the
+ * GNU ZRTP core and specific code that binds the GNU ZRTP core to
+ * the underlying RTP/SRTP stack and the operating system:
+ * <ul>
+ * <li>
+ *      The GNU ZRTP core is independent of a specific RTP/SRTP
+ *      stack and the operationg system and consists of the ZRTP
+ *      protocol state engine, the ZRTP protocol messages, and the
+ *      GNU ZRTP engine. The GNU ZRTP engine provides methods to
+ *      setup ZRTP message and to analyze received ZRTP messages,
+ *      to compute the crypto data required for SRTP, and to
+ *      maintain the required hashes and HMAC.
+ * </li>
+ * <li>
+ *      The second part of an implementation is specific
+ *      <em>glue</em> code the binds the GNU ZRTP core to the
+ *      actual RTP/SRTP implementation and other operating system
+ *      specific services  such as timers.
+ * </li>
+ * </ul>
+ *
+ * The GNU ZRTP core uses a callback interface class (refer to
+ * ZrtpCallback) to access RTP/SRTP or operating specific methods,
+ * for example to send data via the RTP/SRTP stack, to access
+ * timers, provide mutex handling, and to report events to the
+ * application.
+ *
+ * <b>The ZrtpQueue</b>
+ *
+ * ZrtpQueue implements code that is specific to the GNU ccRTP
+ * implementation. ZrtpQueue also implements the specific code to
+ * provide the mutex and timeout handling to the GNU ZRTP
+ * core. Both, the mutex and the timeout handling, use the GNU
+ * Common C++ library to stay independent of the operating
+ * seystem. For more information refer to the <a
+ * href="http://www.gnutelephony.org/index.php/GNU_Common_C%2B%2B">GNU
+ * Common C++</a> web site.
+ *
+ * To perform its tasks ZrtpQueue
+ * <ul>
+ * <li> extends GNU ccRTP classes to use the underlying
+ *      ccRTP methods and the RTP/SRTP send and receive queues
+ * </li>
+ * <li> implements the ZrtpCallback interface to provide ccRTP
+ *      access and other specific services (timer, mutex) to GNU
+ *      ZRTP
+ * </li>
+ * <li> provides ZRTP specific methods that applications may use
+ *      to control and setup GNU ZRTP
+ * </li>
+ * <li> can register and use an application specific callback
+ *      class (refer to ZrtpUserCallback)
+ * </li>
+ * </ul>
+ *
+ * After instantiating a GNU ZRTP session (see below for a short
+ * example) applications may use the ZRTP specific methods of
+ * ZrtpQueue to control and setup GNU ZRTP, for example enable or
+ * disable ZRTP processing or getting ZRTP status information.
+ *
+ * GNU ZRTP provides a ZrtpUserCallback class that an application
+ * may extend and register with ZrtpQueue. GNU ZRTP and ZrtpQueue
+ * use the ZrtpUserCallback methods to report ZRTP events to the
+ * application. The application may display this information to
+ * the user or act otherwise.
+ *
+ * The following figure depicts the relationships between
+ * ZrtpQueue, ccRTP RTP/SRTP implementation, the GNU ZRTP core,
+ * and an application that provides an ZrtpUserCallback class.
+ *
+@verbatim
+
+                      +----------+
+                      |  ccRTP   |
+                      | RTP/SRTP |
+                      |          |
+                      +----------+
+                           ^
+                           | extends
+                           |
++----------------+      +-----+------+
+|  Application   |      |            |      +-----------------+
+|  instantiates  | uses | ZrtpQueue  | uses |                 |
+| a ZRTP Session +------+ implements +------+    GNU ZRTP     |
+|  and provides  |      |ZrtpCallback|      |      core       |
+|ZrtpUserCallback|      |            |      | implementation  |
++----------------+      +------------+      |  (ZRtp et al)   |
+                                         |                 |
+                                         +-----------------+
+@endverbatim
+ *
+ * Because ZrtpQueue extends the ccRTP RTP/SRTP implementation
+ * (AVPQueue) all public methods defined by ccRTP are also
+ * available for a ZRTP session. ZrtpQueue overwrites some of the
+ * public methods of ccRTP (AVPQueue) to implement ZRTP specific
+ * code.
+ *
+ * GNU ZRTP provides a <em>SymmetricZRTPSession</em> type to
+ * simplify its use. An application uses this type in the same way
+ * as it would use the normal ccRTP <em>SymmetricRTPSession</em>
+ * type. The following short code snippets show how an application
+ * could instantiate ccRTP and GNU ZRTP sessions. The first
+ * snippet shows how to instantiate a ccRTP session:
+ *
+ * @code
+ * ...
+ * #include <ccrtp/rtp.h>
+ * ...
+ *     SymmetricRTPSession tx(pattern.getSsrc(),
+ *                            InetHostAddress("localhost"));
+ * ...
+ *
+ * @endcode
+ *
+ * The same code as above but using a GNU ZRTP session this time:
+ * @code
+ * ...
+ * #include <libzrtpcpp/zrtpccrtp.h>
+ * ...
+ *     SymmetricZRTPSession tx(pattern.getSsrc(),
+ *                             InetHostAddress("localhost"));
+ * ...
+ *
+ * @endcode
+ *
+ * The only differences are the different include statements and
+ * the different session types.
+ *
+ * The <em>demo</em> folder contains a small example that shows
+ * how to use GNU ZRTP.
+ *
+ * Please refer to the GNU ccRTP documentation for a description
+ * of ccRTP methods and functions. This ZrtpQueue documentation
+ * shows the ZRTP specific extensions and describes overloaded
+ * methods and a possible different behaviour.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpQueue : public AVPQueue, ZrtpCallback {
+
+public:
+
+    /**
+     * Initialize the ZrtpQueue.
+     *
+     * Before an application can use ZRTP it has to initialize the
+     * ZRTP implementation. This method initializes the timeout
+     * thread and opens a file that contains ZRTP specific
+     * information such as the applications ZID (ZRTP id) and its
+     * retained shared secrets.
+     *
+     * If one application requires several ZRTP sessions all
+     * sessions use the same timeout thread and use the same ZID
+     * file. Therefore an application does not need to do any
+     * synchronisation regading ZID files or timeouts. This is
+     * managed by the ZRTP implementation.
+     *
+     * The current implementation of ZrtpQueue does not support
+     * different ZID files for one application instance. This
+     * restriction may be removed in later versions.
+     *
+     * The application may specify its own ZID file name. If no
+     * ZID file name is specified it defaults to
+     * <code>$HOME/.GNUccRTP.zid</code> if the <code>HOME</code>
+     * environment variable is set. If it is not set the current
+     * directory is used.
+     *
+     * If the method could set up the timeout thread and open the ZID
+     * file then it enables ZRTP processing and returns.
+     *
+     * @param zidFilename
+     *     The name of the ZID file, can be a relative or absolut
+     *     filename.
+     *
+     * @param autoEnable
+     *     if set to true the method automatically sets enableZrtp to
+     *     true. This enables the ZRTP auto-sense mode. Default is true.
+     *
+     * @param config
+     *     this parameter points to ZRTP configuration data. If it is
+     *     NULL then ZrtpQueue uses a default setting. Default is NULL.
+     *
+     * @return
+     *     1 on success, ZRTP processing enabled, -1 on failure,
+     *     ZRTP processing disabled.
+     *
+     */
+    int32_t initialize(const char *zidFilename, bool autoEnable = true,
+                       ZrtpConfigure* config = NULL);
+
+    /*
+     * Applications use the following methods to control ZRTP, for example
+     * to enable ZRTP, set flags etc.
+     */
+
+    /**
+     * Enable or disable ZRTP processing.
+     *
+     * Call this method to enable or disable ZRTP processing after
+     * calling <code>initialize()</code>. This can be done before
+     * using a RTP session or at any time during a RTP session.
+     *
+     * Existing SRTP sessions or currently active ZRTP processing will
+     * not be stopped or disconnected.
+     *
+     * If the application enables ZRTP then:
+     * <ul>
+     * <li>ZrtpQueue starts to send ZRTP Hello packets after at least
+     * one RTP packet was sent and received on the associated RTP
+     * session. Thus if an application enables ZRTP and ZrtpQueue
+     * detects traffic on the RTP session then ZrtpQueue automatically
+     * starts the ZRTP protocol. This automatic start is convenient
+     * for applications that negotiate RTP parameters and set up RTP
+     * sessions but the actual RTP traffic starts some time later.
+     * </li>
+     * <li>ZrtpQueue analyses incoming packets to detect ZRTP
+     * messages. If ZRTP was started, either via automatic start (see
+     * above) or explicitly via startZrtp(), then ZrtpQueue
+     * forwards ZRTP packets to the GNU ZRTP core.
+     * </ul>
+     *
+     * @param onOff
+     *     @c true to enable ZRTP, @c false to disable ZRTP
+     */
+    void setEnableZrtp(bool onOff);
+
+    /**
+     * Return the state of ZRTP enable state.
+     *
+     * @return @c true if ZRTP processing is enabled, @c false
+     * otherwise.
+     */
+    bool isEnableZrtp();
+
+    /**
+     * Set SAS as verified.
+     *
+     * The application may call this method if the user confirmed
+     * (verfied) the Short Authentication String (SAS) with the peer.
+     *
+     * ZRTP calls ZrtpUserCallback#showSAS after it computed the SAS
+     * and the application registered a user callback class. The
+     * application should display the SAS and provide a mechanism at
+     * the user interface that enables the user to confirm the SAS.
+     *
+     * ZRTP remembers the SAS confirmation status together with the
+     * retained secrets data. If both parties confirmed the SAS then
+     * ZRTP informs the application about this status on the next ZRTP
+     * session.
+     *
+     * For more detailed information regarding SAS please refer to the
+     * ZRTP specification, chapter 8.
+     */
+    void SASVerified();
+
+    /**
+     * Reset the SAS verfied flag for the current user's retained secrets.
+     *
+     */
+    void resetSASVerified();
+
+    /**
+     * To confirm a go clear request.
+     *
+     * Call this method if the user confirmed a go clear (secure mode off).
+     */
+    void goClearOk();
+
+    /**
+     * Request to switch off secure mode.
+     *
+     * Call this method is the user itself wants to switch off secure
+     * mode (go clear). After sending the "go clear" request to the peer
+     * ZRTP immediatly switch off SRTP processing. Every RTP data is sent
+     * in clear after the go clear request.
+     */
+    void requestGoClear();
+
+    /**
+     * Set the auxilliary secret.
+     *
+     * Use this method to set the srtps secret data. Refer to ZRTP
+     * specification, chapter 5.3 ff
+     *
+     * @param data
+     *     Points to the auxilliary secret data.
+     * @param length
+     *     Length of the auxilliary secrect in bytes
+     */
+    void setAuxSecret(uint8_t* data, int32_t length);
+
+    /**
+     * Set the application's callback class.
+     *
+     * The destructor of ZrtpQueue also destorys the user callback
+     * class if it was set. The application must not delete the
+     * callback object or use/reference the callback object after
+     * ZrtpQueue was destroyed.
+     *
+     * @param ucb
+     *     Implementation of the application's ZrtpUserCallback class
+     */
+    void setUserCallback(ZrtpUserCallback* ucb);
+
+    /**
+     * Set the client ID for ZRTP Hello message.
+     *
+     * The GNU ccRTP client may set its id to identify itself in the
+     * ZRTP Hello message. The maximum length is 16 characters. A
+     * shorter id string is possible, it will be filled with blanks. A
+     * longer id string will be truncated to 16 characters. The
+     * standard client id is <code>'GNU ccRTP ZRTP '</code> (without
+     * the quotes).
+     *
+     * Setting the client's id must be done before calling
+     * ZrtpQueue#initialize() or ZrtpQueue#startZrtp() .
+     *
+     * @param id
+     *     The client's id string
+     */
+    void setClientId(std::string id);
+
+    /**
+     * Get the ZRTP Hello Hash data.
+     *
+     * Use this method to get the ZRTP Hello Hash data. The method
+     * returns the data as a string containing hex-digits. Refer
+     * to ZRTP specification, chapter 9.1.
+     *
+     * @return
+     *    a std:string containing the Hello hash value as hex-digits. The
+     *    hello hash is available immediatly after calling
+     *    ZrtpQueue#startZrtp. If ZRTP was not started the method returns
+     *    an empty string.
+     */
+    std::string getHelloHash();
+
+    /**
+     * Get the peer's ZRTP Hello Hash data.
+     *
+     * Use this method to get the peer's ZRTP Hello Hash data. The method
+     * returns the data as a string containing the ZRTP protocol version and
+     * hex-digits.
+     *
+     * The peer's hello hash is available only after ZRTP received a hello. If
+     * no data is available the function returns an empty string.
+     *
+     * Refer to ZRTP specification, chapter 8.
+     *
+     * @return
+     *    a std:string containing the Hello version and the hello hash as hex digits.
+     */
+    std::string getPeerHelloHash();
+
+    /**
+     * Get Multi-stream parameters.
+     *
+     * Use this method to get the Multi-stream that were computed during
+     * the ZRTP handshake. An application may use these parameters to
+     * enable multi-stream processing for an associated SRTP session.
+     *
+     * Refer to chapter 5.4.2 in the ZRTP specification for further details
+     * and restriction how and when to use multi-stream mode.
+     *
+     * @return
+     *    a string that contains the multi-stream parameters. The application
+     *    must not modify the contents of this string, it is opaque data. The
+     *    application may hand over this string to a new ZrtpQueue instance
+     *    to enable multi-stream processing for this ZrtpQueue. If ZRTP was
+     *    not started or ZRTP is not yet in secure state the method returns an
+     *    empty string.
+     *
+     * @see setMultiStrParams()
+     */
+    std::string getMultiStrParams();
+
+    /**
+     * Set Multi-stream parameters.
+     *
+     * Use this method to set the parameters required to enable Multi-stream
+     * processing of ZRTP. The multi-stream parameters must be set before the
+     * application starts the ZRTP protocol engine.
+     *
+     * Refer to chapter 5.4.2 in the ZRTP specification for further details
+     * of multi-stream mode.
+     *
+     * @param parameters
+     *     A string that contains the multi-stream parameters that this
+     *     new ZrtpQueue instanace shall use.
+     *
+     * @see getMultiStrParams()
+     */
+    void setMultiStrParams(std::string parameters);
+
+    /**
+     * Check if this ZRTP use Multi-stream.
+     *
+     * Use this method to check if this ZRTP instance uses multi-stream. Even
+     * if the application provided multi-stram parameters it may happen that
+     * full DH mode was used. Refer to chapters 5.2 and 5.4.2 in the ZRTP #
+     * when this may happen.
+     *
+     * @return
+     *     True if multi-stream is used, false otherwise.
+     */
+    bool isMultiStream();
+
+    /**
+     * Check if the other ZRTP client supports Multi-stream.
+     *
+     * Use this method to check if the other ZRTP client supports
+     * Multi-stream mode.
+     *
+     * @return
+     *     True if multi-stream is available, false otherwise.
+     */
+    bool isMultiStreamAvailable();
+
+    /**
+     * Accept a PBX enrollment request.
+     *
+     * If a PBX service asks to enroll the MiTM key and the user accepts this
+     * requtes, for example by pressing an OK button, the client application
+     * shall call this method and set the parameter <code>accepted</code> to
+     * true. If the user does not accept the request set the parameter to
+     * false.
+     *
+     * @param accepted
+     *     True if the enrollment request is accepted, false otherwise.
+     */
+    void acceptEnrollment(bool accepted);
+
+    /**
+     * Get the commited SAS rendering algorithm for this ZRTP session.
+     *
+     * @return the commited SAS rendering algorithm
+     */
+    std::string getSasType();
+
+    /**
+     * Get the computed SAS hash for this ZRTP session.
+     *
+     * A PBX ZRTP back-to-Back function uses this function to get the SAS
+     * hash of an enrolled client to construct the SAS relay packet for
+     * the other client.
+     *
+     * @return a refernce to the byte array that contains the full
+     *         SAS hash.
+     */
+    uint8_t* getSasHash();
+
+    /**
+     * Send the SAS relay packet.
+     *
+     * The method creates and sends a SAS relay packet according to the ZRTP
+     * specifications. Usually only a MitM capable user agent (PBX) uses this
+     * function.
+     *
+     * @param sh the full SAS hash value
+     * @param render the SAS rendering algorithm
+     */
+    bool sendSASRelayPacket(uint8_t* sh, std::string render);
+
+    /**
+     * Check the state of the MitM mode flag.
+     *
+     * If true then this ZRTP session acts as MitM, usually enabled by a PBX
+     * client (user agent)
+     *
+     * @return state of mitmMode
+     */
+    bool isMitmMode();
+
+    /**
+     * Set the state of the MitM mode flag.
+     *
+     * If MitM mode is set to true this ZRTP session acts as MitM, usually
+     * enabled by a PBX client (user agent).
+     *
+     * @param mitmMode defines the new state of the mitmMode flag
+     */
+    void setMitmMode(bool mitmMode);
+
+    /**
+     * Enable or disable paranoid mode.
+     *
+     * The Paranoid mode controls the behaviour and handling of the SAS verify flag. If
+     * Panaoid mode is set to flase then ZRtp applies the normal handling. If Paranoid
+     * mode is set to true then the handling is:
+     *
+     * <ul>
+     * <li> always set the SAS verify flag to <code>false</code> at srtpSecretsOn() callback. The
+     *      user interface (UI) must show <b>SAS not verified</b>. See implementation note below.</li>
+     * <li> don't set the SAS verify flag in the <code>Confirm</code> packets, thus forcing the other
+     *      peer to report <b>SAS not verified</b>.</li>
+     * <li> ignore the <code>SASVerified()</code> function, thus do not set the SAS verified flag
+     *      in the ZRTP cache. </li>
+     * <li> Disable the <em>Trusted PBX MitM</em> feature. Just send the <code>SASRelay</code> packet
+     *      but do not process the relayed data. This protects the user from a malicious
+     *      "trusted PBX".</li>
+     * </ul>
+     * ZRtp performs alls other steps during the ZRTP negotiations as usual, in particular it
+     * computes, compares, uses, and stores the retained secrets. This avoids unnecessary warning
+     * messages. The user may enable or disable the Paranoid mode on a call-by-call basis without
+     * breaking the key continuity data.
+     *
+     * <b>Implementation note:</b><br/>
+     * An application shall <b>always display the SAS if the SAS verify flag is <code>false</code></b>.
+     * The application shall remind the user to compare the SAS code, for example using larger fonts,
+     * different colours and other display features.
+     */
+    void setParanoidMode(bool yesNo);
+
+    /**
+     * Check status of paranoid mode.
+     *
+     * @return
+     *    Returns true if paranoid mode is enabled.
+     */
+    bool isParanoidMode();
+
+    /**
+     * Check the state of the enrollment mode.
+     *
+     * If true then we will set the enrollment flag (E) in the confirm
+     * packets and performs the enrollment actions. A MitM (PBX) enrollment service sets this flagstarted this ZRTP
+     * session. Can be set to true only if mitmMode is also true.
+     * @return status of the enrollmentMode flag.
+     */
+    bool isEnrollmentMode();
+
+    /**
+     * Check the state of the enrollment mode.
+     *
+     * If true then we will set the enrollment flag (E) in the confirm
+     * packets and perform the enrollment actions. A MitM (PBX) enrollment
+     * service must sets this mode to true.
+     *
+     * Can be set to true only if mitmMode is also true.
+     *
+     * @param enrollmentMode defines the new state of the enrollmentMode flag
+     */
+    void setEnrollmentMode(bool enrollmentMode);
+
+    /**
+     * Backwards compatible api fix...
+     */
+    inline void setPBXEnrollment(bool enrollmentMode)
+        {setMitmMode(enrollmentMode); setEnrollmentMode(enrollmentMode);}
+
+    /**
+     * Check if a peer's cache entry has a vaild MitM key.
+     *
+     * If true then the other peer ha a valid MtiM key, i.e. the peer has performed
+     * the enrollment procedure. A PBX ZRTP Back-2-Back application can use this function
+     * to check which of the peers is enrolled.
+     *
+     * @return True if the other peer has a valid Mitm key (is enrolled).
+     */
+    bool isPeerEnrolled();
+
+    /**
+     * Set the state of the SAS signature mode flag.
+     *
+     * If SAS signature mode is set to true this ZRTP session support SAS signature
+     * callbacks and signature transfer between clients.
+     *
+     * @param sasSignMode defines the new state of the sasSignMode flag
+     */
+    void setSignSas(bool sasSignMode);
+
+    /**
+     * Set signature data
+     *
+     * This functions stores signature data and transmitts it during ZRTP
+     * processing to the other party as part of the Confirm packets. Refer to
+     * chapters 6.7 and 8.2 in the ZRTP specification.
+     *
+     * @param data
+     *    The signature data including the signature type block. The method
+     *    copies this data into the Confirm packet at signature type block.
+     * @param length
+     *    The length of the signature data in bytes. This length must be
+     *    multiple of 4.
+     * @return
+     *    True if the method stored the data, false otherwise.
+     */
+    bool setSignatureData(uint8* data, int32 length);
+
+    /**
+     * Get signature data
+     *
+     * This functions returns signature data that was receivied during ZRTP
+     * processing. Refer to chapters 6.7 and 8.2.
+     *
+     * @return
+     *    Pointer to signature data. This is a pointer to volatile data that is
+     *    only valid during the checkSASSignature() callback. The application
+     *    shall copy the data if necessary.
+     */
+    const uint8* getSignatureData();
+
+    /**
+     * Get length of signature data
+     *
+     * This functions returns the length of signature data that was receivied
+     * during ZRTP processing. Refer to chapters 6.7 and 8.2.
+     *
+     * @return
+     *    Length in bytes of the received signature data. The method returns
+     *    zero if no signature data avilable.
+     */
+    int32 getSignatureLength();
+
+    /**
+     * Put data into the RTP output queue.
+     *
+     * This is used to create a data packet in the send queue.
+     * Sometimes a "NULL" or empty packet will be used instead, and
+     * these are known as "silent" packets.  "Silent" packets are
+     * used simply to "push" the scheduler along more accurately
+     * by giving the appearence that a next packet is waiting to
+     * be sent and to provide a valid timestamp for that packet.
+     *
+     * This method overrides the same method in OutgoingDataQueue class.
+     * During ZRTP processing it may be necessary to control the
+     * flow of outgoing RTP payload packets (GoClear processing).
+     *
+     * @param stamp Timestamp for expected send time of packet.
+     * @param data Value or NULL if special "silent" packet.
+     * @param len May be 0 to indicate a default by payload type.
+     **/
+    void
+    putData(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);
+
+    /**
+     * Immediatly send a data packet.
+     *
+     * This is used to create a data packet and send it immediately.
+     * Sometimes a "NULL" or empty packet will be used instead, and
+     * these are known as "silent" packets.  "Silent" packets are
+     * used simply to "push" the scheduler along more accurately
+     * by giving the appearence that a next packet is waiting to
+     * be sent and to provide a valid timestamp for that packet.
+     *
+     * This method overrides the same method in OutgoingDataQueue
+     * class.  During ZRTP processing it may be necessary to
+     * control the flow of outgoing RTP payload packets (GoClear
+     * processing).
+     *
+     * @param stamp Timestamp immediate send time of packet.
+     * @param data Value or NULL if special "silent" packet.
+     * @param len May be 0 to indicate a default by payload type.
+     **/
+    void
+    sendImmediate(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);
+
+    /**
+     * Starts the ZRTP protocol engine.
+     *
+     * Applications may call this method to immediatly start the ZRTP protocol
+     * engine any time after initializing ZRTP and setting optinal parameters,
+     * for example client id or multi-stream parameters.
+     *
+     * If the application does not call this method but sucessfully initialized
+     * the ZRTP engine using <code>initialize()</code> then ZRTP also starts
+     * after the application sent and received RTP packets. An application can
+     * disable this automatic, delayed start of the ZRTP engine using
+     * <code>setEnableZrtp(false)</code> before sending or receiving RTP
+     * packets.
+     *
+     */
+    void startZrtp();
+
+    /**
+     * Stops the ZRTP protocol engine.
+     *
+     * Applications call this method to stop the ZRTP protocol
+     * engine.
+     *
+     */
+    void stopZrtp();
+
+    /**
+     * Get other party's ZID (ZRTP Identifier) data
+     *
+     * This functions returns the other party's ZID that was receivied
+     * during ZRTP processing.
+     *
+     * The ZID data can be retrieved after ZRTP receive the first Hello
+     * packet from the other party. The application may call this method
+     * for example during SAS processing in showSAS(...) user callback
+     * method.
+     *
+     * @param data
+     *    Pointer to a data buffer. This buffer must have a size of
+     *    at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
+     * @return
+     *    Number of bytes copied into the data buffer - must be equivalent
+     *    to 96 bit, usually 12 bytes.
+     */
+    int32 getPeerZid(uint8* data);
+
+protected:
+    friend class TimeoutProvider<std::string, ost::ZrtpQueue*>;
+
+    /**
+     * A hook that gets called if the decoding of an incoming SRTP
+     * was erroneous
+     *
+     * @param pkt
+     *     The SRTP packet with error.
+     * @param errorCode
+     *     The error code: -1 - SRTP authentication failure, -2 - replay
+     *     check failed
+     * @return
+     *     True: put the packet in incoming queue for further processing
+     *     by the applications; false: dismiss packet. The default
+     *     implementation returns false.
+     */
+    virtual bool
+    onSRTPPacketError(IncomingRTPPkt& pkt, int32 errorCode);
+
+    /**
+     * Handle timeout event forwarded by the TimeoutProvider.
+     *
+     * Just call the ZRTP engine for further processing.
+     */
+    void handleTimeout(const std::string &c);
+
+    /**
+     * This function is used by the service thread to process
+     * the next incoming packet and place it in the receive list.
+     *
+     * This class overloads the function of IncomingDataQueue
+     * implementation.
+     *
+     * @return number of payload bytes received,  <0 if error.
+     */
+    virtual size_t takeInDataPacket();
+
+    /*
+     * The following methods implement the GNU ZRTP callback interface.
+     * For detailed documentation refer to file ZrtpCallback.h
+     */
+    int32_t sendDataZRTP(const unsigned char* data, int32_t length);
+
+    int32_t activateTimer(int32_t time);
+
+    int32_t cancelTimer();
+
+    void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+    bool srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part);
+
+    void srtpSecretsOff(EnableSecurity part);
+
+    void srtpSecretsOn(std::string c, std::string s, bool verified);
+
+    void handleGoClear();
+
+    void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+    void zrtpNotSuppOther();
+
+    void synchEnter();
+
+    void synchLeave();
+
+    void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info);
+
+    void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment  info);
+
+    void signSAS(uint8_t* sasHash);
+
+    bool checkSASSignature(uint8_t* sasHash);
+
+    /*
+     * End of ZrtpCallback functions.
+     */
+
+    ZrtpQueue(uint32 size = RTPDataQueue::defaultMembersHashSize,
+              RTPApplication& app = defaultApplication());
+
+    /**
+     * Local SSRC is given instead of computed by the queue.
+     */
+    ZrtpQueue(uint32 ssrc, uint32 size =
+                  RTPDataQueue::defaultMembersHashSize,
+              RTPApplication& app = defaultApplication());
+
+    virtual ~ZrtpQueue();
+
+private:
+    void init();
+    size_t rtpDataPacket(unsigned char* packet, int32 rtn,
+                         InetHostAddress network_address,
+                         tpport_t transport_port);
+
+    ZRtp *zrtpEngine;
+    ZrtpUserCallback* zrtpUserCallback;
+
+    std::string clientIdString;
+
+    bool enableZrtp;
+
+    int32 secureParts;
+
+    int16 senderZrtpSeqNo;
+    ost::Mutex synchLock;   // Mutex for ZRTP (used by ZrtpStateClass)
+    uint32 peerSSRC;
+    bool started;
+    bool mitmMode;
+    bool signSas;
+    bool enableParanoidMode;
+};
+
+class IncomingZRTPPkt : public IncomingRTPPkt {
+
+public:
+    /**
+     * Build a ZRTP packet object from a data buffer.
+     *
+     * @param block pointer to the buffer the whole packet is stored in.
+     * @param len length of the whole packet, expressed in octets.
+     *
+     **/
+
+    IncomingZRTPPkt(const unsigned char* block, size_t len);
+
+    ~IncomingZRTPPkt()
+    { }
+
+    uint32
+    getZrtpMagic() const;
+
+    uint32
+    getSSRC() const;
+};
+
+class OutgoingZRTPPkt : public OutgoingRTPPkt {
+
+public:
+    /**
+     * Construct a new ZRTP packet to be sent.
+     *
+     * A new copy in memory (holding all this components
+     * along with the fixed header) is created.
+     *
+     * @param hdrext whole header extension.
+     * @param hdrextlen size of whole header extension, in octets.
+     **/
+    OutgoingZRTPPkt(const unsigned char* const hdrext, uint32 hdrextlen);
+    ~OutgoingZRTPPkt()
+    { }
+};
+
+END_NAMESPACE
+
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpStateClass.h b/jni/libzrtp/src/libzrtpcpp/ZrtpStateClass.h
new file mode 100644
index 0000000..fba061d
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpStateClass.h
@@ -0,0 +1,324 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPSTATECLASS_H_
+#define _ZRTPSTATECLASS_H_
+
+/**
+ * @file ZrtpStateClass.h
+ * @brief The ZRTP state handling class
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpStates.h>
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * The ZRTP states
+ *
+ * Depending on the role of this state engine and the actual protocl flow
+ * not all states are processed during a ZRTP handshake.
+ */
+enum zrtpStates {
+    Initial,            ///< Initial state after starting the state engine
+    Detect,             ///< State sending Hello, try to detect answer message
+    AckDetected,        ///< HelloAck received
+    AckSent,            ///< HelloAck sent after Hello received
+    WaitCommit,         ///< Wait for a Commit message
+    CommitSent,         ///< Commit message sent
+    WaitDHPart2,        ///< Wait for a DHPart2 message
+    WaitConfirm1,       ///< Wait for a Confirm1 message
+    WaitConfirm2,       ///< Wait for a confirm2 message
+    WaitConfAck,        ///< Wait for Conf2Ack
+    WaitClearAck,       ///< Wait for clearAck - not used
+    SecureState,        ///< This is the secure state - SRTP active
+    WaitErrorAck,       ///< Wait for ErrorAck message
+    numberOfStates      ///< Gives total number of protocol states
+};
+
+enum EventReturnCodes {
+    Fail = 0,           ///< ZRTP event processing failed.
+    Done = 1            ///< Event processing ok.
+};
+
+enum EventDataType {
+    ZrtpInitial = 1,    ///< Initial event, enter Initial state
+    ZrtpClose,          ///< Close event, shut down state engine
+    ZrtpPacket,         ///< Normal ZRTP message event, process according to state
+    Timer,              ///< Timer event
+    ErrorPkt            ///< Error packet event
+};
+
+enum SecureSubStates {
+    Normal,
+    WaitSasRelayAck,
+    numberofSecureSubStates
+};
+
+/// A ZRTP state event
+typedef struct Event {
+    EventDataType type; ///< Type of event
+    uint8_t* packet;    ///< Event data if availabe, usually a ZRTP message
+} Event_t;
+
+
+/**
+ * The ZRTP timer structure.
+ *
+ * This structure holds all necessary data to compute the timer for
+ * the protocol timers. The state engine allocate one structure for
+ * each timer. ZRTP uses two timers, T1 and T2, to monitor protocol
+ * timeouts. As a slight misuse but to make overall handling a bit
+ * simpler this structure also contains the resend counter. This is
+ * possible in ZRTP because it uses a simple timeout strategy.
+ */
+typedef struct zrtpTimer {
+    int32_t time,       ///< Current timeout value
+    start,              ///< Start value for timeout
+    increment,          ///< increment timeout after each timeout event (not used anymore)
+    capping,            ///< Maximum timeout value
+    counter,            ///< Current number of timeouts
+    maxResend;          ///< Maximum number of timeout resends
+} zrtpTimer_t;
+
+
+class ZRtp;
+
+/**
+ * This class is the ZRTP protocol state engine.
+ *
+ * This class is responsible to handle the ZRTP protocol. It does not
+ * handle the ZRTP HMAC, DH, and other data management. This is done in
+ * class ZRtp, which is the parent of this class.
+ *
+ * The methods of this class implement the ZRTP state actions.
+ *
+ */
+
+
+class __EXPORT ZrtpStateClass {
+
+private:
+    ZRtp* parent;           ///< The ZRTP implmentation
+    ZrtpStates* engine;     ///< The state switching engine
+    Event_t* event;         ///< Current event to process
+
+    /**
+     * The last packet that was sent.
+     *
+     * If we are <code>Initiator</code> then resend this packet in case of
+     * timeout.
+     */
+    ZrtpPacketBase* sentPacket;
+
+    /**
+     * Points to prepared Commit packet after receiving a Hello packet
+     */
+    ZrtpPacketCommit* commitPkt;
+
+    zrtpTimer_t T1;         ///< The Hello message timeout timer
+    zrtpTimer_t T2;         ///< Timeout timer for other messages
+
+    /*
+     * If this is set to true the protocol engine handle the multi-stream
+     * variant of ZRTP. Refer to chapter 5.4.2 in the ZRTP specification.
+     */
+    bool multiStream;
+    
+    // Secure substate to handle SAS relay packets
+    SecureSubStates secSubstate;
+
+    /**
+     * Secure Sub state WaitSasRelayAck.
+     *
+     * This state belongs to the secure substates and handles
+     * SAS Relay Ack. 
+     *
+     * When entering this transition function
+     * - sentPacket contains Error packet, Error timer active
+     *
+     * Possible events in this state are:
+     * - timeout for sent SAS Relay packet: causes a resend check and repeat sending
+     *   of packet
+     * - SASRelayAck: Stop timer and switch to secure substate Normal.
+     */
+    bool subEvWaitRelayAck();
+
+public:
+    /// Create a ZrtpStateClass
+    ZrtpStateClass(ZRtp *p);
+    ~ZrtpStateClass();
+
+    /// Check if in a specified state
+    bool inState(const int32_t state) { return engine->inState(state); };
+
+    /// Switch to the specified state
+    void nextState(int32_t state)        { engine->nextState(state); };
+
+    /// Process an event, the main entry point into the state engine
+    void processEvent(Event_t *ev);
+
+    /**
+     * The state event handling methods.
+     *
+     * Refer to the protocol state diagram for further documentation.
+     */
+    /// Initial event state
+    void evInitial();
+
+    /// Detect state
+    void evDetect();
+
+    /// HelloAck detected state
+    void evAckDetected();
+
+    /// HelloAck sent state
+    void evAckSent();
+
+    /// Wait for Commit message
+    void evWaitCommit();
+
+    /// Commit sent state
+    void evCommitSent();
+
+    /// Wait for DHPart2 message
+    void evWaitDHPart2();
+
+    /// Wait for Confirm2 message
+    void evWaitConfirm1();
+
+    /// Wait for Confirm2 message
+    void evWaitConfirm2();
+
+    /// Wait for ConfAck message
+    void evWaitConfAck();
+
+    /// Wait for ClearAck message (not used)
+    void evWaitClearAck();
+
+    /// Secure reached state
+    void evSecureState();
+
+    /// Wait for ErrorAck message
+    void evWaitErrorAck();
+
+    /**
+     * Initialize and activate a timer.
+     *
+     * @param t
+     *    The ZRTP timer structure to use for the timer.
+     * @return
+     *    1 timer was activated
+     *    0 activation failed
+     */
+    int32_t startTimer(zrtpTimer_t *t);
+
+    /**
+     * Compute and set the next timeout value.
+     *
+     * @param t
+     *    The ZRTP timer structure to use for the timer.
+     * @return
+     *    1 timer was activated
+     *    0 activation failed
+     *   -1 resend counter exceeded
+     */
+    int32_t nextTimer(zrtpTimer_t *t);
+
+    /**
+     * Cancel the active timer.
+     *
+     * @return
+     *    1 timer was canceled
+     *    0 cancelation failed
+     */
+    int32_t cancelTimer() {return parent->cancelTimer(); };
+
+    /**
+     * Prepare and send an Error packet.
+     *
+     * Preparse an Error packet and sends it. It stores the Error
+     * packet in the sentPacket variable to enable resending. The
+     * method switches to protocol state Initial.
+     */
+    void sendErrorPacket(uint32_t errorCode);
+
+    /**
+     * Set status if an error occured while sending a ZRTP packet.
+     *
+     * This functions clears data and set the state to Initial after the engine
+     * detected a problem while sending a ZRTP packet.
+     *
+     * @return
+     *    Fail code
+     */
+    void sendFailed();
+
+    /**
+     * Set status if a timer problems occure.
+     *
+     * This functions clears data and set state to Initial after a timer
+     * error occured. Either no timer available or resend counter exceedeed.
+     *
+     * @return
+     *    Fail code
+     */
+    void timerFailed(int32_t subCode);
+
+    /**
+     * Set multi-stream mode flag.
+     *
+     * This functions set the multi-stream mode. The protocol
+     * engine will run the multi-stream mode variant of the ZRTP
+     * protocol if this flag is set to true.
+     *
+     * @param multi
+     *    Set the multi-stream mode flag to true or false.
+     */
+    void setMultiStream(bool multi);
+
+    /**
+     * Status of multi-stream mode flag.
+     *
+     * This functions returns the value of the multi-stream mode flag.
+     *
+     * @return
+     *    Value of the multi-stream mode flag.
+     */
+    bool isMultiStream();
+
+    /**
+     * Send a SAS relay packet.
+     *
+     * the functions stores sends the SAS relay packet and stores the pointer in
+     * the sentPacket variable to enable resending.
+     *
+     * The method switches to secure substate WaitSasRelayAck.
+     * 
+     * @param relay
+     *    Pointer to the SAS relay packet.
+     */
+    void sendSASRelay(ZrtpPacketSASrelay* relay);
+};
+
+/**
+ * @}
+ */
+#endif // _ZRTPSTATECLASS_H_
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpStates.h b/jni/libzrtp/src/libzrtpcpp/ZrtpStates.h
new file mode 100644
index 0000000..44662a0
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpStates.h
@@ -0,0 +1,90 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPSTATES_H_
+#define _ZRTPSTATES_H_
+
+/**
+ * @file ZrtpStates.h
+ * @brief The ZRTP state switching class
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdint.h>
+
+class __EXPORT ZrtpStateClass;
+/**
+ * This structure hold the state name as enum (int) number and the pointer to
+ * the functions that handles the various triggers that can occur in a state.
+ */
+typedef struct  {
+    int32_t stateName;                      ///< The state number
+    void (ZrtpStateClass::* handler)(void); ///< The state handler
+} state_t;
+
+/**
+ * Implement a simple state switching.
+ *
+ * This class provides functions that manage the states and the event handler
+ * functions. Its a very simple implementation.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpStates {
+ public:
+
+    /// Create an initialize state switching
+    ZrtpStates(state_t* const zstates,
+           const int32_t numStates,
+           const int32_t initialState):
+    numStates(numStates), states(zstates), state(initialState) {}
+
+    /// Call a state handler
+    int32_t processEvent(ZrtpStateClass& zsc) {
+        (zsc.*states[state].handler)();
+        return 0;
+    }
+
+    /// Check if in specified state
+    bool inState(const int32_t s) { return ((s == state)); }
+
+    /// Set the next state
+    void nextState(int32_t s)        { state = s; }
+
+ private:
+    const int32_t numStates;
+    const state_t* states;
+    int32_t  state;
+
+    ZrtpStates();
+};
+
+/**
+ * @}
+ */
+#endif  //ZRTPSTATES
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpTextData.h b/jni/libzrtp/src/libzrtpcpp/ZrtpTextData.h
new file mode 100644
index 0000000..e79cb98
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpTextData.h
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPTEXTDATA_H_
+#define _ZRTPTEXTDATA_H_
+
+/**
+ * @file ZrtpTextData.h
+ * @brief The ZRTP ASCII texts - extern references
+ *  
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpConfigure.h>
+
+/**
+ * The extern references to the global data.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+extern char clientId[];
+extern char zrtpVersion[];
+
+/**
+ *
+ */
+extern char HelloMsg[];
+extern char HelloAckMsg[];
+extern char CommitMsg[];
+extern char DHPart1Msg[];
+extern char DHPart2Msg[];
+extern char Confirm1Msg[];
+extern char Confirm2Msg[];
+extern char Conf2AckMsg[];
+extern char ErrorMsg[];
+extern char ErrorAckMsg[];
+extern char GoClearMsg[];
+extern char ClearAckMsg[];
+extern char PingMsg[];
+extern char PingAckMsg[];
+extern char SasRelayMsg[];
+extern char RelayAckMsg[];
+
+/**
+ *
+ */
+extern char responder[];
+extern char initiator[];
+extern char iniMasterKey[];
+extern char iniMasterSalt[];
+extern char respMasterKey[];
+extern char respMasterSalt[];
+
+extern char iniHmacKey[];
+extern char respHmacKey[];
+extern char retainedSec[];
+
+extern char iniZrtpKey[];
+extern char respZrtpKey[];
+
+extern char sasString[];
+
+extern char KDFString[];
+extern char zrtpSessionKey[];
+extern char zrtpMsk[];
+extern char zrtpTrustedMitm[];
+
+
+extern char s256[];
+extern char s384[];
+extern const char* mandatoryHash;
+
+extern char aes3[];
+extern char aes2[];
+extern char aes1[];
+extern char two3[];
+extern char two2[];
+extern char two1[];
+
+extern const char* mandatoryCipher;
+
+extern char dh2k[];
+extern char dh3k[];
+extern char ec25[];
+extern char ec38[];
+
+extern char mult[];
+
+extern const char* mandatoryPubKey;
+
+extern char b32[];
+extern const char* mandatorySasType;
+
+extern char hs32[];
+extern char hs80[];
+extern char sk32[];
+extern char sk64[];
+extern const char* mandatoryAuthLen_1;
+extern const char* mandatoryAuthLen_2;
+
+/**
+ * @}
+ */
+#endif     // _ZRTPTEXTDATA_H_
+
diff --git a/jni/libzrtp/src/libzrtpcpp/ZrtpUserCallback.h b/jni/libzrtp/src/libzrtpcpp/ZrtpUserCallback.h
new file mode 100644
index 0000000..3e4871c
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/ZrtpUserCallback.h
@@ -0,0 +1,234 @@
+/*

+  Copyright (C) 2006-2008 Werner Dittmann

+

+  This program is free software: you can redistribute it and/or modify

+  it under the terms of the GNU General Public License as published by

+  the Free Software Foundation, either version 3 of the License, or

+  (at your option) any later version.

+

+  This program is distributed in the hope that it will be useful,

+  but WITHOUT ANY WARRANTY; without even the implied warranty of

+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+  GNU General Public License for more details.

+

+  You should have received a copy of the GNU General Public License

+  along with this program.  If not, see <http://www.gnu.org/licenses/>.

+*/

+

+#ifndef _ZRTPUSERCALLBACK_H_

+#define _ZRTPUSERCALLBACK_H_

+

+/**

+ * @file ZrtpUserCallback.h

+ * @brief The ZRTP UserCallback class

+ *

+ * @ingroup GNU_ZRTP

+ * @{

+ */

+

+#include <stdint.h>

+#include <string>

+

+#include <libzrtpcpp/ZrtpCodes.h>

+

+/**

+ * Application callback methods.

+ *

+ * The ccRTP specific part of GNU ZRTP uses these callback methods

+ * to report ZRTP events to the application. This class implements a

+ * default behaviour for each callback method, usually just a return.

+ *

+ * An application may extend this class and overload methods

+ * to implement its own behaviour. The application must register its

+ * callback class using ZrtpQueue#setUserCallback().

+ *

+ * <b>CAVEAT</b><br/>

+ * All methods of the user callback class and classes that

+ * extend this class run in the context of the RTP thread. Thus it is

+ * of paramount importance to keep the execution time of the methods

+ * as short as possible.

+ *

+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>

+ */

+

+class __EXPORT ZrtpUserCallback {

+

+    public:

+

+        /// Create the stadard user callback class.

+        ZrtpUserCallback() {}

+

+        virtual ~ZrtpUserCallback() {};

+

+        /**

+         * Inform user interface that security is active now.

+         *

+         * ZRTP calls this method if the sender and the receiver are

+         * in secure mode now.

+         *

+         * @param cipher

+         *    Name and mode of cipher used to encrypt the SRTP stream

+         */

+        virtual void secureOn(std::string cipher) {

+            return;

+        }

+        /**

+         * Inform user interface that security is not active any more.

+         *

+         * ZRTP calls this method if either the sender or the receiver

+         * left secure mode.

+         *

+         */

+        virtual void secureOff() {

+            return;

+        }

+

+        /**

+         * Show the Short Authentication String (SAS) on user interface.

+         *

+         * ZRTP calls this method to display the SAS and inform about the SAS

+         * verification status. The user interface shall enable a SAS verfication

+         * button (or similar UI element). The user shall click on this UI

+         * element after he/she confirmed the SAS code with the partner.

+         *

+         * @param sas

+         *     The string containing the SAS.

+         * @param verified

+         *    If <code>verified</code> is true then SAS was verified by both

+         *    parties during a previous call, otherwise it is set to false.

+         */

+        virtual void showSAS(std::string sas, bool verified) {

+            return;

+        }

+

+        /**

+         * Inform the user that ZRTP received "go clear" message from its peer.

+         *

+         * On receipt of a go clear message the user is requested to confirm

+         * a switch to unsecure (clear) modus. Until the user confirms ZRTP

+         * (and the underlying RTP) does not send any data.

+         */

+        virtual void confirmGoClear() {

+            return;

+        }

+

+        /**

+         * Show some information to user.

+         *

+         * ZRTP calls this method to display some information to the user.

+         * Along with the message ZRTP provides a severity indicator that

+         * defines: Info, Warning, Error, and Alert. Refer to the <code>

+         * MessageSeverity</code> enum in <code>ZrtpCodes.h</code>. The

+         * UI may use this indicator to highlight messages or alike.

+         *

+         * @param sev

+         *     Severity of the message.

+         * @param subCode

+         *     The subcode identifying the reason.

+         */

+        virtual void showMessage(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) {

+            return;

+        }

+

+        /**

+         * ZRTPQueue calls this if the negotiation failed.

+         *

+         * ZRTPQueue calls this method in case ZRTP negotiation failed. The

+         * parameters show the severity as well as some explanatory text.

+         * Refer to the <code>MessageSeverity</code> enum above.

+         *

+         * @param severity

+         *     This defines the message's severity

+         * @param subCode

+         *     The subcode identifying the reason.

+         */

+        virtual void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity,

+                                           int32_t subCode) {

+            return;

+        }

+

+        /**

+         * ZRTPQueue calls this method if the other side does not support ZRTP.

+         *

+         * If the other side does not answer the ZRTP <em>Hello</em> packets then

+         * ZRTP calls this method.

+         *

+         */

+        virtual void zrtpNotSuppOther() {

+            return;

+        }

+

+        /**

+         * ZRTPQueue calls this method to inform about a PBX enrollment request.

+         *

+         * Please refer to chapter 8.3 ff to get more details about PBX enrollment

+         * and SAS relay.

+         *

+         * @param info

+         *    Give some information to the user about the PBX requesting an

+         *    enrollment.

+         *

+         */

+        virtual void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info) {

+            return;

+        }

+

+        /**

+         * ZRTPQueue calls this method to inform about PBX enrollment result.

+         *

+         * Informs the use about the acceptance or denial of an PBX enrollment

+         * request

+         *

+         * @param info

+         *    Give some information to the user about the result of an

+         *    enrollment.

+         *

+         */

+        virtual void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info) {

+            return;

+        }

+

+        /**

+         * ZRTPQueue calls this method to request a SAS signature.

+         *

+         * After ZRTP core was able to compute the Short Authentication String

+         * (SAS) it calls this method. The client may now use an approriate

+         * method to sign the SAS. The client may use

+         * setSignatureData() of ZrtpQueue to store the signature

+         * data an enable signature transmission to the other peer. Refer

+         * to chapter 8.2 of ZRTP specification.

+         *

+         * @param sasHash

+         *    Pointer to the 32 byte SAS hash to be signed.

+         * @see ZrtpQueue#setSignatureData

+         *

+         */

+        virtual void signSAS(uint8_t* sasHash) {

+            return;

+        }

+

+        /**

+         * ZRTPQueue calls this method to request a SAS signature check.

+         *

+         * After ZRTP received a SAS signature in one of the Confirm packets it

+         * call this method. The client may use <code>getSignatureLength()</code>

+         * and <code>getSignatureData()</code>of ZrtpQueue to get the signature

+         * data and perform the signature check. Refer to chapter 8.2 of ZRTP

+         * specification.

+         *

+         * If the signature check fails the client may return false to ZRTP. In

+         * this case ZRTP signals an error to the other peer and terminates

+         * the ZRTP handshake.

+         *

+         * @param sasHash

+         *    Pointer to the 32 byte SAS hash that was signed by the other peer.

+         * @return

+         *    true if the signature was ok, false otherwise.

+         *

+         */

+        virtual bool checkSASSignature(uint8_t* sasHash) {

+            return true;

+        }

+};

+

+#endif

diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/TwoCFB.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/TwoCFB.cpp
new file mode 100755
index 0000000..be3dda4
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/TwoCFB.cpp
@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2011 by Werner Dittmann
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/** Copyright (C) 2011
+ *
+ * @author  Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <string.h>
+
+#include <libzrtpcpp/crypto/twoCFB.h>
+#include <libzrtpcpp/crypto/twofish.h>
+
+static int initialized = 0;
+
+void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+                   int32_t dataLength)
+{
+    Twofish_key keyCtx;
+    int usedBytes = 0;
+
+    if (!initialized) {
+        Twofish_initialise();
+        initialized = 1;
+    }
+
+    memset(&keyCtx, 0, sizeof(Twofish_key));
+    Twofish_prepare_key(key, keyLength, &keyCtx);
+
+    Twofish_cfb128_encrypt(&keyCtx, (Twofish_Byte*)data, (Twofish_Byte*)data,
+			   (size_t)dataLength, (Twofish_Byte*)IV, &usedBytes);
+}
+
+
+void twoCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+                   int32_t dataLength)
+{
+    Twofish_key keyCtx;
+    int usedBytes = 0;
+
+    if (!initialized) {
+        Twofish_initialise();
+        initialized = 1;
+    }
+
+    memset(&keyCtx, 0, sizeof(Twofish_key));
+    Twofish_prepare_key(key, keyLength, &keyCtx);
+
+    Twofish_cfb128_decrypt(&keyCtx, (Twofish_Byte*)data, (Twofish_Byte*)data, 
+			   (size_t)dataLength, (Twofish_Byte*)IV, &usedBytes);
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/ZrtpDH.h b/jni/libzrtp/src/libzrtpcpp/crypto/ZrtpDH.h
new file mode 100644
index 0000000..bd32f7f
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/ZrtpDH.h
@@ -0,0 +1,168 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPDH_H__
+#define _ZRTPDH_H__
+
+#include <stdint.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+
+/**
+ * @file ZrtpDH.h
+ * @brief Class that implemets Diffie-Helman key agreement for ZRTP
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+/**
+ * Generates a number of random bytes.
+ *
+ * @param buf
+ *    Pointer to a buffer that receives the random data. Must have a size
+ *    of at least <code>length</code> bytes.
+ *
+ * @param length
+ *    Number of random bytes to produce.
+ */
+void randomZRTP(uint8_t *buf, int32_t length);
+
+const int32_t DH2K = 0;
+const int32_t DH3K = 1;
+const int32_t EC25 = 2;
+const int32_t EC38 = 3;
+
+
+/**
+ * Implementation of Diffie-Helman for ZRTP
+ *
+ * This class defines functions to generate and compute the
+ * Diffie-Helman public and secret data and the shared secret. According to
+ * the ZRTP specification we use the MODP groups as defined by RFC 3526 for
+ * length 3072 and 4096.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class ZrtpDH {
+
+private:
+    void* ctx;      ///< Context the DH
+    int pkType;     ///< Which type of DH to use
+
+public:
+    /**
+     * Create a Diffie-Helman key agreement algorithm
+     * 
+     * @param type
+     *     Name of the DH algorithm to use
+     */
+    ZrtpDH(const char* type);
+    
+    ~ZrtpDH();
+
+    /**
+     * Generates a public key based on the DH parameters and a random
+     * private key.
+     *
+     * @return 1 on success, 0 on failure
+     */
+    int32_t generatePublicKey();
+
+    /**
+     * Returns the size in bytes of the DH parameter p.
+     *
+     * @return Size in bytes.
+     */
+    int32_t getDhSize() const;
+
+    /**
+     * Returns the size in bytes of computed public key.
+     *
+     * @return Size in bytes.
+     */
+    int32_t getPubKeySize() const;
+
+    /**
+     * Returns the bytes of computed secret key.
+     *
+     * Returns the bytes of the public key in network (big endian) order.#
+     *
+     * @param buf
+     *    Pointer to a buffer of at least <code>getPubKeySize()</code> bytes.
+     *
+     * @return Size in bytes.
+     */
+    int32_t getPubKeyBytes(uint8_t *buf) const;
+
+    /**
+     * Compute the secret key and returns it to caller.
+     *
+     * This method computes the secret key based on the DH parameters, the
+     * private key and the peer's public key.
+     *
+     * @param pubKeyBytes
+     *    Pointer to the peer's public key bytes. Must be in big endian order.
+     *
+     * @param secret
+     *    Pointer to a buffer that receives the secret key. This buffer must
+     *    have a length of at least <code>getSecretSize()</code> bytes.
+     *
+     * @return the size of the shared secret on success, -1 on error.
+     */
+    int32_t computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret);
+
+    /**
+     * Check and validate the public key received from peer.
+     *
+     * Check if this is a correct Diffie-Helman public key. If the public
+     * key value is either one or (P-1) then this is a wrong public key
+     * value.
+     *
+     * @param pubKeyBytes
+     *     Pointer to the peer's public key bytes. Must be in big endian order.
+     *
+     * @return 0 if check faild, 1 if public key value is ok.
+     */
+    int32_t checkPubKey(uint8_t* pubKeyBytes) const;
+
+    /**
+     * Get type of DH algorithm.
+     * 
+     * @return
+     *     Pointer to DH algorithm name
+     */
+    const char* getDHtype();
+};
+
+#endif // ZRTPDH_H
+
+/**
+ * @}
+ */
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/aesCFB.h b/jni/libzrtp/src/libzrtpcpp/crypto/aesCFB.h
new file mode 100644
index 0000000..6b4ab6e
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/aesCFB.h
@@ -0,0 +1,87 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _AESCFB_H__
+#define _AESCFB_H__
+
+#include <stdint.h>
+
+/**
+ * @file aesCFB.h
+ * @brief Function that provide AES CFB mode support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#ifndef AES_BLOCK_SIZE
+#define AES_BLOCK_SIZE 16
+#endif
+
+/**
+ * Encrypt data with AES CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and encrypts it with
+ * AES CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of AES blocksize.
+ *
+ * @param key
+ *    Points to the key bytes.
+ * @param keyLength
+ *    Length of the key in bytes
+ * @param IV
+ *    The initialization vector which must be AES_BLOCKSIZE (16) bytes.
+ * @param data
+ *    Points to a buffer that contains and receives the computed
+ *    the data (in-place encryption).
+ * @param dataLength
+ *    Length of the data in bytes
+ */
+
+void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+                   int32_t dataLength);
+
+/**
+ * Decrypt data with AES CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and decrypts it with
+ * AES CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of AES blocksize.
+ *
+ * @param key
+ *    Points to the key bytes.
+ * @param keyLength
+ *    Length of the key in bytes
+ * @param IV
+ *    The initialization vector which must be AES_BLOCKSIZE (16) bytes.
+ * @param data
+ *    Points to a buffer that contains and receives the computed
+ *    the data (in-place decryption).
+ * @param dataLength
+ *    Length of the data in bytes
+ */
+
+void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+                   int32_t dataLength);
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp
new file mode 100644
index 0000000..1372578
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+
+#include <malloc.h>
+#include <errno.h>
+#include <gcrypt.h>
+
+#include <libzrtpcpp-config.h>
+#ifdef  HAVE_PTHREAD_H
+#include <pthread.h>
+#else
+#include <winbase.h>
+#endif
+
+static int initialized = 0;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef  HAVE_PTHREAD_H
+static int gcry_thread_mutex_init (void **priv)
+{
+    int err = 0;
+    pthread_mutex_t *lock = (pthread_mutex_t *)malloc (sizeof (pthread_mutex_t));
+    if (!lock)
+        err = ENOMEM;
+    if (!err) {
+        err = pthread_mutex_init (lock, NULL);
+        if (err)
+            free (lock);
+        else
+            *priv = lock;
+    }
+    return err;
+}
+
+static int gcry_thread_mutex_destroy (void **lock)
+{ 
+    int err = pthread_mutex_destroy ((pthread_mutex_t *)*lock);  
+    free (*lock); return err; 
+}
+
+static int gcry_thread_mutex_lock (void **lock)
+{ 
+    return pthread_mutex_lock ((pthread_mutex_t *)*lock); 
+}
+
+static int gcry_thread_mutex_unlock (void **lock)
+{
+    return pthread_mutex_unlock ((pthread_mutex_t *)*lock); 
+}
+ 
+static struct gcry_thread_cbs gcry_threads = { 
+    GCRY_THREAD_OPTION_PTHREAD, NULL,
+    gcry_thread_mutex_init, gcry_thread_mutex_destroy,
+    gcry_thread_mutex_lock, gcry_thread_mutex_unlock 
+};
+
+#else
+static int gcry_thread_mutex_init (void **priv)
+{
+    int err = 0;
+	CRITICAL_SECTION *lock = (CRITICAL_SECTION *)malloc(sizeof(CRITICAL_SECTION));
+    if (!lock)
+        err = ENOMEM;
+    if (!err) {
+		InitializeCriticalSection(lock);
+        *priv = lock;
+    }
+    return err;
+}
+
+static int gcry_thread_mutex_destroy (void **lock)
+{ 
+	free(*lock);
+	return 0;
+}
+
+static int gcry_thread_mutex_lock (void **lock)
+{ 
+	EnterCriticalSection((CRITICAL_SECTION *)*lock);
+	return 0;
+}
+
+static int gcry_thread_mutex_unlock (void **lock)
+{
+	LeaveCriticalSection((CRITICAL_SECTION *)*lock);
+	return 0;
+}
+ 
+static struct gcry_thread_cbs gcry_threads = { 
+    GCRY_THREAD_OPTION_PTHREAD, NULL,
+    gcry_thread_mutex_init, gcry_thread_mutex_destroy,
+    gcry_thread_mutex_lock, gcry_thread_mutex_unlock 
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+int initializeGcrypt ()
+{
+
+    if (initialized) {
+	      return 1;
+    }
+    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads);
+    gcry_check_version(NULL);
+    gcry_control(GCRYCTL_DISABLE_SECMEM);
+    initialized = 1;
+    return 1;
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp
new file mode 100644
index 0000000..3673619
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp
@@ -0,0 +1,77 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/** Copyright (C) 2006, 2007
+ *
+ * @author  Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/aesCFB.h>
+
+
+extern void initializeGcrypt();
+
+void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+                   int32_t dataLength)
+{
+    gcry_error_t err = 0;
+    int algo;
+
+    initializeGcrypt();
+
+    if (keyLength == 16) {
+        algo = GCRY_CIPHER_AES;
+    }
+    else if (keyLength == 32) {
+        algo = GCRY_CIPHER_AES256;
+    }
+    else {
+	return;
+    }
+    gcry_cipher_hd_t tmp;
+    err = gcry_cipher_open(&tmp, algo, GCRY_CIPHER_MODE_CFB, 0);
+    err = gcry_cipher_setkey(tmp, key, keyLength);
+    err = gcry_cipher_setiv (tmp, IV, AES_BLOCK_SIZE);
+    err = gcry_cipher_encrypt (tmp, data, dataLength, data, dataLength);
+    gcry_cipher_close(tmp);
+}
+
+void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+                   int32_t dataLength)
+{
+    gcry_error_t err = 0;
+    int algo;
+
+    initializeGcrypt();
+
+    if (keyLength == 16) {
+        algo = GCRY_CIPHER_AES;
+    }
+    else if (keyLength == 32) {
+        algo = GCRY_CIPHER_AES256;
+    }
+    else {
+	return;
+    }
+    gcry_cipher_hd_t tmp;
+    err = gcry_cipher_open(&tmp, algo, GCRY_CIPHER_MODE_CFB, 0);
+    err = gcry_cipher_setkey(tmp, key, keyLength);
+    err = gcry_cipher_setiv (tmp, IV, AES_BLOCK_SIZE);
+    err = gcry_cipher_decrypt (tmp, data, dataLength, data, dataLength);
+    gcry_cipher_close(tmp);
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp
new file mode 100644
index 0000000..1aba680
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp
@@ -0,0 +1,349 @@
+/*
+  Copyright (C) 2006, 2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/** Copyright (C) 2006, 2009
+ *
+ * @author  Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/ZrtpDH.h>
+#include <libzrtpcpp/ZrtpTextData.h>
+#include <sstream>
+
+struct gcryptCtx {
+    gcry_mpi_t privKey;
+    gcry_mpi_t pubKey;
+//    int32_t pLength;
+};
+
+extern void initializeGcrypt();
+
+static gcry_mpi_t bnP2048 = NULL;
+static gcry_mpi_t bnP3072 = NULL;
+// static gcry_mpi_t bnP4096 = NULL;
+static gcry_mpi_t two = NULL;
+static gcry_mpi_t bnP2048MinusOne = NULL;
+static gcry_mpi_t bnP3072MinusOne = NULL;
+// static gcry_mpi_t bnP4096MinusOne = NULL;
+
+static uint8_t dhinit = 0;
+
+void randomZRTP(uint8_t *buf, int32_t length) {
+    initializeGcrypt();
+    gcry_randomize(buf, length, GCRY_STRONG_RANDOM);
+}
+
+static const uint8_t P2048[] =
+{
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 
+    0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 
+    0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 
+    0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 
+    0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 
+    0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 
+    0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 
+    0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 
+    0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+    0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+    0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 
+    0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t P3072[] =
+    {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+	0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+	0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+	0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+	0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+	0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+	0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+	0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+	0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+	0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+	0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+	0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+	0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+	0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+	0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+	0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+	0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+	0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+	0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+	0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+	0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+	0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+	0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+	0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+	0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+	0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+	0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+	0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+	0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+	0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+	0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+    };
+
+    /* *************
+static const uint8_t P4096[] =
+{
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+	0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+	0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+	0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+	0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+	0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+	0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+	0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+	0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+	0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+	0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+	0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+	0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+	0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+	0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+	0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+	0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+	0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+	0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+	0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+	0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+	0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+	0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+	0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+	0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+	0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+	0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+	0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+	0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+	0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+	0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+	0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+	0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
+	0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+	0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
+	0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+	0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
+	0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+	0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
+	0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+	0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
+	0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+    *************** */
+#define DH3K 1
+#define DH2K 0
+ZrtpDH::ZrtpDH(const char* type){
+
+    // Well - the algo type is only 4 char thus cast to int32 and compare
+    if (*(int32_t*)type == *(int32_t*)dh2k) {
+        pkType = DH2K;
+    }
+    else if (*(int32_t*)type == *(int32_t*)dh3k) {
+        pkType = DH3K;
+    }
+    else {
+        fprintf(stderr, "Unknown pubkey algo: %d\n", pkType);
+    }
+    ctx = static_cast<void*>(new gcryptCtx);
+    gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+    tmpCtx->privKey = NULL;
+    tmpCtx->pubKey = NULL;
+
+    initializeGcrypt();
+
+    if (!dhinit) {
+	gcry_mpi_scan(&bnP2048, GCRYMPI_FMT_USG, P2048, sizeof(P2048), NULL);
+        gcry_mpi_scan(&bnP3072, GCRYMPI_FMT_USG, P3072, sizeof(P3072), NULL);
+//        gcry_mpi_scan(&bnP4096, GCRYMPI_FMT_USG, P4096, sizeof(P4096), NULL);
+        two = gcry_mpi_set_ui(NULL, 2);
+
+        bnP2048MinusOne = gcry_mpi_new(sizeof(P2048)*8);
+        gcry_mpi_sub_ui(bnP2048MinusOne, bnP2048, 1);
+
+        bnP3072MinusOne = gcry_mpi_new(sizeof(P3072)*8);
+        gcry_mpi_sub_ui(bnP3072MinusOne, bnP3072, 1);
+
+//        bnP4096MinusOne = gcry_mpi_new(sizeof(P4096)*8);
+//        gcry_mpi_sub_ui(bnP4096MinusOne, bnP4096, 1);
+        dhinit = 1;
+    }
+
+    if (pkType == DH3K) {
+        tmpCtx->privKey = gcry_mpi_new(256);
+        gcry_mpi_randomize(tmpCtx->privKey, 256, GCRY_STRONG_RANDOM);
+    }
+    else if (pkType == DH2K) {
+        tmpCtx->privKey = gcry_mpi_new(512);
+        gcry_mpi_randomize(tmpCtx->privKey, 512, GCRY_STRONG_RANDOM);
+    }
+//    else {
+//        tmpCtx->privKey = gcry_mpi_new(512);
+//        gcry_mpi_randomize(tmpCtx->privKey, 512, GCRY_STRONG_RANDOM);
+//    }
+}
+
+ZrtpDH::~ZrtpDH() {
+    gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+
+    if (tmpCtx != NULL) {
+        gcry_mpi_release(tmpCtx->privKey);
+        tmpCtx->privKey = NULL;
+        gcry_mpi_release(tmpCtx->pubKey);
+        tmpCtx->pubKey = NULL;
+        delete tmpCtx;
+        ctx = NULL;
+    }
+}
+
+int32_t ZrtpDH::computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret) {
+
+    int32_t length = getDhSize();
+    gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+
+    gcry_mpi_t pubKeyOther;
+    gcry_mpi_t sec = gcry_mpi_new(0);
+    gcry_mpi_scan(&pubKeyOther, GCRYMPI_FMT_USG, pubKeyBytes, length, NULL);
+
+    if (pkType == DH2K) {
+        gcry_mpi_powm(sec, pubKeyOther, tmpCtx->privKey, bnP2048);
+    }
+    else if (pkType == DH3K) {
+        gcry_mpi_powm(sec, pubKeyOther, tmpCtx->privKey, bnP3072);
+    }
+    else {
+//	gcry_mpi_powm(sec, pubKeyOther, tmpCtx->privKey, bnP4096);
+        return 0;
+    }
+    gcry_mpi_release(pubKeyOther);
+
+    size_t result;
+    gcry_mpi_print(GCRYMPI_FMT_USG, secret, length, &result, sec);
+    gcry_mpi_release(sec);
+
+    return result;
+}
+
+int32_t ZrtpDH::generatePublicKey()
+{
+    gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+
+    tmpCtx->pubKey = gcry_mpi_new(0);
+    if (pkType == DH2K) {
+        gcry_mpi_powm(tmpCtx->pubKey, two, tmpCtx->privKey, bnP2048);
+    }
+    else if (pkType == DH3K) {
+        gcry_mpi_powm(tmpCtx->pubKey, two, tmpCtx->privKey, bnP3072);
+    }
+    else {
+//	gcry_mpi_powm(tmpCtx->pubKey, two, tmpCtx->privKey, bnP4096);
+        return 0;
+    }
+    return 1;
+}
+
+int32_t ZrtpDH::getPubKeyBytes(uint8_t *buf) const
+{
+    gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+    int32_t len = getPubKeySize();
+
+    // get length of Dh in bytes, prepend buffer with zeros if necessary
+    int32_t prepend = getDhSize() - getPubKeySize();
+    if (prepend > 0) {
+        memset(buf, 0, prepend);
+    }
+    size_t i = 0;
+    gcry_mpi_print(GCRYMPI_FMT_USG, buf + prepend, len, &i, tmpCtx->pubKey);
+    return i;
+}
+
+int32_t ZrtpDH::getDhSize() const
+{
+    switch (pkType) {
+	case DH2K:
+	    return 2048/8;
+	    break;
+	case DH3K:
+	    return 3072/8;
+	    break;
+    }
+    return 0;
+}
+
+int32_t ZrtpDH::getPubKeySize() const
+{
+    return ((gcry_mpi_get_nbits(static_cast<gcryptCtx*>(ctx)->pubKey) + 7) / 8);
+}
+
+int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes) const
+{
+    gcry_mpi_t pubKeyOther = NULL;
+    gcry_mpi_scan(&pubKeyOther, GCRYMPI_FMT_USG, pubKeyBytes, getDhSize(), NULL);
+
+    if (pkType == DH2K) {
+        if (gcry_mpi_cmp(bnP2048MinusOne, pubKeyOther) == 0)
+            return 0;
+    }
+    else if (pkType == DH3K) {
+        if (gcry_mpi_cmp(bnP3072MinusOne, pubKeyOther) == 0)
+            return 0;
+    }
+    else {
+//        if (gcry_mpi_cmp(bnP4096MinusOne, pubKeyOther) == 0)
+            return 0;
+    }
+    if (gcry_mpi_cmp_ui(pubKeyOther, 1) == 0) {
+        return 0;
+    }
+
+    gcry_mpi_release(pubKeyOther);
+    return 1;
+}
+
+const char* ZrtpDH::getDHtype()
+{
+    switch (pkType) {
+	case DH2K:
+	    return dh2k;
+	    break;
+	case DH3K:
+	    return dh3k;
+	    break;
+    }
+    return NULL;
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp
new file mode 100644
index 0000000..3a44504
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/hmac256.h>
+
+void hmac_sha256(uint8_t* key, uint32_t keyLength,
+		uint8_t* data, int32_t dataLength,
+                uint8_t* mac, uint32_t* macLength)
+{
+    gcry_md_hd_t hd;
+    gcry_error_t err = 0;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+    gcry_md_setkey(hd, key, keyLength);
+
+    gcry_md_write (hd, data, dataLength);
+
+    uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+    memcpy(mac, p, SHA256_DIGEST_LENGTH);
+    if (macLength != NULL) {
+        *macLength = SHA256_DIGEST_LENGTH;
+    }
+    gcry_md_close (hd);
+}
+
+void hmac_sha256( uint8_t* key, uint32_t keyLength,
+                  uint8_t* dataChunks[],
+                  uint32_t dataChunkLength[],
+                  uint8_t* mac, uint32_t* macLength )
+{
+    gcry_md_hd_t hd;
+    gcry_error_t err = 0;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+    gcry_md_setkey(hd, key, keyLength);
+
+    while (*dataChunks) {
+        gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+	dataChunks++;
+	dataChunkLength++;
+    }
+    uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+    memcpy(mac, p, SHA256_DIGEST_LENGTH);
+    if (macLength != NULL) {
+        *macLength = SHA256_DIGEST_LENGTH;
+    }
+    gcry_md_close (hd);
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp
new file mode 100644
index 0000000..c48813c
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2006-2009 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/hmac384.h>
+
+void hmac_sha384(uint8_t* key, uint32_t keyLength,
+		uint8_t* data, int32_t dataLength,
+                uint8_t* mac, uint32_t* macLength)
+{
+    gcry_md_hd_t hd;
+    gcry_error_t err = 0;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC);
+    gcry_md_setkey(hd, key, keyLength);
+
+    gcry_md_write (hd, data, dataLength);
+
+    uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+    memcpy(mac, p, SHA384_DIGEST_LENGTH);
+    if (macLength != NULL) {
+        *macLength = SHA384_DIGEST_LENGTH;
+    }
+    gcry_md_close (hd);
+}
+
+void hmac_sha384( uint8_t* key, uint32_t keyLength,
+                  uint8_t* dataChunks[],
+                  uint32_t dataChunkLength[],
+                  uint8_t* mac, uint32_t* macLength )
+{
+    gcry_md_hd_t hd;
+    gcry_error_t err = 0;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC);
+    gcry_md_setkey(hd, key, keyLength);
+
+    while (*dataChunks) {
+        gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+	dataChunks++;
+	dataChunkLength++;
+    }
+    uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+    memcpy(mac, p, SHA384_DIGEST_LENGTH);
+    if (macLength != NULL) {
+        *macLength = SHA384_DIGEST_LENGTH;
+    }
+    gcry_md_close (hd);
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp
new file mode 100644
index 0000000..0c32bd8
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp
@@ -0,0 +1,89 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ *	    Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/sha256.h>
+
+void sha256(unsigned char* data, unsigned int dataLength,
+            unsigned char* mac)
+{
+    gcry_md_hash_buffer(GCRY_MD_SHA256, mac, data, dataLength);
+}
+
+void sha256(unsigned char* dataChunks[],
+            unsigned int dataChunkLength[],
+            unsigned char* mac)
+{
+    gcry_md_hd_t hd;
+    gcry_error_t err = 0;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA256, 0);
+    while (*dataChunks) {
+        gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+        dataChunks++;
+        dataChunkLength++;
+    }
+    uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+    memcpy(mac, p, SHA256_DIGEST_LENGTH);
+    gcry_md_close (hd);
+}
+
+void* createSha256Context()
+{
+    gcry_error_t err = 0;
+    gcry_md_hd_t hd;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA256, 0);
+    return (void*)hd;
+}
+
+void closeSha256Context(void* ctx, unsigned char* digest)
+{
+    gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+    if (digest != NULL) {
+        uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+        memcpy(digest, p, SHA256_DIGEST_LENGTH);
+    }
+    gcry_md_close (hd);
+}
+
+void sha256Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength)
+{
+    gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+    gcry_md_write (hd, data, dataLength);
+}
+
+void sha256Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[])
+{
+    gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+    while (*dataChunks) {
+        gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+        dataChunks++;
+        dataChunkLength++;
+    }
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp
new file mode 100644
index 0000000..19c8c5b
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp
@@ -0,0 +1,89 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ *	    Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/sha384.h>
+
+void sha384(unsigned char* data, unsigned int dataLength,
+            unsigned char* mac)
+{
+    gcry_md_hash_buffer(GCRY_MD_SHA384, mac, data, dataLength);
+}
+
+void sha384(unsigned char* dataChunks[],
+            unsigned int dataChunkLength[],
+            unsigned char* mac)
+{
+    gcry_md_hd_t hd;
+    gcry_error_t err = 0;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA384, 0);
+    while (*dataChunks) {
+        gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+        dataChunks++;
+        dataChunkLength++;
+    }
+    uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+    memcpy(mac, p, SHA384_DIGEST_LENGTH);
+    gcry_md_close (hd);
+}
+
+void* createSha384Context()
+{
+    gcry_error_t err = 0;
+    gcry_md_hd_t hd;
+
+    err = gcry_md_open(&hd, GCRY_MD_SHA384, 0);
+    return (void*)hd;
+}
+
+void closeSha384Context(void* ctx, unsigned char* digest)
+{
+    gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+    if (digest != NULL) {
+        uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+        memcpy(digest, p, SHA384_DIGEST_LENGTH);
+    }
+    gcry_md_close (hd);
+}
+
+void sha384Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength)
+{
+    gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+    gcry_md_write (hd, data, dataLength);
+}
+
+void sha384Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[])
+{
+    gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+    while (*dataChunks) {
+        gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+        dataChunks++;
+        dataChunkLength++;
+    }
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/hmac256.h b/jni/libzrtp/src/libzrtpcpp/crypto/hmac256.h
new file mode 100644
index 0000000..f9110a6
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/hmac256.h
@@ -0,0 +1,96 @@
+/*
+  Copyright (C) 2006, 2005, 2004 Erik Eliasson, Johan Bilien, Werner Dittmann
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+ * Methods to compute a SHA256 HMAC.
+ *
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * @author Johan Bilien <jobi@via.ecp.fr>
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef HMAC_SHA256_H
+#define HMAC_SHA256_H
+
+/**
+ * @file hmac256.h
+ * @brief Function that provide SHA256 HMAC support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
+/**
+ * Compute SHA256 HMAC.
+ *
+ * This functions takes one data chunk and computes its SHA256 HMAC.
+ *
+ * @param key
+ *    The MAC key.
+ * @param key_length
+ *    Lneght of the MAC key in bytes
+ * @param data
+ *    Points to the data chunk.
+ * @param data_length
+ *    Length of the data in bytes
+ * @param mac
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+void hmac_sha256( uint8_t* key, uint32_t key_length,
+    uint8_t* data, int32_t data_length,
+    uint8_t* mac, uint32_t* mac_length );
+
+/**
+ * Compute SHA256 HMAC over several data cunks.
+ *
+ * This functions takes several data chunk and computes the SHA256 HAMAC. It
+ * uses the openSSL HAMAC SHA256 implementation.
+ *
+ * @param key
+ *    The MAC key.
+ * @param key_length
+ *    Lneght of the MAC key in bytes
+ * @param data
+ *    Points to an array of pointers that point to the data chunks. A NULL
+ *    pointer in an array element terminates the data chunks.
+ * @param data_length
+ *    Points to an array of integers that hold the length of each data chunk.
+ * @param mac
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+
+void hmac_sha256( uint8_t* key, uint32_t key_length,
+                           uint8_t* data[], uint32_t data_length[],
+                           uint8_t* mac, uint32_t* mac_length );
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/hmac384.h b/jni/libzrtp/src/libzrtpcpp/crypto/hmac384.h
new file mode 100644
index 0000000..223444a
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/hmac384.h
@@ -0,0 +1,96 @@
+/*
+  Copyright (C) 2009, 2006, 2005, 2004 Erik Eliasson, Johan Bilien, Werner Dittmann
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+ * Methods to compute a SHA384 HMAC.
+ *
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * @author Johan Bilien <jobi@via.ecp.fr>
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef HMAC_SHA384_H
+#define HMAC_SHA384_H
+
+/**
+ * @file hmac384.h
+ * @brief Function that provide SHA384 HMAC support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA384_DIGEST_LENGTH
+#define SHA384_DIGEST_LENGTH 48
+#endif
+
+/**
+ * Compute SHA384 HMAC.
+ *
+ * This functions takes one data chunk and computes its SHA384 HMAC.
+ *
+ * @param key
+ *    The MAC key.
+ * @param key_length
+ *    Lneght of the MAC key in bytes
+ * @param data
+ *    Points to the data chunk.
+ * @param data_length
+ *    Length of the data in bytes
+ * @param mac
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+void hmac_sha384( uint8_t* key, uint32_t key_length,
+    uint8_t* data, int32_t data_length,
+    uint8_t* mac, uint32_t* mac_length );
+
+/**
+ * Compute SHA384 HMAC over several data cunks.
+ *
+ * This functions takes several data chunk and computes the SHA384 HAMAC. It
+ * uses the openSSL HAMAC SHA384 implementation.
+ *
+ * @param key
+ *    The MAC key.
+ * @param key_length
+ *    Lneght of the MAC key in bytes
+ * @param data
+ *    Points to an array of pointers that point to the data chunks. A NULL
+ *    pointer in an array element terminates the data chunks.
+ * @param data_length
+ *    Points to an array of integers that hold the length of each data chunk.
+ * @param mac
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+
+void hmac_sha384( uint8_t* key, uint32_t key_length,
+                           uint8_t* data[], uint32_t data_length[],
+                           uint8_t* mac, uint32_t* mac_length );
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/openssl/AesCFB.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/AesCFB.cpp
new file mode 100644
index 0000000..595d1ff
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/AesCFB.cpp
@@ -0,0 +1,89 @@
+/*
+  Copyright (C) 2006, 2007 by Werner Dittmann
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/** Copyright (C) 2006, 2007
+ *
+ * @author  Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/aes.h>
+#include <string.h>
+
+#include <libzrtpcpp/crypto/aesCFB.h>
+
+// extern void initializeOpenSSL();
+
+
+void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+                   int32_t dataLength)
+{
+    AES_KEY aesKey;
+    int usedBytes = 0;
+
+//    initializeOpenSSL();
+
+    memset(&aesKey, 0, sizeof( AES_KEY ) );
+    if (keyLength == 16) {
+        AES_set_encrypt_key(key, 128, &aesKey);
+    }
+    else if (keyLength == 32) {
+        AES_set_encrypt_key(key, 256, &aesKey);
+    }
+    else {
+        return;
+    }
+    AES_cfb128_encrypt(data, data, dataLength, &aesKey,
+                       IV, &usedBytes, AES_ENCRYPT);
+}
+
+
+void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+                   int32_t dataLength)
+{
+    AES_KEY aesKey;
+    int usedBytes = 0;
+
+//    initializeOpenSSL();
+
+    memset(&aesKey, 0, sizeof( AES_KEY ) );
+    if (keyLength == 16) {
+        AES_set_encrypt_key(key, 128, &aesKey);
+    }
+    else if (keyLength == 32) {
+        AES_set_encrypt_key(key, 256, &aesKey);
+    }
+    else {
+        return;
+    }
+    AES_cfb128_encrypt(data, data, dataLength, &aesKey,
+                       (unsigned char*)IV, &usedBytes, AES_DECRYPT);
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp
new file mode 100755
index 0000000..17961c3
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp
@@ -0,0 +1,242 @@
+/*
+  Copyright (C) 2006 Werner Dittmann
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2, or (at your option)
+  any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Boston, MA 02111.
+*/
+
+#include <stdio.h>
+#include <openssl/evp.h>
+#include <libzrtpcpp-config.h>
+
+#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
+#undef  _MSWINDOWS_
+#define _MSWINDOWS_
+#include <windows.h>
+#endif
+
+#if defined SOLARIS && !defined HAVE_PTHREAD_H
+#include <synch.h>
+#include <thread.h>
+#endif
+#if !defined(_MSWINDOWS_) && !defined SOLARIS
+#include <pthread.h>
+#endif
+
+#ifdef  const
+#undef  const
+#endif
+
+static void threadLockSetup(void);
+static void threadLockCleanup(void);
+static void myLockingCallback(int, int, const char *, int);
+
+/**
+ * Implement the locking callback functions for openSSL.
+ *
+ * Unfortunatly we can't use the Commonc++ Mutex here because the
+ * Mutex may use (for some cases) the Commonc++ Thread class. OpenSSL
+ * does not use this Thread class.
+ */
+
+static int initialized = 0;
+
+int initializeOpenSSL ()
+{
+
+    if (initialized) {
+    return 1;
+    }
+    initialized = 1;
+    threadLockSetup();
+    return 1;
+}
+
+int finalizeOpenSSL ()
+{
+    if(!initialized)
+        return 1;
+
+    initialized = 0;
+    threadLockCleanup();
+    return 1;
+}
+
+#ifdef _MSWINDOWS_
+#define __LOCKING
+
+static HANDLE *lock_cs;
+
+static void threadLockSetup(void) {
+    int i;
+
+    lock_cs=(HANDLE*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
+    for (i = 0; i < CRYPTO_num_locks(); i++) {
+    lock_cs[i] = CreateMutex(NULL,FALSE,NULL);
+    }
+
+    CRYPTO_set_locking_callback((void (*)(int,int,const char *,int))myLockingCallback);
+    /* id callback defined */
+}
+
+static void threadLockCleanup(void) {
+    int i;
+
+    CRYPTO_set_locking_callback(NULL);
+    for (i = 0; i < CRYPTO_num_locks(); i++) {
+    CloseHandle(lock_cs[i]);
+    }
+    OPENSSL_free(lock_cs);
+}
+
+static void myLockingCallback(int mode, int type, const char *file, int line) {
+    if (mode & CRYPTO_LOCK) {
+    WaitForSingleObject(lock_cs[type], INFINITE);
+    }
+    else {
+    ReleaseMutex(lock_cs[type]);
+    }
+}
+
+#endif /* OPENSSL_SYS_WIN32 */
+
+
+#if defined SOLARIS && !defined HAVE_PTHREAD_H && !defined(_MSWINDOWS)
+#define __LOCKING
+
+static mutex_t *lock_cs;
+static long *lock_count;
+
+static void threadLockSetup(void) {
+    int i;
+
+    lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t));
+    lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
+    for (i = 0; i < CRYPTO_num_locks(); i++) {
+    lock_count[i] = 0;
+    /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
+    mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL);
+    }
+    CRYPTO_set_locking_callback((void (*)(int, int ,const char *, int))myLockingCallback);
+}
+
+static void threadLockCleanup(void) {
+    int i;
+
+    CRYPTO_set_locking_callback(NULL);
+
+    fprintf(stderr,"cleanup\n");
+
+    for (i = 0; i < CRYPTO_num_locks(); i++) {
+    /* rwlock_destroy(&(lock_cs[i])); */
+    mutex_destroy(&(lock_cs[i]));
+    fprintf(stderr,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
+    }
+    OPENSSL_free(lock_cs);
+    OPENSSL_free(lock_count);
+}
+
+static void myLockingCallback(int mode, int type, const char *file, int line)
+{
+#ifdef undef
+    fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
+        CRYPTO_thread_id(),
+        (mode&CRYPTO_LOCK)?"l":"u",
+        (type&CRYPTO_READ)?"r":"w",file,line);
+#endif
+
+    /*
+      if (CRYPTO_LOCK_SSL_CERT == type)
+      fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
+      CRYPTO_thread_id(),
+      mode,file,line);
+    */
+    if (mode & CRYPTO_LOCK) {
+    mutex_lock(&(lock_cs[type]));
+    lock_count[type]++;
+    }
+    else {
+    mutex_unlock(&(lock_cs[type]));
+    }
+}
+
+static unsigned long solaris_thread_id(void) {
+    unsigned long ret;
+
+    ret=(unsigned long)thr_self();
+    return(ret);
+}
+#endif /* SOLARIS */
+
+
+#ifndef __LOCKING
+static pthread_mutex_t* lock_cs;
+static long* lock_count;
+
+static void threadLockSetup(void) {
+    int i;
+
+    lock_cs = (pthread_mutex_t*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+    lock_count = (long*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
+    for (i = 0; i < CRYPTO_num_locks(); i++) {
+    lock_count[i] = 0;
+    pthread_mutex_init(&(lock_cs[i]),NULL);
+    }
+
+    // CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
+    CRYPTO_set_locking_callback((void (*)(int,int,const char *, int))myLockingCallback);
+}
+
+static void threadLockCleanup(void)
+{
+    int i;
+
+    CRYPTO_set_locking_callback(NULL);
+    fprintf(stderr,"cleanup\n");
+    for (i = 0; i < CRYPTO_num_locks(); i++) {
+    pthread_mutex_destroy(&(lock_cs[i]));
+    fprintf(stderr,"%8ld:%s\n",lock_count[i],
+        CRYPTO_get_lock_name(i));
+    }
+    OPENSSL_free(lock_cs);
+    OPENSSL_free(lock_count);
+}
+
+static void myLockingCallback(int mode, int type, const char *file,
+                  int line) {
+#ifdef undef
+    fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
+        CRYPTO_thread_id(),
+        (mode&CRYPTO_LOCK)?"l":"u",
+        (type&CRYPTO_READ)?"r":"w",file,line);
+#endif
+    if (mode & CRYPTO_LOCK) {
+    pthread_mutex_lock(&(lock_cs[type]));
+    lock_count[type]++;
+    }
+    else {
+    pthread_mutex_unlock(&(lock_cs[type]));
+    }
+}
+
+/*
+static unsigned long pthreads_thread_id(void)
+{
+    unsigned long ret;
+
+    ret = (unsigned long)pthread_self();
+    return(ret);
+}
+*/
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp
new file mode 100644
index 0000000..fbd623c
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp
@@ -0,0 +1,426 @@
+/*
+  Copyright (C) 2006, 2009 by Werner Dittmann
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/** Copyright (C) 2006, 2009
+ *
+ * @author  Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+
+#include <libzrtpcpp/crypto/ZrtpDH.h>
+#include <libzrtpcpp/ZrtpTextData.h>
+
+// extern void initializeOpenSSL();
+
+static BIGNUM* bnP2048 = NULL;
+static BIGNUM* bnP3072 = NULL;
+// static BIGNUM* bnP4096 = NULL;
+
+static BIGNUM* bnP2048MinusOne = NULL;
+static BIGNUM* bnP3072MinusOne = NULL;
+// static BIGNUM* bnP4096MinusOne = NULL;
+
+static uint8_t dhinit = 0;
+
+void randomZRTP(uint8_t *buf, int32_t length)
+{
+//    initializeOpenSSL();
+    RAND_bytes(buf, length);
+}
+
+static const uint8_t P2048[] =
+{
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+    0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+    0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+    0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+    0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+    0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+    0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+    0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+    0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+    0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+    0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t P3072[] =
+{
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+    0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+    0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+    0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+    0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+    0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+    0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+    0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+    0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+    0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+    0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+    0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+    0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+    0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+    0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+    0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+    0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* **************
+static const uint8_t P4096[] =
+{
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
+0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
+0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
+0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
+0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
+0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+*************** */
+
+ZrtpDH::ZrtpDH(const char* type) {
+
+    uint8_t random[64];
+
+    // Well - the algo type is only 4 char thus cast to int32 and compare
+    if (*(int32_t*)type == *(int32_t*)dh2k) {
+        pkType = DH2K;
+    }
+    else if (*(int32_t*)type == *(int32_t*)dh3k) {
+        pkType = DH3K;
+    }
+    else if (*(int32_t*)type == *(int32_t*)ec25) {
+        pkType = EC25;
+    }
+    else if (*(int32_t*)type == *(int32_t*)ec38) {
+        pkType = EC38;
+    }
+    else {
+        return;
+    }
+
+//  initializeOpenSSL();
+
+    if (!dhinit) {
+        bnP2048 = BN_bin2bn(P2048,sizeof(P2048),NULL);
+        bnP3072 = BN_bin2bn(P3072,sizeof(P3072),NULL);
+//      bnP4096 = BN_bin2bn(P4096,sizeof(P4096),NULL);
+
+        bnP2048MinusOne = BN_dup(bnP2048);
+        BN_sub_word(bnP2048MinusOne, 1);
+
+        bnP3072MinusOne = BN_dup(bnP3072);
+        BN_sub_word(bnP3072MinusOne, 1);
+
+//      bnP4096MinusOne = BN_dup(bnP4096);
+//      BN_sub_word(bnP4096MinusOne, 1);
+        dhinit = 1;
+    }
+
+    DH* tmpCtx = NULL;
+    switch (pkType) {
+    case DH2K:
+    case DH3K:
+        ctx = static_cast<void*>(DH_new());
+        tmpCtx = static_cast<DH*>(ctx);
+        tmpCtx->g = BN_new();
+        BN_set_word(tmpCtx->g, DH_GENERATOR_2);
+
+        if (pkType == DH2K) {
+            tmpCtx->p = BN_dup(bnP2048);
+            RAND_bytes(random, 32);
+            tmpCtx->priv_key = BN_bin2bn(random, 32, NULL);
+        }
+        else if (pkType == DH3K) {
+            tmpCtx->p = BN_dup(bnP3072);
+            RAND_bytes(random, 64);
+            tmpCtx->priv_key = BN_bin2bn(random, 32, NULL);
+        }
+        break;
+
+    case EC25:
+        ctx = static_cast<void*>(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+        break;
+    case EC38:
+        ctx = static_cast<void*>(EC_KEY_new_by_curve_name(NID_secp384r1));
+        break;
+    }
+}
+
+ZrtpDH::~ZrtpDH() {
+    if (ctx == NULL)
+        return;
+
+    switch (pkType) {
+    case DH2K:
+    case DH3K:
+        DH_free(static_cast<DH*>(ctx));
+        break;
+
+    case EC25:
+    case EC38:
+        EC_KEY_free(static_cast<EC_KEY*>(ctx));
+        break;
+    }
+}
+
+int32_t ZrtpDH::computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret) {
+
+    if (pkType == DH2K || pkType == DH3K) {
+        DH* tmpCtx = static_cast<DH*>(ctx);
+
+        if (tmpCtx->pub_key != NULL) {
+            BN_free(tmpCtx->pub_key);
+        }
+        tmpCtx->pub_key = BN_bin2bn(pubKeyBytes, getDhSize(), NULL);
+        return DH_compute_key(secret, tmpCtx->pub_key, tmpCtx);
+    }
+    if (pkType == EC25 || pkType == EC38) {
+        uint8_t buffer[100];
+        int32_t ret;
+        int32_t len = getPubKeySize();
+
+        buffer[0] = POINT_CONVERSION_UNCOMPRESSED;
+        memcpy(buffer+1, pubKeyBytes, len);
+        
+        EC_POINT* point = EC_POINT_new(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)));
+        EC_POINT_oct2point(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+                                             point, buffer, len+1, NULL);
+        ret = ECDH_compute_key(secret, getDhSize(), point, static_cast<EC_KEY*>(ctx), NULL);
+        EC_POINT_free(point);
+        return ret;
+    }
+    return -1;
+}
+
+int32_t ZrtpDH::generatePublicKey()
+{
+    if (pkType == DH2K || pkType == DH3K)
+        return DH_generate_key(static_cast<DH*>(ctx));
+
+    if (pkType == EC25 || pkType == EC38)
+        return EC_KEY_generate_key(static_cast<EC_KEY*>(ctx));
+    return 0;
+}
+
+int32_t ZrtpDH::getDhSize() const
+{
+    if (pkType == DH2K || pkType == DH3K)
+        return DH_size(static_cast<DH*>(ctx));
+
+    if (pkType == EC25)
+        return 32;
+    if (pkType == EC38)
+        return 48;
+
+    return 0;
+}
+
+int32_t ZrtpDH::getPubKeySize() const
+{
+    if (pkType == DH2K || pkType == DH3K)
+        return BN_num_bytes(static_cast<DH*>(ctx)->pub_key);
+
+    if (pkType == EC25 || pkType == EC38)
+        return EC_POINT_point2oct(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+                                  EC_KEY_get0_public_key(static_cast<EC_KEY*>(ctx)),
+                                  POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL) - 1;
+    return 0;
+
+}
+
+int32_t ZrtpDH::getPubKeyBytes(uint8_t *buf) const
+{
+
+    if (pkType == DH2K || pkType == DH3K) {
+        // get len of pub_key, prepend with zeros to DH size
+        int32_t prepend = getDhSize() - getPubKeySize();
+        if (prepend > 0) {
+            memset(buf, 0, prepend);
+        }
+        return BN_bn2bin(static_cast<DH*>(ctx)->pub_key, buf + prepend);
+    }
+    if (pkType == EC25 || pkType == EC38) {
+        uint8_t buffer[100];
+
+        int len = EC_POINT_point2oct(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+                                     EC_KEY_get0_public_key(static_cast<EC_KEY*>(ctx)),
+                                     POINT_CONVERSION_UNCOMPRESSED, buffer, 100, NULL);
+        memcpy(buf, buffer+1, len-1);
+        return len-1;
+    }
+    return 0;
+}
+
+int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes) const
+{
+    if (pkType == EC25 || pkType == EC38) {
+        uint8_t buffer[100];
+        int32_t ret;
+        int32_t len = getPubKeySize();
+
+        buffer[0] = POINT_CONVERSION_UNCOMPRESSED;
+        memcpy(buffer+1, pubKeyBytes, len);
+
+        EC_POINT* point = EC_POINT_new(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)));
+        EC_POINT_oct2point(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+                                             point, buffer, len+1, NULL);
+        EC_KEY* chkKey = EC_KEY_new();
+        EC_KEY_set_group(chkKey, EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)));
+        EC_KEY_set_public_key(chkKey, point);
+        ret = EC_KEY_check_key(chkKey);
+
+        EC_POINT_free(point);
+        EC_KEY_free(chkKey);
+        
+        return ret;
+    }
+
+    BIGNUM* pubKeyOther = BN_bin2bn(pubKeyBytes, getDhSize(), NULL);
+
+    if (pkType == DH2K) {
+        if (BN_cmp(bnP2048MinusOne, pubKeyOther) == 0)
+            return 0;
+    }
+    else if (pkType == DH3K) {
+        if (BN_cmp(bnP3072MinusOne, pubKeyOther) == 0)
+            return 0;
+    }
+    else {
+//        if (BN_cmp(bnP4096MinusOne, pubKeyOther) == 0)
+        return 0;
+    }
+    int one = BN_is_one(pubKeyOther);
+    if (one == 1)
+        return 0;
+
+    BN_free(pubKeyOther);
+    return 1;
+}
+
+const char* ZrtpDH::getDHtype()
+{
+    switch (pkType) {
+    case DH2K:
+        return dh2k;
+        break;
+    case DH3K:
+        return dh3k;
+        break;
+    case EC25:
+        return ec25;
+        break;
+    case EC38:
+        return ec38;
+        break;
+    }
+    return NULL;
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/openssl/hmac256.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/hmac256.cpp
new file mode 100644
index 0000000..a054c02
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/hmac256.cpp
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <openssl/hmac.h>
+#include <libzrtpcpp/crypto/hmac256.h>
+
+void hmac_sha256(uint8_t* key, uint32_t key_length,
+		uint8_t* data, int32_t data_length,
+                uint8_t* mac, uint32_t* mac_length)
+{
+    unsigned int tmp;
+    HMAC( EVP_sha256(), key, key_length, data, data_length, mac, &tmp );
+    *mac_length = tmp;
+}
+
+void hmac_sha256(uint8_t* key, uint32_t key_length,
+                 uint8_t* data_chunks[],
+                 uint32_t data_chunck_length[],
+                 uint8_t* mac, uint32_t* mac_length )
+{
+    unsigned int tmp;
+    HMAC_CTX ctx;
+    HMAC_CTX_init( &ctx );
+    HMAC_Init_ex( &ctx, key, key_length, EVP_sha256(), NULL );
+    while( *data_chunks ){
+      HMAC_Update( &ctx, *data_chunks, *data_chunck_length );
+      data_chunks ++;
+      data_chunck_length ++;
+    }
+    HMAC_Final( &ctx, mac, &tmp);
+    *mac_length = tmp;
+    HMAC_CTX_cleanup( &ctx );
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/openssl/hmac384.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/hmac384.cpp
new file mode 100644
index 0000000..10d6fbc
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/hmac384.cpp
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <openssl/hmac.h>
+#include <libzrtpcpp/crypto/hmac256.h>
+
+void hmac_sha384(uint8_t* key, uint32_t key_length,
+		uint8_t* data, int32_t data_length,
+                uint8_t* mac, uint32_t* mac_length)
+{
+    unsigned int tmp;
+    HMAC( EVP_sha384(), key, key_length, data, data_length, mac, &tmp );
+    *mac_length = tmp;
+}
+
+void hmac_sha384(uint8_t* key, uint32_t key_length,
+                 uint8_t* data_chunks[],
+                 uint32_t data_chunck_length[],
+                 uint8_t* mac, uint32_t* mac_length )
+{
+    unsigned int tmp;
+    HMAC_CTX ctx;
+    HMAC_CTX_init( &ctx );
+    HMAC_Init_ex( &ctx, key, key_length, EVP_sha384(), NULL );
+    while( *data_chunks ){
+      HMAC_Update( &ctx, *data_chunks, *data_chunck_length );
+      data_chunks ++;
+      data_chunck_length ++;
+    }
+    HMAC_Final( &ctx, mac, &tmp);
+    *mac_length = tmp;
+    HMAC_CTX_cleanup( &ctx );
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/openssl/sha256.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/sha256.cpp
new file mode 100644
index 0000000..2163a6d
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/sha256.cpp
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ *	    Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/sha.h>
+
+#include <libzrtpcpp/crypto/sha256.h>
+
+void sha256(unsigned char *data, unsigned int data_length,
+	    unsigned char *digest )
+{
+	SHA256(data, data_length, digest);
+}
+
+void sha256(unsigned char * data_chunks[],
+	    unsigned int data_chunck_length[],
+	    unsigned char *digest)
+{
+	SHA256_CTX ctx;
+	SHA256_Init( &ctx);
+	while(*data_chunks) {
+		SHA256_Update(&ctx, *data_chunks, *data_chunck_length);
+		data_chunks++;
+		data_chunck_length++;
+	}
+	SHA256_Final(digest, &ctx);
+}
+
+void* createSha256Context()
+{
+    SHA256_CTX* ctx = (SHA256_CTX*)malloc(sizeof (SHA256_CTX));
+    SHA256_Init(ctx);
+    return (void*)ctx;
+}
+
+void closeSha256Context(void* ctx, unsigned char* digest)
+{
+    SHA256_CTX* hd = (SHA256_CTX*)ctx;
+
+    if (digest != NULL) {
+        SHA256_Final(digest, hd);
+    }
+    free(hd);
+}
+
+void sha256Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength)
+{
+    SHA256_CTX* hd = (SHA256_CTX*)ctx;
+    SHA256_Update(hd, data, dataLength);
+}
+
+void sha256Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[])
+{
+    SHA256_CTX* hd = (SHA256_CTX*)ctx;
+
+    while (*dataChunks) {
+        SHA256_Update (hd, *dataChunks, *dataChunkLength);
+        dataChunks++;
+        dataChunkLength++;
+    }
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/openssl/sha384.cpp b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/sha384.cpp
new file mode 100644
index 0000000..9d166e7
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/openssl/sha384.cpp
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ *          Johan Bilien <jobi@via.ecp.fr>
+ *	    Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/sha.h>
+
+#include <libzrtpcpp/crypto/sha384.h>
+
+void sha384(unsigned char *data, unsigned int data_length,
+	    unsigned char *digest )
+{
+	SHA384(data, data_length, digest);
+}
+
+void sha384(unsigned char * data_chunks[],
+	    unsigned int data_chunck_length[],
+	    unsigned char *digest)
+{
+	SHA512_CTX ctx;
+	SHA384_Init( &ctx);
+	while(*data_chunks) {
+		SHA384_Update(&ctx, *data_chunks, *data_chunck_length);
+		data_chunks++;
+		data_chunck_length++;
+	}
+	SHA384_Final(digest, &ctx);
+}
+
+void* createSha384Context()
+{
+    SHA512_CTX* ctx = (SHA512_CTX*)malloc(sizeof (SHA512_CTX));
+    SHA384_Init(ctx);
+    return (void*)ctx;
+}
+
+void closeSha384Context(void* ctx, unsigned char* digest)
+{
+    SHA512_CTX* hd = (SHA512_CTX*)ctx;
+
+    if (digest != NULL) {
+        SHA384_Final(digest, hd);
+    }
+    free(hd);
+}
+
+void sha384Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength)
+{
+    SHA512_CTX* hd = (SHA512_CTX*)ctx;
+    SHA384_Update(hd, data, dataLength);
+}
+
+void sha384Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[])
+{
+    SHA512_CTX* hd = (SHA512_CTX*)ctx;
+
+    while (*dataChunks) {
+        SHA384_Update (hd, *dataChunks, *dataChunkLength);
+        dataChunks++;
+        dataChunkLength++;
+    }
+}
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/sha256.h b/jni/libzrtp/src/libzrtpcpp/crypto/sha256.h
new file mode 100644
index 0000000..959a620
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/sha256.h
@@ -0,0 +1,144 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Functions to compute SHA256 digest.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _SHA256_H
+#define _SHA256_H
+
+/**
+ * @file sha256.h
+ * @brief Function that provide SHA256 support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
+/**
+ * Compute SHA256 digest.
+ *
+ * This functions takes one data chunk and computes its SHA256 digest. This 
+ * function creates and deletes an own SHA256 context to perform the SHA256
+ * operations.
+ *
+ * @param data
+ *    Points to the data chunk.
+ * @param data_length
+ *    Length of the data in bytes
+ * @param digest
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ */
+void sha256(unsigned char *data,
+            unsigned int data_length,
+            unsigned char *digest);
+
+/**
+ * Compute SHA256 digest over several data cunks.
+ *
+ * This functions takes several data chunks and computes the SHA256 digest.
+ * This function creates and deletes an own SHA256 context to perform the
+ * SHA256 operations.
+ *
+ * @param data
+ *    Points to an array of pointers that point to the data chunks. A NULL
+ *    pointer in an array element terminates the data chunks.
+ * @param data_length
+ *    Points to an array of integers that hold the length of each data chunk.
+ * @param digest
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ */
+void sha256(unsigned char *data[],
+            unsigned int data_length[],
+            unsigned char *digest);
+/**
+ * Create and initialize a SHA256 context.
+ *
+ * An application uses this context to hash several data into one SHA256
+ * digest. See also sha256Ctx(...) and closeSha256Context(...).
+ *
+ * @return Returns a pointer to the initialized SHA256 context
+ */
+void* createSha256Context();
+
+/**
+ * Compute a digest and close the SHa256 digest.
+ *
+ * An application uses this function to compute the SHA256 digest and to
+ * close the SHA256 context.
+ *
+ * @param ctx
+ *    Points to the SHA256 context.
+ * @param digest
+ *    If this pointer is not NULL then it must point to a byte array that
+ *    is big enough to hold the SHA256 digest (256 bit = 32 Bytes). If this
+ *    pointer is NULL then the functions does not compute the digest but
+ *    closes the context only. The context cannot be used anymore.
+ */
+void closeSha256Context(void* ctx,
+                        unsigned char* digest);
+
+/**
+ * Update the SHA256 context with data.
+ *
+ * This functions updates the SHA256 context with some data.
+ * See also CloseSha256Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the SHA256 context.
+ * @param data
+ *    Points to the data to update the context.
+ * @param dataLength
+ *    The length of the data in bytes.
+ */
+void sha256Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength);
+
+/**
+ * Update the SHA256 context with several data chunks.
+ *
+ * This functions updates the SHA256 context with some data.
+ * See also CloseSha256Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the SHA256 context.
+ * @param dataChunks
+ *    Points to an array of pointers that point to the data chunks. A NULL
+ *    pointer in an array element terminates the data chunks.
+ * @param dataChunkLength
+ *    Points to an array of integers that hold the length of each data chunk.
+ *
+ */
+void sha256Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[]);
+
+/**
+ * @}
+ */
+#endif
+
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/sha384.h b/jni/libzrtp/src/libzrtpcpp/crypto/sha384.h
new file mode 100644
index 0000000..6cb7a70
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/sha384.h
@@ -0,0 +1,144 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Functions to compute SHA384 digest.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _SHA384_H
+#define _SHA384_H
+
+/**
+ * @file sha384.h
+ * @brief Function that provide SHA384 support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA384_DIGEST_LENGTH
+#define SHA384_DIGEST_LENGTH 48
+#endif
+
+/**
+ * Compute SHA384 digest.
+ *
+ * This functions takes one data chunk and computes its SHA384 digest. This 
+ * function creates and deletes an own SHA384 context to perform the SHA384
+ * operations.
+ *
+ * @param data
+ *    Points to the data chunk.
+ * @param data_length
+ *    Length of the data in bytes
+ * @param digest
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ */
+void sha384(unsigned char *data,
+            unsigned int data_length,
+            unsigned char *digest);
+
+/**
+ * Compute SHA384 digest over several data cunks.
+ *
+ * This functions takes several data chunks and computes the SHA384 digest.
+ * This function creates and deletes an own SHA384 context to perform the
+ * SHA384 operations.
+ *
+ * @param data
+ *    Points to an array of pointers that point to the data chunks. A NULL
+ *    pointer in an array element terminates the data chunks.
+ * @param data_length
+ *    Points to an array of integers that hold the length of each data chunk.
+ * @param digest
+ *    Points to a buffer that receives the computed digest. This
+ *    buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ */
+void sha384(unsigned char *data[],
+            unsigned int data_length[],
+            unsigned char *digest);
+/**
+ * Create and initialize a SHA384 context.
+ *
+ * An application uses this context to hash several data into one SHA384
+ * digest. See also sha384Ctx(...) and closeSha384Context(...).
+ *
+ * @return Returns a pointer to the initialized SHA384 context
+ */
+void* createSha384Context();
+
+/**
+ * Compute a digest and close the SHA384 digest.
+ *
+ * An application uses this function to compute the SHA384 digest and to
+ * close the SHA384 context.
+ *
+ * @param ctx
+ *    Points to the SHA384 context.
+ * @param digest
+ *    If this pointer is not NULL then it must point to a byte array that
+ *    is big enough to hold the SHA384 digest (384 bit = 48 Bytes). If this
+ *    pointer is NULL then the functions does not compute the digest but
+ *    closes the context only. The context cannot be used anymore.
+ */
+void closeSha384Context(void* ctx,
+                        unsigned char* digest);
+
+/**
+ * Update the SHA384 context with data.
+ *
+ * This functions updates the SHA384 context with some data.
+ * See also CloseSha384Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the SHA384 context.
+ * @param data
+ *    Points to the data to update the context.
+ * @param dataLength
+ *    The length of the data in bytes.
+ */
+void sha384Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength);
+
+/**
+ * Update the SHA384 context with several data chunks.
+ *
+ * This functions updates the SHA384 context with some data.
+ * See also CloseSha384Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the SHA384 context.
+ * @param dataChunks
+ *    Points to an array of pointers that point to the data chunks. A NULL
+ *    pointer in an array element terminates the data chunks.
+ * @param dataChunkLength
+ *    Points to an array of integers that hold the length of each data chunk.
+ *
+ */
+void sha384Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[]);
+
+/**
+ * @}
+ */
+#endif
+
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/twoCFB.h b/jni/libzrtp/src/libzrtpcpp/crypto/twoCFB.h
new file mode 100755
index 0000000..593a59c
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/twoCFB.h
@@ -0,0 +1,87 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _TWOCFB_H__
+#define _TWOCFB_H__
+
+#include <stdint.h>
+
+/**
+ * @file aesCFB.h
+ * @brief Function that provide AES CFB mode support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#ifndef TWO_BLOCK_SIZE
+#define TWO_BLOCK_SIZE 16
+#endif
+
+/**
+ * Encrypt data with Twofish CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and encrypts it with
+ * Twofish CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of Twofish blocksize.
+ *
+ * @param key
+ *    Points to the key bytes.
+ * @param keyLength
+ *    Length of the key in bytes
+ * @param IV
+ *    The initialization vector which must be TWO_BLOCKSIZE (16) bytes.
+ * @param data
+ *    Points to a buffer that contains and receives the computed
+ *    the data (in-place encryption).
+ * @param dataLength
+ *    Length of the data in bytes
+ */
+
+void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+                   int32_t dataLength);
+
+/**
+ * Decrypt data with Twofish CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and decrypts it with
+ * Twofish CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of Twofish blocksize.
+ *
+ * @param key
+ *    Points to the key bytes.
+ * @param keyLength
+ *    Length of the key in bytes
+ * @param IV
+ *    The initialization vector which must be TWO_BLOCKSIZE (16) bytes.
+ * @param data
+ *    Points to a buffer that contains and receives the computed
+ *    the data (in-place decryption).
+ * @param dataLength
+ *    Length of the data in bytes
+ */
+
+void twoCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+                   int32_t dataLength);
+/**
+ * @}
+ */
+#endif
diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/twofish.c b/jni/libzrtp/src/libzrtpcpp/crypto/twofish.c
new file mode 100644
index 0000000..3d390ea
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/twofish.c
@@ -0,0 +1,1733 @@
+/* 

+ * Fast, portable, and easy-to-use Twofish implementation,  

+ * Version 0.3. 

+ * Copyright (c) 2002 by Niels Ferguson.  

+ * (See further down for the almost-unrestricted licensing terms.) 

+ * 

+ * -------------------------------------------------------------------------- 

+ * There are two files for this implementation: 

+ * - twofish.h, the header file. 

+ * - twofish.c, the code file. 

+ * 

+ * To incorporate this code into your program you should: 

+ * - Check the licensing terms further down in this comment. 

+ * - Fix the two type definitions in twofish.h to suit your platform. 

+ * - Fix a few definitions in twofish.c in the section marked  

+ *   PLATFORM FIXES. There is one important ones that affects  

+ *   functionality, and then a few definitions that you can optimise  

+ *   for efficiency but those have no effect on the functionality.  

+ *   Don't change anything else. 

+ * - Put the code in your project and compile it. 

+ * 

+ * To use this library you should: 

+ * - Call Twofish_initialise() in your program before any other function in 

+ *   this library. 

+ * - Use Twofish_prepare_key(...) to convert a key to internal form. 

+ * - Use Twofish_encrypt(...) and Twofish_decrypt(...) to encrypt and decrypt 

+ *   data. 

+ * See the comments in the header file for details on these functions. 

+ * -------------------------------------------------------------------------- 

+ *  

+ * There are many Twofish implementation available for free on the web. 

+ * Most of them are hard to integrate into your own program. 

+ * As we like people to use our cipher, I thought I would make it easier.  

+ * Here is a free and easy-to-integrate Twofish implementation in C. 

+ * The latest version is always available from my personal home page at 

+ *    http://niels.ferguson.net/ 

+ * 

+ * Integrating library code into a project is difficult because the library 

+ * header files interfere with the project's header files and code.  

+ * And of course the project's header files interfere with the library code. 

+ * I've tried to resolve these problems here.  

+ * The header file of this implementation is very light-weight.  

+ * It contains two typedefs, a structure, and a few function declarations. 

+ * All names it defines start with "Twofish_".  

+ * The header file is therefore unlikely to cause problems in your project. 

+ * The code file of this implementation doesn't need to include the header 

+ * files of the project. There is thus no danger of the project interfering 

+ * with all the definitions and macros of the Twofish code. 

+ * In most situations, all you need to do is fill in a few platform-specific 

+ * definitions in the header file and code file,  

+ * and you should be able to run the Twofish code in your project. 

+ * I estimate it should take you less than an hour to integrate this code 

+ * into your project, most of it spent reading the comments telling you what 

+ * to do. 

+ * 

+ * For people using C++: it is very easy to wrap this library into a 

+ * TwofishKey class. One of the big advantages is that you can automate the 

+ * wiping of the key material in the destructor. I have not provided a C++ 

+ * class because the interface depends too much on the abstract base class  

+ * you use for block ciphers in your program, which I don't know about. 

+ * 

+ * This implementation is designed for use on PC-class machines. It uses the  

+ * Twofish 'full' keying option which uses large tables. Total table size is  

+ * around 5-6 kB for static tables plus 4.5 kB for each pre-processed key. 

+ * If you need an implementation that uses less memory, 

+ * take a look at Brian Gladman's code on his web site: 

+ *     http://fp.gladman.plus.com/cryptography_technology/aes/ 

+ * He has code for all AES candidates. 

+ * His Twofish code has lots of options trading off table size vs. speed. 

+ * You can also take a look at the optimised code by Doug Whiting on the 

+ * Twofish web site 

+ *      http://www.counterpane.com/twofish.html 

+ * which has loads of options. 

+ * I believe these existing implementations are harder to re-use because they 

+ * are not clean libraries and they impose requirements on the environment.  

+ * This implementation is very careful to minimise those,  

+ * and should be easier to integrate into any larger program. 

+ * 

+ * The default mode of this implementation is fully portable as it uses no 

+ * behaviour not defined in the C standard. (This is harder than you think.) 

+ * If you have any problems porting the default mode, please let me know 

+ * so that I can fix the problem. (But only if this code is at fault, I  

+ * don't fix compilers.) 

+ * Most of the platform fixes are related to non-portable but faster ways  

+ * of implementing certain functions. 

+ * 

+ * In general I've tried to make the code as fast as possible, at the expense 

+ * of memory and code size. However, C does impose limits, and this  

+ * implementation will be slower than an optimised assembler implementation. 

+ * But beware of assembler implementations: a good Pentium implementation 

+ * uses completely different code than a good Pentium II implementation. 

+ * You basically have to re-write the assembly code for every generation of 

+ * processor. Unless you are severely pressed for speed, stick with C. 

+ * 

+ * The initialisation routine of this implementation contains a self-test. 

+ * If initialisation succeeds without calling the fatal routine, then 

+ * the implementation works. I don't think you can break the implementation 

+ * in such a way that it still passes the tests, unless you are malicious. 

+ * In other words: if the initialisation routine returns,  

+ * you have successfully ported the implementation.  

+ * (Or not implemented the fatal routine properly, but that is your problem.) 

+ * 

+ * I'm indebted to many people who helped me in one way or another to write 

+ * this code. During the design of Twofish and the AES process I had very  

+ * extensive discussions of all implementation issues with various people. 

+ * Doug Whiting in particular provided a wealth of information. The Twofish  

+ * team spent untold hours discussion various cipher features, and their  

+ * implementation. Brian Gladman implemented all AES candidates in C,  

+ * and we had some fruitful discussions on how to implement Twofish in C. 

+ * Jan Nieuwenhuizen tested this code on Linux using GCC. 

+ * 

+ * Now for the license: 

+ * The author hereby grants a perpetual license to everybody to 

+ * use this code for any purpose as long as the copyright message is included 

+ * in the source code of this or any derived work. 

+ *  

+ * Yes, this means that you, your company, your club, and anyone else 

+ * can use this code anywhere you want. You can change it and distribute it 

+ * under the GPL, include it in your commercial product without releasing 

+ * the source code, put it on the web, etc.  

+ * The only thing you cannot do is remove my copyright message,  

+ * or distribute any source code based on this implementation that does not  

+ * include my copyright message.  

+ *  

+ * I appreciate a mention in the documentation or credits,  

+ * but I understand if that is difficult to do. 

+ * I also appreciate it if you tell me where and why you used my code. 

+ * 

+ * Please send any questions or comments to niels@ferguson.net 

+ * 

+ * Have Fun! 

+ * 

+ * Niels 

+ */ 

+ 

+/* 

+ * DISCLAIMER: As I'm giving away my work for free, I'm of course not going 

+ * to accept any liability of any form. This code, or the Twofish cipher, 

+ * might very well be flawed; you have been warned. 

+ * This software is provided as-is, without any kind of warrenty or 

+ * guarantee. And that is really all you can expect when you download  

+ * code for free from the Internet.  

+ * 

+ * I think it is really sad that disclaimers like this seem to be necessary. 

+ * If people only had a little bit more common sense, and didn't come 

+ * whining like little children every time something happens.... 

+ */ 

+  

+/* 

+ * Version history: 

+ * Version 0.0, 2002-08-30 

+ *      First written. 

+ * Version 0.1, 2002-09-03 

+ *      Added disclaimer. Improved self-tests. 

+ * Version 0.2, 2002-09-09 

+ *      Removed last non-portabilities. Default now works completely within 

+ *      the C standard. UInt32 can be larger than 32 bits without problems. 

+ * Version 0.3, 2002-09-28 

+ *      Bugfix: use  instead of  to adhere to ANSI/ISO. 

+ *      Rename BIG_ENDIAN macro to CPU_IS_BIG_ENDIAN. The gcc library  

+ *      header  already defines BIG_ENDIAN, even though it is not  

+ *      supposed to. 

+ */ 

+ 

+ 

+/*  

+ * Minimum set of include files. 

+ * You should not need any application-specific include files for this code.  

+ * In fact, adding you own header files could break one of the many macros or 

+ * functions in this file. Be very careful. 

+ * Standard include files will probably be ok. 

+ */ 

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+/* #include      * for memset(), memcpy(), and memcmp() */ 

+#include "twofish.h" 

+ 

+ 

+/* 

+ * PLATFORM FIXES 

+ * ============== 

+ * 

+ * Fix the type definitions in twofish.h first! 

+ *  

+ * The following definitions have to be fixed for each particular platform  

+ * you work on. If you have a multi-platform program, you no doubt have  

+ * portable definitions that you can substitute here without changing the  

+ * rest of the code. 

+ */ 

+ 

+ 

+/*  

+ * Function called if something is fatally wrong with the implementation.  

+ * This fatal function is called when a coding error is detected in the 

+ * Twofish implementation, or when somebody passes an obviously erroneous 

+ * parameter to this implementation. There is not much you can do when 

+ * the code contains bugs, so we just stop. 

+ *  

+ * The argument is a string. Ideally the fatal function prints this string 

+ * as an error message. Whatever else this function does, it should never 

+ * return. A typical implementation would stop the program completely after 

+ * printing the error message. 

+ * 

+ * This default implementation is not very useful,  

+ * but does not assume anything about your environment.  

+ * It will at least let you know something is wrong.... 

+ * I didn't want to include any libraries to print and error or so, 

+ * as this makes the code much harder to integrate in a project. 

+ * 

+ * Note that the Twofish_fatal function may not return to the caller. 

+ * Unfortunately this is not something the self-test can test for, 

+ * so you have to make sure of this yourself. 

+ * 

+ * If you want to call an external function, be careful about including 

+ * your own header files here. This code uses a lot of macros, and your 

+ * header file could easily break it. Maybe the best solution is to use 

+ * a separate extern statement for your fatal function. 

+ */ 

+/* #define Twofish_fatal(pmsgx) { fprintf(stderr, pmsgx); exit(1); } */

+#define Twofish_fatal(pmsgx, code) { return(code); } 

+ 

+ 

+/* 

+ * The rest of the settings are not important for the functionality 

+ * of this Twofish implementation. That is, their default settings 

+ * work on all platforms. You can change them to improve the  

+ * speed of the implementation on your platform. Erroneous settings 

+ * will result in erroneous implementations, but the self-test should 

+ * catch those. 

+ */ 

+ 

+ 

+/*  

+ * Macros to rotate a Twofish_UInt32 value left or right by the  

+ * specified number of bits. This should be a 32-bit rotation,  

+ * and not rotation of, say, 64-bit values. 

+ * 

+ * Every encryption or decryption operation uses 32 of these rotations, 

+ * so it is a good idea to make these macros efficient. 

+ * 

+ * This fully portable definition has one piece of tricky stuff. 

+ * The UInt32 might be larger than 32 bits, so we have to mask 

+ * any higher bits off. The simplest way to do this is to 'and' the 

+ * value first with 0xffffffff and then shift it right. An optimising 

+ * compiler that has a 32-bit type can optimise this 'and' away. 

+ *  

+ * Unfortunately there is no portable way of writing the constant 

+ * 0xffffffff. You don't know which suffix to use (U, or UL?) 

+ * The UINT32_MASK definition uses a bit of trickery. Shift-left 

+ * is only defined if the shift amount is strictly less than the size 

+ * of the UInt32, so we can't use (1<<32). The answer it to take the value 

+ * 2, cast it to a UInt32, shift it left 31 positions, and subtract one. 

+ * Another example of how to make something very simple extremely difficult. 

+ * I hate C. 

+ *  

+ * The rotation macros are straightforward. 

+ * They are only applied to UInt32 values, which are _unsigned_ 

+ * so the >> operator must do a logical shift that brings in zeroes. 

+ * On most platforms you will only need to optimise the ROL32 macro; the 

+ * ROR32 macro is not inefficient on an optimising compiler as all rotation 

+ * amounts in this code are known at compile time. 

+ * 

+ * On many platforms there is a faster solution. 

+ * For example, MS compilers have the __rotl and __rotr functions 

+ * that generate x86 rotation instructions. 

+ */ 

+#define UINT32_MASK    ( (((Twofish_UInt32)2)<<31) - 1 ) 

+ 

+#ifndef _MSC_VER 

+#define ROL32(x,n) ( (x)<<(n) | ((x) & UINT32_MASK) >> (32-(n)) ) 

+#define ROR32(x,n) ( (x)>>(n) | ((x) & UINT32_MASK) << (32-(n)) ) 

+#else 

+#define ROL32(x,n) (_lrotl((x), (n))) 

+#define ROR32(x,n) (_lrotr((x), (n))) 

+#endif 

+ 

+/* 

+ * Select data type for q-table entries.  

+ * 

+ * Larger entry types cost more memory (1.5 kB), and might be faster  

+ * or slower depending on the CPU and compiler details. 

+ * 

+ * This choice only affects the static data size and the key setup speed. 

+ * Functionality, expanded key size, or encryption speed are not affected. 

+ * Define to 1 to get large q-table entries. 

+ */ 

+#define LARGE_Q_TABLE   0    /* default = 0 */ 

+ 

+ 

+/* 

+ * Method to select a single byte from a UInt32. 

+ * WARNING: non-portable code if set; might not work on all platforms. 

+ * 

+ * Inside the inner loop of Twofish it is necessary to access the 4  

+ * individual bytes of a UInt32. This can be done using either shifts 

+ * and masks, or memory accesses. 

+ * 

+ * Set to 0 to use shift and mask operations for the byte selection. 

+ * This is more ALU intensive. It is also fully portable.  

+ *  

+ * Set to 1 to use memory accesses. The UInt32 is stored in memory and 

+ * the individual bytes are read from memory one at a time. 

+ * This solution is more memory-intensive, and not fully portable. 

+ * It might be faster on your platform, or not. If you use this option, 

+ * make sure you set the CPU_IS_BIG_ENDIAN flag appropriately. 

+ *  

+ * This macro does not affect the conversion of the inputs and outputs 

+ * of the cipher. See the CONVERT_USING_CASTS macro for that. 

+ */ 

+#define SELECT_BYTE_FROM_UINT32_IN_MEMORY    0    /* default = 0 */ 

+ 

+ 

+/* 

+ * Method used to read the input and write the output. 

+ * WARNING: non-portable code if set; might not work on all platforms. 

+ * 

+ * Twofish operates on 32-bit words. The input to the cipher is 

+ * a byte array, as is the output. The portable method of doing the 

+ * conversion is a bunch of rotate and mask operations, but on many  

+ * platforms it can be done faster using a cast. 

+ * This only works if your CPU allows UInt32 accesses to arbitrary Byte 

+ * addresses. 

+ *  

+ * Set to 0 to use the shift and mask operations. This is fully 

+ * portable. . 

+ * 

+ * Set to 1 to use a cast. The Byte * is cast to a UInt32 *, and a 

+ * UInt32 is read. If necessary (as indicated by the CPU_IS_BIG_ENDIAN  

+ * macro) the byte order in the UInt32 is swapped. The reverse is done 

+ * to write the output of the encryption/decryption. Make sure you set 

+ * the CPU_IS_BIG_ENDIAN flag appropriately. 

+ * This option does not work unless a UInt32 is exactly 32 bits. 

+ * 

+ * This macro only changes the reading/writing of the plaintext/ciphertext. 

+ * See the SELECT_BYTE_FROM_UINT32_IN_MEMORY to affect the way in which 

+ * a UInt32 is split into 4 bytes for the S-box selection. 

+ */ 

+#define CONVERT_USING_CASTS    0    /* default = 0 */ 

+ 

+ 

+/*  

+ * Endianness switch. 

+ * Only relevant if SELECT_BYTE_FROM_UINT32_IN_MEMORY or 

+ * CONVERT_USING_CASTS is set. 

+ * 

+ * Set to 1 on a big-endian machine, and to 0 on a little-endian machine.  

+ * Twofish uses the little-endian convention (least significant byte first) 

+ * and big-endian machines (using most significant byte first)  

+ * have to do a few conversions.  

+ * 

+ * CAUTION: This code has never been tested on a big-endian machine,  

+ * because I don't have access to one. Feedback appreciated. 

+ */ 

+#define CPU_IS_BIG_ENDIAN    0 

+ 

+ 

+/*  

+ * Macro to reverse the order of the bytes in a UInt32. 

+ * Used to convert to little-endian on big-endian machines. 

+ * This macro is always tested, but only used in the encryption and 

+ * decryption if CONVERT_USING_CASTS, and CPU_IS_BIG_ENDIAN 

+ * are both set. In other words: this macro is only speed-critical if 

+ * both these flags have been set. 

+ * 

+ * This default definition of SWAP works, but on many platforms there is a  

+ * more efficient implementation.  

+ */ 

+#define BSWAP(x) ((ROL32((x),8)&0x00ff00ff) | (ROR32((x),8) & 0xff00ff00)) 

+ 

+ 

+/* 

+ * END OF PLATFORM FIXES 

+ * ===================== 

+ *  

+ * You should not have to touch the rest of this file. 

+ */ 

+ 

+ 

+/* 

+ * Convert the external type names to some that are easier to use inside 

+ * this file. I didn't want to use the names Byte and UInt32 in the 

+ * header file, because many programs already define them and using two 

+ * conventions at once can be very difficult. 

+ * Don't change these definitions! Change the originals  

+ * in twofish.h instead.  

+ */ 

+/* A Byte must be an unsigned integer, 8 bits long. */ 

+/* typedef Twofish_Byte    Byte; */

+/* A UInt32 must be an unsigned integer at least 32 bits long. */ 

+/* typedef Twofish_UInt32  UInt32; */

+ 

+ 

+/*  

+ * Define a macro ENDIAN_CONVERT. 

+ * 

+ * We define a macro ENDIAN_CONVERT that performs a BSWAP on big-endian 

+ * machines, and is the identity function on little-endian machines. 

+ * The code then uses this macro without considering the endianness. 

+ */ 

+ 

+#if CPU_IS_BIG_ENDIAN 

+#define ENDIAN_CONVERT(x)    BSWAP(x) 

+#else 

+#define ENDIAN_CONVERT(x)    (x) 

+#endif 

+ 

+ 

+/*  

+ * Compute byte offset within a UInt32 stored in memory. 

+ * 

+ * This is only used when SELECT_BYTE_FROM_UINT32_IN_MEMORY is set. 

+ *  

+ * The input is the byte number 0..3, 0 for least significant. 

+ * Note the use of sizeof() to support UInt32 types that are larger 

+ * than 4 bytes. 

+ */ 

+#if CPU_IS_BIG_ENDIAN 

+#define BYTE_OFFSET( n )  (sizeof(Twofish_UInt32) - 1 - (n) ) 

+#else 

+#define BYTE_OFFSET( n )  (n) 

+#endif 

+ 

+ 

+/* 

+ * Macro to get Byte no. b from UInt32 value X. 

+ * We use two different definition, depending on the settings. 

+ */ 

+#if SELECT_BYTE_FROM_UINT32_IN_MEMORY 

+    /* Pick the byte from the memory in which X is stored. */ 

+#define SELECT_BYTE( X, b ) (((Twofish_Byte *)(&(X)))[BYTE_OFFSET(b)]) 

+#else 

+    /* Portable solution: Pick the byte directly from the X value. */ 

+#define SELECT_BYTE( X, b ) (((X) >> (8*(b))) & 0xff) 

+#endif 

+ 

+ 

+/* Some shorthands because we use byte selection in large formulae. */ 

+#define b0(X)   SELECT_BYTE((X),0) 

+#define b1(X)   SELECT_BYTE((X),1) 

+#define b2(X)   SELECT_BYTE((X),2) 

+#define b3(X)   SELECT_BYTE((X),3) 

+ 

+ 

+/* 

+ * We need macros to load and store UInt32 from/to byte arrays 

+ * using the least-significant-byte-first convention. 

+ * 

+ * GET32( p ) gets a UInt32 in lsb-first form from four bytes pointed to 

+ * by p. 

+ * PUT32( v, p ) writes the UInt32 value v at address p in lsb-first form. 

+ */ 

+#if CONVERT_USING_CASTS 

+ 

+    /* Get UInt32 from four bytes pointed to by p. */ 

+#define GET32( p )    ENDIAN_CONVERT( *((Twofish_UInt32 *)(p)) ) 

+    /* Put UInt32 into four bytes pointed to by p */ 

+#define PUT32( v, p ) *((Twofish_UInt32 *)(p)) = ENDIAN_CONVERT(v) 

+ 

+#else 

+ 

+    /* Get UInt32 from four bytes pointed to by p. */ 

+#define GET32( p ) \

+    ( \

+      (Twofish_UInt32)((p)[0])     \

+    | (Twofish_UInt32)((p)[1])<< 8 \

+    | (Twofish_UInt32)((p)[2])<<16 \

+    | (Twofish_UInt32)((p)[3])<<24 \

+    ) 

+    /* Put UInt32 into four bytes pointed to by p */ 

+#define PUT32( v, p ) \

+    (p)[0] = (Twofish_Byte)(((v)      ) & 0xff); \

+    (p)[1] = (Twofish_Byte)(((v) >>  8) & 0xff); \

+    (p)[2] = (Twofish_Byte)(((v) >> 16) & 0xff); \

+    (p)[3] = (Twofish_Byte)(((v) >> 24) & 0xff)

+ 

+#endif 

+ 

+ 

+/* 

+ * Test the platform-specific macros. 

+ * This function tests the macros defined so far to make sure the  

+ * definitions are appropriate for this platform. 

+ * If you make any mistake in the platform configuration, this should detect 

+ * that and inform you what went wrong. 

+ * Somewhere, someday, this is going to save somebody a lot of time, 

+ * because misbehaving macros are hard to debug. 

+ */ 

+static int test_platform() 

+    { 

+    /* Buffer with test values. */ 

+    Twofish_Byte buf[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0}; 

+    Twofish_UInt32 C; 

+    Twofish_UInt32 x,y; 

+    int i; 

+ 

+    /*  

+     * Some sanity checks on the types that can't be done in compile time.  

+     * A smart compiler will just optimise these tests away. 

+     * The pre-processor doesn't understand different types, so we cannot 

+     * do these checks in compile-time. 

+     * 

+     * I hate C. 

+     * 

+     * The first check in each case is to make sure the size is correct. 

+     * The second check is to ensure that it is an unsigned type. 

+     */ 

+    if( ((Twofish_UInt32)((Twofish_UInt32)1 << 31) == 0) || ((Twofish_UInt32)-1 < 0 ))  

+        { 

+	  Twofish_fatal( "Twofish code: Twofish_UInt32 type not suitable", ERR_UINT32 ); 

+        } 

+    if( (sizeof( Twofish_Byte ) != 1) || (((Twofish_Byte)-1) < 0) )  

+        { 

+	  Twofish_fatal( "Twofish code: Twofish_Byte type not suitable", ERR_BYTE ); 

+        } 

+ 

+    /*  

+     * Sanity-check the endianness conversions.  

+     * This is just an aid to find problems. If you do the endianness 

+     * conversion macros wrong you will fail the full cipher test, 

+     * but that does not help you find the error. 

+     * Always make it easy to find the bugs!  

+     * 

+     * Detail: There is no fully portable way of writing UInt32 constants, 

+     * as you don't know whether to use the U or UL suffix. Using only U you 

+     * might only be allowed 16-bit constants. Using UL you might get 64-bit 

+     * constants which cannot be stored in a UInt32 without warnings, and 

+     * which generally behave subtly different from a true UInt32. 

+     * As long as we're just comparing with the constant,  

+     * we can always use the UL suffix and at worst lose some efficiency.  

+     * I use a separate '32-bit constant' macro in most of my other code. 

+     * 

+     * I hate C. 

+     * 

+     * Start with testing GET32. We test it on all positions modulo 4  

+     * to make sure we can handly any position of inputs. (Some CPUs 

+     * do not allow non-aligned accesses which we would do if you used 

+     * the CONVERT_USING_CASTS option. 

+     */ 

+    if( (GET32( buf ) != 0x78563412UL) || (GET32(buf+1) != 0x9a785634UL)  

+        || (GET32( buf+2 ) != 0xbc9a7856UL) || (GET32(buf+3) != 0xdebc9a78UL) ) 

+        { 

+	  Twofish_fatal( "Twofish code: GET32 not implemented properly", ERR_GET32 ); 

+        } 

+ 

+    /*  

+     * We can now use GET32 to test PUT32. 

+     * We don't test the shifted versions. If GET32 can do that then 

+     * so should PUT32. 

+     */ 

+    C = GET32( buf ); 

+    PUT32( 3*C, buf ); 

+    if( GET32( buf ) != 0x69029c36UL ) 

+        { 

+	  Twofish_fatal( "Twofish code: PUT32 not implemented properly", ERR_PUT32 ); 

+        } 

+ 

+ 

+    /* Test ROL and ROR */ 

+    for( i=1; i<32; i++ )  

+        { 

+        /* Just a simple test. */ 

+        x = ROR32( C, i ); 

+        y = ROL32( C, i ); 

+        x ^= (C>>i) ^ (C<<(32-i)); 

+        /*y ^= (C<>(32-i));  */

+        y ^= (C<<i) ^ (C>>(32-i));

+        x |= y; 

+        /*  

+         * Now all we check is that x is zero in the least significant 

+         * 32 bits. Using the UL suffix is safe here, as it doesn't matter 

+         * if we get a larger type. 

+         */ 

+	if( (x & 0xffffffffUL) != 0 ) 

+            { 

+	      Twofish_fatal( "Twofish ROL or ROR not properly defined.", ERR_ROLR ); 

+            } 

+        } 

+ 

+    /* Test the BSWAP macro */ 

+    if( BSWAP(C) != 0x12345678UL ) 

+        { 

+        /* 

+         * The BSWAP macro should always work, even if you are not using it. 

+         * A smart optimising compiler will just remove this entire test. 

+         */ 

+	  Twofish_fatal( "BSWAP not properly defined.", ERR_BSWAP ); 

+        } 

+ 

+    /* And we can test the b macros which use SELECT_BYTE. */ 

+    if( (b0(C)!=0x12) || (b1(C) != 0x34) || (b2(C) != 0x56) || (b3(C) != 0x78) ) 

+        { 

+        /* 

+         * There are many reasons why this could fail. 

+         * Most likely is that CPU_IS_BIG_ENDIAN has the wrong value.  

+         */ 

+	  Twofish_fatal( "Twofish code: SELECT_BYTE not implemented properly", ERR_SELECTB ); 

+        }

+    return SUCCESS;

+    } 

+ 

+ 

+/* 

+ * Finally, we can start on the Twofish-related code. 

+ * You really need the Twofish specifications to understand this code. The 

+ * best source is the Twofish book: 

+ *     "The Twofish Encryption Algorithm", by Bruce Schneier, John Kelsey, 

+ *     Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson. 

+ * you can also use the AES submission document of Twofish, which is  

+ * available from my list of publications on my personal web site at  

+ *    http://niels.ferguson.net/. 

+ * 

+ * The first thing we do is write the testing routines. This is what the  

+ * implementation has to satisfy in the end. We only test the external 

+ * behaviour of the implementation of course. 

+ */ 

+ 

+ 

+/* 

+ * Perform a single self test on a (plaintext,ciphertext,key) triple. 

+ * Arguments: 

+ *  key     array of key bytes 

+ *  key_len length of key in bytes 

+ *  p       plaintext 

+ *  c       ciphertext 

+ */ 

+static int test_vector( Twofish_Byte key[], int key_len, Twofish_Byte p[16], Twofish_Byte c[16] ) 

+    { 

+    Twofish_Byte tmp[16];               /* scratch pad. */ 

+    Twofish_key xkey;           /* The expanded key */ 

+    int i; 

+ 

+ 

+    /* Prepare the key */ 

+    if ((i = Twofish_prepare_key( key, key_len, &xkey)) < 0)

+	return i; 

+ 

+    /*  

+     * We run the test twice to ensure that the xkey structure 

+     * is not damaged by the first encryption.  

+     * Those are hideous bugs to find if you get them in an application. 

+     */ 

+    for( i=0; i<2; i++ )  

+        { 

+        /* Encrypt and test */ 

+        Twofish_encrypt( &xkey, p, tmp ); 

+        if( memcmp( c, tmp, 16 ) != 0 )  

+            { 

+	      Twofish_fatal( "Twofish encryption failure", ERR_TEST_ENC ); 

+            } 

+ 

+        /* Decrypt and test */ 

+        Twofish_decrypt( &xkey, c, tmp ); 

+        if( memcmp( p, tmp, 16 ) != 0 )  

+            { 

+	      Twofish_fatal( "Twofish decryption failure", ERR_TEST_DEC ); 

+            } 

+        } 

+ 

+    /* The test keys are not secret, so we don't need to wipe xkey. */

+    return SUCCESS;

+    }

+ 

+ 

+/* 

+ * Check implementation using three (key,plaintext,ciphertext) 

+ * test vectors, one for each major key length. 

+ *  

+ * This is an absolutely minimal self-test.  

+ * This routine does not test odd-sized keys. 

+ */ 

+static int test_vectors() 

+    { 

+    /* 

+     * We run three tests, one for each major key length. 

+     * These test vectors come from the Twofish specification. 

+     * One encryption and one decryption using randomish data and key 

+     * will detect almost any error, especially since we generate the 

+     * tables ourselves, so we don't have the problem of a single 

+     * damaged table entry in the source. 

+     */ 

+ 

+    /* 128-bit test is the I=3 case of section B.2 of the Twofish book. */ 

+    static Twofish_Byte k128[] = { 

+        0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,  

+        0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A, 

+        }; 

+    static Twofish_Byte p128[] = { 

+        0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E,  

+        0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 

+        }; 

+    static Twofish_Byte c128[] = { 

+        0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85,  

+        0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 

+        }; 

+ 

+    /* 192-bit test is the I=4 case of section B.2 of the Twofish book. */ 

+    static Twofish_Byte k192[] = { 

+        0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36,  

+        0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,  

+        0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 

+        }; 

+    static Twofish_Byte p192[] = { 

+        0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 

+        0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 

+        }; 

+    static Twofish_Byte c192[] = { 

+        0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 

+        0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 

+        }; 

+ 

+    /* 256-bit test is the I=4 case of section B.2 of the Twofish book. */ 

+    static Twofish_Byte k256[] = { 

+        0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46,  

+        0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, 

+        0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 

+        0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F 

+        }; 

+    static Twofish_Byte p256[] = { 

+        0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 

+        0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 

+        }; 

+    static Twofish_Byte c256[] = { 

+        0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 

+        0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA 

+        }; 

+

+    int ret;

+

+    /* Run the actual tests. */ 

+    if ((ret = test_vector( k128, 16, p128, c128 )) < 0)

+      return ret; 

+    if ((ret = test_vector( k192, 24, p192, c192 )) < 0)

+      return ret; 

+    if ((ret = test_vector( k256, 32, p256, c256 )) < 0)

+      return ret;

+    return SUCCESS;

+    }    

+ 

+ 

+/* 

+ * Perform extensive test for a single key size. 

+ *  

+ * Test a single key size against the test vectors from section 

+ * B.2 in the Twofish book. This is a sequence of 49 encryptions 

+ * and decryptions. Each plaintext is equal to the ciphertext of 

+ * the previous encryption. The key is made up from the ciphertext 

+ * two and three encryptions ago. Both plaintext and key start 

+ * at the zero value.  

+ * We should have designed a cleaner recurrence relation for 

+ * these tests, but it is too late for that now. At least we learned 

+ * how to do it better next time. 

+ * For details see appendix B of the book. 

+ * 

+ * Arguments: 

+ * key_len      Number of bytes of key 

+ * final_value  Final plaintext value after 49 iterations 

+ */ 

+static int test_sequence( int key_len, Twofish_Byte final_value[] ) 

+    { 

+    Twofish_Byte buf[ (50+3)*16 ];      /* Buffer to hold our computation values. */ 

+    Twofish_Byte tmp[16];               /* Temp for testing the decryption. */ 

+    Twofish_key xkey;           /* The expanded key */ 

+    int i, ret;

+    Twofish_Byte * p; 

+ 

+    /* Wipe the buffer */ 

+    memset( buf, 0, sizeof( buf ) ); 

+ 

+    /* 

+     * Because the recurrence relation is done in an inconvenient manner 

+     * we end up looping backwards over the buffer. 

+     */ 

+ 

+    /* Pointer in buffer points to current plaintext. */ 

+    p = &buf[50*16]; 

+    for( i=1; i<50; i++ ) 

+        { 

+        /*  

+         * Prepare a key. 

+         * This automatically checks that key_len is valid. 

+         */ 

+	  if ((ret = Twofish_prepare_key( p+16, key_len, &xkey)) < 0)

+	    return ret; 

+ 

+        /* Compute the next 16 bytes in the buffer */ 

+        Twofish_encrypt( &xkey, p, p-16 ); 

+ 

+        /* Check that the decryption is correct. */ 

+        Twofish_decrypt( &xkey, p-16, tmp ); 

+        if( memcmp( tmp, p, 16 ) != 0 ) 

+            { 

+	      Twofish_fatal( "Twofish decryption failure in sequence", ERR_SEQ_DEC ); 

+            } 

+        /* Move on to next 16 bytes in the buffer. */ 

+        p -= 16; 

+        } 

+ 

+    /* And check the final value. */ 

+    if( memcmp( p, final_value, 16 ) != 0 )  

+        { 

+	  Twofish_fatal( "Twofish encryption failure in sequence", ERR_SEQ_ENC ); 

+        } 

+ 

+    /* None of the data was secret, so there is no need to wipe anything. */

+    return SUCCESS;

+    } 

+ 

+ 

+/*  

+ * Run all three sequence tests from the Twofish test vectors.  

+ * 

+ * This checks the most extensive test vectors currently available  

+ * for Twofish. The data is from the Twofish book, appendix B.2. 

+ */ 

+static int test_sequences() 

+    { 

+    static Twofish_Byte r128[] = { 

+        0x5D, 0x9D, 0x4E, 0xEF, 0xFA, 0x91, 0x51, 0x57, 

+        0x55, 0x24, 0xF1, 0x15, 0x81, 0x5A, 0x12, 0xE0 

+        }; 

+    static Twofish_Byte r192[] = { 

+        0xE7, 0x54, 0x49, 0x21, 0x2B, 0xEE, 0xF9, 0xF4, 

+        0xA3, 0x90, 0xBD, 0x86, 0x0A, 0x64, 0x09, 0x41 

+        }; 

+    static Twofish_Byte r256[] = { 

+        0x37, 0xFE, 0x26, 0xFF, 0x1C, 0xF6, 0x61, 0x75, 

+        0xF5, 0xDD, 0xF4, 0xC3, 0x3B, 0x97, 0xA2, 0x05 

+        }; 

+ 

+    /* Run the three sequence test vectors */

+    int ret;

+    if ((ret = test_sequence( 16, r128)) < 0)

+      return ret; 

+    if ((ret = test_sequence( 24, r192)) < 0)

+      return ret; 

+    if ((ret = test_sequence( 32, r256)) < 0)

+      return ret;

+    return SUCCESS;

+    } 

+ 

+ 

+/* 

+ * Test the odd-sized keys. 

+ * 

+ * Every odd-sized key is equivalent to a one of 128, 192, or 256 bits. 

+ * The equivalent key is found by padding at the end with zero bytes 

+ * until a regular key size is reached. 

+ * 

+ * We just test that the key expansion routine behaves properly. 

+ * If the expanded keys are identical, then the encryptions and decryptions 

+ * will behave the same. 

+ */ 

+static int test_odd_sized_keys() 

+    { 

+    Twofish_Byte buf[32]; 

+    Twofish_key xkey; 

+    Twofish_key xkey_two; 

+    int i, ret;

+ 

+    /*  

+     * We first create an all-zero key to use as PRNG key.  

+     * Normally we would not have to fill the buffer with zeroes, as we could 

+     * just pass a zero key length to the Twofish_prepare_key function. 

+     * However, this relies on using odd-sized keys, and those are just the 

+     * ones we are testing here. We can't use an untested function to test  

+     * itself.  

+     */ 

+    memset( buf, 0, sizeof( buf ) ); 

+    if ((ret = Twofish_prepare_key( buf, 16, &xkey)) < 0)

+      return ret; 

+ 

+    /* Fill buffer with pseudo-random data derived from two encryptions */ 

+    Twofish_encrypt( &xkey, buf, buf ); 

+    Twofish_encrypt( &xkey, buf, buf+16 ); 

+ 

+    /* Create all possible shorter keys that are prefixes of the buffer. */ 

+    for( i=31; i>=0; i-- ) 

+        { 

+        /* Set a byte to zero. This is the new padding byte */ 

+        buf[i] = 0; 

+ 

+        /* Expand the key with only i bytes of length */ 

+        if ((ret = Twofish_prepare_key( buf, i, &xkey)) < 0)

+	  return ret; 

+ 

+        /* Expand the corresponding padded key of regular length */ 

+        if ((ret = Twofish_prepare_key( buf, i<=16 ? 16 : (i<= 24 ? 24 : 32), &xkey_two )) < 0)

+	  return ret; 

+ 

+        /* Compare the two */ 

+        if( memcmp( &xkey, &xkey_two, sizeof( xkey ) ) != 0 ) 

+            { 

+	      Twofish_fatal( "Odd sized keys do not expand properly", ERR_ODD_KEY ); 

+            } 

+        } 

+ 

+    /* None of the key values are secret, so we don't need to wipe them. */

+    return SUCCESS;

+    } 

+ 

+ 

+/* 

+ * Test the Twofish implementation. 

+ * 

+ * This routine runs all the self tests, in order of importance. 

+ * It is called by the Twofish_initialise routine. 

+ *  

+ * In almost all applications the cost of running the self tests during 

+ * initialisation is insignificant, especially 

+ * compared to the time it takes to load the application from disk.  

+ * If you are very pressed for initialisation performance,  

+ * you could remove some of the tests. Make sure you did run them 

+ * once in the software and hardware configuration you are using. 

+ */ 

+static int self_test() 

+    {

+      int ret;

+    /* The three test vectors form an absolute minimal test set. */ 

+      if ((ret = test_vectors()) < 0)

+	return ret;

+ 

+    /*  

+     * If at all possible you should run these tests too. They take 

+     * more time, but provide a more thorough coverage. 

+     */ 

+      if ((ret = test_sequences()) < 0)

+	return ret;

+ 

+    /* Test the odd-sized keys. */ 

+      if ((ret = test_odd_sized_keys()) < 0)

+	return ret;

+      return SUCCESS;

+    } 

+ 

+ 

+/* 

+ * And now, the actual Twofish implementation. 

+ * 

+ * This implementation generates all the tables during initialisation.  

+ * I don't like large tables in the code, especially since they are easily  

+ * damaged in the source without anyone noticing it. You need code to  

+ * generate them anyway, and this way all the code is close together. 

+ * Generating them in the application leads to a smaller executable  

+ * (the code is smaller than the tables it generates) and a  

+ * larger static memory footprint. 

+ * 

+ * Twofish can be implemented in many ways. I have chosen to  

+ * use large tables with a relatively long key setup time. 

+ * If you encrypt more than a few blocks of data it pays to pre-compute  

+ * as much as possible. This implementation is relatively inefficient for  

+ * applications that need to re-key every block or so. 

+ */ 

+ 

+/*  

+ * We start with the t-tables, directly from the Twofish definition.  

+ * These are nibble-tables, but merging them and putting them two nibbles  

+ * in one byte is more work than it is worth. 

+ */ 

+static Twofish_Byte t_table[2][4][16] = { 

+    { 

+        {0x8,0x1,0x7,0xD,0x6,0xF,0x3,0x2,0x0,0xB,0x5,0x9,0xE,0xC,0xA,0x4}, 

+        {0xE,0xC,0xB,0x8,0x1,0x2,0x3,0x5,0xF,0x4,0xA,0x6,0x7,0x0,0x9,0xD}, 

+        {0xB,0xA,0x5,0xE,0x6,0xD,0x9,0x0,0xC,0x8,0xF,0x3,0x2,0x4,0x7,0x1}, 

+        {0xD,0x7,0xF,0x4,0x1,0x2,0x6,0xE,0x9,0xB,0x3,0x0,0x8,0x5,0xC,0xA} 

+    }, 

+    { 

+        {0x2,0x8,0xB,0xD,0xF,0x7,0x6,0xE,0x3,0x1,0x9,0x4,0x0,0xA,0xC,0x5}, 

+        {0x1,0xE,0x2,0xB,0x4,0xC,0x3,0x7,0x6,0xD,0xA,0x5,0xF,0x9,0x0,0x8}, 

+        {0x4,0xC,0x7,0x5,0x1,0x6,0x9,0xA,0x0,0xE,0xD,0x8,0x2,0xB,0x3,0xF}, 

+        {0xB,0x9,0x5,0x1,0xC,0x3,0xD,0xE,0x6,0x4,0x7,0xF,0x2,0x0,0x8,0xA} 

+    } 

+}; 

+ 

+ 

+/* A 1-bit rotation of 4-bit values. Input must be in range 0..15 */ 

+#define ROR4BY1( x ) (((x)>>1) | (((x)<<3) & 0x8) ) 

+ 

+/* 

+ * The q-boxes are only used during the key schedule computations.  

+ * These are 8->8 bit lookup tables. Some CPUs prefer to have 8->32 bit  

+ * lookup tables as it is faster to load a 32-bit value than to load an  

+ * 8-bit value and zero the rest of the register. 

+ * The LARGE_Q_TABLE switch allows you to choose 32-bit entries in  

+ * the q-tables. Here we just define the Qtype which is used to store  

+ * the entries of the q-tables. 

+ */ 

+#if LARGE_Q_TABLE 

+typedef Twofish_UInt32      Qtype; 

+#else 

+typedef Twofish_Byte        Qtype; 

+#endif 

+ 

+/*  

+ * The actual q-box tables.  

+ * There are two q-boxes, each having 256 entries. 

+ */ 

+static Qtype q_table[2][256]; 

+ 

+ 

+/* 

+ * Now the function that converts a single t-table into a q-table. 

+ * 

+ * Arguments: 

+ * t[4][16] : four 4->4bit lookup tables that define the q-box 

+ * q[256]   : output parameter: the resulting q-box as a lookup table. 

+ */ 

+static void make_q_table( Twofish_Byte t[4][16], Qtype q[256] ) 

+    { 

+    int ae,be,ao,bo;        /* Some temporaries. */ 

+    int i; 

+    /* Loop over all input values and compute the q-box result. */ 

+    for( i=0; i<256; i++ ) { 

+        /*  

+         * This is straight from the Twofish specifications.  

+         *  

+         * The ae variable is used for the a_i values from the specs 

+         * with even i, and ao for the odd i's. Similarly for the b's. 

+         */ 

+        ae = i>>4; be = i&0xf; 

+        ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8); 

+        ae = t[0][ao]; be = t[1][bo]; 

+        ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8); 

+        ae = t[2][ao]; be = t[3][bo]; 

+ 

+        /* Store the result in the q-box table, the cast avoids a warning. */ 

+        q[i] = (Qtype) ((be<<4) | ae); 

+        } 

+    } 

+ 

+ 

+/*  

+ * Initialise both q-box tables.  

+ */ 

+static void initialise_q_boxes() { 

+    /* Initialise each of the q-boxes using the t-tables */ 

+    make_q_table( t_table[0], q_table[0] ); 

+    make_q_table( t_table[1], q_table[1] ); 

+    } 

+ 

+ 

+/* 

+ * Next up is the MDS matrix multiplication. 

+ * The MDS matrix multiplication operates in the field 

+ * GF(2)[x]/p(x) with p(x)=x^8+x^6+x^5+x^3+1. 

+ * If you don't understand this, read a book on finite fields. You cannot 

+ * follow the finite-field computations without some background. 

+ *  

+ * In this field, multiplication by x is easy: shift left one bit  

+ * and if bit 8 is set then xor the result with 0x169.  

+ * 

+ * The MDS coefficients use a multiplication by 1/x, 

+ * or rather a division by x. This is easy too: first make the 

+ * value 'even' (i.e. bit 0 is zero) by xorring with 0x169 if necessary,  

+ * and then shift right one position.  

+ * Even easier: shift right and xor with 0xb4 if the lsbit was set. 

+ * 

+ * The MDS coefficients are 1, EF, and 5B, and we use the fact that 

+ *   EF = 1 + 1/x + 1/x^2 

+ *   5B = 1       + 1/x^2 

+ * in this field. This makes multiplication by EF and 5B relatively easy. 

+ * 

+ * This property is no accident, the MDS matrix was designed to allow 

+ * this implementation technique to be used. 

+ * 

+ * We have four MDS tables, each mapping 8 bits to 32 bits. 

+ * Each table performs one column of the matrix multiplication.  

+ * As the MDS is always preceded by q-boxes, each of these tables 

+ * also implements the q-box just previous to that column. 

+ */ 

+ 

+/* The actual MDS tables. */ 

+static Twofish_UInt32 MDS_table[4][256]; 

+ 

+/* A small table to get easy conditional access to the 0xb4 constant. */ 

+static Twofish_UInt32 mds_poly_divx_const[] = {0,0xb4}; 

+ 

+/* Function to initialise the MDS tables. */ 

+static void initialise_mds_tables() 

+    { 

+    int i; 

+    Twofish_UInt32 q,qef,q5b;       /* Temporary variables. */ 

+ 

+    /* Loop over all 8-bit input values */ 

+    for( i=0; i<256; i++ )  

+        { 

+        /*  

+         * To save some work during the key expansion we include the last 

+         * of the q-box layers from the h() function in these MDS tables. 

+         */ 

+ 

+        /* We first do the inputs that are mapped through the q0 table. */ 

+        q = q_table[0][i]; 

+        /* 

+         * Here we divide by x, note the table to get 0xb4 only if the  

+         * lsbit is set.  

+         * This sets qef = (1/x)*q in the finite field 

+         */ 

+        qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ]; 

+        /* 

+         * Divide by x again, and add q to get (1+1/x^2)*q.  

+         * Note that (1+1/x^2) =  5B in the field, and addition in the field 

+         * is exclusive or on the bits. 

+         */ 

+        q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q; 

+        /*  

+         * Add q5b to qef to set qef = (1+1/x+1/x^2)*q. 

+         * Again, (1+1/x+1/x^2) = EF in the field. 

+         */ 

+        qef ^= q5b; 

+ 

+        /*  

+         * Now that we have q5b = 5B * q and qef = EF * q  

+         * we can fill two of the entries in the MDS matrix table.  

+         * See the Twofish specifications for the order of the constants. 

+         */ 

+        MDS_table[1][i] = (q  <<24) | (q5b<<16) | (qef<<8) | qef; 

+        MDS_table[3][i] = (q5b<<24) | (qef<<16) | (q  <<8) | q5b; 

+ 

+        /* Now we do it all again for the two columns that have a q1 box. */ 

+        q = q_table[1][i]; 

+        qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ]; 

+        q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q; 

+        qef ^= q5b; 

+ 

+        /* The other two columns use the coefficient in a different order. */ 

+        MDS_table[0][i] = (qef<<24) | (qef<<16) | (q5b<<8) | q  ; 

+        MDS_table[2][i] = (qef<<24) | (q  <<16) | (qef<<8) | q5b; 

+        } 

+    } 

+ 

+ 

+/* 

+ * The h() function is the heart of the Twofish cipher.  

+ * It is a complicated sequence of q-box lookups, key material xors,  

+ * and finally the MDS matrix. 

+ * We use lots of macros to make this reasonably fast. 

+ */ 

+ 

+/* First a shorthand for the two q-tables */ 

+#define q0  q_table[0] 

+#define q1  q_table[1] 

+ 

+/* 

+ * Each macro computes one column of the h for either 2, 3, or 4 stages. 

+ * As there are 4 columns, we have 12 macros in all. 

+ *  

+ * The key bytes are stored in the Byte array L at offset  

+ * 0,1,2,3,  8,9,10,11,  [16,17,18,19,   [24,25,26,27]] as this is the 

+ * order we get the bytes from the user. If you look at the Twofish  

+ * specs, you'll see that h() is applied to the even key words or the 

+ * odd key words. The bytes of the even words appear in this spacing, 

+ * and those of the odd key words too. 

+ * 

+ * These macros are the only place where the q-boxes and the MDS table 

+ * are used. 

+ */ 

+#define H02( y, L )  MDS_table[0][q0[q0[y]^L[ 8]]^L[0]] 

+#define H12( y, L )  MDS_table[1][q0[q1[y]^L[ 9]]^L[1]] 

+#define H22( y, L )  MDS_table[2][q1[q0[y]^L[10]]^L[2]] 

+#define H32( y, L )  MDS_table[3][q1[q1[y]^L[11]]^L[3]] 

+#define H03( y, L )  H02( q1[y]^L[16], L ) 

+#define H13( y, L )  H12( q1[y]^L[17], L ) 

+#define H23( y, L )  H22( q0[y]^L[18], L ) 

+#define H33( y, L )  H32( q0[y]^L[19], L ) 

+#define H04( y, L )  H03( q1[y]^L[24], L ) 

+#define H14( y, L )  H13( q0[y]^L[25], L ) 

+#define H24( y, L )  H23( q0[y]^L[26], L ) 

+#define H34( y, L )  H33( q1[y]^L[27], L ) 

+ 

+/* 

+ * Now we can define the h() function given an array of key bytes.  

+ * This function is only used in the key schedule, and not to pre-compute 

+ * the keyed S-boxes. 

+ * 

+ * In the key schedule, the input is always of the form k*(1+2^8+2^16+2^24) 

+ * so we only provide k as an argument. 

+ * 

+ * Arguments: 

+ * k        input to the h() function. 

+ * L        pointer to array of key bytes at  

+ *          offsets 0,1,2,3, ... 8,9,10,11, [16,17,18,19, [24,25,26,27]] 

+ * kCycles  # key cycles, 2, 3, or 4. 

+ */ 

+static Twofish_UInt32 h( int k, Twofish_Byte L[], int kCycles ) 

+    { 

+    switch( kCycles ) { 

+        /* We code all 3 cases separately for speed reasons. */ 

+    case 2: 

+        return H02(k,L) ^ H12(k,L) ^ H22(k,L) ^ H32(k,L); 

+    case 3: 

+        return H03(k,L) ^ H13(k,L) ^ H23(k,L) ^ H33(k,L); 

+    case 4: 

+        return H04(k,L) ^ H14(k,L) ^ H24(k,L) ^ H34(k,L); 

+    default:  

+        /* This is always a coding error, which is fatal. */ 

+      Twofish_fatal( "Twofish h(): Illegal argument", ERR_ILL_ARG ); 

+      return ERR_ILL_ARG;

+        } 

+    } 

+ 

+ 

+/* 

+ * Pre-compute the keyed S-boxes. 

+ * Fill the pre-computed S-box array in the expanded key structure. 

+ * Each pre-computed S-box maps 8 bits to 32 bits. 

+ * 

+ * The S argument contains half the number of bytes of the full key, but is 

+ * derived from the full key. (See Twofish specifications for details.) 

+ * S has the weird byte input order used by the Hxx macros. 

+ * 

+ * This function takes most of the time of a key expansion. 

+ * 

+ * Arguments: 

+ * S        pointer to array of 8*kCycles Bytes containing the S vector. 

+ * kCycles  number of key words, must be in the set {2,3,4} 

+ * xkey     pointer to Twofish_key structure that will contain the S-boxes. 

+ */ 

+static int fill_keyed_sboxes( Twofish_Byte S[], int kCycles, Twofish_key * xkey ) 

+    { 

+    int i; 

+    switch( kCycles ) { 

+        /* We code all 3 cases separately for speed reasons. */ 

+    case 2: 

+        for( i=0; i<256; i++ ) 

+            { 

+            xkey->s[0][i]= H02( i, S ); 

+            xkey->s[1][i]= H12( i, S ); 

+            xkey->s[2][i]= H22( i, S ); 

+            xkey->s[3][i]= H32( i, S ); 

+            } 

+        break; 

+    case 3: 

+        for( i=0; i<256; i++ ) 

+            { 

+            xkey->s[0][i]= H03( i, S ); 

+            xkey->s[1][i]= H13( i, S ); 

+            xkey->s[2][i]= H23( i, S ); 

+            xkey->s[3][i]= H33( i, S ); 

+            } 

+        break; 

+    case 4: 

+        for( i=0; i<256; i++ ) 

+            { 

+            xkey->s[0][i]= H04( i, S ); 

+            xkey->s[1][i]= H14( i, S ); 

+            xkey->s[2][i]= H24( i, S ); 

+            xkey->s[3][i]= H34( i, S ); 

+            } 

+        break; 

+    default:  

+        /* This is always a coding error, which is fatal. */ 

+      Twofish_fatal( "Twofish fill_keyed_sboxes(): Illegal argument", ERR_ILL_ARG ); 

+        }

+    return SUCCESS;

+    }

+ 

+ 

+/* A flag to keep track of whether we have been initialised or not. */ 

+static int Twofish_initialised = 0; 

+ 

+/* 

+ * Initialise the Twofish implementation. 

+ * This function must be called before any other function in the 

+ * Twofish implementation is called. 

+ * This routine also does some sanity checks, to make sure that 

+ * all the macros behave, and it tests the whole cipher. 

+ */ 

+int Twofish_initialise() 

+    {

+      int ret;

+    /* First test the various platform-specific definitions. */ 

+      if ((ret = test_platform()) < 0)

+	return ret;

+ 

+    /* We can now generate our tables, in the right order of course. */ 

+    initialise_q_boxes(); 

+    initialise_mds_tables(); 

+ 

+    /* We're finished with the initialisation itself. */ 

+    Twofish_initialised = 1; 

+ 

+    /*  

+     * And run some tests on the whole cipher.  

+     * Yes, you need to do this every time you start your program.  

+     * It is called assurance; you have to be certain that your program 

+     * still works properly.  

+     */ 

+    return self_test(); 

+    } 

+ 

+ 

+/* 

+ * The Twofish key schedule uses an Reed-Solomon code matrix multiply. 

+ * Just like the MDS matrix, the RS-matrix is designed to be easy 

+ * to implement. Details are below in the code.  

+ * 

+ * These constants make it easy to compute in the finite field used  

+ * for the RS code. 

+ * 

+ * We use Bytes for the RS computation, but these are automatically 

+ * widened to unsigned integers in the expressions. Having unsigned 

+ * ints in these tables therefore provides the fastest access. 

+ */ 

+static unsigned int rs_poly_const[] = {0, 0x14d}; 

+static unsigned int rs_poly_div_const[] = {0, 0xa6 }; 

+ 

+ 

+/* 

+ * Prepare a key for use in encryption and decryption. 

+ * Like most block ciphers, Twofish allows the key schedule  

+ * to be pre-computed given only the key.  

+ * Twofish has a fairly 'heavy' key schedule that takes a lot of time  

+ * to compute. The main work is pre-computing the S-boxes used in the  

+ * encryption and decryption. We feel that this makes the cipher much  

+ * harder to attack. The attacker doesn't even know what the S-boxes  

+ * contain without including the entire key schedule in the analysis.  

+ * 

+ * Unlike most Twofish implementations, this one allows any key size from 

+ * 0 to 32 bytes. Odd key sizes are defined for Twofish (see the  

+ * specifications); the key is simply padded with zeroes to the next real  

+ * key size of 16, 24, or 32 bytes. 

+ * Each odd-sized key is thus equivalent to a single normal-sized key. 

+ * 

+ * Arguments: 

+ * key      array of key bytes 

+ * key_len  number of bytes in the key, must be in the range 0,...,32. 

+ * xkey     Pointer to an Twofish_key structure that will be filled  

+ *             with the internal form of the cipher key. 

+ */ 

+int Twofish_prepare_key( Twofish_Byte key[], int key_len, Twofish_key * xkey ) 

+    { 

+    /* We use a single array to store all key material in,  

+     * to simplify the wiping of the key material at the end. 

+     * The first 32 bytes contain the actual (padded) cipher key. 

+     * The next 32 bytes contain the S-vector in its weird format, 

+     * and we have 4 bytes of overrun necessary for the RS-reduction. 

+     */ 

+    Twofish_Byte K[32+32+4];  

+ 

+    int kCycles;        /* # key cycles, 2,3, or 4. */ 

+ 

+    int i; 

+    Twofish_UInt32 A, B;        /* Used to compute the round keys. */ 

+ 

+    Twofish_Byte * kptr;        /* Three pointers for the RS computation. */ 

+    Twofish_Byte * sptr; 

+    Twofish_Byte * t; 

+ 

+    Twofish_Byte b,bx,bxx;      /* Some more temporaries for the RS computation. */ 

+ 

+    /* Check that the Twofish implementation was initialised. */ 

+    if( Twofish_initialised == 0 ) 

+        { 

+        /*  

+         * You didn't call Twofish_initialise before calling this routine. 

+         * This is a programming error, and therefore we call the fatal 

+         * routine.  

+         * 

+         * I could of course call the initialisation routine here, 

+         * but there are a few reasons why I don't. First of all, the  

+         * self-tests have to be done at startup. It is no good to inform 

+         * the user that the cipher implementation fails when he wants to 

+         * write his data to disk in encrypted form. You have to warn him 

+         * before he spends time typing his data. Second, the initialisation 

+         * and self test are much slower than a single key expansion. 

+         * Calling the initialisation here makes the performance of the 

+         * cipher unpredictable. This can lead to really weird problems  

+         * if you use the cipher for a real-time task. Suddenly it fails  

+         * once in a while the first time you try to use it. Things like  

+         * that are almost impossible to debug. 

+         */ 

+	  /* Twofish_fatal( "Twofish implementation was not initialised.", ERR_INIT ); */

+         

+        /* 

+         * There is always a danger that the Twofish_fatal routine returns, 

+         * in spite of the specifications that it should not.  

+         * (A good programming rule: don't trust the rest of the code.) 

+         * This would be disasterous. If the q-tables and MDS-tables have 

+         * not been initialised, they are probably still filled with zeroes. 

+         * Suppose the MDS-tables are all zero. The key expansion would then 

+         * generate all-zero round keys, and all-zero s-boxes. The danger 

+         * is that nobody would notice as the encry

+         * mangles the input, and the decryption still 'decrypts' it, 

+         * but now in a completely key-independent manner.  

+         * To stop such security disasters, we use blunt force. 

+         * If your program hangs here: fix the fatal routine! 

+         */ 

+        for(;;);        /* Infinite loop, which beats being insecure. */ 

+        } 

+ 

+    /* Check for valid key length. */ 

+    if( key_len < 0 || key_len > 32 ) 

+        { 

+        /*  

+         * This can only happen if a programmer didn't read the limitations 

+         * on the key size.  

+         */ 

+	  Twofish_fatal( "Twofish_prepare_key: illegal key length", ERR_KEY_LEN ); 

+        /*  

+         * A return statement just in case the fatal macro returns. 

+         * The rest of the code assumes that key_len is in range, and would 

+         * buffer-overflow if it wasn't.  

+         * 

+         * Why do we still use a programming language that has problems like 

+         * buffer overflows, when these problems were solved in 1960 with 

+         * the development of Algol? Have we not leared anything? 

+         */ 

+        return ERR_KEY_LEN; 

+        } 

+ 

+    /* Pad the key with zeroes to the next suitable key length. */ 

+    memcpy( K, key, key_len ); 

+    memset( K+key_len, 0, sizeof(K)-key_len ); 

+ 

+    /*  

+     * Compute kCycles: the number of key cycles used in the cipher.  

+     * 2 for 128-bit keys, 3 for 192-bit keys, and 4 for 256-bit keys. 

+     */ 

+    kCycles = (key_len + 7) >> 3; 

+    /* Handle the special case of very short keys: minimum 2 cycles. */ 

+    if( kCycles < 2 ) 

+        { 

+        kCycles = 2; 

+        } 

+ 

+    /*  

+     * From now on we just pretend to have 8*kCycles bytes of  

+     * key material in K. This handles all the key size cases.  

+     */ 

+ 

+    /*  

+     * We first compute the 40 expanded key words,  

+     * formulas straight from the Twofish specifications. 

+     */ 

+    for( i=0; i<40; i+=2 ) 

+        { 

+        /*  

+         * Due to the byte spacing expected by the h() function  

+         * we can pick the bytes directly from the key K. 

+         * As we use bytes, we never have the little/big endian 

+         * problem. 

+         * 

+         * Note that we apply the rotation function only to simple 

+         * variables, as the rotation macro might evaluate its argument 

+         * more than once. 

+         */ 

+        A = h( i  , K  , kCycles ); 

+        B = h( i+1, K+4, kCycles ); 

+        B = ROL32( B, 8 ); 

+ 

+        /* Compute and store the round keys. */ 

+        A += B; 

+        B += A; 

+        xkey->K[i]   = A; 

+        xkey->K[i+1] = ROL32( B, 9 ); 

+        } 

+ 

+    /* Wipe variables that contained key material. */ 

+    A=B=0; 

+ 

+    /*  

+     * And now the dreaded RS multiplication that few seem to understand. 

+     * The RS matrix is not random, and is specially designed to compute the 

+     * RS matrix multiplication in a simple way. 

+     * 

+     * We work in the field GF(2)[x]/x^8+x^6+x^3+x^2+1. Note that this is a 

+     * different field than used for the MDS matrix.  

+     * (At least, it is a different representation because all GF(2^8)  

+     * representations are equivalent in some form.) 

+     *  

+     * We take 8 consecutive bytes of the key and interpret them as  

+     * a polynomial k_0 + k_1 y + k_2 y^2 + ... + k_7 y^7 where  

+     * the k_i bytes are the key bytes and are elements of the finite field. 

+     * We multiply this polynomial by y^4 and reduce it modulo 

+     *     y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1.  

+     * using straightforward polynomial modulo reduction. 

+     * The coefficients of the result are the result of the RS 

+     * matrix multiplication. When we wrote the Twofish specification,  

+     * the original RS definition used the polynomials,  

+     * but that requires much more mathematical knowledge.  

+     * We were already using matrix multiplication in a finite field for  

+     * the MDS matrix, so I re-wrote the RS operation as a matrix  

+     * multiplication to reduce the difficulty of understanding it.  

+     * Some implementors have not picked up on this simpler method of 

+     * computing the RS operation, even though it is mentioned in the 

+     * specifications. 

+     * 

+     * It is possible to perform these computations faster by using 32-bit  

+     * word operations, but that is not portable and this is not a speed- 

+     * critical area. 

+     * 

+     * We explained the 1/x computation when we did the MDS matrix.  

+     * 

+     * The S vector is stored in K[32..64]. 

+     * The S vector has to be reversed, so we loop cross-wise. 

+     * 

+     * Note the weird byte spacing of the S-vector, to match the even  

+     * or odd key words arrays. See the discussion at the Hxx macros for 

+     * details. 

+     */ 

+    kptr = K + 8*kCycles;           /* Start at end of key */ 

+    sptr = K + 32;                  /* Start at start of S */ 

+ 

+    /* Loop over all key material */ 

+    while( kptr > K )  

+        { 

+        kptr -= 8; 

+        /*  

+         * Initialise the polynimial in sptr[0..12] 

+         * The first four coefficients are 0 as we have to multiply by y^4. 

+         * The next 8 coefficients are from the key material. 

+         */ 

+        memset( sptr, 0, 4 ); 

+        memcpy( sptr+4, kptr, 8 ); 

+ 

+        /*  

+         * The 12 bytes starting at sptr are now the coefficients of 

+         * the polynomial we need to reduce. 

+         */ 

+ 

+        /* Loop over the polynomial coefficients from high to low */ 

+        t = sptr+11; 

+        /* Keep looping until polynomial is degree 3; */ 

+        while( t > sptr+3 ) 

+            { 

+            /* Pick up the highest coefficient of the poly. */ 

+            b = *t; 

+ 

+            /*  

+             * Compute x and (x+1/x) times this coefficient.  

+             * See the MDS matrix implementation for a discussion of  

+             * multiplication by x and 1/x. We just use different  

+             * constants here as we are in a  

+             * different finite field representation. 

+             * 

+             * These two statements set  

+             * bx = (x) * b  

+             * bxx= (x + 1/x) * b 

+             */ 

+            bx = (Twofish_Byte)((b<<1) ^ rs_poly_const[ b>>7 ]); 

+            bxx= (Twofish_Byte)((b>>1) ^ rs_poly_div_const[ b&1 ] ^ bx); 

+ 

+            /* 

+             * Subtract suitable multiple of  

+             * y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1  

+             * from the polynomial, except that we don't bother 

+             * updating t[0] as it will become zero anyway. 

+             */ 

+            t[-1] ^= bxx; 

+            t[-2] ^= bx; 

+            t[-3] ^= bxx; 

+            t[-4] ^= b; 

+             

+            /* Go to the next coefficient. */ 

+            t--; 

+            } 

+ 

+        /* Go to next S-vector word, obeying the weird spacing rules. */ 

+        sptr += 8; 

+        } 

+ 

+    /* Wipe variables that contained key material. */ 

+    b = bx = bxx = 0; 

+ 

+    /* And finally, we can compute the key-dependent S-boxes. */ 

+    fill_keyed_sboxes( &K[32], kCycles, xkey ); 

+ 

+    /* Wipe array that contained key material. */ 

+    memset( K, 0, sizeof( K ) );

+    return SUCCESS;

+    } 

+ 

+ 

+/* 

+ * We can now start on the actual encryption and decryption code. 

+ * As these are often speed-critical we will use a lot of macros. 

+ */ 

+ 

+/* 

+ * The g() function is the heart of the round function. 

+ * We have two versions of the g() function, one without an input 

+ * rotation and one with. 

+ * The pre-computed S-boxes make this pretty simple. 

+ */ 

+#define g0(X,xkey) \

+ (xkey->s[0][b0(X)]^xkey->s[1][b1(X)]^xkey->s[2][b2(X)]^xkey->s[3][b3(X)]) 

+ 

+#define g1(X,xkey) \

+ (xkey->s[0][b3(X)]^xkey->s[1][b0(X)]^xkey->s[2][b1(X)]^xkey->s[3][b2(X)]) 

+ 

+/* 

+ * A single round of Twofish. The A,B,C,D are the four state variables, 

+ * T0 and T1 are temporaries, xkey is the expanded key, and r the  

+ * round number. 

+ * 

+ * Note that this macro does not implement the swap at the end of the round. 

+ */ 

+#define ENCRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \

+    T0 = g0(A,xkey); T1 = g1(B,xkey);\

+    C ^= T0+T1+xkey->K[8+2*(r)]; C = ROR32(C,1);\

+    D = ROL32(D,1); D ^= T0+2*T1+xkey->K[8+2*(r)+1] 

+ 

+/* 

+ * Encrypt a single cycle, consisting of two rounds. 

+ * This avoids the swapping of the two halves.  

+ * Parameter r is now the cycle number. 

+ */ 

+#define ENCRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \

+    ENCRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r)   );\

+    ENCRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r)+1 )

+ 

+/* Full 16-round encryption */ 

+#define ENCRYPT( A,B,C,D,T0,T1,xkey ) \

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 );\

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\

+    ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 )

+ 

+/* 

+ * A single round of Twofish for decryption. It differs from 

+ * ENCRYTP_RND only because of the 1-bit rotations. 

+ */ 

+#define DECRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \

+    T0 = g0(A,xkey); T1 = g1(B,xkey);\

+    C = ROL32(C,1); C ^= T0+T1+xkey->K[8+2*(r)];\

+    D ^= T0+2*T1+xkey->K[8+2*(r)+1]; D = ROR32(D,1)

+ 

+/* 

+ * Decrypt a single cycle, consisting of two rounds.  

+ * This avoids the swapping of the two halves.  

+ * Parameter r is now the cycle number. 

+ */ 

+#define DECRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \

+    DECRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r)+1 );\

+    DECRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r)   )

+ 

+/* Full 16-round decryption. */ 

+#define DECRYPT( A,B,C,D,T0,T1, xkey ) \

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 );\

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\

+    DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 ) 

+

+/* 

+ * A macro to read the state from the plaintext and do the initial key xors. 

+ * The koff argument allows us to use the same macro  

+ * for the decryption which uses different key words at the start. 

+ */ 

+#define GET_INPUT( src, A,B,C,D, xkey, koff ) \

+    A = GET32(src   )^xkey->K[  koff]; B = GET32(src+ 4)^xkey->K[1+koff]; \

+    C = GET32(src+ 8)^xkey->K[2+koff]; D = GET32(src+12)^xkey->K[3+koff]

+ 

+/* 

+ * Similar macro to put the ciphertext in the output buffer. 

+ * We xor the keys into the state variables before we use the PUT32  

+ * macro as the macro might use its argument multiple times. 

+ */ 

+#define PUT_OUTPUT( A,B,C,D, dst, xkey, koff ) \

+    A ^= xkey->K[  koff]; B ^= xkey->K[1+koff]; \

+    C ^= xkey->K[2+koff]; D ^= xkey->K[3+koff]; \

+    PUT32( A, dst   ); PUT32( B, dst+ 4 ); \

+    PUT32( C, dst+8 ); PUT32( D, dst+12 )

+ 

+ 

+/* 

+ * Twofish block encryption 

+ * 

+ * Arguments: 

+ * xkey         expanded key array 

+ * p            16 bytes of plaintext 

+ * c            16 bytes in which to store the ciphertext 

+ */ 

+void Twofish_encrypt( Twofish_key * xkey, Twofish_Byte p[16], Twofish_Byte c[16]) 

+    { 

+    Twofish_UInt32 A,B,C,D,T0,T1;       /* Working variables */ 

+ 

+    /* Get the four plaintext words xorred with the key */ 

+    GET_INPUT( p, A,B,C,D, xkey, 0 ); 

+ 

+    /* Do 8 cycles (= 16 rounds) */ 

+    ENCRYPT( A,B,C,D,T0,T1,xkey ); 

+ 

+    /* Store them with the final swap and the output whitening. */ 

+    PUT_OUTPUT( C,D,A,B, c, xkey, 4 ); 

+    } 

+ 

+ 

+/* 

+ * Twofish block decryption. 

+ * 

+ * Arguments: 

+ * xkey         expanded key array 

+ * p            16 bytes of plaintext 

+ * c            16 bytes in which to store the ciphertext 

+ */ 

+void Twofish_decrypt( Twofish_key * xkey, Twofish_Byte c[16], Twofish_Byte p[16]) 

+    { 

+    Twofish_UInt32 A,B,C,D,T0,T1;       /* Working variables */ 

+ 

+    /* Get the four plaintext words xorred with the key */ 

+    GET_INPUT( c, A,B,C,D, xkey, 4 ); 

+ 

+    /* Do 8 cycles (= 16 rounds) */ 

+    DECRYPT( A,B,C,D,T0,T1,xkey ); 

+ 

+    /* Store them with the final swap and the output whitening. */ 

+    PUT_OUTPUT( C,D,A,B, p, xkey, 0 ); 

+    } 

+ 

+/* 

+ * Using the macros it is easy to make special routines for 

+ * CBC mode, CTR mode etc. The only thing you might want to 

+ * add is a XOR_PUT_OUTPUT which xors the outputs into the 

+ * destinationa instead of overwriting the data. This requires 

+ * a XOR_PUT32 macro as well, but that should all be trivial. 

+ * 

+ * I thought about including routines for the separate cipher 

+ * modes here, but it is unclear which modes should be included, 

+ * and each encryption or decryption routine takes up a lot of code space. 

+ * Also, I don't have any test vectors for any cipher modes 

+ * with Twofish. 

+ */ 

+

+

diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/twofish.h b/jni/libzrtp/src/libzrtpcpp/crypto/twofish.h
new file mode 100755
index 0000000..0c8b0d7
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/twofish.h
@@ -0,0 +1,265 @@
+/* 

+ * Fast, portable, and easy-to-use Twofish implementation,  

+ * Version 0.3. 

+ * Copyright (c) 2002 by Niels Ferguson. 

+ * 

+ * See the twofish.c file for the details of the how and why of this code. 

+ * 

+ * The author hereby grants a perpetual license to everybody to 

+ * use this code for any purpose as long as the copyright message is included 

+ * in the source code of this or any derived work. 

+ */ 

+ 

+ 

+/* 

+ * PLATFORM FIXES 

+ * ============== 

+ * 

+ * The following definitions have to be fixed for each particular platform  

+ * you work on. If you have a multi-platform program, you no doubt have  

+ * portable definitions that you can substitute here without changing  

+ * the rest of the code. 

+ * 

+ * The defaults provided here should work on most PC compilers. 

+ */ 

+ 

+#ifndef TWOFISH_H

+#define TWOFISH_H

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+/**

+ * @file twofish.h

+ * @brief Function that provide basic Twofish crypto support

+ * 

+ * @ingroup GNU_ZRTP

+ * @{

+ */

+ 

+/**

+ * A Twofish_Byte must be an unsigned 8-bit integer.

+ *

+ * It must also be the elementary data size of your C platform, 

+ * i.e. sizeof( Twofish_Byte ) == 1. 

+ */ 

+typedef unsigned char   Twofish_Byte; 

+ 

+/**

+ * A Twofish_UInt32 must be an unsigned integer of at least 32 bits.  

+ *  

+ * This type is used only internally in the implementation, so ideally it 

+ * would not appear in the header file, but it is used inside the 

+ * Twofish_key structure which means it has to be included here. 

+ */ 

+typedef unsigned int    Twofish_UInt32; 

+ 

+ 

+/* 

+ * END OF PLATFORM FIXES 

+ * ===================== 

+ *  

+ * You should not have to touch the rest of this file, but the code 

+ * in twofish.c has a few things you need to fix too. 

+ */ 

+

+/**

+ * Return  codes

+ */

+#define SUCCESS          1

+#define ERR_UINT32      -2

+#define ERR_BYTE        -3

+#define ERR_GET32       -4

+#define ERR_PUT32       -5

+#define ERR_ROLR        -6

+#define ERR_BSWAP       -7

+#define ERR_SELECTB     -8

+#define ERR_TEST_ENC    -9

+#define ERR_TEST_DEC   -10

+#define ERR_SEQ_ENC    -11

+#define ERR_SEQ_DEC    -12

+#define ERR_ODD_KEY    -13

+#define ERR_INIT       -14

+#define ERR_KEY_LEN    -15

+#define ERR_ILL_ARG    -16

+

+

+/**

+ * Structure that contains a prepared Twofish key.

+ *

+ * A cipher key is used in two stages. In the first stage it is converted 

+ * form the original form to an internal representation.  

+ * This internal form is then used to encrypt and decrypt data.  

+ * This structure contains the internal form. It is rather large: 4256 bytes 

+ * on a platform with 32-bit unsigned values. 

+ * 

+ * Treat this as an opague structure, and don't try to manipulate the 

+ * elements in it. I wish I could hide the inside of the structure, 

+ * but C doesn't allow that. 

+ */ 

+typedef 

+    struct

+        {

+        Twofish_UInt32 s[4][256];   /* pre-computed S-boxes */ 

+        Twofish_UInt32 K[40];       /* Round key words */ 

+        }

+    Twofish_key; 

+

+

+/**

+ * Initialise and test the Twofish implementation.  

+ *  

+ * This function MUST be called before any other function in the  

+ * Twofish implementation is called. 

+ * It only needs to be called once. 

+ *  

+ * Apart from initialising the implementation it performs a self test. 

+ * If the Twofish_fatal function is not called, the code passed the test. 

+ * (See the twofish.c file for details on the Twofish_fatal function.)

+ *

+ * @returns a negative number if an error happend, +1 otherwise

+ */ 

+extern int Twofish_initialise(); 

+ 

+ 

+/**

+ * Convert a cipher key to the internal form used for  

+ * encryption and decryption. 

+ *  

+ * The cipher key is an array of bytes; the Twofish_Byte type is  

+ * defined above to a type suitable on your platform.  

+ * 

+ * Any key must be converted to an internal form in the Twofisk_key structure 

+ * before it can be used. 

+ * The encryption and decryption functions only work with the internal form. 

+ * The conversion to internal form need only be done once for each key value. 

+ * 

+ * Be sure to wipe all key storage, including the Twofish_key structure,  

+ * once you are done with the key data.  

+ * A simple memset( TwofishKey, 0, sizeof( TwofishKey ) ) will do just fine. 

+ * 

+ * Unlike most implementations, this one allows any key size from 0 bytes  

+ * to 32 bytes. According to the Twofish specifications,  

+ * irregular key sizes are handled by padding the key with zeroes at the end  

+ * until the key size is 16, 24, or 32 bytes, whichever 

+ * comes first. Note that each key of irregular size is equivalent to exactly 

+ * one key of 16, 24, or 32 bytes. 

+ * 

+ * WARNING: Short keys have low entropy, and result in low security. 

+ * Anything less than 8 bytes is utterly insecure. For good security 

+ * use at least 16 bytes. I prefer to use 32-byte keys to prevent 

+ * any collision attacks on the key. 

+ * 

+ * The key length argument key_len must be in the proper range. 

+ * If key_len is not in the range 0,...,32 this routine attempts to generate  

+ * a fatal error (depending on the code environment),  

+ * and at best (or worst) returns without having done anything. 

+ * 

+ * @param key      Array of key bytes 

+ * @param key_len  Number of key bytes, must be in the range 0,1,...,32.  

+ * @param xkey     Pointer to an Twofish_key structure that will be filled  

+ *                 with the internal form of the cipher key.

+ * @returns a negative number if an error happend, +1 otherwise

+ */ 

+extern int Twofish_prepare_key(

+                                Twofish_Byte key[],

+                                int key_len,

+                                Twofish_key * xkey

+                                );

+

+

+/**

+ * Encrypt a single block of data. 

+ * 

+ * This function encrypts a single block of 16 bytes of data. 

+ * If you want to encrypt a larger or variable-length message,  

+ * you will have to use a cipher mode, such as CBC or CTR.  

+ * These are outside the scope of this implementation. 

+ * 

+ * The xkey structure is not modified by this routine, and can be 

+ * used for further encryption and decryption operations. 

+ * 

+ * @param xkey     pointer to Twofish_key, internal form of the key 

+ *                 produces by Twofish_prepare_key() 

+ * @param p        Plaintext to be encrypted 

+ * @param c        Place to store the ciphertext 

+ */ 

+extern void Twofish_encrypt(

+                            Twofish_key * xkey,

+                            Twofish_Byte p[16],

+                            Twofish_Byte c[16]

+                            ); 

+

+

+/**

+ * Decrypt a single block of data. 

+ * 

+ * This function decrypts a single block of 16 bytes of data. 

+ * If you want to decrypt a larger or variable-length message,  

+ * you will have to use a cipher mode, such as CBC or CTR.  

+ * These are outside the scope of this implementation. 

+ * 

+ * The xkey structure is not modified by this routine, and can be 

+ * used for further encryption and decryption operations. 

+ * 

+ * @param xkey     pointer to Twofish_key, internal form of the key 

+ *                 produces by Twofish_prepare_key() 

+ * @param c        Ciphertext to be decrypted 

+ * @param p        Place to store the plaintext 

+ */ 

+extern void Twofish_decrypt(

+                            Twofish_key * xkey,

+                            Twofish_Byte c[16],

+                            Twofish_Byte p[16]

+                            ); 

+

+

+/**

+ * Encrypt data in CFB mode. 

+ * 

+ * This function encrypts data in CFB mode.

+ *

+ * The key structure is not modified by this routine, and can be 

+ * used for further encryption and decryption operations. 

+ * 

+ * @param keyCtx   pointer to Twofish_key, internal form of the key 

+ *                 produced by Twofish_prepare_key() 

+ * @param in       Plaintext to be encrypted 

+ * @param out      Place to store the ciphertext 

+ * @param len      number of bytes to encrypt.

+ * @param ivec     initialization vector for this CFB mode encryption.

+ * @param num      pointer to integer that holds number of available crypto bytes.

+ */

+void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in,

+                            Twofish_Byte* out, size_t len,

+                            Twofish_Byte* ivec, int *num);

+

+/**

+ * Decrypt data in CFB mode. 

+ * 

+ * This function decrypts data in CFB. 

+ *

+ * The key structure is not modified by this routine, and can be 

+ * used for further encryption and decryption operations. 

+ * 

+ * @param keyCtx   pointer to Twofish_key, internal form of the key 

+ *                 produced by Twofish_prepare_key() 

+ * @param in       Ciphertext to be decrypted 

+ * @param out      Place to store the plaintext 

+ * @param len      number of bytes to decrypt.

+ * @param ivec     initialization vector for this CFB mode encryption.

+ * @param num      pointer to integer that holds number of available crypto bytes.

+ */ 

+void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in,

+                            Twofish_Byte* out, size_t len,

+                            Twofish_Byte* ivec, int *num);

+/**

+ * @}

+ */

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/jni/libzrtp/src/libzrtpcpp/crypto/twofish_cfb.c b/jni/libzrtp/src/libzrtpcpp/crypto/twofish_cfb.c
new file mode 100755
index 0000000..7540738
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/crypto/twofish_cfb.c
@@ -0,0 +1,82 @@
+#include <stdint.h>

+#include <stdlib.h>

+

+#include "twofish.h"

+

+void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in, 

+			    Twofish_Byte* out, size_t len,

+			    Twofish_Byte* ivec, int32_t *num)

+{

+  uint32_t n;

+

+  n = *num;

+

+  do {

+    while (n && len) {

+      *(out++) = ivec[n] ^= *(in++);

+      --len;

+      n = (n+1) % 16;

+    }

+    while (len>=16) {

+      Twofish_encrypt(keyCtx, ivec, ivec);

+      for (n=0; n<16; n+=sizeof(size_t)) {

+	*(size_t*)(out+n) =

+	  *(size_t*)(ivec+n) ^= *(size_t*)(in+n);

+      }

+      len -= 16;

+      out += 16;

+      in  += 16;

+    }

+    n = 0;

+    if (len) {

+      Twofish_encrypt(keyCtx, ivec, ivec);

+      while (len--) {

+	out[n] = ivec[n] ^= in[n];

+	++n;

+      }

+    }

+    *num = n;

+    return;

+  } while (0);

+}

+

+

+void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in, 

+			    Twofish_Byte* out, size_t len,

+			    Twofish_Byte* ivec, int32_t *num)

+{

+  uint32_t n;

+

+  n = *num;

+

+  do {

+    while (n && len) {

+      unsigned char c;

+      *(out++) = ivec[n] ^ (c = *(in++)); ivec[n] = c;

+      --len;

+      n = (n+1) % 16;

+    }

+    while (len>=16) {

+      Twofish_encrypt(keyCtx, ivec, ivec);

+      for (n=0; n<16; n+=sizeof(size_t)) {

+	size_t t = *(size_t*)(in+n);

+	*(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t;

+	*(size_t*)(ivec+n) = t;

+      }

+      len -= 16;

+      out += 16;

+      in  += 16;

+    }

+    n = 0;

+    if (len) {

+      Twofish_encrypt(keyCtx, ivec, ivec);

+      while (len--) {

+	unsigned char c;

+	out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c;

+	++n;

+      }

+    }

+    *num = n;

+    return;

+  } while (0);

+}

diff --git a/jni/libzrtp/src/libzrtpcpp/zrtpPacket.h b/jni/libzrtp/src/libzrtpcpp/zrtpPacket.h
new file mode 100644
index 0000000..18ba7a1
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/zrtpPacket.h
@@ -0,0 +1,342 @@
+/*
+  Copyright (C) 2006-2010 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef ZRTPPACKET_H
+#define ZRTPPACKET_H
+
+/**
+ *
+ * @file zrtpPacket.h
+ * @brief The data structures and definitions for ZRTP messages
+ * 
+ * This include file defines the ZRTP message structures. Refer to
+ * chapter 5 of the ZRTP specification which defines the ZRTP messages and
+ * the transport format.
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdio.h>
+
+/**
+ * The following defines match the ZRTP specification, chapter 5
+ */
+#define ZRTP_MAGIC       0x5a525450
+
+#define ZRTP_WORD_SIZE   4
+#define CRC_SIZE         4
+
+#define TYPE_SIZE        (2*ZRTP_WORD_SIZE)
+#define CLIENT_ID_SIZE   (4*ZRTP_WORD_SIZE)
+#define HASH_IMAGE_SIZE  (8*ZRTP_WORD_SIZE)
+#define ZID_SIZE         (3*ZRTP_WORD_SIZE)
+#define HVI_SIZE         (8*ZRTP_WORD_SIZE)
+#define HMAC_SIZE        (2*ZRTP_WORD_SIZE)
+#define ID_SIZE          (2*ZRTP_WORD_SIZE)
+#define IV_SIZE          (4*ZRTP_WORD_SIZE)
+#define PING_HASH_SIZE   (2*ZRTP_WORD_SIZE)
+
+
+/**
+ * The ZRTP message header
+ * 
+ * A complete ZRTP message always consists of the ZRTP header
+ * and a message specific part. This specific part may have a variable
+ * length. The length field includes the header.
+ */
+typedef struct zrtpPacketHeader {
+    uint16_t    zrtpId;         ///< Id to identify the message, always 0x505a
+    uint16_t    length;         ///< Length of the ZRTP message in words
+    uint8_t     messageType[TYPE_SIZE]; ///< 2 word (8 octest) message type in ASCII
+} zrtpPacketHeader_t;
+
+/**
+ * Hello message, fixed part.
+ * 
+ * The complete Hello message consists of ZRTP message header, Hello fixed 
+ * part and a variable part. The Hello class initializes the variable part.
+ */
+typedef struct Hello {
+    uint8_t  version[ZRTP_WORD_SIZE];   ///< Announces the ZRTP protocol version 
+    uint8_t  clientId[CLIENT_ID_SIZE];  ///< A 4 word ASCII identifier of the ZRTP client
+    uint8_t  hashH3[HASH_IMAGE_SIZE];   ///< The last hash of the hash chain (chap. 9)
+    uint8_t  zid[ZID_SIZE];             ///< ZID - 3 word identifier for the ZRTP endpoint
+    uint8_t  flags;                     ///< flag bits (chap 7.2)
+    uint8_t  lengths[3];                ///< number of algorithms present
+} Hello_t;
+
+/**
+ * The complete ZRTP Hello message.
+ */
+typedef struct HelloPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    Hello_t hello;                  ///< Fixed part of Hello message
+} HelloPacket_t;
+
+/**
+ * HelloAck message.
+ * 
+ * The complete HelloAck message consists of ZRTP message header and
+ * the CRC which is the only HelloAck specific data.
+ */
+typedef struct HelloAckPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} HelloAckPacket_t;
+
+/**
+ * Commit message
+ * 
+ * There are three subtypes of Commit messages, each of which
+ * has a fixed size. The data structure defines the maximum
+ * Commit message. During the ZRTP protocol the implementation
+ * uses fileds according to the use case (DH handshake,
+ * Multi-stream handshake) and adjusts the length.
+ */
+typedef struct Commit {
+    uint8_t hashH2[HASH_IMAGE_SIZE];        ///< The second hash of the hash chain (chap. 9)
+    uint8_t	zid[ZID_SIZE];                  ///< ZID - 3 word identifier for the ZRTP endpoint
+    uint8_t hash[ZRTP_WORD_SIZE];           ///< Commited hash algorithm
+    uint8_t cipher[ZRTP_WORD_SIZE];         ///< Commited symmetrical cipher algorithm
+    uint8_t authlengths[ZRTP_WORD_SIZE];    ///< Commited SRTP authentication algorithm
+    uint8_t	pubkey[ZRTP_WORD_SIZE];         ///< Commited key agreement algorithm
+    uint8_t	sas[ZRTP_WORD_SIZE];            ///< Commited SAS algorithm
+    uint8_t	hvi[HVI_SIZE];                  ///< Hash value Initiator - chap 4.4.1.1
+    uint8_t	hmac[HMAC_SIZE];                ///< MAC of the Commit message
+} Commit_t;
+
+/**
+ * The complete ZRTP Commit message.
+ */
+typedef struct CommitPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    Commit_t commit;                ///< Commit message
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} CommitPacket_t;
+
+/**
+ * DHPart1 and DHPart2 messages
+ * 
+ * The DHPart messages have a variable length. The following struct
+ * defines the fixed part only. The DHPart class initializes the
+ * variable part.
+ */
+typedef struct DHPart {
+    uint8_t hashH1[HASH_IMAGE_SIZE];        ///< The first hash of the hash chain (chap. 9)
+    uint8_t rs1Id[ID_SIZE];                 ///< Id of first retained secret
+    uint8_t rs2Id[ID_SIZE];                 ///< Id of second retained secret
+    uint8_t auxSecretId[ID_SIZE];           ///< Id of additional (auxilliary) secret
+    uint8_t pbxSecretId[ID_SIZE];           ///< Id of PBX secret (chap 7.3.1)
+}  DHPart_t;
+
+/**
+ * The complete ZRTP DHPart message.
+ */
+typedef struct DHPartPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    DHPart_t dhPart;                ///< DHPart message fixed part
+} DHPartPacket_t;
+
+/**
+ * Confirm1 and Confirm2 messages
+ * 
+ * The Confirm message have a variable length. The following struct
+ * defines the fixed part only. The Confirm class initializes the
+ * variable part.
+ * 
+ * ZRTP encrypts a part of the Confirm messages, starting at @c hashH0 
+ * and includes the variable part.
+ */
+typedef struct Confirm {
+    uint8_t	 hmac[HMAC_SIZE];           ///< MAC over the encrypted part of Commit message 
+    uint8_t  iv[IV_SIZE];               ///< IV for CFB mode to encrypt part of Commit
+    uint8_t  hashH0[HASH_IMAGE_SIZE];   ///< starting hash of hash chain (chap. 9)
+    uint8_t  filler[2];                 ///< Filler bytes
+    uint8_t  sigLength;                 ///< Length of an optional signature length (chap 7.2)
+    uint8_t  flags;                     ///< various flags to control behaviour
+    uint32_t expTime;                   ///< Expiration time of retained secrets (chap 4.9)
+} Confirm_t;
+
+/**
+ * The complete ZRTP Confirm message.
+ */
+typedef struct ConfirmPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    Confirm_t confirm;              ///< Confirm message fixed part
+} ConfirmPacket_t;
+
+/**
+ * Conf2Ack message.
+ * 
+ * The complete Conf2Ack message consists of ZRTP message header and
+ * the CRC which is the only Conf2Ack specific data.
+ */
+typedef struct Conf2AckPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} Conf2AckPacket_t;
+
+/**
+ * The GoClear message is currently not used in
+ * GNU ZRTP C++ - not support for GoClear.
+ */
+typedef struct GoClear {
+    uint8_t clearHmac[HMAC_SIZE];   ///< no used
+} GoClear_t;
+
+/**
+ * The complete ZRTP GoClear message - no used.
+ */
+typedef struct GoClearPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    GoClear_t goClear;              ///< not used
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} GoClearPacket_t;
+
+/**
+ * The ClearAck message is currently not used in
+ * GNU ZRTP C++ - not support for GoClear.
+ */
+typedef struct ClearAckPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} ClearAckPacket_t;
+
+/**
+ * The Error message
+ */
+typedef struct Error {
+    uint32_t errorCode;             ///< Error code, see chap 5.9
+} Error_t;
+
+/**
+ * The complete ZRTP Error message.
+ */
+typedef struct ErrorPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    Error_t error;                  ///< Error message part
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} ErrorPacket_t;
+
+/**
+ * ErrorAck message.
+ * 
+ * The complete ErrorAck message consists of ZRTP message header and
+ * the CRC which is the only ErrorAck specific data.
+ */
+typedef struct ErrorAckPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} ErrorAckPacket_t;
+
+/**
+ * Ping message.
+ * 
+ * The Ping message has a fixed size.
+ */
+typedef struct Ping {
+    uint8_t version[ZRTP_WORD_SIZE];    ///< The ZRTP protocol version
+    uint8_t epHash[PING_HASH_SIZE];     ///< End point hash, see chap 5.16
+} Ping_t;
+
+/**
+ * The complete ZRTP Ping message.
+ */
+typedef struct PingPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    Ping_t ping;                    ///< Ping message part
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} PingPacket_t;
+
+/**
+ * PingAck message.
+ * 
+ * The PingAck message has a fixed size.
+ */
+typedef struct PingAck {
+    uint8_t version[ZRTP_WORD_SIZE];        ///< The ZRTP protocol version
+    uint8_t localEpHash[PING_HASH_SIZE];    ///< Local end point hash, see chap 5.16
+    uint8_t remoteEpHash[PING_HASH_SIZE];   ///< Remote end point hash, see chap 5.16
+    uint32_t ssrc;                          ///< SSRC copied from the Ping message (RTP packet part)
+} PingAck_t;
+
+/**
+ * The complete ZRTP PingAck message.
+ */
+typedef struct PingAckPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    PingAck_t pingAck;              ///< PingAck message part
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} PingAckPacket_t;
+
+/**
+ * SASrelay message
+ * 
+ * The SASrelay message has a variable length. The following struct
+ * defines the fixed part only. The SASrelay class initializes the
+ * variable part.
+ * 
+ * ZRTP encrypts a part of the SASrelay message, starting at @c hashH0 
+ * and includes the variable part.
+ */
+typedef struct SASrelay {
+    uint8_t  hmac[HMAC_SIZE];           ///< MAC over the encrypted part of Commit message 
+    uint8_t  iv[IV_SIZE];               ///< IV for CFB mode to encrypt part of Commit
+    uint8_t  filler[2];                 ///< Filler bytes
+    uint8_t  sigLength;                 ///< Length of an optional signature length (chap 7.2)
+    uint8_t  flags;                     ///< various flags to control behaviour
+    uint8_t  sas[ZRTP_WORD_SIZE];       ///< SAS algorithm to use
+    uint8_t  trustedSasHash[HASH_IMAGE_SIZE];  ///< New trusted SAS hash for enrolled client
+} SASrelay_t;
+
+/**
+ * The complete ZRTP SASrelay message.
+ */
+typedef struct SASrelayPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    SASrelay_t sasrelay;            ///< SASrelay message fixed part
+} SASrelayPacket_t;
+
+/**
+ * RelayAck message.
+ * 
+ * The complete RelayAck message consists of ZRTP message header and
+ * the CRC which is the only RelayAck specific data.
+ */
+typedef struct RelayAckPacket {
+    zrtpPacketHeader_t hdr;         ///< ZRTP Header
+    uint8_t crc[ZRTP_WORD_SIZE];    ///< CRC of ZRTP message
+} RelayAckPacket_t;
+
+#endif // ZRTPPACKET_H
+
+/**
+ * @}
+ */
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/jni/libzrtp/src/libzrtpcpp/zrtpccrtp.h b/jni/libzrtp/src/libzrtpcpp/zrtpccrtp.h
new file mode 100644
index 0000000..d94ca5a
--- /dev/null
+++ b/jni/libzrtp/src/libzrtpcpp/zrtpccrtp.h
@@ -0,0 +1,76 @@
+/*
+  Copyright (C) 2006-2007 Werner Dittmann
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCCRTP_H_
+#define _ZRTPCCRTP_H_
+
+#include <ccrtp/rtp.h>
+#include <libzrtpcpp/ZrtpQueue.h>
+
+NAMESPACE_COMMONCPP
+
+// Define a dummy variable only to overcome a doxygen problem.
+static int dummy __attribute__ ((unused)) = 0;
+
+
+/**
+ * @typedef SymmetricZRTPSession
+ *
+ * Uses one pair of sockets, (1) for RTP data and (2) for RTCP
+ * transmission/reception.
+ *
+ * This session uses the ZrtpQueue instead of the AVPQueue. The ZrtpQueue
+ * inherits from AVPQueue and adds support for ZRTP thus enabling
+ * ad-hoc key negotiation to setup SRTP sessions.
+ *
+ * @short Symmetric UDP/IPv4 RTP session scheduled by one thread of execution.
+ **/
+typedef SingleThreadRTPSession<SymmetricRTPChannel,
+                               SymmetricRTPChannel,
+                               ZrtpQueue> SymmetricZRTPSession;
+
+
+#ifdef CCXX_IPV6
+/**
+ * @typedef SymmetricZRTPSession
+ *
+ * Uses one pair of sockets, (1) for RTP data and (2) for RTCP
+ * transmission/reception.
+ *
+ * This session uses the ZrtpQueue instead of the AVPQueue. The ZrtpQueue
+ * inherits from AVPQueue and adds support for ZRTP thus enabling
+ * ad-hoc key negotiation to setup SRTP sessions.
+ *
+ * @short Symmetric UDP/IPv6 RTP session scheduled by one thread of execution.
+ **/
+typedef SingleThreadRTPSessionIPV6<SymmetricRTPChannelIPV6,
+                   SymmetricRTPChannelIPV6,
+                   ZrtpQueue> SymmetricZRTPSessionIPV6;
+#endif // CCXX_IPV6
+
+END_NAMESPACE
+
+#endif // _ZRTPCCRTP_H_
+
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */