* #40116: Add zrtp related files, update libzrtpcpp
diff --git a/jni/libzrtp/sources/.gitignore b/jni/libzrtp/sources/.gitignore
index ee3d613..4876ff9 100644
--- a/jni/libzrtp/sources/.gitignore
+++ b/jni/libzrtp/sources/.gitignore
@@ -1,4 +1,4 @@
-build/
+build*/
 autoconf/
 doc/html/
 configure
@@ -16,4 +16,8 @@
 *.pc
 *.spec
 *~
+.DS_Store
+._.DS_Store
+._buildmac
+.directory
 
diff --git a/jni/libzrtp/sources/CMakeLists.txt b/jni/libzrtp/sources/CMakeLists.txt
index 430f5e7..8e0bb80 100755
--- a/jni/libzrtp/sources/CMakeLists.txt
+++ b/jni/libzrtp/sources/CMakeLists.txt
@@ -11,84 +11,54 @@
 cmake_minimum_required(VERSION 2.6)
 
 PROJECT(libzrtpcpp)
-set (PACKAGE libzrtpcpp)
-set (VERSION 3.0.0)
-set (SOVERSION ${VERSION})
-STRING(REGEX REPLACE "[.].*$" "" SOVERSION ${SOVERSION})
 
-SET(CPACK_PACKAGE_VERSION_MAJOR ${SOVERSION})
-SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION})
-SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION})
-STRING(REGEX REPLACE "[.][0-9]*$" "" CPACK_PACKAGE_VERSION_MINOR ${VERSION})
-STRING(REGEX REPLACE ".*[.]" "" CPACK_PACKAGE_VERSION_MINOR ${CPACK_PACKAGE_VERSION_MINOR})
-STRING(REGEX REPLACE ".*[.]" "" CPACK_PACKAGE_VERSION_PATCH ${VERSION})
+SET(CPACK_PACKAGE_VERSION_MAJOR 4)
+SET(CPACK_PACKAGE_VERSION_MINOR 1)
+SET(CPACK_PACKAGE_VERSION_PATCH 1)
 
-include(cmake/Modules/AutoArgs.cmake)
-include(cmake/Modules/FindGcryptConfig.cmake)
+set (VERSION 4.1.1)
+set (SOVERSION 4)
 
-# Define supported -Denable-* command line parameters.
+# Define supported command line parameters.
 #
-# Example to build the tivi client: cmake -Denable-tivi=true ..
+# Example to build the tivi client: cmake -DTIVI=true ..
 # Without any options cmake generates libzrtpcpp for use with GNU ccRTP
 #
-enable_arg(ccrtp false "Build library to use with GNU ccRTP.")
-enable_arg(crypto_standalone false "Use embedded crypto and big number modules.")
-enable_arg(tivi false "Build library for the tivi client, implies '-Denable-crypto_standalone=true'.")
-enable_arg(sqlite false "Use SQLite DB as backend for ZRTP cache.")
-args_help()
+option(CCRTP "Build library to use with GNU ccRTP." OFF)
+option(CORE_LIB "Build core library only, no spcific client support." OFF)
+option(CRYPTO_STANDALONE "Use embedded crypto and big number modules." ON)
+option(TIVI "Build library for the tivi client, implies '-DCRYPTO_STNDALONE=true'." OFF)
+option(SQLITE "Use SQLite DB as backend for ZRTP cache." OFF)
+option(SDES "Include SDES when not building for CCRTP." ON)
+
+option(ANDROID "Generate Android makefiles (Android.mk)" ON)
+option(JAVA "Generate Java support files (requires JDK and SWIG)" OFF)
+
 
 # **** Check what and how to build ****
 #
-if (enable_ccrtp AND enable_tivi)
+if (CCRTP AND TIVI)
     MESSAGE(FATAL_ERROR "Cannot build more than one client at once. Use different build directories.")
 endif()
 
-if (enable_ccrtp)
-    if (USES_CCRTP_INCLUDE_DIRS)
-        message(STATUS "  Using local commoncpp dependency")
-    else()
-        find_package(PkgConfig)
-        pkg_check_modules(USES_CCRTP libccrtp>=2.0.0)
-    endif()
-    include_directories(${USES_CCRTP_INCLUDE_DIRS})
-    link_directories(${USES_CRTP_LIBRARY_DIRS})
-    add_definitions(${USES_CCRTP_CFLAGS})
-    set (LIBS ${LIBS} ${USES_CCRTP_LDFLAGS} ${USES_CCRTP_LIBRARIES})
+if (CCRTP)
     set (PACKAGE libzrtpcpp)
     set(zrtplibName zrtpcpp)
-elseif (enable_tivi)
+elseif (TIVI)
     set (PACKAGE libzrtptivi)
     set(zrtplibName zrtptivi)
-    set (enable_crypto_standalone true)
+    set(CRYPTO_STANDALONE true)
+    set(SQLITE true)
+elseif (CORE_LIB)
+    set (PACKAGE libzrtpcore)
+    set(zrtplibName zrtpcppcore)
 else()
     MESSAGE(WARNING "No client defined, building for GNU ccRTP.")
     set (PACKAGE libzrtpcpp)
-    set(enable_ccrtp true)
+    set(CCRTP true)
     set(zrtplibName zrtpcpp)
 endif()
 
-if (enable_crypto_standalone)
-    set(CRYPTO_STANDALONE TRUE)
-endif()
-
-if(CMAKE_GENERATOR MATCHES "Unix Makefiles")
-	add_custom_target(cleandist
-		WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
-		COMMAND rm -f "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}[-_]*.gz"
-		COMMAND rm -f "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}_*.dsc"
-		COMMAND rm -f "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}-*.rpm"
-		COMMAND rm -f "${CMAKE_CURRENT_BINARY_DIR}/*${PACKAGE}*[-_]*.deb"
-		COMMAND rm -f "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}-*.zip"
-    COMMAND rm -f "${CMAKE_CURRENT_BINARY_DIR}/*${PACKAGE}*.changes"
-	)
-
-	add_custom_target(dist
-		DEPENDS cleandist
-		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-		COMMAND git archive --format tar --output="${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}-${VERSION}.tar" --prefix="${PACKAGE}-${VERSION}/" HEAD
-		COMMAND gzip "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}-${VERSION}.tar"
-	)
-endif()
 
 if(MSVC60)
     set(BUILD_STATIC ON CACHE BOOL "static linking only" FORCE)
@@ -100,7 +70,10 @@
 # set to true for debug and trace during CMakeLists development
 # set(CMAKE_VERBOSE_MAKEFILE TRUE)
 
-MESSAGE( STATUS "Configuring GNU ${PROJECT_NAME} ${VERSION} for ${PACKAGE}...")
+execute_process(COMMAND git rev-parse --short HEAD OUTPUT_VARIABLE GIT_COMMIT)
+STRING(REGEX REPLACE "(\r?\n)+$" "" GIT_COMMIT "${GIT_COMMIT}")
+
+MESSAGE( STATUS "Configuring GNU ${PROJECT_NAME} ${VERSION} for ${PACKAGE}, commit: ${GIT_COMMIT} ...")
 
 # include most of the fine stuff we need
 include(FindPkgConfig)
@@ -123,7 +96,7 @@
 check_include_files(stdlib.h HAVE_STDLIB_H)
 check_include_files(string.h HAVE_STRING_H)
 
-if (NOT enable_crypto_standalone)
+if (NOT CRYPTO_STANDALONE)
     pkg_check_modules(OPENSSL libcrypto>=0.9.8)
     if (OPENSSL_FOUND)
       set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) #update include files search directory
@@ -165,7 +138,7 @@
     configure_file(${CMAKE_SOURCE_DIR}/bnlib/bnconfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/bnconfig.h)
 endif()
 
-if (enable_sqlite)
+if (SQLITE)
     pkg_check_modules(SQLITE3 sqlite3>=3.7)
     if (SQLITE3_FOUND)
         check_include_files(sqlite3.h HAVE_SQLITE_H)
@@ -175,148 +148,119 @@
     endif()
 endif()
 
-# now get info about crypto libraries
-gcr_check(GCRYPT gcrypt)
-#if(GCRYPT_FOUND)
-#  check_include_files(gcrypt.h HAVE_GCRYPT_H)
-#  set(LIBS ${LIBS} ${GCRYPT_LIBRARIES})
-#  set(BUILD_REQ "libgcrypt-devel")
-#  set(CRYPTOBACKEND="")
-#  set(PACKAGE_REQ "libgcrypt")
-#else()
-  pkg_check_modules(OPENSSL libcrypto>=0.9.8)
-  if (OPENSSL_FOUND)
-    set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIRS}) #update include files search directory
-    check_include_files(openssl/bn.h HAVE_OPENSSL_BN_H)
-    check_include_files(openssl/aes.h HAVE_OPENSSL_AES_H)
-    check_include_files(openssl/sha.h HAVE_OPENSSL_SHA_H)
-    check_library_exists(crypto EVP_CipherInit_ex "${OPENSSL_LIBDIR}" HAVE_SSL_CRYPT) #use search lib directory from pkg-config
-    set(LIBS ${LIBS} -lcrypto)
-    set(CRYPTOBACKEND "libcrypto >= 0.9.8")
-    set(BUILD_REQ "libopenssl-devel >= 0.9.8")
-    set(PACKAGE_REQ "libopenssl >= 0.9.8")
-    include_directories(${OPENSSL_INCLUDE_DIRS}) #update includes directory from pkg-config
-  else()
-    message(FATAL_ERROR "No crypto library found")
-  endif()
-#endif()
-
-check_include_files(stdlib.h HAVE_STDLIB_H)
-check_include_files(string.h HAVE_STRING_H)
-
-# necessary and required modules checked, ready to generate config.h
-configure_file(libzrtpcpp-config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/libzrtpcpp-config.h)
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-# the following set(...) commands are only to have backward
-# compatibility with autoconf stuff to generate the pc file
-set(prefix ${CMAKE_INSTALL_PREFIX})
-set(exec_prefix ${prefix}/bin)
-set(libdir ${prefix}/${LIBDIRNAME})
-set(includedir ${prefix}/include)
-set(PACKAGE pkgconfig)
-configure_file(libzrtpcpp.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libzrtpcpp.pc @ONLY)
-
-configure_file(libzrtpcpp.spec.cmake ${CMAKE_CURRENT_BINARY_DIR}/libzrtpcpp.spec @ONLY)
-
-#to make sure includes are first taken from those directory
-include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src)
+# necessary and required modules checked, ready to generate config.h in top-level build directory
+configure_file(config.h.cmake ${CMAKE_BINARY_DIR}/config.h)
 
 add_definitions(-g -O2 -fno-strict-aliasing)
 if(CMAKE_COMPILER_IS_GNUCXX)
-  add_definitions(-Wno-long-long -Wno-char-subscripts)
-  add_definitions(-Wall -pedantic)
-  add_definitions(-DNEW_STDCPP)
+#    add_definitions(-Wno-long-long -Wno-char-subscripts)
+#    add_definitions(-Wall -ansi -pedantic)
+#    add_definitions(-Wall -pedantic)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -std=c99")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -std=c++11")
+    add_definitions(-DNEW_STDCPP)
 endif()
 
 include_directories(BEFORE ${CMAKE_BINARY_DIR})
-include_directories (${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/zrtp)
-if(enable_standalone)
-    include_directories (${CMAKE_CURRENT_SOURCE_DIR}/bnlib)
+include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/zrtp)
+
+if(CRYPTO_STANDALONE)
+    add_definitions(-DSUPPORT_NON_NIST)
+    include_directories (${CMAKE_SOURCE_DIR}/bnlib)
+endif()
+
+if (SDES AND NOT CCRTP)
+    set (sdes_src ${CMAKE_SOURCE_DIR}/zrtp/ZrtpSdesStream.cpp)
 endif()
 
 # **** The following source files a common for all clients ****
 #
-if (NOT enable_ccrtp)
-    set (sdes_src ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpSdesStream.cpp)
-endif()
-
 set(zrtp_src_no_cache
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpCallbackWrapper.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZRtp.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpCrc32.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketCommit.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketConf2Ack.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketConfirm.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketDHPart.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketGoClear.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketClearAck.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketHelloAck.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketHello.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketError.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketErrorAck.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketPingAck.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketPing.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketSASrelay.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpPacketRelayAck.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpStateClass.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpTextData.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpConfigure.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZrtpCWrapper.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/Base32.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/common/osSpecifics.c ${sdes_src})
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpCallbackWrapper.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZRtp.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpCrc32.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketCommit.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketConf2Ack.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketConfirm.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketDHPart.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketGoClear.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketClearAck.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketHelloAck.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketHello.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketError.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketErrorAck.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketPingAck.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketPing.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketSASrelay.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpPacketRelayAck.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpStateClass.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpTextData.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpConfigure.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/ZrtpCWrapper.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/Base32.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/zrtpB64Encode.c
+    ${CMAKE_SOURCE_DIR}/zrtp/zrtpB64Decode.c
+    ${CMAKE_SOURCE_DIR}/common/osSpecifics.c ${sdes_src})
 
 set(bnlib_src
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/bn00.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/lbn00.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/bn.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/lbnmem.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/sieve.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/prime.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/bnprint.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/jacobi.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/germain.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/ec/ec.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/ec/ecdh.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/bnlib/bnprint.c)
+    ${CMAKE_SOURCE_DIR}/bnlib/bn00.c
+    ${CMAKE_SOURCE_DIR}/bnlib/lbn00.c
+    ${CMAKE_SOURCE_DIR}/bnlib/bn.c
+    ${CMAKE_SOURCE_DIR}/bnlib/lbnmem.c
+    ${CMAKE_SOURCE_DIR}/bnlib/sieve.c
+    ${CMAKE_SOURCE_DIR}/bnlib/prime.c
+    ${CMAKE_SOURCE_DIR}/bnlib/bnprint.c
+    ${CMAKE_SOURCE_DIR}/bnlib/jacobi.c
+    ${CMAKE_SOURCE_DIR}/bnlib/germain.c
+    ${CMAKE_SOURCE_DIR}/bnlib/ec/ec.c
+    ${CMAKE_SOURCE_DIR}/bnlib/ec/ecdh.c
+    ${CMAKE_SOURCE_DIR}/bnlib/ec/curve25519-donna.c)
+
+set(zrtp_skein_src
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/skeinMac256.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/skein256.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/skeinMac384.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/skein384.cpp)
 
 set(zrtp_crypto_src
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/zrtpDH.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/hmac256.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/sha256.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/hmac384.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/sha384.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/aesCFB.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/twoCFB.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/crypto/sha2.c)
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/zrtpDH.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/hmac256.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/sha256.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/hmac384.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/sha384.cpp
 
-if (NOT enable_sqlite)
-    set(zrtp_src ${zrtp_src_no_cache} 
-        ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZIDCacheFile.cpp 
-        ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZIDRecordFile.cpp)
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/aesCFB.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/twoCFB.cpp
+    ${CMAKE_SOURCE_DIR}/zrtp/crypto/sha2.c)
+
+if (NOT SQLITE)
+    set(zrtp_src ${zrtp_src_no_cache}
+        ${CMAKE_SOURCE_DIR}/zrtp/ZIDCacheFile.cpp
+        ${CMAKE_SOURCE_DIR}/zrtp/ZIDRecordFile.cpp)
 else()
     set(zrtp_src ${zrtp_src_no_cache}
-        ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZIDCacheDb.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/ZIDRecordDb.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/zrtpB64Encode.c
-        ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/zrtpB64Decode.c
-        ${CMAKE_CURRENT_SOURCE_DIR}/zrtp/zrtpCacheSqliteBackend.c)
+        ${CMAKE_SOURCE_DIR}/zrtp/ZIDCacheDb.cpp
+        ${CMAKE_SOURCE_DIR}/zrtp/ZIDRecordDb.cpp
+        ${CMAKE_SOURCE_DIR}/zrtp/zrtpCacheSqliteBackend.c)
+
 endif()
 
-if (enable_ccrtp)
+if (CCRTP)
     add_subdirectory(clients/ccrtp)
     add_subdirectory(demo)
 endif()
 
-if (enable_tivi)
+if (TIVI)
     add_subdirectory(clients/tivi)
 endif()
 
+if (CORE_LIB)
+    add_subdirectory(clients/no_client)
+endif()
+
 ##very usefull for macosx, specially when using gtkosx bundler
 if(APPLE)
     if (NOT CMAKE_INSTALL_NAME_DIR)
         set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE STRING "CMAKE_INSTALL_NAME_DIR set for macosx" )
     endif (NOT CMAKE_INSTALL_NAME_DIR)
 endif(APPLE)
-
-
diff --git a/jni/libzrtp/sources/COPYING b/jni/libzrtp/sources/COPYING
index 4432540..02bbb60 100644
--- a/jni/libzrtp/sources/COPYING
+++ b/jni/libzrtp/sources/COPYING
@@ -1,676 +1,165 @@
-
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 3, 29 June 2007
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
 
  Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-			    Preamble
 
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
 
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
+  0. Additional Definitions.
 
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
 
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
 
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
 
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
 
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
 
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
 
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
+  1. Exception to Section 3 of the GNU GPL.
 
-  The precise terms and conditions for copying, distribution and
-modification follow.
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
 
-		       TERMS AND CONDITIONS
+  2. Conveying Modified Versions.
 
-  0. Definitions.
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
 
-  "This License" refers to version 3 of the GNU General Public License.
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
 
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
- 
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
 
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
+  3. Object Code Incorporating Material from Library Header Files.
 
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
 
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
 
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
 
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
+  4. Combined Works.
 
-  1. Source Code.
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
 
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
 
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
 
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
 
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
+   d) Do one of the following:
 
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
 
-  The Corresponding Source for a work in source code form is that
-same work.
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
 
-  2. Basic Permissions.
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
 
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
+  5. Combined Libraries.
 
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
 
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
 
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
 
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
+  6. Revised Versions of the GNU Lesser General Public License.
 
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
 
-  4. Conveying Verbatim Copies.
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
 
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-  
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
-
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
\ No newline at end of file
diff --git a/jni/libzrtp/sources/NEWS b/jni/libzrtp/sources/NEWS
index 6224923..f2b72e6 100755
--- a/jni/libzrtp/sources/NEWS
+++ b/jni/libzrtp/sources/NEWS
@@ -1,3 +1,128 @@
+== GNU ZRTP 4.1.1 ==
+
+Is a bug fix release that fixes some problems when building a standalone
+version of the library, i.e. with embedded crypto algorithms and not using
+on openSSL.
+
+Another fix was necessary for NetBSD thread handling.
+
+
+== GNU ZRTP 4.1.0 ==
+
+Small enhancements when dealing with non-NIST algorithms. An application may
+set a ''algorithm selection policy'' to control the selection behaviour. In
+addition the the standrad selection policy (as per RFC6189) this version
+provides a _non-NIST_ selection policy: if the selected public key algorithm
+is a non-NIST ECC algorithm then the other selection functions prefer non-NIST
+HASH algorithms (Skein etc).
+
+
+== GNU ZRTP 4.0.0 ==
+
+For this version I added some new algorithms for the DH key agreement
+and the Skein Hash for ZRTP. Not further functional enhancments.
+
+Added a new (old) build parameter -DCORE_LIB that will build a ZRTP core
+library. This was available in V2.3 but I somehow lost this for 3.0
+You may add other build parameters, such as SQLITE and CRYPTO_STANDALONE
+if you build the core library.
+
+
+== GNU ZRTP 3.2.0 ==
+
+The main ZRTP modules contain fixes for three vulnerabilities found by Mark
+Dowd. Thus we advise application developers to use this version of the
+library. The vulnerabilities may lead to application crashes during ZRTP
+negotiation if an attacker sends prepared ZRTP packets. The fixes remove these
+attack vectors.
+
+Some small other enhancements and cleanup, mainly inside client code.
+
+Some enhancements in cache handling and the handling of retained shared
+secrets. This change was proposed by Phil, is a slight security enhacement and
+is fully backward comaptible.
+
+Because of some API changes clients must be compiled and linked with the new
+library.
+
+For details please refer to the Git logs.
+
+
+== GNU ZRTP 3.1.0 ==
+
+This version adds some new features and code that supports some other
+client and this accounts for the most changes inside this release. 
+
+The ZRTP core functionality was not changed as much (bug fixes, cleanup
+mainly) and remains fully backward compatible with older library
+versions. However, one nice enhancement was done: the addition of a standalone
+SDES support module. This module supports basic SDES only without the fancy
+stuff like many other SDES implementations. Thus it's pretty interoperable.
+
+Some other features are:
+- add some android support for a client, may serve as template for others
+- documentation and code cleanup
+
+Because of some API changes clients must be compiled and linked with the new
+library.
+
+
+== GNU ZRTP 3.0.0 ==
+
+This is a major enhancement and restructuring of the overall ZRTP
+distribution. This was necessary because more and more other clients use ZRTP
+and add their specific glue code. Also some clients are not prepared to use
+openSSL or other crypto libraries to their code and distributions. 
+
+Here a summary of the changes
+- a new directory layout to accomodate various clients
+- add standalone crypto modules, for example for AES, to have a real
+  standalone ZRTP/SRTP library that does not require any other crypto library
+  (optional via CMake configuration)
+- Re-structure ZRTP cache and add SQlite3 as optional storage backend
+
+The default settings for CMake build the normal ZRTP library that use openSSL
+as crypto backend, use the normal file based cache and include the GNU ccRTP
+modules. This is a librray that is to a large degree compatible with the
+earlier builds.
+
+Please refer to the top level CMakeFile.txt for options how to switch on the
+standalone crypto mode or the SQlite3 based cache storage.
+
+
+== GNU ZRTP 2.3.0 ==
+
+Add a "paranoid" mode to ZRTP. If and applications switches to this mode then
+the ZRTP stack _always_ asks the user to confirm the SAS thus ZRTP behaves as
+if it does not have a cache to store the retained secrets. However, setting
+the paranoid mode does not diable the cache, only the GUI behaviour.
+
+Enhance the CMake scripts to build a ZRTP library that does not contain GNU
+ccRTP modules and does not require ccRTP dependencies.
+
+== GNU ZRTP 2.2.0 ==
+
+Add stubs, callbacks and other provisions to prepare the full implementation
+of the SAS signing feature, see RFC6189, section 7.2. This feature needs
+support from applications and is rarely used if at all.
+
+As usual smaller fixes, code clean up etc.
+
+Because of some API changes clients must be compiled and linked with the new
+library.
+
+== GNU ZRTP 2.1.2 ==
+
+The main topic of this release was to add SRTCP support and some missing
+optional features of ZRTP. 
+
+As such I've added some new API and classes that applications may use to add
+SRTCP or to use the new ZRTP features. the ZRTP stack now supports PBX
+handling, refer to RFC6189 section 7.3ff.
+
+Because of some API changes clients must be compiled and linked with the new
+library.
+
 == GNU ZRTP 2.0.0 ==
 
 Modify some files to use the new uCommon/commoncpp libraries instead
@@ -150,7 +275,7 @@
 The method ''setOtherSecret(...)'' was renamed to ''setPbxSecret(...)''
 to reflect the modification in the draft.
 
-The methos ''setSrtpsSecret(...)'' is was renamed to ''setAuxSecret(...)''
+The method ''setSrtpsSecret(...)'' was renamed to ''setAuxSecret(...)''
 to reflect the modification in the draft.
 
 
diff --git a/jni/libzrtp/sources/README.md b/jni/libzrtp/sources/README.md
index cac0592..f7b9966 100644
--- a/jni/libzrtp/sources/README.md
+++ b/jni/libzrtp/sources/README.md
@@ -1,29 +1,49 @@
 ## GNU ZRTP C++
 
 This package provides a library that adds ZRTP support to the GNU
-ccRTP stack. Phil Zimmermann developed ZRTP to allow ad-hoc, easy to
+ccRTP stack and serves as library for other RTP stacks (PJSIP, GStreamer).
+Phil Zimmermann developed ZRTP to allow ad-hoc, easy to
 use key negotiation to setup Secure RTP (SRTP) sessions. GNU ZRTP works
 together with GNU ccRTP (1.5.0 or later) and provides a ZRTP
 implementation that can be directly embedded into client and server
 applications.
 
-The GNU ZRTP implementation is compliant to [RFC 6189][]. Currently GNU ZRTP
-C++ supports the following features:
+The GNU ZRTP implementation is compliant to [RFC 6189][] and adds some more
+algorithms. Currently GNU ZRTP C++ supports the following features:
 
 * multi-stream mode
-* Finite field Diffie-Helman with 2048 and 3072 bit primes
-* Elliptic curve Diffie-Helman with 256 and 384 bit curves
-* AES-128 and AES-256 symmetric cipher
+* Finite field Diffie-Hellman with 2048 and 3072 bit primes
+* Elliptic curve Diffie-Hellman with 256 and 384 bit curves (NIST curves)
+* Elliptic curves Curve25519 and Curve3617 (Dan Bernstein, Tanja Lange)
+* Skein Hash and MAC for ZRTP
+* AES-128 and AES-256 symmetric ciphers
 * Twofish-128 and Twofish-256 bit symmetric ciphers
 * The SRTP authentication methods HMAC-SHA1 with 32 bit and 80 bit length and
   the Skein MAC with 32 bit and 64 bit length
 * The Short Authentication String (SAS) type with base 32 encoding (4
-  characters)
+  characters) and the SAS 256 type using words.
 
-Enhanced features like PBX SAS relay aka *trusted Man-in-the-Middle* or
-preshared mode are not supported but the GNU ZRTP C++ implementation defines
-the necessary external interfaces and functions for these enhanced features
-(stubs only).
+Some features like preshared mode are not supported but the GNU
+ZRTP C++ implementation defines the necessary external interfaces and
+functions for these enhanced features.
+
+**Note:** The Elliptic curves Cure25519 and Curve3617 are available only if you
+select the crypto standalone mode during build.
+
+The newer verisons (starting with 4.1) implement an extensible mechanisms to
+define algorithm selection policies that control selection of Hash, symmetric
+cipher, and the SRTP authentication. Currently two policies exist: _Standard_
+and _PreferNonNist_. The Standard policy selects algorihms based on the
+preferences (order) in the Hello packet, the PreferNonNist policy prefers 
+non-NIST algorithms, for example Skein and Twofish, if the selected public key
+(Diffie-Hellman) algorithm is also one of the non-NIST algorithms. This is 
+fully backward compatible and in-line with RFC6189.
+
+### SDES support
+This release also provides SDES support. The SDES implementation does not
+support all of the fancy stuff but is usable in most cases. This implementation
+however supports the new SDES crypto mixing to overcome some security issues
+for SIP forking. Please look for `draft-zimmermann-mmusic-sdesc-mix-00`.
 
 ### Interoperability
 During the development of ZRTP and its sister implementation ZRTP4J (the Java
@@ -48,7 +68,7 @@
 functionality to C based RTP implementations. The first use of the ZRTP C
 wrapper was for the [PJSIP][] library, actually the RTP part of this
 library. The ZRTP handler for PJSIP is [here][pjzrtp]. This port enables PJSIP
-based clients to use ZRTP. One of the first clients that use this feature is
+based clients to use ZRTP. One of the first clients that uses this feature is
 *[CSipSimple][]*, an very good open source Android SIP client.
 
 [pjsip]: http://www.pjsip.org
@@ -71,13 +91,21 @@
 
 
 ### License and further information
-Please note, this library is licensed under the GNU GPL, version 3 or 
-later, and has been copyright assigned to the Free Software Foundation.
+I changed the license of the ZRTP core source files from GPL to LGPL. Other
+sources files may have own license. Please refer to the copyright notices of
+the files.
+
+Thus most of this library is licensed under the GNU LGPL, version 3 or later.
 
 For further information refer to the [ZRTP FAQ][zrtpfaq] and the
 [GNU ZRTP howto][zrtphow]. Both are part of the GNU Telephony wiki and are
 located in its documentation category.
 
+Source code in the directory `clients/tivi` and below is not licensed under the
+GNU LGPL and is for reference and review only. Refer to the copyright statments
+of the source code in these directories, in particular the sqlite3 sources which
+have their own license.
+
 [zrtphow]:  http://www.gnutelephony.org/index.php/GNU_ZRTP_How_To
 [zrtpfaq]:  http://www.gnutelephony.org/index.php/ZRTP_FAQ
 [rfc 6189]: http://tools.ietf.org/html/rfc6189
@@ -89,11 +117,23 @@
 the source archive or pulled the source from [Github][]:
 
     cd <zrtpsrc_dir>
-	mkdir build
-	cd build
-	cmake ..
-	make
-	
+    mkdir build
+    cd build
+    cmake ..
+    make
+
+The CMakeLists.txt supports several options. If you don't specify any options
+then `cmake` generates the build that supports GNU ccRTP library and it uses
+the standalone cryptographic modules, thus no it's not necessary to install an
+cryptographic library on the system. Optionally you may configure ZRTP to use
+_sqlite3_ instead of a simple file to store the ZRTP cache data. For example
+
+    cmake -DSQLITE=true ..
+
+creates the build files that use _sqlite3_.
+
+Please have a look at the `CMakeLists.txt` for other options.
+
 Running cmake in a separate `build` directory is the preferred way. Cmake and
 the following `make` generate all files in or below the build directory. Thus
 the base directory and the source directories are not polluted with `*.o`,
@@ -103,3 +143,13 @@
 different settings without mixing the two builds.
 
 [github]: http://github.com/wernerd/ZRTPCPP
+
+
+### Notes when building ZRTP C++ for Android
+
+The CMake files support creation of an `Android.mk` file for the Tivi client
+and may give you an idea how to do it for other clients. The generated
+`Android.mk` generates `buildinfo_*.c` files in the root directory. You may
+delete these files after the Android static libraries are ready.
+
+Since version 4.1.1 the example Android build files require NDK r9c.
diff --git a/jni/libzrtp/sources/bnlib/bn.h b/jni/libzrtp/sources/bnlib/bn.h
index f4dedfc..5cc80f0 100644
--- a/jni/libzrtp/sources/bnlib/bn.h
+++ b/jni/libzrtp/sources/bnlib/bn.h
@@ -30,6 +30,7 @@
 	unsigned allocated;
 };
 
+#ifndef SWIG
 /*
  * User-supplied function: if non-NULL, this is called during long-running
  * computations.  You may put Yield() calls in here to give CPU time to
@@ -226,6 +227,7 @@
 	struct BnBasePrecomp const *pre1, struct BigNum const *exp1,
 	struct BnBasePrecomp const *pre2, struct BigNum const *exp2,
 	struct BigNum const *mod);
+#endif /* SWIF */
 
 #ifdef __cplusplus
 }
diff --git a/jni/libzrtp/sources/bnlib/bn32.c b/jni/libzrtp/sources/bnlib/bn32.c
index b0a3b85..ee0d257 100644
--- a/jni/libzrtp/sources/bnlib/bn32.c
+++ b/jni/libzrtp/sources/bnlib/bn32.c
@@ -13,7 +13,7 @@
 #define HAVE_CONFIG_H 0
 #endif
 #if HAVE_CONFIG_H
-#include "bnconfig.h"
+#include <bnconfig.h>
 #endif
 
 /*
diff --git a/jni/libzrtp/sources/bnlib/bn64.c b/jni/libzrtp/sources/bnlib/bn64.c
index 6cb98ba..23cf185 100644
--- a/jni/libzrtp/sources/bnlib/bn64.c
+++ b/jni/libzrtp/sources/bnlib/bn64.c
@@ -13,7 +13,7 @@
 #define HAVE_CONFIG_H 0
 #endif
 #if HAVE_CONFIG_H
-#include "bnconfig.h"
+#include <bnconfig.h>
 #endif
 
 /*
diff --git a/jni/libzrtp/sources/bnlib/bnprint.c b/jni/libzrtp/sources/bnlib/bnprint.c
index 080e4a8..a407248 100644
--- a/jni/libzrtp/sources/bnlib/bnprint.c
+++ b/jni/libzrtp/sources/bnlib/bnprint.c
@@ -112,12 +112,7 @@
         getAsciiDigit(&d, radix, s[i]);
         bnMulQ(X, X, radix);
 
-        if(!neg ) {
-            bnAddQ(X, d);
-        }
-        else {
-            bnSubQ(X, d );
-        }
+        bnAddQ(X, d);
     }
-    return( 0 );
+    return(neg);
 }
diff --git a/jni/libzrtp/sources/bnlib/bnprint.h b/jni/libzrtp/sources/bnlib/bnprint.h
index 38830fb..b10393a 100644
--- a/jni/libzrtp/sources/bnlib/bnprint.h
+++ b/jni/libzrtp/sources/bnlib/bnprint.h
@@ -10,11 +10,13 @@
 
 struct BigNum;
 
+#ifndef SWIG
 int bnPrint(FILE *f, char const *prefix, struct BigNum const *bn,
 	char const *suffix);
+#endif
 
 /**
- * Convert and ASCII string into a BigNum.
+ * Convert an ASCII string into a BigNum.
  *
  * This function converts an ASCII string into a Big number. If the first
  * character of the string is a minus sign the big number is a negative number.
diff --git a/jni/libzrtp/sources/bnlib/ec/curve25519-donna.c b/jni/libzrtp/sources/bnlib/ec/curve25519-donna.c
new file mode 100644
index 0000000..de11280
--- /dev/null
+++ b/jni/libzrtp/sources/bnlib/ec/curve25519-donna.c
@@ -0,0 +1,731 @@
+/* Copyright 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * curve25519-donna: Curve25519 elliptic curve, public key function
+ *
+ * http://code.google.com/p/curve25519-donna/
+ *
+ * Adam Langley <agl@imperialviolet.org>
+ *
+ * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
+ *
+ * More information about curve25519 can be found here
+ *   http://cr.yp.to/ecdh.html
+ *
+ * djb's sample implementation of curve25519 is written in a special assembly
+ * language called qhasm and uses the floating point registers.
+ *
+ * This is, almost, a clean room reimplementation from the curve25519 paper. It
+ * uses many of the tricks described therein. Only the crecip function is taken
+ * from the sample implementation.
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+#ifdef _MSC_VER
+#define inline __inline
+#endif
+
+typedef uint8_t u8;
+typedef int32_t s32;
+typedef int64_t limb;
+
+/* Field element representation:
+ *
+ * Field elements are written as an array of signed, 64-bit limbs, least
+ * significant first. The value of the field element is:
+ *   x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ...
+ *
+ * i.e. the limbs are 26, 25, 26, 25, ... bits wide.
+ */
+
+/* Sum two numbers: output += in */
+static void fsum(limb *output, const limb *in) {
+  unsigned i;
+  for (i = 0; i < 10; i += 2) {
+    output[0+i] = (output[0+i] + in[0+i]);
+    output[1+i] = (output[1+i] + in[1+i]);
+  }
+}
+
+/* Find the difference of two numbers: output = in - output
+ * (note the order of the arguments!)
+ */
+static void fdifference(limb *output, const limb *in) {
+  unsigned i;
+  for (i = 0; i < 10; ++i) {
+    output[i] = (in[i] - output[i]);
+  }
+}
+
+/* Multiply a number by a scalar: output = in * scalar */
+static void fscalar_product(limb *output, const limb *in, const limb scalar) {
+  unsigned i;
+  for (i = 0; i < 10; ++i) {
+    output[i] = in[i] * scalar;
+  }
+}
+
+/* Multiply two numbers: output = in2 * in
+ *
+ * output must be distinct to both inputs. The inputs are reduced coefficient
+ * form, the output is not.
+ */
+static void fproduct(limb *output, const limb *in2, const limb *in) {
+  output[0] =       ((limb) ((s32) in2[0])) * ((s32) in[0]);
+  output[1] =       ((limb) ((s32) in2[0])) * ((s32) in[1]) +
+                    ((limb) ((s32) in2[1])) * ((s32) in[0]);
+  output[2] =  2 *  ((limb) ((s32) in2[1])) * ((s32) in[1]) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[2]) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[0]);
+  output[3] =       ((limb) ((s32) in2[1])) * ((s32) in[2]) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[1]) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[3])) * ((s32) in[0]);
+  output[4] =       ((limb) ((s32) in2[2])) * ((s32) in[2]) +
+               2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[3])) * ((s32) in[1])) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[4]) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[0]);
+  output[5] =       ((limb) ((s32) in2[2])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[3])) * ((s32) in[2]) +
+                    ((limb) ((s32) in2[1])) * ((s32) in[4]) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[1]) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[5])) * ((s32) in[0]);
+  output[6] =  2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[1])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[5])) * ((s32) in[1])) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[4]) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[2]) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[6]) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[0]);
+  output[7] =       ((limb) ((s32) in2[3])) * ((s32) in[4]) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[5])) * ((s32) in[2]) +
+                    ((limb) ((s32) in2[1])) * ((s32) in[6]) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[1]) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[7])) * ((s32) in[0]);
+  output[8] =       ((limb) ((s32) in2[4])) * ((s32) in[4]) +
+               2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[5])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[1])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[7])) * ((s32) in[1])) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[6]) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[2]) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[0]);
+  output[9] =       ((limb) ((s32) in2[4])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[5])) * ((s32) in[4]) +
+                    ((limb) ((s32) in2[3])) * ((s32) in[6]) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[7])) * ((s32) in[2]) +
+                    ((limb) ((s32) in2[1])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[1]) +
+                    ((limb) ((s32) in2[0])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[0]);
+  output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[3])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[7])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[1])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[1])) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[6]) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[4]) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[2]);
+  output[11] =      ((limb) ((s32) in2[5])) * ((s32) in[6]) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[7])) * ((s32) in[4]) +
+                    ((limb) ((s32) in2[3])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[3]) +
+                    ((limb) ((s32) in2[2])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[2]);
+  output[12] =      ((limb) ((s32) in2[6])) * ((s32) in[6]) +
+               2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[7])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[3])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[3])) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[4]);
+  output[13] =      ((limb) ((s32) in2[6])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[7])) * ((s32) in[6]) +
+                    ((limb) ((s32) in2[5])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[5]) +
+                    ((limb) ((s32) in2[4])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[4]);
+  output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[5])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[5])) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[6]);
+  output[15] =      ((limb) ((s32) in2[7])) * ((s32) in[8]) +
+                    ((limb) ((s32) in2[8])) * ((s32) in[7]) +
+                    ((limb) ((s32) in2[6])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[6]);
+  output[16] =      ((limb) ((s32) in2[8])) * ((s32) in[8]) +
+               2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[7]));
+  output[17] =      ((limb) ((s32) in2[8])) * ((s32) in[9]) +
+                    ((limb) ((s32) in2[9])) * ((s32) in[8]);
+  output[18] = 2 *  ((limb) ((s32) in2[9])) * ((s32) in[9]);
+}
+
+/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
+static void freduce_degree(limb *output) {
+  /* Each of these shifts and adds ends up multiplying the value by 19. */
+  output[8] += output[18] << 4;
+  output[8] += output[18] << 1;
+  output[8] += output[18];
+  output[7] += output[17] << 4;
+  output[7] += output[17] << 1;
+  output[7] += output[17];
+  output[6] += output[16] << 4;
+  output[6] += output[16] << 1;
+  output[6] += output[16];
+  output[5] += output[15] << 4;
+  output[5] += output[15] << 1;
+  output[5] += output[15];
+  output[4] += output[14] << 4;
+  output[4] += output[14] << 1;
+  output[4] += output[14];
+  output[3] += output[13] << 4;
+  output[3] += output[13] << 1;
+  output[3] += output[13];
+  output[2] += output[12] << 4;
+  output[2] += output[12] << 1;
+  output[2] += output[12];
+  output[1] += output[11] << 4;
+  output[1] += output[11] << 1;
+  output[1] += output[11];
+  output[0] += output[10] << 4;
+  output[0] += output[10] << 1;
+  output[0] += output[10];
+}
+
+#if (-1 & 3) != 3
+#error "This code only works on a two's complement system"
+#endif
+
+/* return v / 2^26, using only shifts and adds. */
+static limb div_by_2_26(const limb v)
+{
+  /* High word of v; no shift needed*/
+  const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
+  /* Set to all 1s if v was negative; else set to 0s. */
+  const int32_t sign = ((int32_t) highword) >> 31;
+  /* Set to 0x3ffffff if v was negative; else set to 0. */
+  const int32_t roundoff = ((uint32_t) sign) >> 6;
+  /* Should return v / (1<<26) */
+  return (v + roundoff) >> 26;
+}
+
+/* return v / (2^25), using only shifts and adds. */
+static limb div_by_2_25(const limb v)
+{
+  /* High word of v; no shift needed*/
+  const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
+  /* Set to all 1s if v was negative; else set to 0s. */
+  const int32_t sign = ((int32_t) highword) >> 31;
+  /* Set to 0x1ffffff if v was negative; else set to 0. */
+  const int32_t roundoff = ((uint32_t) sign) >> 7;
+  /* Should return v / (1<<25) */
+  return (v + roundoff) >> 25;
+}
+
+static s32 div_s32_by_2_25(const s32 v)
+{
+   const s32 roundoff = ((uint32_t)(v >> 31)) >> 7;
+   return (v + roundoff) >> 25;
+}
+
+/* Reduce all coefficients of the short form input so that |x| < 2^26.
+ *
+ * On entry: |output[i]| < 2^62
+ */
+static void freduce_coefficients(limb *output) {
+  unsigned i;
+
+  output[10] = 0;
+
+  for (i = 0; i < 10; i += 2) {
+    limb over = div_by_2_26(output[i]);
+    output[i] -= over << 26;
+    output[i+1] += over;
+
+    over = div_by_2_25(output[i+1]);
+    output[i+1] -= over << 25;
+    output[i+2] += over;
+  }
+  /* Now |output[10]| < 2 ^ 38 and all other coefficients are reduced. */
+  output[0] += output[10] << 4;
+  output[0] += output[10] << 1;
+  output[0] += output[10];
+
+  output[10] = 0;
+
+  /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19 * 2^38
+   * So |over| will be no more than 77825  */
+  {
+    limb over = div_by_2_26(output[0]);
+    output[0] -= over << 26;
+    output[1] += over;
+  }
+
+  /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 77825
+   * So |over| will be no more than 1. */
+  {
+    /* output[1] fits in 32 bits, so we can use div_s32_by_2_25 here. */
+    s32 over32 = div_s32_by_2_25((s32) output[1]);
+    output[1] -= over32 << 25;
+    output[2] += over32;
+  }
+
+  /* Finally, output[0,1,3..9] are reduced, and output[2] is "nearly reduced":
+   * we have |output[2]| <= 2^26.  This is good enough for all of our math,
+   * but it will require an extra freduce_coefficients before fcontract. */
+}
+
+/* A helpful wrapper around fproduct: output = in * in2.
+ *
+ * output must be distinct to both inputs. The output is reduced degree and
+ * reduced coefficient.
+ */
+static void
+fmul(limb *output, const limb *in, const limb *in2) {
+  limb t[19];
+  fproduct(t, in, in2);
+  freduce_degree(t);
+  freduce_coefficients(t);
+  memcpy(output, t, sizeof(limb) * 10);
+}
+
+static void fsquare_inner(limb *output, const limb *in) {
+  output[0] =       ((limb) ((s32) in[0])) * ((s32) in[0]);
+  output[1] =  2 *  ((limb) ((s32) in[0])) * ((s32) in[1]);
+  output[2] =  2 * (((limb) ((s32) in[1])) * ((s32) in[1]) +
+                    ((limb) ((s32) in[0])) * ((s32) in[2]));
+  output[3] =  2 * (((limb) ((s32) in[1])) * ((s32) in[2]) +
+                    ((limb) ((s32) in[0])) * ((s32) in[3]));
+  output[4] =       ((limb) ((s32) in[2])) * ((s32) in[2]) +
+               4 *  ((limb) ((s32) in[1])) * ((s32) in[3]) +
+               2 *  ((limb) ((s32) in[0])) * ((s32) in[4]);
+  output[5] =  2 * (((limb) ((s32) in[2])) * ((s32) in[3]) +
+                    ((limb) ((s32) in[1])) * ((s32) in[4]) +
+                    ((limb) ((s32) in[0])) * ((s32) in[5]));
+  output[6] =  2 * (((limb) ((s32) in[3])) * ((s32) in[3]) +
+                    ((limb) ((s32) in[2])) * ((s32) in[4]) +
+                    ((limb) ((s32) in[0])) * ((s32) in[6]) +
+               2 *  ((limb) ((s32) in[1])) * ((s32) in[5]));
+  output[7] =  2 * (((limb) ((s32) in[3])) * ((s32) in[4]) +
+                    ((limb) ((s32) in[2])) * ((s32) in[5]) +
+                    ((limb) ((s32) in[1])) * ((s32) in[6]) +
+                    ((limb) ((s32) in[0])) * ((s32) in[7]));
+  output[8] =       ((limb) ((s32) in[4])) * ((s32) in[4]) +
+               2 * (((limb) ((s32) in[2])) * ((s32) in[6]) +
+                    ((limb) ((s32) in[0])) * ((s32) in[8]) +
+               2 * (((limb) ((s32) in[1])) * ((s32) in[7]) +
+                    ((limb) ((s32) in[3])) * ((s32) in[5])));
+  output[9] =  2 * (((limb) ((s32) in[4])) * ((s32) in[5]) +
+                    ((limb) ((s32) in[3])) * ((s32) in[6]) +
+                    ((limb) ((s32) in[2])) * ((s32) in[7]) +
+                    ((limb) ((s32) in[1])) * ((s32) in[8]) +
+                    ((limb) ((s32) in[0])) * ((s32) in[9]));
+  output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) +
+                    ((limb) ((s32) in[4])) * ((s32) in[6]) +
+                    ((limb) ((s32) in[2])) * ((s32) in[8]) +
+               2 * (((limb) ((s32) in[3])) * ((s32) in[7]) +
+                    ((limb) ((s32) in[1])) * ((s32) in[9])));
+  output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) +
+                    ((limb) ((s32) in[4])) * ((s32) in[7]) +
+                    ((limb) ((s32) in[3])) * ((s32) in[8]) +
+                    ((limb) ((s32) in[2])) * ((s32) in[9]));
+  output[12] =      ((limb) ((s32) in[6])) * ((s32) in[6]) +
+               2 * (((limb) ((s32) in[4])) * ((s32) in[8]) +
+               2 * (((limb) ((s32) in[5])) * ((s32) in[7]) +
+                    ((limb) ((s32) in[3])) * ((s32) in[9])));
+  output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) +
+                    ((limb) ((s32) in[5])) * ((s32) in[8]) +
+                    ((limb) ((s32) in[4])) * ((s32) in[9]));
+  output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) +
+                    ((limb) ((s32) in[6])) * ((s32) in[8]) +
+               2 *  ((limb) ((s32) in[5])) * ((s32) in[9]));
+  output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) +
+                    ((limb) ((s32) in[6])) * ((s32) in[9]));
+  output[16] =      ((limb) ((s32) in[8])) * ((s32) in[8]) +
+               4 *  ((limb) ((s32) in[7])) * ((s32) in[9]);
+  output[17] = 2 *  ((limb) ((s32) in[8])) * ((s32) in[9]);
+  output[18] = 2 *  ((limb) ((s32) in[9])) * ((s32) in[9]);
+}
+
+static void
+fsquare(limb *output, const limb *in) {
+  limb t[19];
+  fsquare_inner(t, in);
+  freduce_degree(t);
+  freduce_coefficients(t);
+  memcpy(output, t, sizeof(limb) * 10);
+}
+
+/* Take a little-endian, 32-byte number and expand it into polynomial form */
+static void
+fexpand(limb *output, const u8 *input) {
+#define F(n,start,shift,mask) \
+  output[n] = ((((limb) input[start + 0]) | \
+                ((limb) input[start + 1]) << 8 | \
+                ((limb) input[start + 2]) << 16 | \
+                ((limb) input[start + 3]) << 24) >> shift) & mask;
+  F(0, 0, 0, 0x3ffffff);
+  F(1, 3, 2, 0x1ffffff);
+  F(2, 6, 3, 0x3ffffff);
+  F(3, 9, 5, 0x1ffffff);
+  F(4, 12, 6, 0x3ffffff);
+  F(5, 16, 0, 0x1ffffff);
+  F(6, 19, 1, 0x3ffffff);
+  F(7, 22, 3, 0x1ffffff);
+  F(8, 25, 4, 0x3ffffff);
+  F(9, 28, 6, 0x1ffffff);
+#undef F
+}
+
+#if (-32 >> 1) != -16
+#error "This code only works when >> does sign-extension on negative numbers"
+#endif
+
+/* Take a fully reduced polynomial form number and contract it into a
+ * little-endian, 32-byte array
+ */
+static void
+fcontract(u8 *output, limb *input) {
+  int i;
+  int j;
+
+  for (j = 0; j < 2; ++j) {
+    for (i = 0; i < 9; ++i) {
+      if ((i & 1) == 1) {
+        /* This calculation is a time-invariant way to make input[i] positive
+           by borrowing from the next-larger limb.
+        */
+        const s32 mask = (s32)(input[i]) >> 31;
+        const s32 carry = -(((s32)(input[i]) & mask) >> 25);
+        input[i] = (s32)(input[i]) + (carry << 25);
+        input[i+1] = (s32)(input[i+1]) - carry;
+      } else {
+        const s32 mask = (s32)(input[i]) >> 31;
+        const s32 carry = -(((s32)(input[i]) & mask) >> 26);
+        input[i] = (s32)(input[i]) + (carry << 26);
+        input[i+1] = (s32)(input[i+1]) - carry;
+      }
+    }
+    {
+      const s32 mask = (s32)(input[9]) >> 31;
+      const s32 carry = -(((s32)(input[9]) & mask) >> 25);
+      input[9] = (s32)(input[9]) + (carry << 25);
+      input[0] = (s32)(input[0]) - (carry * 19);
+    }
+  }
+
+  /* The first borrow-propagation pass above ended with every limb
+     except (possibly) input[0] non-negative.
+
+     Since each input limb except input[0] is decreased by at most 1
+     by a borrow-propagation pass, the second borrow-propagation pass
+     could only have wrapped around to decrease input[0] again if the
+     first pass left input[0] negative *and* input[1] through input[9]
+     were all zero.  In that case, input[1] is now 2^25 - 1, and this
+     last borrow-propagation step will leave input[1] non-negative.
+  */
+  {
+    const s32 mask = (s32)(input[0]) >> 31;
+    const s32 carry = -(((s32)(input[0]) & mask) >> 26);
+    input[0] = (s32)(input[0]) + (carry << 26);
+    input[1] = (s32)(input[1]) - carry;
+  }
+
+  /* Both passes through the above loop, plus the last 0-to-1 step, are
+     necessary: if input[9] is -1 and input[0] through input[8] are 0,
+     negative values will remain in the array until the end.
+   */
+
+  input[1] <<= 2;
+  input[2] <<= 3;
+  input[3] <<= 5;
+  input[4] <<= 6;
+  input[6] <<= 1;
+  input[7] <<= 3;
+  input[8] <<= 4;
+  input[9] <<= 6;
+#define F(i, s) \
+  output[s+0] |=  input[i] & 0xff; \
+  output[s+1]  = (input[i] >> 8) & 0xff; \
+  output[s+2]  = (input[i] >> 16) & 0xff; \
+  output[s+3]  = (input[i] >> 24) & 0xff;
+  output[0] = 0;
+  output[16] = 0;
+  F(0,0);
+  F(1,3);
+  F(2,6);
+  F(3,9);
+  F(4,12);
+  F(5,16);
+  F(6,19);
+  F(7,22);
+  F(8,25);
+  F(9,28);
+#undef F
+}
+
+/* Input: Q, Q', Q-Q'
+ * Output: 2Q, Q+Q'
+ *
+ *   x2 z3: long form
+ *   x3 z3: long form
+ *   x z: short form, destroyed
+ *   xprime zprime: short form, destroyed
+ *   qmqp: short form, preserved
+ */
+static void fmonty(limb *x2, limb *z2,  /* output 2Q */
+                   limb *x3, limb *z3,  /* output Q + Q' */
+                   limb *x, limb *z,    /* input Q */
+                   limb *xprime, limb *zprime,  /* input Q' */
+                   const limb *qmqp /* input Q - Q' */) {
+  limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
+        zzprime[19], zzzprime[19], xxxprime[19];
+
+  memcpy(origx, x, 10 * sizeof(limb));
+  fsum(x, z);
+  fdifference(z, origx);  /* does x - z */
+
+  memcpy(origxprime, xprime, sizeof(limb) * 10);
+  fsum(xprime, zprime);
+  fdifference(zprime, origxprime);
+  fproduct(xxprime, xprime, z);
+  fproduct(zzprime, x, zprime);
+  freduce_degree(xxprime);
+  freduce_coefficients(xxprime);
+  freduce_degree(zzprime);
+  freduce_coefficients(zzprime);
+  memcpy(origxprime, xxprime, sizeof(limb) * 10);
+  fsum(xxprime, zzprime);
+  fdifference(zzprime, origxprime);
+  fsquare(xxxprime, xxprime);
+  fsquare(zzzprime, zzprime);
+  fproduct(zzprime, zzzprime, qmqp);
+  freduce_degree(zzprime);
+  freduce_coefficients(zzprime);
+  memcpy(x3, xxxprime, sizeof(limb) * 10);
+  memcpy(z3, zzprime, sizeof(limb) * 10);
+
+  fsquare(xx, x);
+  fsquare(zz, z);
+  fproduct(x2, xx, zz);
+  freduce_degree(x2);
+  freduce_coefficients(x2);
+  fdifference(zz, xx);         /* does zz = xx - zz */
+  memset(zzz + 10, 0, sizeof(limb) * 9);
+  fscalar_product(zzz, zz, 121665);
+  /* No need to call freduce_degree here:
+     fscalar_product doesn't increase the degree of its input.
+   */
+  freduce_coefficients(zzz);
+  fsum(zzz, xx);
+  fproduct(z2, zz, zzz);
+  freduce_degree(z2);
+  freduce_coefficients(z2);
+}
+
+/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave
+ * them unchanged if 'iswap' is 0.  Runs in data-invariant time to avoid
+ * side-channel attacks.
+ *
+ * NOTE that this function requires that 'iswap' be 1 or 0; other values give
+ * wrong results.  Also, the two limb arrays must be in reduced-coefficient,
+ * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped,
+ * and all all values in a[0..9],b[0..9] must have magnitude less than
+ * INT32_MAX.
+ */
+static void
+swap_conditional(limb a[19], limb b[19], limb iswap) {
+  unsigned i;
+  const s32 swap = (s32) -iswap;
+
+  for (i = 0; i < 10; ++i) {
+    const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) );
+    a[i] = ((s32)a[i]) ^ x;
+    b[i] = ((s32)b[i]) ^ x;
+  }
+}
+
+/* Calculates nQ where Q is the x-coordinate of a point on the curve
+ *
+ *   resultx/resultz: the x coordinate of the resulting curve point (short form)
+ *   n: a little endian, 32-byte number
+ *   q: a point of the curve (short form)
+ */
+static void
+cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {
+  limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
+  limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
+  limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
+  limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
+
+  unsigned i, j;
+
+  memcpy(nqpqx, q, sizeof(limb) * 10);
+
+  for (i = 0; i < 32; ++i) {
+    u8 byte = n[31 - i];
+    for (j = 0; j < 8; ++j) {
+      const limb bit = byte >> 7;
+
+      swap_conditional(nqx, nqpqx, bit);
+      swap_conditional(nqz, nqpqz, bit);
+      fmonty(nqx2, nqz2,
+             nqpqx2, nqpqz2,
+             nqx, nqz,
+             nqpqx, nqpqz,
+             q);
+      swap_conditional(nqx2, nqpqx2, bit);
+      swap_conditional(nqz2, nqpqz2, bit);
+
+      t = nqx;
+      nqx = nqx2;
+      nqx2 = t;
+      t = nqz;
+      nqz = nqz2;
+      nqz2 = t;
+      t = nqpqx;
+      nqpqx = nqpqx2;
+      nqpqx2 = t;
+      t = nqpqz;
+      nqpqz = nqpqz2;
+      nqpqz2 = t;
+
+      byte <<= 1;
+    }
+  }
+
+  memcpy(resultx, nqx, sizeof(limb) * 10);
+  memcpy(resultz, nqz, sizeof(limb) * 10);
+}
+
+/* -----------------------------------------------------------------------------
+ * Shamelessly copied from djb's code
+ * ----------------------------------------------------------------------------- */
+static void
+crecip(limb *out, const limb *z) {
+  limb z2[10];
+  limb z9[10];
+  limb z11[10];
+  limb z2_5_0[10];
+  limb z2_10_0[10];
+  limb z2_20_0[10];
+  limb z2_50_0[10];
+  limb z2_100_0[10];
+  limb t0[10];
+  limb t1[10];
+  int i;
+
+  /* 2 */ fsquare(z2,z);
+  /* 4 */ fsquare(t1,z2);
+  /* 8 */ fsquare(t0,t1);
+  /* 9 */ fmul(z9,t0,z);
+  /* 11 */ fmul(z11,z9,z2);
+  /* 22 */ fsquare(t0,z11);
+  /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);
+
+  /* 2^6 - 2^1 */ fsquare(t0,z2_5_0);
+  /* 2^7 - 2^2 */ fsquare(t1,t0);
+  /* 2^8 - 2^3 */ fsquare(t0,t1);
+  /* 2^9 - 2^4 */ fsquare(t1,t0);
+  /* 2^10 - 2^5 */ fsquare(t0,t1);
+  /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);
+
+  /* 2^11 - 2^1 */ fsquare(t0,z2_10_0);
+  /* 2^12 - 2^2 */ fsquare(t1,t0);
+  /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+  /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);
+
+  /* 2^21 - 2^1 */ fsquare(t0,z2_20_0);
+  /* 2^22 - 2^2 */ fsquare(t1,t0);
+  /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+  /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);
+
+  /* 2^41 - 2^1 */ fsquare(t1,t0);
+  /* 2^42 - 2^2 */ fsquare(t0,t1);
+  /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
+  /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);
+
+  /* 2^51 - 2^1 */ fsquare(t0,z2_50_0);
+  /* 2^52 - 2^2 */ fsquare(t1,t0);
+  /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+  /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);
+
+  /* 2^101 - 2^1 */ fsquare(t1,z2_100_0);
+  /* 2^102 - 2^2 */ fsquare(t0,t1);
+  /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
+  /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);
+
+  /* 2^201 - 2^1 */ fsquare(t0,t1);
+  /* 2^202 - 2^2 */ fsquare(t1,t0);
+  /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+  /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);
+
+  /* 2^251 - 2^1 */ fsquare(t1,t0);
+  /* 2^252 - 2^2 */ fsquare(t0,t1);
+  /* 2^253 - 2^3 */ fsquare(t1,t0);
+  /* 2^254 - 2^4 */ fsquare(t0,t1);
+  /* 2^255 - 2^5 */ fsquare(t1,t0);
+  /* 2^255 - 21 */ fmul(out,t1,z11);
+}
+
+int curve25519_donna(u8 *, const u8 *, const u8 *);
+
+int curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
+  limb bp[10], x[10], z[11], zmone[10];
+  uint8_t e[32];
+  int i;
+
+  for (i = 0; i < 32; ++i) e[i] = secret[i];
+  e[0] &= 248;
+  e[31] &= 127;
+  e[31] |= 64;
+
+  fexpand(bp, basepoint);
+  cmult(x, z, e, bp);
+  crecip(zmone, z);
+  fmul(z, x, zmone);
+  freduce_coefficients(z);
+  fcontract(mypublic, z);
+  return 0;
+}
diff --git a/jni/libzrtp/sources/bnlib/ec/ec.c b/jni/libzrtp/sources/bnlib/ec/ec.c
index 1f4123a..18e612f 100644
--- a/jni/libzrtp/sources/bnlib/ec/ec.c
+++ b/jni/libzrtp/sources/bnlib/ec/ec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Werner Dittmann
+ * Copyright (C) 2012-2013 Werner Dittmann
  * All rights reserved. For licensing and other legal details, see the file legal.c.
  *
  * @author Werner Dittmann <Werner.Dittmann@t-online.de>
@@ -100,6 +100,46 @@
         "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
 };
 
+
+/*
+ * The data for curve3617 copied from:
+ * http://safecurves.cr.yp.to/field.html
+ * http://safecurves.cr.yp.to/base.html
+ */
+static curveData curve3617 = {
+    "3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef",  /* Prime */
+    "7ffffffffffffffffffffffffffffffffffffffffffffffffffeb3cc92414cf706022b36f1c0338ad63cf181b0e71a5e106af79",   /* order */
+    "",                                                                                                          /* SEED */
+    "",                                                                                                          /* c */
+    "",                                                                                                          /* b */
+    "1a334905141443300218c0631c326e5fcd46369f44c03ec7f57ff35498a4ab4d6d6ba111301a73faa8537c64c4fd3812f3cbc595",  /* Gx*/
+    "22",                                                                                                        /* Gy (radix 16) */
+};
+
+/*
+ * The data for curve25519 copied from:
+ * http://safecurves.cr.yp.to/field.html
+ * http://safecurves.cr.yp.to/base.html
+ * 
+ * Note: 
+ * The data for Curve25519 is here for the sake of completeness and to have the same
+ * set of initialization. One exception if the base point X coordinate (Gx) that we use to
+ * compute the DH public value, refer to function ecdhGeneratePublic(...) in ecdh.c.
+ * 
+ * Otherwise the functions use EcCurve structure only to get the pointers to the Curve25519
+ * wrapper functions.
+ * 
+ */
+static curveData curve25519 = {
+    "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",   /* Prime */
+    "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",   /* order */
+    "",                                                                   /* SEED */
+    "",                                                                   /* c */
+    "",                                                                   /* b */
+    "9",                                                                  /* Gx */
+    "20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9",   /* Gy */
+};
+
 /*============================================================================*/
 /*    Bignum Shorthand Functions                                              */
 /*============================================================================*/
@@ -140,53 +180,90 @@
     return 0;
 }
 
-int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod)
+int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod, const EcCurve *curve)
 {
     bnMul (rslt, n1, n2);
-    bnMod (rslt, rslt, mod);
+    if (curve)
+        curve->modOp(rslt, rslt, mod);
+    else
+        bnMod(rslt, rslt, mod);
     return 0;
 }
 
-int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod)
+int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod, const EcCurve *curve)
 {
     bnMulQ (rslt, n1, n2);
-    bnMod (rslt, rslt, mod);
-    return 0;
+    if (curve)
+        curve->modOp(rslt, rslt, mod);
+    else
+        bnMod(rslt, rslt, mod);
+   return 0;
 }
 
-int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod)
+int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod, const EcCurve *curve)
 {
     bnSquare (rslt, n1);
-    bnMod (rslt, rslt, mod);
+    if (curve)
+        curve->modOp(rslt, rslt, mod);
+    else
+        bnMod(rslt, rslt, mod);
     return 0;
 }
 
-int ecGetCurveNistECp(NistCurves curveId, NistECpCurve *curve)
+/*
+ * Note on the Curve25519 functions and usage of BigNumber:
+ * In most cases the functions to compute Curve25519 data are small wrapper functions
+ * that implement the same API as for the other curve functions. The wrapper functions
+ * then call the very specific, high-efficient function in curve25519-donna.c .
+ * 
+ * For Curve25519 we don't have a real implementation for point add, point doubling, modulo
+ * and check public key. Please refer to the actual implementations below.
+ */
+
+static int ecGetAffineNist(const EcCurve *curve, EcPoint *R, const EcPoint *P);
+static int ecGetAffineEd(const EcCurve *curve, EcPoint *R, const EcPoint *P);
+static int ecGetAffine25519(const EcCurve *curve, EcPoint *R, const EcPoint *P);
+
+static int ecDoublePointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P);
+static int ecDoublePointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P);
+static int ecDoublePoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P);
+
+static int ecAddPointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q);
+static int ecAddPointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q);
+static int ecAddPoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q);
+
+static int ecCheckPubKeyNist(const EcCurve *curve, const EcPoint *pub);
+static int ecCheckPubKey3617(const EcCurve *curve, const EcPoint *pub);
+static int ecCheckPubKey25519(const EcCurve *curve, const EcPoint *pub);
+
+static int ecGenerateRandomNumberNist(const EcCurve *curve, BigNum *d);
+static int ecGenerateRandomNumber3617(const EcCurve *curve, BigNum *d);
+static int ecGenerateRandomNumber25519(const EcCurve *curve, BigNum *d);
+
+static int ecMulPointScalarNormal(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar);
+static int ecMulPointScalar25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar);
+
+/* Forward declaration of new modulo functions for the EC curves */
+static int newMod192(BigNum *r, const BigNum *a, const BigNum *modulo);
+static int newMod256(BigNum *r, const BigNum *a, const BigNum *modulo);
+static int newMod384(BigNum *r, const BigNum *a, const BigNum *modulo);
+static int newMod521(BigNum *r, const BigNum *a, const BigNum *modulo);
+
+static int mod3617(BigNum *r, const BigNum *a, const BigNum *modulo);
+static int mod25519(BigNum *r, const BigNum *a, const BigNum *modulo);
+
+static void commonInit()
 {
-    size_t maxBits;
-    curveData *cd;
+    bnBegin(mpiZero); bnSetQ(mpiZero, 0);
+    bnBegin(mpiOne); bnSetQ(mpiOne, 1);
+    bnBegin(mpiTwo); bnSetQ(mpiTwo, 2);
+    bnBegin(mpiThree); bnSetQ(mpiThree, 3);
+    bnBegin(mpiFour); bnSetQ(mpiFour, 4);
+    bnBegin(mpiEight); bnSetQ(mpiEight, 8);
+}
 
-    if (!initialized) {
-        bnBegin(mpiZero); bnSetQ(mpiZero, 0);
-        bnBegin(mpiOne); bnSetQ(mpiOne, 1);
-        bnBegin(mpiTwo); bnSetQ(mpiTwo, 2);
-        bnBegin(mpiThree); bnSetQ(mpiThree, 3);
-        bnBegin(mpiFour); bnSetQ(mpiFour, 4);
-        bnBegin(mpiEight); bnSetQ(mpiEight, 8);
-        initialized = 1;
-    }
-    if (curve == NULL)
-        return -2;
-
-    bnBegin(&curve->_p);    curve->p = &curve->_p;
-    bnBegin(&curve->_n);    curve->n = &curve->_n;
-    bnBegin(&curve->_SEED); curve->SEED = &curve->_SEED;
-    bnBegin(&curve->_c);    curve->c = &curve->_c;
-    bnBegin(&curve->_a);    curve->a = &curve->_a;
-    bnBegin(&curve->_b);    curve->b = &curve->_b;
-    bnBegin(&curve->_Gx);   curve->Gx = &curve->_Gx;
-    bnBegin(&curve->_Gy);   curve->Gy = &curve->_Gy;
-
+static void curveCommonInit(EcCurve *curve)
+{
     /* Initialize scratchpad variables and their pointers */
     bnBegin(&curve->_S1); curve->S1 = &curve->_S1;
     bnBegin(&curve->_U1); curve->U1 = &curve->_U1;
@@ -196,41 +273,11 @@
     bnBegin(&curve->_t1); curve->t1 = &curve->_t1;
     bnBegin(&curve->_t2); curve->t2 = &curve->_t2;
     bnBegin(&curve->_t3); curve->t3 = &curve->_t3;
+}
 
-    switch (curveId) {
-    case NIST192P:
-        cd = &nist192;
-        break;
-
-    case NIST224P:
-        cd = &nist224;
-        break;
-
-    case NIST256P:
-        cd = &nist256;
-        break;
-
-    case NIST384P:
-        cd = &nist384;
-        break;
-
-    case NIST521P:
-        cd = &nist521;
-        break;
-
-    default:
-        return -2;
-    }
-
-    bnReadAscii(curve->p, cd->p, 10);
-    bnReadAscii(curve->n, cd->n, 10);
-    bnReadAscii(curve->SEED, cd->SEED, 16);
-    bnReadAscii(curve->c, cd->c, 16);
-    bnCopy(curve->a, curve->p);
-    bnSub(curve->a, mpiThree);
-    bnReadAscii(curve->b, cd->b, 16);
-    bnReadAscii(curve->Gx, cd->Gx, 16);
-    bnReadAscii(curve->Gy, cd->Gy, 16);
+static void curveCommonPrealloc(EcCurve *curve)
+{
+    size_t maxBits;
 
     /* variables must be able to hold p^2, plus one nimb (min. 15 bits) for overflow */
     maxBits = bnBits(curve->p) * 2 + 15;
@@ -245,16 +292,151 @@
     bnPrealloc(curve->t1, maxBits);
     bnPrealloc(curve->t2, maxBits);
     bnPrealloc(curve->t3, maxBits);
-
-    return 0;
-
-/*     ecFreeCurveNistECp(curve);
-     return ret;
-*/
 }
 
+int ecGetCurveNistECp(Curves curveId, EcCurve *curve)
+{
+    curveData *cd;
 
-void ecFreeCurveNistECp(NistECpCurve *curve) 
+    if (curveId >= Curve25519 && curveId <= Curve3617)
+        return ecGetCurvesCurve(curveId, curve);
+
+    if (!initialized) {
+        commonInit();
+        initialized = 1;
+    }
+    if (curve == NULL)
+        return -2;
+
+    bnBegin(&curve->_p);    curve->p = &curve->_p;
+    bnBegin(&curve->_n);    curve->n = &curve->_n;
+    bnBegin(&curve->_SEED); curve->SEED = &curve->_SEED;
+    bnBegin(&curve->_c);    curve->c = &curve->_c;
+    bnBegin(&curve->_a);    curve->a = &curve->_a;
+    bnBegin(&curve->_b);    curve->b = &curve->_b;
+    bnBegin(&curve->_Gx);   curve->Gx = &curve->_Gx;
+    bnBegin(&curve->_Gy);   curve->Gy = &curve->_Gy;
+
+    curveCommonInit(curve);
+
+    switch (curveId) {
+    case NIST192P:
+        cd = &nist192;
+        curve->modOp = newMod192;
+        break;
+
+    case NIST224P:
+        cd = &nist224;
+        curve->modOp = bnMod;
+        break;
+
+    case NIST256P:
+        cd = &nist256;
+        curve->modOp = bnMod;
+        break;
+
+    case NIST384P:
+        cd = &nist384;
+        curve->modOp = newMod384;
+        break;
+
+    case NIST521P:
+        cd = &nist521;
+        curve->modOp = newMod521;
+        break;
+
+    default:
+        return -2;
+    }
+
+    curve->affineOp = ecGetAffineNist;
+    curve->doubleOp = ecDoublePointNist;
+    curve->addOp = ecAddPointNist;
+    curve->checkPubOp = ecCheckPubKeyNist;
+    curve->randomOp = ecGenerateRandomNumberNist;
+    curve->mulScalar = ecMulPointScalarNormal;
+
+    bnReadAscii(curve->p, cd->p, 10);
+    bnReadAscii(curve->n, cd->n, 10);
+    bnReadAscii(curve->SEED, cd->SEED, 16);
+    bnReadAscii(curve->c, cd->c, 16);
+    bnCopy(curve->a, curve->p);
+    bnSub(curve->a, mpiThree);
+    bnReadAscii(curve->b, cd->b, 16);
+    bnReadAscii(curve->Gx, cd->Gx, 16);
+    bnReadAscii(curve->Gy, cd->Gy, 16);
+
+    curveCommonPrealloc(curve);
+    curve->id = curveId;
+
+    return 0;
+}
+
+int ecGetCurvesCurve(Curves curveId, EcCurve *curve)
+{
+    curveData *cd;
+
+    if (!initialized) {
+        commonInit();
+        initialized = 1;
+    }
+    if (curve == NULL)
+        return -2;
+
+    /* set-up all bignum structures, simplifies "free" handling */
+    bnBegin(&curve->_p);    curve->p = &curve->_p;
+    bnBegin(&curve->_n);    curve->n = &curve->_n;
+    bnBegin(&curve->_SEED); curve->SEED = &curve->_SEED;
+    bnBegin(&curve->_c);    curve->c = &curve->_c;
+    bnBegin(&curve->_a);    curve->a = &curve->_a;
+    bnBegin(&curve->_b);    curve->b = &curve->_b;
+    bnBegin(&curve->_Gx);   curve->Gx = &curve->_Gx;
+    bnBegin(&curve->_Gy);   curve->Gy = &curve->_Gy;
+
+    curveCommonInit(curve);
+
+    switch (curveId) {
+    case Curve3617:
+        cd = &curve3617;
+        curve->modOp = mod3617;
+        curve->affineOp = ecGetAffineEd;
+        curve->doubleOp = ecDoublePointEd;
+        curve->addOp = ecAddPointEd;
+        curve->checkPubOp = ecCheckPubKey3617;
+        curve->randomOp = ecGenerateRandomNumber3617;
+        curve->mulScalar = ecMulPointScalarNormal;
+
+        bnReadAscii(curve->a, "3617", 10);
+        break;
+
+    case Curve25519:
+        cd = &curve25519;
+        curve->modOp = mod25519;
+        curve->affineOp = ecGetAffine25519;
+        curve->doubleOp = ecDoublePoint25519;
+        curve->addOp = ecAddPoint25519;
+        curve->checkPubOp = ecCheckPubKey25519;
+        curve->randomOp = ecGenerateRandomNumber25519;
+        curve->mulScalar = ecMulPointScalar25519;
+
+        bnReadAscii(curve->a, "486662", 10);
+        break;
+
+    default:
+        return -2;
+    }
+    bnReadAscii(curve->p, cd->p, 16);
+    bnReadAscii(curve->n, cd->n, 16);
+
+    bnReadAscii(curve->Gx, cd->Gx, 16);
+    bnReadAscii(curve->Gy, cd->Gy, 16);
+
+    curveCommonPrealloc(curve);
+    curve->id = curveId;
+    return 0;
+}
+
+void ecFreeCurveNistECp(EcCurve *curve) 
 {
     if (curve == NULL)
         return;
@@ -277,12 +459,40 @@
     bnEnd(curve->t3);
 }
 
+/*
+ * EC point helper functions
+ */
+
+void ecInitPoint(EcPoint *P)
+{
+    INIT_EC_POINT(P);
+}
+
+void ecFreePoint(EcPoint *P)
+{
+    FREE_EC_POINT(P);
+}
+
+void ecSetBasePoint(EcCurve *C, EcPoint *P)
+{
+    SET_EC_BASE_POINT(C, P);
+}
+
+void ecFreeCurvesCurve(EcCurve *curve)
+{
+    ecFreeCurveNistECp(curve);
+}
 
 /*============================================================================*/
 /*    Elliptic Curve arithmetic                                               */
 /*============================================================================*/
 
-int ecGetAffine(const NistECpCurve *curve, EcPoint *R, const EcPoint *P)
+int ecGetAffine(const EcCurve *curve, EcPoint *R, const EcPoint *P)
+{
+    return curve->affineOp(curve, R, P);
+}
+
+static int ecGetAffineNist(const EcCurve *curve, EcPoint *R, const EcPoint *P)
 {
     int ret = 0;
 
@@ -292,13 +502,13 @@
     bnBegin(&z_2);
 
     /* affine x = X / Z^2 */
-    bnInv (&z_1, P->z, curve->p);          /* z_1 = Z^(-1) */
-    bnMulMod_(&z_2, &z_1, &z_1, curve->p); /* z_2 = Z^(-2) */
-    bnMulMod_(R->x, P->x, &z_2, curve->p);
-    
+    bnInv (&z_1, P->z, curve->p);                 /* z_1 = Z^(-1) */
+    bnMulMod_(&z_2, &z_1, &z_1, curve->p, curve); /* z_2 = Z^(-2) */
+    bnMulMod_(R->x, P->x, &z_2, curve->p, curve);
+
     /* affine y = Y / Z^3 */
-    bnMulMod_(&z_2, &z_2, &z_1, curve->p); /* z_2 = Z^(-3) */
-    bnMulMod_(R->y, P->y, &z_2, curve->p);
+    bnMulMod_(&z_2, &z_2, &z_1, curve->p, curve); /* z_2 = Z^(-3) */
+    bnMulMod_(R->y, P->y, &z_2, curve->p, curve);
 
     bnSetQ(R->z, 1);
 
@@ -307,7 +517,48 @@
     return ret;
 }
 
-int ecDoublePoint(const NistECpCurve *curve, EcPoint *R, const EcPoint *P)
+static int ecGetAffineEd(const EcCurve *curve, EcPoint *R, const EcPoint *P)
+{
+    int ret = 0;
+
+    struct BigNum z_1;
+
+    bnBegin(&z_1);
+
+    /* affine x = X / Z */
+    bnInv (&z_1, P->z, curve->p);                 /* z_1 = Z^(-1) */
+    bnMulMod_(R->x, P->x, &z_1, curve->p, curve);
+
+    /* affine y = Y / Z */
+    bnMulMod_(R->y, P->y, &z_1, curve->p, curve);
+
+    bnSetQ(R->z, 1);
+
+    bnEnd(&z_1);
+    return ret;
+
+}
+
+/* 
+ * If the arguments do not point to the same EcPoint then copy P to result.
+ * Curve25519 has no specific GetAffine function, it's all inside curve25519-donna
+ */
+static int ecGetAffine25519(const EcCurve *curve, EcPoint *R, const EcPoint *P)
+{
+    if (R != P) {
+        bnCopy(R->x, P->x);
+        bnCopy(R->y, P->y);
+        bnCopy(R->z, P->z);
+    }
+    return 0;
+}
+
+int ecDoublePoint(const EcCurve *curve, EcPoint *R, const EcPoint *P)
+{
+    return curve->doubleOp(curve, R, P);
+}
+
+static int ecDoublePointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P)
 {
     int ret = 0;
 
@@ -333,37 +584,37 @@
         ptP = P;
 
     /* S = 4*X*Y^2, save Y^2 in t1 for later use */
-    bnMulMod_(curve->t1, ptP->y, ptP->y, curve->p);       /* t1 = Y^2 */
-    bnMulMod_(curve->t0, ptP->x, mpiFour, curve->p);      /* t0 = 4 * X */
-    bnMulMod_(curve->S1, curve->t0, curve->t1, curve->p); /* S1 = t0 * t1 */
+    bnMulMod_(curve->t1, ptP->y, ptP->y, curve->p, curve);       /* t1 = Y^2 */
+    bnMulMod_(curve->t0, ptP->x, mpiFour, curve->p, curve);      /* t0 = 4 * X */
+    bnMulMod_(curve->S1, curve->t0, curve->t1, curve->p, curve); /* S1 = t0 * t1 */
 
     /* M = 3*(X + Z^2)*(X - Z^2), use scratch variable U1 to store M value */
-    bnMulMod_(curve->t2, ptP->z, ptP->z, curve->p);       /* t2 = Z^2 */
+    bnMulMod_(curve->t2, ptP->z, ptP->z, curve->p, curve);       /* t2 = Z^2 */
     bnCopy(curve->t0, ptP->x);
-    bnAddMod_(curve->t0, curve->t2, curve->p);            /* t0 = X + t2  */
-    bnMulMod_(curve->t3, curve->t0, mpiThree, curve->p);  /* t3 = 3 * t0 */
+    bnAddMod_(curve->t0, curve->t2, curve->p);                   /* t0 = X + t2  */
+    bnMulMod_(curve->t3, curve->t0, mpiThree, curve->p, curve);  /* t3 = 3 * t0 */
     bnCopy(curve->t0, ptP->x);
-    bnSubMod_(curve->t0, curve->t2, curve->p);            /* t0 = X - t2 */
-    bnMulMod_(curve->U1, curve->t3, curve->t0, curve->p); /* M = t3 * t0 */
+    bnSubMod_(curve->t0, curve->t2, curve->p);                   /* t0 = X - t2 */
+    bnMulMod_(curve->U1, curve->t3, curve->t0, curve->p, curve); /* M = t3 * t0 */
     
     /* X' = M^2 - 2*S */
-    bnMulMod_(curve->t2, curve->U1, curve->U1, curve->p); /* t2 = M^2 */
-    bnMulMod_(curve->t0, curve->S1, mpiTwo, curve->p);    /* t0 = S * 2 */
+    bnMulMod_(curve->t2, curve->U1, curve->U1, curve->p, curve); /* t2 = M^2 */
+    bnMulMod_(curve->t0, curve->S1, mpiTwo, curve->p, curve);    /* t0 = S * 2 */
     bnCopy(R->x, curve->t2);
-    bnSubMod_(R->x, curve->t0, curve->p);                 /* X' = t2 - t0 */
+    bnSubMod_(R->x, curve->t0, curve->p);                        /* X' = t2 - t0 */
 
     /* Y' = M*(S - X') - 8*Y^4 */
-    bnMulMod_(curve->t3, curve->t1, curve->t1, curve->p); /* t3 = Y^4 (t1 saved above) */
-    bnMulMod_(curve->t2, curve->t3, mpiEight, curve->p); /* t2 = t3 * 8 */
+    bnMulMod_(curve->t3, curve->t1, curve->t1, curve->p, curve); /* t3 = Y^4 (t1 saved above) */
+    bnMulMod_(curve->t2, curve->t3, mpiEight, curve->p, curve);  /* t2 = t3 * 8 */
     bnCopy(curve->t3, curve->S1);
-    bnSubMod_(curve->t3, R->x, curve->p);                 /* t3 = S - X' */
-    bnMulMod_(curve->t0, curve->U1, curve->t3, curve->p); /* t0 = M * t3 */
+    bnSubMod_(curve->t3, R->x, curve->p);                        /* t3 = S - X' */
+    bnMulMod_(curve->t0, curve->U1, curve->t3, curve->p, curve); /* t0 = M * t3 */
     bnCopy(R->y, curve->t0);
-    bnSubMod_(R->y, curve->t2, curve->p);                 /* Y' = t0 - t2 */
+    bnSubMod_(R->y, curve->t2, curve->p);                        /* Y' = t0 - t2 */
 
     /* Z' = 2*Y*Z */
-    bnMulMod_(curve->t0, ptP->y, mpiTwo, curve->p);       /* t0 = 2 * Y */
-    bnMulMod_(R->z, curve->t0, ptP->z, curve->p);         /* Z' = to * Z */
+    bnMulMod_(curve->t0, ptP->y, mpiTwo, curve->p, curve);       /* t0 = 2 * Y */
+    bnMulMod_(R->z, curve->t0, ptP->z, curve->p, curve);         /* Z' = to * Z */
 
     if (P == R)
         FREE_EC_POINT(&tP);
@@ -371,8 +622,72 @@
     return ret;
 }
 
+static int ecDoublePointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P)
+{
+    EcPoint tP;
+    const EcPoint *ptP = 0;
+
+    /* Check for overlapping arguments, copy if necessary and set pointer */
+    if (P == R) {
+        INIT_EC_POINT(&tP);
+        ptP = &tP;
+        bnCopy(tP.x, P->x);
+        bnCopy(tP.y, P->y);
+        bnCopy(tP.z, P->z);
+    }
+    else 
+        ptP = P;
+
+    /* Compute B, C, D, H, E */
+    bnCopy(curve->t1, ptP->x);
+    bnAddMod_(curve->t1, ptP->y, curve->p);
+    bnSquareMod_(curve->t0, curve->t1, curve->p, curve);       /* t0 -> B */
+
+    bnSquareMod_(R->x, ptP->x, curve->p, curve);               /* Rx -> C */
+
+    bnSquareMod_(R->y, ptP->y, curve->p, curve);               /* Ry -> D */
+
+    bnSquareMod_(R->z, ptP->z, curve->p, curve);               /* Rz -> H */
+    bnAddMod_(R->z, R->z, curve->p);                           /* Rz -> 2H */
+
+    bnCopy(curve->t1, R->x);
+    bnAddMod_(curve->t1, R->y, curve->p);                      /* t1 -> E */
+
+    /* Compute Ry */
+    bnCopy(curve->t2, R->x);
+    bnSubMod_(curve->t2, R->y, curve->p);                      /* C - D */
+    bnMulMod_(R->y, curve->t1, curve->t2, curve->p, curve);    /* E * t3; Ry */
+
+    /* Compute Rx */
+    bnSubMod_(curve->t0, curve->t1, curve->p);                 /* B - E; sub result */
+    bnCopy(curve->t2, curve->t1);
+    bnSubMod_(curve->t2, R->z, curve->p);                      /* t2 -> J; (E - 2H) */
+    bnMulMod_(R->x, curve->t2, curve->t0, curve->p, curve);    /* J * t0 */
+
+    /* Compute Rz */
+    bnMulMod_(R->z, curve->t2, curve->t1, curve->p, curve);    /* J * E */
+
+    if (P == R)
+        FREE_EC_POINT(&tP);
+
+    return 0;
+}
+
+/* 
+ * Curve25519 has no specific Double Point function, all inside curve25519-donna
+ */
+static int ecDoublePoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P)
+{
+    return -2;
+}
+
 /* Add two elliptic curve points. Any of them may be the same object. */
-int ecAddPoint(const NistECpCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q)
+int ecAddPoint(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q)
+{
+    return curve->addOp(curve, R, P, Q);
+}
+
+static int ecAddPointNist(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q)
 {
     int ret = 0;
 
@@ -424,23 +739,23 @@
         ptQ = Q;
 
     /* U1 = X1*Z2^2, where X1: P->x, Z2: Q->z */
-    bnMulMod_(curve->t1, ptQ->z, ptQ->z, curve->p);    /* t1 = Z2^2 */
-    bnMulMod_(curve->U1, ptP->x, curve->t1, curve->p); /* U1 = X1 * z_2 */
+    bnMulMod_(curve->t1, ptQ->z, ptQ->z, curve->p, curve);    /* t1 = Z2^2 */
+    bnMulMod_(curve->U1, ptP->x, curve->t1, curve->p, curve); /* U1 = X1 * z_2 */
 
     /* S1 = Y1*Z2^3, where Y1: P->y */
-    bnMulMod_(curve->t1, curve->t1, ptQ->z, curve->p); /* t1 = Z2^3 */
-    bnMulMod_(curve->S1, ptP->y, curve->t1, curve->p); /* S1 = Y1 * z_2 */
+    bnMulMod_(curve->t1, curve->t1, ptQ->z, curve->p, curve); /* t1 = Z2^3 */
+    bnMulMod_(curve->S1, ptP->y, curve->t1, curve->p, curve); /* S1 = Y1 * z_2 */
 
     /* U2 = X2*Z1^2, where X2: Q->x, Z1: P->z */
-    bnMulMod_(curve->t1, ptP->z, ptP->z, curve->p);    /* t1 = Z1^2 */
-    bnMulMod_(curve->H, ptQ->x, curve->t1, curve->p);  /* H = X2 * t1 (store U2 in H) */
+    bnMulMod_(curve->t1, ptP->z, ptP->z, curve->p, curve);    /* t1 = Z1^2 */
+    bnMulMod_(curve->H, ptQ->x, curve->t1, curve->p, curve);  /* H = X2 * t1 (store U2 in H) */
 
     /* H = U2 - U1 */
     bnSubMod_(curve->H, curve->U1, curve->p);
 
     /* S2 = Y2*Z1^3, where Y2: Q->y */
-    bnMulMod_(curve->t1, curve->t1, ptP->z, curve->p); /* t1 = Z1^3 */
-    bnMulMod_(curve->R, ptQ->y, curve->t1, curve->p);  /* R = Y2 * t1 (store S2 in R) */
+    bnMulMod_(curve->t1, curve->t1, ptP->z, curve->p, curve); /* t1 = Z1^3 */
+    bnMulMod_(curve->R, ptQ->y, curve->t1, curve->p, curve);  /* R = Y2 * t1 (store S2 in R) */
 
     /* R = S2 - S1 */
     bnSubMod_(curve->R, curve->S1, curve->p);
@@ -458,26 +773,26 @@
         return ecDoublePoint(curve, R, P);
     }
     /* X3 = R^2 - H^3 - 2*U1*H^2, where X3: R->x */
-    bnMulMod_(curve->t0, curve->H, curve->H, curve->p);   /* t0 = H^2 */
-    bnMulMod_(curve->t1, curve->U1, curve->t0, curve->p); /* t1 = U1 * t0, (hold t1) */
-    bnMulMod_(curve->t0, curve->t0, curve->H, curve->p);  /* t0 = H^3, (hold t0) */
-    bnMulMod_(curve->t2, curve->R, curve->R, curve->p);   /* t2 = R^2 */
+    bnMulMod_(curve->t0, curve->H, curve->H, curve->p, curve);   /* t0 = H^2 */
+    bnMulMod_(curve->t1, curve->U1, curve->t0, curve->p, curve); /* t1 = U1 * t0, (hold t1) */
+    bnMulMod_(curve->t0, curve->t0, curve->H, curve->p, curve);  /* t0 = H^3, (hold t0) */
+    bnMulMod_(curve->t2, curve->R, curve->R, curve->p, curve);   /* t2 = R^2 */
     bnCopy(curve->t3, curve->t2);
-    bnSubMod_(curve->t3, curve->t0, curve->p);            /* t3 = t2 - t0, (-H^3)*/
-    bnMulMod_(curve->t2, mpiTwo, curve->t1, curve->p);    /* t2 = 2 * t1 */
+    bnSubMod_(curve->t3, curve->t0, curve->p);                   /* t3 = t2 - t0, (-H^3)*/
+    bnMulMod_(curve->t2, mpiTwo, curve->t1, curve->p, curve);    /* t2 = 2 * t1 */
     bnCopy(R->x, curve->t3);
-    bnSubMod_(R->x, curve->t2, curve->p);                 /* X3 = t3 - t2 */
+    bnSubMod_(R->x, curve->t2, curve->p);                        /* X3 = t3 - t2 */
 
     /* Y3 = R*(U1*H^2 - X3) - S1*H^3, where Y3: R->y */
-    bnSubMod_(curve->t1, R->x, curve->p);                 /* t1 = t1 - X3, overwrites t1 now */
-    bnMulMod_(curve->t2, curve->R, curve->t1, curve->p);  /* t2 = R * z_2 */
-    bnMulMod_(curve->S1, curve->S1, curve->t0, curve->p); /* S1 = S1 * t0, (t0 has H^3) */
+    bnSubMod_(curve->t1, R->x, curve->p);                        /* t1 = t1 - X3, overwrites t1 now */
+    bnMulMod_(curve->t2, curve->R, curve->t1, curve->p, curve);  /* t2 = R * z_2 */
+    bnMulMod_(curve->S1, curve->S1, curve->t0, curve->p, curve); /* S1 = S1 * t0, (t0 has H^3) */
     bnCopy(R->y, curve->t2);
-    bnSubMod_(R->y, curve->S1, curve->p);                 /* Y3 = t2 - S1 */
+    bnSubMod_(R->y, curve->S1, curve->p);                        /* Y3 = t2 - S1 */
 
     /* Z3 = H*Z1*Z2, where Z1: P->z, Z2: Q->z, Z3: R->z */
-    bnMulMod_(curve->t2, curve->H, P->z, curve->p);       /* t2 = H * Z1 */
-    bnMulMod_(R->z, curve->t2, Q->z, curve->p);           /* Z3 = t2 * Z2 */
+    bnMulMod_(curve->t2, curve->H, P->z, curve->p, curve);       /* t2 = H * Z1 */
+    bnMulMod_(R->z, curve->t2, Q->z, curve->p, curve);           /* Z3 = t2 * Z2 */
 
     if (P == R)
         FREE_EC_POINT(&tP);
@@ -486,10 +801,117 @@
     return ret;
 }
 
-int ecMulPointScalar(const NistECpCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar)
+/*
+ * Refer to the document: Faster addition and doubling on elliptic curves; Daniel J. Bernstein and Tanja Lange
+ * section 4.
+ *
+ * This function is a variant of the 'addition'. The function returns the result in an own curve point
+ * and does not overwrite its input parameters.
+ */
+static int ecAddPointEd(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q)
 {
+    EcPoint tP, tQ;
+    const EcPoint *ptP = 0;
+    const EcPoint *ptQ = 0;
 
-    /* MPI_CHK below macro requires a 'ret' variable and a cleanup label */
+    /* if P is (@,@), R = Q */
+    if (!bnCmp(P->z, mpiZero)) {
+        bnCopy(R->x, Q->x);
+        bnCopy(R->y, Q->y);
+        bnCopy(R->z, Q->z);
+        return 0;
+    }
+
+    /* if Q is (@,@), R = P */
+    if (!bnCmp(Q->z, mpiZero)) {
+        bnCopy(R->x, P->x);
+        bnCopy(R->y, P->y);
+        bnCopy(R->z, P->z);
+        return 0;
+    }
+
+    /* Check for overlapping arguments, copy if necessary and set pointers */
+    if (P == R) {
+        INIT_EC_POINT(&tP);
+        ptP = &tP;
+        bnCopy(tP.x, P->x);
+        bnCopy(tP.y, P->y);
+        bnCopy(tP.z, P->z);
+    }
+    else 
+        ptP = P;
+
+    if (Q == R) {
+        INIT_EC_POINT(&tQ);
+        ptQ = &tQ;
+        bnCopy(tQ.x, Q->x);
+        bnCopy(tQ.y, Q->y);
+        bnCopy(tQ.z, Q->z);
+    }
+    else
+        ptQ = Q;
+
+    /* Compute A, C, D first */
+    bnMulMod_(R->z, ptP->z, ptQ->z, curve->p, curve);            /* Rz -> A; (Z1 * z2); Rz becomes R3 */
+    bnMulMod_(R->x, ptP->x, ptQ->x, curve->p, curve);            /* Rx -> C; (X1 * X2); Rx becomes R1 */
+    bnMulMod_(R->y, ptP->y, ptQ->y, curve->p, curve);            /* Ry -> D; (Y1 * Y2); Ry becomes R2 */
+
+    /* Compute large parts of X3 equation, sub result in t0 */
+    bnCopy(curve->t0, ptP->x);
+    bnAddMod_(curve->t0, ptP->y, curve->p);                      /* t0 -> X1 + Y1 */
+    bnCopy(curve->t1, ptQ->x);
+    bnAddMod_(curve->t1, ptQ->y, curve->p);                      /* t1 -> X2 + Y2 */
+    bnMulMod_(curve->t2, curve->t0, curve->t1, curve->p, curve); /* t2 = t0 * t1 */
+    bnSubMod_(curve->t2, R->x, curve->p);                        /* t2 - C */
+    bnSubMod_(curve->t2, R->y, curve->p);                        /* t2 - D */
+    bnMulMod_(curve->t0, curve->t2, R->z, curve->p, curve);      /* t0 -> R7; (t2 * A); sub result */
+
+    /* Compute E */
+    bnMulMod_(curve->t2, R->x, R->y, curve->p, curve);           /* t2 = C * D */
+    bnMulMod_(curve->t1, curve->t2, curve->a, curve->p, curve);  /* t1 -> E; t1 new R8 */
+
+    /* Compute part of Y3 equation, sub result in t2 */
+    bnSubMod_(R->y, R->x, curve->p);                             /* Ry = D - C; sub result */
+    bnMulMod_(curve->t2, R->y, R->z, curve->p, curve);           /* t2 = Ry * A; sub result */
+
+    /* Compute B */
+    bnSquareMod_(R->z, R->z, curve->p, curve);                   /* Rz -> B; (A^2) */
+
+    /* Compute F */
+    bnCopy(curve->t3, R->z);
+    bnSubMod_(curve->t3, curve->t1, curve->p);                   /* t3 -> F; (B - E) */
+
+    /* Compute G */
+    bnAddMod_(R->z, curve->t1, curve->p);                        /* Rz -> G; (B + E) */
+
+    /* Compute, X, Y, Z results */
+    bnMulMod_(R->x, curve->t3, curve->t0, curve->p, curve);      /* Rx = F * t0 */
+    bnMulMod_(R->y, curve->t2, R->z, curve->p, curve);           /* Ry = t2 * G */
+    bnMulMod_(R->z, curve->t3, R->z, curve->p, curve);           /* Rz = F * G */
+
+    if (P == R)
+        FREE_EC_POINT(&tP);
+    if (Q == R)
+        FREE_EC_POINT(&tQ);
+
+    return 0;
+}
+
+/* 
+ * Curve25519 has no specific Add Point function, all inside curve25519-donna
+ */
+static int ecAddPoint25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q)
+{
+    return -2;
+}
+
+int ecMulPointScalar(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar)
+{
+    return curve->mulScalar(curve, R, P, scalar);
+}
+
+static int ecMulPointScalarNormal(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar)
+{
     int ret = 0;
     int i;
     int bits = bnBits(scalar);
@@ -515,7 +937,26 @@
     return ret;
 }
 
+/* 
+ * This function uses BigNumber only as containers to transport the 32 byte data.
+ * This makes it compliant to the other functions and thus higher-level API does not change.
+ * 
+ * curve25519_donna function uses data in little endian format.
+ */
+static int ecMulPointScalar25519(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar)
+{
+    uint8_t basepoint[32], secret[32], result[32];
+
+    bnExtractLittleBytes(P->x, basepoint, 0, 32);  /* 25519 function requires the X coordinate only (compressed) */
+    bnExtractLittleBytes(scalar, secret, 0, 32);
+    curve25519_donna(result, secret, basepoint);
+    bnInsertLittleBytes(R->x, result, 0, 32);
+    return 0;
+}
+
 #ifdef WEAKRANDOM
+#include <fcntl.h>
+
 /*
  * A standard random number generator that uses the portable random() system function.
  *
@@ -523,10 +964,15 @@
  */
 static int _random(unsigned char *output, size_t len)
 {
-    size_t i;
+    size_t num = 0;
 
-    for(i = 0; i < len; ++i )
-        output[i] = random();
+    int rnd = open("/dev/urandom", O_RDONLY);
+    if (rnd >= 0) {
+        num = read(rnd, output, len);
+        close(rnd);
+    }
+    else
+        return num;
 
     return( 0 );
 }
@@ -538,7 +984,12 @@
 }
 #endif
 
-int ecGenerateRandomNumber(const NistECpCurve *curve, BigNum *d)
+int ecGenerateRandomNumber(const EcCurve *curve, BigNum *d)
+{
+    return curve->randomOp(curve, d);
+}
+
+static int ecGenerateRandomNumberNist(const EcCurve *curve, BigNum *d)
 {
     BigNum c, nMinusOne;
 
@@ -568,3 +1019,677 @@
 
     return 0;
 }
+
+static int ecGenerateRandomNumber3617(const EcCurve *curve, BigNum *d)
+{
+    unsigned char random[52];
+    _random(random, 52);
+
+    /* prepare the secret random data: clear bottom 3 bits. Clearing top 2 bits
+     * makes is a 414 bit value
+     */
+    random[51] &= ~0x7;
+    random[0] &= 0x3f;
+    /* convert the random data into big numbers */
+    bnInsertBigBytes(d, random, 0, 52);
+    return 0;
+}
+
+static int ecGenerateRandomNumber25519(const EcCurve *curve, BigNum *d)
+{
+    unsigned char random[32];
+    _random(random, 32);
+
+    /* No specific preparation. The curve25519_donna functions prepares the data.
+     *
+     * convert the random data into big numbers. the bigNumber is a container only.
+     * we don not use the big number for any arithmetic
+     */
+    bnInsertLittleBytes(d, random, 0, 32);
+    return 0;
+
+}
+
+int ecCheckPubKey(const EcCurve *curve, const EcPoint *pub)
+{
+    return curve->checkPubOp(curve, pub);
+}
+
+static int ecCheckPubKeyNist(const NistECpCurve *curve, const EcPoint *pub)
+{
+    /* Represent point at infinity by (0, 0), make sure it's not that */
+    if (bnCmpQ(pub->x, 0) == 0 && bnCmpQ(pub->y, 0) == 0) {
+        return 0;
+    }
+    /* Check that coordinates are within range */
+    if (bnCmpQ(pub->x, 0) < 0 || bnCmp(pub->x, curve->p) >= 0) {
+        return 0;
+    }
+    if (bnCmpQ(pub->y, 0) < 0 || bnCmp(pub->y, curve->p) >= 0) {
+        return 0;
+    }
+    /* Check that point satisfies EC equation y^2 = x^3 - 3x + b, mod P */
+    bnSquareMod_(curve->t1, pub->y, curve->p, curve);
+    bnSquareMod_(curve->t2, pub->x, curve->p, curve);
+    bnSubQMod_(curve->t2, 3, curve->p);
+    bnMulMod_(curve->t2, curve->t2, pub->x, curve->p, curve);
+    bnAddMod_(curve->t2, curve->b, curve->p);
+    if (bnCmp (curve->t1, curve->t2) != 0) {
+        return 0;
+    }
+    return 1;
+
+}
+
+static int ecCheckPubKey3617(const EcCurve *curve, const EcPoint *pub)
+{
+    /* Represent point at infinity by (0, 0), make sure it's not that */
+    if (bnCmpQ(pub->x, 0) == 0 && bnCmpQ(pub->y, 0) == 0) {
+        return 0;
+    }
+    /* Check that coordinates are within range */
+    if (bnCmpQ(pub->x, 0) < 0 || bnCmp(pub->x, curve->p) >= 0) {
+        return 0;
+    }
+    if (bnCmpQ(pub->y, 0) < 0 || bnCmp(pub->y, curve->p) >= 0) {
+        return 0;
+    }
+    /* Check that point satisfies EC equation x^2+y^2 = 1+3617x^2y^2, mod P */
+    bnSquareMod_(curve->t1, pub->y, curve->p, curve);
+    bnSquareMod_(curve->t2, pub->x, curve->p, curve);
+    bnCopy(curve->t3, curve->t1);                                /* Load t3 */
+    bnAddMod_(curve->t3, curve->t2, curve->p);                   /* t3 = t1 + t2, (x^2+y^2)*/
+
+    bnMulMod_(curve->t0, curve->a, curve->t1, curve->p, curve);  /* t0 = a * t1,  (3617 * x^2) */
+    bnMulMod_(curve->t0, curve->t0, curve->t2, curve->p, curve); /* t0 = t0 * t1, (3617 * x^2 * y^2) */
+    bnAddMod_(curve->t0, mpiOne, curve->p);                      /* t0 = t0 + 1,  (3617 * x^2 * y^2 + 1) */
+
+    if (bnCmp (curve->t0, curve->t3) != 0) {
+        return 0;
+    }
+    return 1;
+}
+
+/**
+ * According to http://cr.yp.to/ecdh.html#validate no validation is required if used for Diffie-Hellman
+ * thus always return success.
+ */
+static int ecCheckPubKey25519(const EcCurve *curve, const EcPoint *pub)
+{
+    return 1;
+}
+
+static int mod3617(BigNum *r, const BigNum *a, const BigNum *modulo)
+{
+    unsigned char buffer[52] = {0};
+    int cmp;
+    BigNum tmp;
+
+    bnBegin(&tmp);
+    cmp = bnCmp(modulo, a);
+    if (cmp == 0) {             /* a is equal modulo, set resul to zero */
+        bnSetQ(r, 0);
+        return 0;
+    }
+    if (cmp > 0) {              /* modulo is greater than a - copy a to r and return it */
+        bnCopy(r, a);
+        return 0;
+    }
+    bnExtractLittleBytes(a, buffer, 0, 52);
+    buffer[51] &= 0x3f;
+
+    bnCopy(&tmp, a);
+    bnRShift(&tmp, 414);
+    bnCopy(r, &tmp);
+    bnLShift(r, 4);
+    bnAdd(r, &tmp);
+
+    bnInsertLittleBytes(&tmp, buffer, 0, 52);
+
+    bnAdd(r, &tmp);
+    while (bnCmp(r, modulo) >= 0) {
+        bnSub(r, modulo);
+    }
+    bnEnd(&tmp);
+    return 0;
+}
+
+/* 
+ * Curve25519 has no specific modulo function, all inside curve25519-donna
+ */
+static int mod25519(BigNum *r, const BigNum *a, const BigNum *modulo)
+{
+    return -2;
+}
+
+/*
+ * Beware: Here are the dragons.
+ *
+ * The modulo implementations for the NIST curves. For more detailled information see
+ * FIPS 186-3, chapter D.2 and other papers about Generailzed Mersenne numbers.
+ *
+ * I use byte operations to perfom the additions with carry. On a little endian machine
+ * this saves conversion from/to big endian format if I would use integers for example. Also
+ * using byte addition into a short carry accumulator works on every word size and avoids
+ * complex testing and handling of wordsizes and big/little endian stuff.
+ *
+ */
+
+/* new modulo for 192bit curve */
+static int newMod192(BigNum *r, const BigNum *a, const BigNum *modulo)
+{
+    unsigned char buffer[200] = {0};
+    unsigned char *pt;
+    unsigned char *ps1;
+    unsigned char *ps2;
+    unsigned char *ps3;
+    short ac;
+    int cmp;
+
+    /* Binary big number representation in PolarSSL is always big endian
+     *
+     * the least significant 64bit large word starts at byte offset 40,
+     * the least significant 32bit word starts at byte offset 44
+     * the least significant byte starts at byte offset 47
+     *
+     *           S3    S2   S1          T
+     *                            /-----^------\
+     *           A5    A4   A3    A2    A1    A0
+     * 64bit  0     1     2     3     4     5
+     *        |--+--|--+--|--+--|--+--|--+--|--+--|
+     * 32bit  0  1  2  3  4  5  6  7  8  9 10 11
+     *
+     * perform T + S1 + S2 + S3 mod p
+
+     * where T  = (A2 || A1 || A0)
+     *     + S1 = ( 0 || A3 || A3)
+     *     + S2 = (A4 || A4 ||  0)
+     *     + S3 = (A5 || A5 || A5)
+     *
+     * TODO: error check if input variable is > modulo^2 (do normal mpi_mod_mpi),
+     */
+
+    /* TODO: check if a is > modulo^2 */
+    cmp = bnCmp(modulo, a);
+    if (cmp == 0) {             /* a is equal modulo, set resul to zero */
+        bnSetQ(r, 0);
+        return 0;
+    }
+    if (cmp > 0) {              /* modulo is greater than a - copy a to r and return it */
+        bnCopy(r, a);
+        return 0;
+    }
+    bnExtractBigBytes(a, buffer, 0, bnBytes(modulo)*2);
+
+    /* 6 'A' words, each word is 8 byte. Compute offset to least significant byte of word X */
+#define A(X) buffer + (((6-X)*8)-1)
+
+    ac = 0;
+
+    pt = A(0);      /* pt points to least significant byte of A0  */
+
+    /* Add up first 8 byte word, no need to add ps2 */
+    ps1 = A(3);        /* ps1 points to least significant byte of S1 (A3) */
+    ps3 = A(5);        /* ps3 points to least significant byte of S3 (A5)*/
+
+    /* Each block processes one 32 bit word, big endian, using byte operations */
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+
+    /* Add up second 8 byte word, all three S words are used here */
+    ps1 = A(3); ps2 = A(4); ps3 = A(5);
+
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1--; ac += *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+
+    /* Add up third 8 byte word, no need to add S1 word */
+    ps2 = A(4); ps3 = A(5);
+
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; *pt-- = ac; ac >>= 8;
+
+    /* In this function we cannot have a negative carry and at most a carry of 2
+     * thus just subtract the modulo until we are less than modulo
+     */
+    bnSetQ(r, 0);
+
+    *(A(3)) = ac;      /* Store the carry */
+    bnInsertBigBytes(r, A(3), 0, 25);  /* 25: 3 * 8 byte words + 1 carry byte */
+    while (bnCmp(r, modulo) >= 0) {
+        bnSub(r, modulo);
+    }
+    return 0;
+}
+#undef A
+
+/* new modulo for 256bit curve */
+static int newMod256(BigNum *r, const BigNum *a, const BigNum *modulo)
+{
+    unsigned char buffer[200] = {0};
+    unsigned char *pt;
+    unsigned char *ps1;
+    unsigned char *ps2;
+    unsigned char *ps3;
+    unsigned char *ps4;
+
+    unsigned char *pd1;
+    unsigned char *pd2;
+    unsigned char *pd3;
+    unsigned char *pd4;
+    short ac;
+    int cmp;
+
+    /* Binary big number representation in PolarSSL is always big endian
+     *
+     * the least significant byte starts at byte offset 63
+     *
+     *                                                                    T
+     *                                                  /-----------------^------------------\
+     *          A15  A14  A13  A12  A11  A10  A9   A8   A7   A6   A5   A4   A3   A2   A1   A0
+     *        |----+----|----+----|----+----|----+----|----+----|----+----|----+----|----+----|
+     * offset 0    4    8   12   16   20   24   28   32   36   40   44   48   52   56   60    64
+     *
+     * T  = (  A7 ||  A6 ||  A5 ||  A4 ||  A3 ||  A2 ||  A1 ||  A0 )
+     *
+     * S1 = ( A15 || A14 || A13 || A12 || A11 ||  00 ||  00 ||  00 )
+     * S2 = (  00 || A15 || A14 || A13 || A12 ||  00 ||  00 ||  00 )
+     * S3 = ( A15 || A14 ||  00 ||  00 ||  00 || A10 ||  A9 ||  A8 )
+     * S4 = (  A8 || A13 || A15 || A14 || A13 || A11 || A10 ||  A9 )
+     * D1 = ( A10 ||  A8 ||  00 ||  00 ||  00 || A13 || A12 || A11 )
+     * D2 = ( A11 ||  A9 ||  00 ||  00 || A15 || A14 || A13 || A12 )
+     * D3 = ( A12 ||  00 || A10 ||  A9 ||  A8 || A15 || A14 || A13 )
+     * D4 = ( A13 ||  00 || A11 || A10 ||  A9 ||  00 || A15 || A14 )
+     *
+     * perform B = T + 2*S1 + 2*S2 + S3 + S4 - D1 - D2 - D3 - D4 mod p
+     *
+     * TODO: error check if input variable is > modulo^2 (do normal mpi_mod_mpi),
+     */
+
+    cmp = bnCmp(modulo, a);
+    if (cmp == 0) {             /* a is equal modulo, set resul to zero */
+        bnSetQ(r, 0);
+        return 0;
+    }
+    if (cmp > 0) {              /* modulo is greater than a - copya to r and return it */
+        bnCopy(r, a);
+        return 0;
+    }
+    bnExtractBigBytes(a, buffer, 0, bnBytes(modulo)*2);
+
+    /* 16 'A' words, each word is 4 byte. Compute offset to least significant byte of word X */
+#define A(X) buffer + (((16-X)*4)-1)
+
+    ac = 0;
+
+    pt = A(0);          /* pt points to least significant byte of A0  */
+
+    /* Set up to add up data that goes into A0 (right-most column abover); S1, S2 not used */
+    ps3 = A(8);         /* ps3 points to least significant byte of S3 */
+    ps4 = A(9);         /* ps4 points to least significant byte of S4 */
+    pd1 = A(11);        /* pd1 points to least significant byte of D1 */
+    pd2 = A(12);        /* pd2 points to least significant byte of D2 */
+    pd3 = A(13);        /* pd3 points to least significant byte of D3 */
+    pd4 = A(14);        /* pd4 points to least significant byte of D4 */
+
+    /* Each block processes one 32 bit word, big endian, using byte operations */
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add up data that goes into A1; S1, S2 not used */
+    ps3 = A(9);  ps4 = A(10); pd1 = A(12); pd2 = A(13); pd3 = A(14); pd4 = A(15);
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add up data that goes into A2; S1, S2, D4 not used */
+    ps3 = A(10); ps4 = A(11); pd1 = A(13); pd2 = A(14); pd3 = A(15);
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add up data that goes into A3; S3, D1 not used */
+    ps1 = A(11); ps2 = A(12); ps4 = A(13); pd2 = A(15); pd3 = A(8); pd4 = A(9);
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add up data that goes into A4; S3, D1, D2 not used */
+    ps1 = A(12); ps2 = A(13); ps4 = A(14); pd3 = A(9); pd4 = A(10);
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add up data that goes into A5; S3, D1, D2 not used */
+    ps1 = A(13); ps2 = A(14); ps4 = A(15); pd3 = A(10); pd4 = A(11);
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps4--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add up data that goes into A6; D3, D4 not used */
+    ps1 = A(14); ps2 = A(15); ps3 = A(14); ps4 = A(13); pd1 = A(8); pd2 = A(9);
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps2;ac += *ps2--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add up data that goes into A7; S2 not used */
+    ps1 = A(15); ps3 = A(15); ps4 = A(8); pd1 = A(10); pd2 = A(11); pd3 = A(12); pd4 = A(13);
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--;  ac += *ps3--; ac += *ps4--; ac -= *pd1--; ac -= *pd2--; ac -= *pd3--; ac -= *pd4--; *pt-- = ac; ac >>= 8;
+
+    bnSetQ(r, 0);
+    if (ac > 0) {
+        *(A(8)) = ac;      /* Store the carry */
+        bnInsertBigBytes(r, A(8), 0, 33);  /* 33: 8 * 4 byte words + 1 carry byte */
+    }
+    /* Negative carry requires that we add the modulo (carry * -1) times to make
+     * the result positive. Then get the result mod(256).
+     */
+    else if (ac < 0) {
+        int msb, maxMsb;
+
+        *(A(8)) = 0;
+        bnInsertBigBytes(r, A(8), 0, 33);  /* 33: 8 * 4 byte words + 1 carry byte */
+        ac *= -1;
+        while (ac--) {
+            bnAdd(r, modulo);
+        }
+        maxMsb =  bnBits(modulo);
+        msb = bnBits(r) - maxMsb;
+        /* clear all bits above bit length of modulo. This length is 256 here, thus
+         * we effectiviely doing a mod(256)
+         */
+        if (msb > 0) {
+            BigNum tmp;
+            bnBegin(&tmp);
+            bnSetQ (&tmp, 1);
+            bnLShift (&tmp, maxMsb);
+            bnMod(r, r, &tmp);
+            bnEnd(&tmp);
+        }
+    }
+    else {
+        *(A(8)) = 0;
+        bnInsertBigBytes(r, A(8), 0, 33);  /* 33: 8 * 4 byte words + 1 carry byte */
+    }
+    while (bnCmp(r, modulo) >= 0) {
+        bnSub(r, modulo);
+    }
+    return 0;
+}
+#undef A
+
+
+/* new modulo for 384bit curve */
+static int newMod384(BigNum *r, const BigNum *a, const BigNum *modulo)
+{
+    unsigned char buffer[200] = {0};
+    unsigned char *pt;
+    unsigned char *ps1;
+    unsigned char *ps2;
+    unsigned char *ps3;
+    unsigned char *ps4;
+    unsigned char *ps5;
+    unsigned char *ps6;
+
+    unsigned char *pd1;
+    unsigned char *pd2;
+    unsigned char *pd3;
+    short ac;
+    int cmp;
+
+    /*
+     *
+     * the least significant byte starts at byte offset 97
+     *
+     *                                                                    T
+     *                                        /---------------------------^----------------------------\
+     *      A23 ......... A15  A14  A13  A12  A11  A10  A9   A8   A7   A6   A5   A4   A3   A2   A1   A0
+     *    |----+ ...... |----+----|----+----|----+----|----+----|----+----|----+----|----+----|----+----|
+     *
+     * T  = (A11 || A10 ||  A9 ||  A8 ||  A7 ||  A6 ||  A5 ||  A4 ||  A3 ||  A2 ||  A1 ||  A0)
+
+     * S1 = ( 00 ||  00 ||  00 ||  00 ||  00 || A23 || A22 || A21 ||  00 ||  00 ||  00 ||  00)
+     * S2 = (A23 || A22 || A21 || A20 || A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12)
+     * S3 = (A20 || A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12 || A23 || A22 || A21)
+     * S4 = (A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12 || A20 ||  00 || A23 ||  00)
+     * S5 = ( 00 ||  00 ||  00 ||  00 || A23 || A22 || A21 || A20 ||  00 ||  00 ||  00 ||  00)
+     * S6 = ( 00 ||  00 ||  00 ||  00 ||  00 ||  00 || A23 || A22 || A21 ||  00 ||  00 || A20)
+     * D1 = (A22 || A21 || A20 || A19 || A18 || A17 || A16 || A15 || A14 || A13 || A12 || A23)
+     * D2 = ( 00 ||  00 ||  00 ||  00 ||  00 ||  00 ||  00 || A23 || A22 || A21 || A20 ||  00)
+     * D3 = ( 00 ||  00 ||  00 ||  00 ||  00 ||  00 ||  00 || A23 || A23 ||  00 ||  00 ||  00)
+     *
+     * perform B =  T + 2S1 + S2 + S3 + S4 + S5 + S6 – D1 – D2 – D3 mod p
+     *
+     * TODO: error check if input variable is > modulo^2 (do normal mpi_mod_mpi),
+     *       optimize if input is already < modulo  (just copy over in this case).
+     */
+
+    cmp = bnCmp(modulo, a);
+    if (cmp == 0) {             /* a is equal modulo, set resul to zero */
+        bnSetQ(r, 0);
+        return 0;
+    }
+    if (cmp > 0) {              /* modulo is greater than a - copy a to r and return it */
+        bnCopy(r, a);
+        return 0;
+    }
+
+    bnExtractBigBytes(a, buffer, 0, bnBytes(modulo)*2);
+
+    /* 24 'A' words, each word is 4 byte. Compute offset to least significant byte of word X */
+#define A(X) buffer + (((24-X)*4)-1)
+
+    ac = 0;
+
+    pt = A(0);      /* pt points to least significant byte of A0  */
+
+    /* Set up to add data that goes into A0; S1, S4, S5, D2, D3 not used */
+    ps2 = A(12); ps3 = A(21); ps6 = A(20); pd1 = A(23);
+
+    /* Each block processes one 32 bit word, big endian, using byte operations */
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A1; S1, S5, S6, D3 not used */
+    ps2 = A(13); ps3 = A(22); ps4 = A(23); pd1= A(12); pd2 = A(20);
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A2; S1, S4, S5, S6, D3 not used */
+    ps2 = A(14); ps3 = A(23); pd1 = A(13); pd2 = A(21);
+    ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac -= *pd1--;  ac -= *pd2--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A3; S1, S5, S6 not used */
+    ps2 = A(15); ps3 = A(12); ps4 = A(20); ps6 = A(21); pd1 = A(14); pd2 = A(22); pd3 = A(23);
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A4 */
+    ps1 = A(21); ps2 = A(16); ps3 = A(13); ps4 = A(12); ps5 = A(20); ps6 = A(22); pd1 = A(15); pd2 = A(23), pd3 = A(23);
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--;  ac -= *pd2--; ac -= *pd3--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A5; D2, D3 not used */
+    ps1 = A(22); ps2 = A(17); ps3 = A(14); ps4 = A(13); ps5 = A(21); ps6 = A(23); pd1 = A(16);
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac += *ps6--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A6; S6, D2, D3 not used */
+    ps1 = A(23); ps2 = A(18); ps3 = A(15); ps4 = A(14); ps5 = A(22); pd1 = A(17);
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps1;ac += *ps1--; ac += *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A7; S1, S6, D2, D3 not used */
+    ps2 = A(19); ps3 = A(16); ps4 = A(15); ps5 = A(23); pd1 = A(18);
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac += *ps5--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A8; S1, S5, S6, D2, D3 not used */
+    ps2 = A(20); ps3 = A(17); ps4 = A(16); pd1 = A(19);
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A9; S1, S5, S6, D2, D3 not used */
+    ps2 = A(21); ps3 = A(18); ps4 = A(17); pd1 = A(20);
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A10; S1, S5, S6, D2, D3 not used */
+    ps2 = A(22); ps3 = A(19); ps4 = A(18); pd1 = A(21);
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    /* Set up to add data that goes into A10; S1, S5, S6, D2, D3 not used */
+    ps2 = A(23); ps3 = A(20); ps4 = A(19); pd1 = A(22);
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+    ac += *pt + *ps2--; ac += *ps3--; ac += *ps4--; ac -= *pd1--; *pt-- = ac; ac >>= 8;
+
+    bnSetQ(r, 0);
+    if (ac > 0) {
+        *(A(12)) = ac;      /* Store the carry */
+        bnInsertBigBytes(r, A(12), 0, 49);  /* 49: 12 * 4 byte words + 1 carry byte */
+    }
+    /* Negative carry requires that we add the modulo (carry * -1) times to make
+     * the result positive. Then get the result mod(256).
+     */
+    else if (ac < 0) {
+        int msb, maxMsb;
+
+        *(A(12)) = 0;
+        bnInsertBigBytes(r, A(12), 0, 49);  /* 49: 12 * 4 byte words + 1 carry byte */
+        ac *= -1;
+        while (ac--) {
+            bnAdd(r, modulo);
+        }
+        maxMsb =  bnBits(modulo);
+        msb = bnBits(r) - maxMsb;
+        /* clear all bits above bit length of modulo. This length is 384 here, thus
+         * we effectiviely doing a mod(384)
+         */
+        if (msb > 0) {
+            BigNum tmp;
+            bnBegin(&tmp);
+            bnSetQ (&tmp, 1);
+            bnLShift (&tmp, maxMsb);
+            bnMod(r, r, &tmp);
+            bnEnd(&tmp);
+        }
+    }
+    else {
+        *(A(12)) = 0;
+        bnInsertBigBytes(r, A(12), 0, 49);  /* 49: 12 * 4 byte words + 1 carry byte */
+    }
+    while (bnCmp(r, modulo) >= 0) {
+        bnSub(r, modulo);
+    }
+    return 0;
+}
+#undef A
+
+
+/* new modulo for 521bit curve, much easier because the prime for 521 is a real Mersenne prime */
+static int newMod521(BigNum *r, const BigNum *a, const BigNum *modulo)
+{
+    unsigned char buf1[200] = {0};
+    unsigned char buf2[200] = {0};
+    unsigned char *p1;
+    unsigned char *p2;
+    size_t modSize;
+    short ac = 0;
+    unsigned int i;
+    int cmp;
+
+    /* TODO: check if a is > modulo^2 */
+#if 0
+    if (a->s < 0)               /* is it a negative value? */
+        return bnMod(r, a, modulo);
+#endif
+    cmp = bnCmp(modulo, a);
+    if (cmp == 0) {             /* a is equal modulo, set resul to zero */
+        bnSetQ(r, 0);
+        return 0;
+    }
+    bnCopy(r, a);
+    if (cmp > 0) {              /* modulo is greater than a - return the prepared r */
+        return 0;
+    }
+    modSize = bnBytes(modulo);
+
+    bnExtractBigBytes(a, buf1, 0, modSize*2); /* a must be less modulo^2 */
+    buf1[modSize] &= 1;                   /* clear all bits except least significat */
+
+    bnRShift(r, 521);
+    bnExtractBigBytes(r, buf2, 0, modSize*2);
+    buf2[modSize] &= 1;
+
+    p1 = &buf2[131];            /* p1 is pointer to A0 */
+    p2 = &buf1[131];            /* p2 is pointer to A1 */
+
+    for (i = 0; i < modSize; i++) {
+        ac += *p1 + *p2--; *p1-- = ac; ac >>= 8;
+    }
+    bnSetQ(r, 0);
+    bnInsertBigBytes(r, p1+1, 0, modSize);
+
+    while (bnCmp(r, modulo) >= 0) {
+        bnSub(r, modulo);
+    }
+    return 0;
+}
+
diff --git a/jni/libzrtp/sources/bnlib/ec/ec.h b/jni/libzrtp/sources/bnlib/ec/ec.h
index b1bb47c..172ffd8 100644
--- a/jni/libzrtp/sources/bnlib/ec/ec.h
+++ b/jni/libzrtp/sources/bnlib/ec/ec.h
@@ -29,18 +29,34 @@
     NIST224P = 2,
     NIST256P = 3,
     NIST384P = 4,
-    NIST521P = 5
-} NistCurves;
+    NIST521P = 5,
+    Curve25519 = 10,
+    Curve3617  = 11
+} Curves;
 
 /**
- * @brief This structure contains the value of NIST EC curves over Prime Fields.
- *
- * The <b>a</b> curve parameter is the constant -3 and is computed during initialization
- * of the curve structure.
- *
- * The field names correspond to the variable names defined in NIST FIPS 186-3, E.1.2
+ * \brief This structure contains the x, y affine coordinates and the z value if we
+ *        use projective coordinates during EC point arithmetic.
  */
-typedef struct {
+typedef struct _EcPoint {
+    BigNum *x, *y, *z;
+    BigNum tx, ty, tz;
+} EcPoint;
+
+/**
+ * @brief This structure contains the value of EC curves over Prime Fields.
+ *
+ * The for NIST curves the field names correspond to the variable names defined in 
+ * NIST FIPS 186-3, E.1.2. The <b>a</b> curve parameter is the constant -3 and is 
+ * computed during initialization of the curve structure.
+ *
+ * For other curves, for example curve3917 we have less parameters to fill in, mostly
+ * the prime number, the base point, etc. Refer to the curve's initialization function
+ * about the use of the fileds.
+ */
+struct EcCurve;
+struct EcCurve {
+    Curves id;
     BigNum _p;
     BigNum _n;
     BigNum _SEED;
@@ -62,16 +78,18 @@
        avoid to much memory allocation/deallocatio0n overhead */
   BigNum _S1, _U1, _H, _R, _t0, _t1, _t2, _t3;
   BigNum *S1, *U1, *H, *R, *t0, *t1, *t2, *t3;
-} NistECpCurve;
+  int (*affineOp)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P);
+  int (*doubleOp)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P);
+  int (*addOp)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q);
+  int (*modOp)(BigNum *, const BigNum *, const BigNum *);
+  int (*checkPubOp)(const struct EcCurve *curve, const EcPoint *pub);
+  int (*randomOp)(const struct EcCurve *curve, BigNum *d);
+  int (*mulScalar)(const struct EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar);
 
-/**
- * \brief This structure contains the x, y affine coordinates and the z value if we
- *        use projective coordinates during EC point arithmetic.
- */
-typedef struct _EcPoint {
-    BigNum *x, *y, *z;
-    BigNum tx, ty, tz;
-} EcPoint;
+};
+
+typedef struct EcCurve EcCurve;
+typedef EcCurve NistECpCurve;
 
 /**
  * \brief          Marco to initialize a EC point structure.
@@ -94,7 +112,16 @@
  *
  * \param P        Address of the EC point structure.
  */
-#define SET_EC_BASE_POINT(C, P) {EcPoint *e = P;  const NistECpCurve *c = C; bnCopy(e->x, c->Gx); bnCopy(e->y, c->Gy); bnSetQ(e->z, 1);}
+#define SET_EC_BASE_POINT(C, P) {EcPoint *e = P;  const EcCurve *c = C; bnCopy(e->x, c->Gx); bnCopy(e->y, c->Gy); bnSetQ(e->z, 1);}
+
+/*
+ * EC point helper functions
+ */
+extern void ecInitPoint(EcPoint *P);
+
+extern void ecFreePoint(EcPoint *P);
+
+extern void ecSetBasePoint(EcCurve *C, EcPoint *P);
 
 /**
  * \brief          Get NIST EC curve parameters.
@@ -104,23 +131,23 @@
  *
  * \param curveId  Which curve to initialize
  *
- * \param curve    Pointer to a NistECpCurve structure
+ * \param curve    Pointer to a EcCurve structure
  *
- * \return         0 if successful, or a POLARSSL_ERR_EC_XXX/ POLARSSL_ERR_MPI_XXX error code.
+ * \return         0 if successful
  *
  * \note           Call ecFreeCurveNistECp to return allocated memory.
  */
-int ecGetCurveNistECp(NistCurves curveId, NistECpCurve *curve);
+int ecGetCurveNistECp(Curves curveId, NistECpCurve *curve);
 
 
 /**
- * \brief          Free NIST EC curve parameters.
+ * \brief          Free EC curve parameters.
  *
- * \param curve    Pointer to a NistECpCurve structure
+ * \param curve    Pointer to a EcCurve structure
  *
  * \note           Curve parameters must be initialized calling ecGetCurveNistECp.
  */
-void ecFreeCurveNistECp(NistECpCurve *curve);
+void ecFreeCurveNistECp(EcCurve *curve);
 
 /**
  * \brief          Double an EC point.
@@ -129,13 +156,13 @@
  *                 further reference see RFC 6090 or the standard work <i>Guide to Elliptic
  *                 Curve Cryptography</i>.
  *
- * \param          curve  Address of Nist EC curve structure
+ * \param          curve  Address of EC curve structure
  * \param          R      Address of resulting EC point structure
  * \param          P      Address of the EC point structure
  *
- * \return         0 if successful, or a POLARSSL_ERR_EC_XXX / POLARSSL_ERR_MPI_XXX error code.
+ * \return         0 if successful
  */
-int ecDoublePoint(const NistECpCurve *curve, EcPoint *R, const EcPoint *P);
+int ecDoublePoint(const EcCurve *curve, EcPoint *R, const EcPoint *P);
 
 /**
  * \brief          Add two EC points.
@@ -144,43 +171,43 @@
  *                 further reference see RFC 6090 or the standard work <i>Guide to Elliptic
  *                 Curve Cryptography</i>.
  *
- * \param          curve  Address of Nist EC curve structure
+ * \param          curve  Address of EC curve structure
  * \param          R      Address of resulting EC point structure
  * \param          P      Address of the first EC point structure
  * \param          Q      Address of the second EC point structure
  *
- * \return         0 if successful, or a POLARSSL_ERR_EC_XXX / POLARSSL_ERR_MPI_XXX error code.
+ * \return         0 if successful
  */
-int ecAddPoint(const NistECpCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q);
+int ecAddPoint(const EcCurve *curve, EcPoint *R, const EcPoint *P, const EcPoint *Q);
 
 /**
  * \brief          Mulitply an EC point with a scalar value.
  *
- * \param          curve  Address of Nist EC curve structure
+ * \param          curve  Address of EC curve structure
  * \param          R      Address of resulting EC point structure
  * \param          P      Address of the EC point structure
  * \param          scalar Address of the scalar multi-precision integer value
  *
- * \return         0 if successful, or a POLARSSL_ERR_EC_XXX / POLARSSL_ERR_MPI_XXX error code.
+ * \return         0 if successful
  */
-int ecMulPointScalar(const NistECpCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar);
+int ecMulPointScalar(const EcCurve *curve, EcPoint *R, const EcPoint *P, const BigNum *scalar);
 
 /**
  * \brief          Convert an EC point from Jacobian projective coordinates to normal affine x/y coordinates.
  *
- * \param          curve  Address of Nist EC curve structure
+ * \param          curve  Address of EC curve structure
  * \param          R      Address of EC point structure that receives the x/y coordinates
  * \param          P      Address of the EC point structure that contains the jacobian x/y/z coordinates.
  *
- * \return         0 if successful, or a POLARSSL_ERR_EC_XXX / POLARSSL_ERR_MPI_XXX error code.
+ * \return         0 if successful
  */
-int ecGetAffine(const NistECpCurve *curve, EcPoint *R, const EcPoint *P);
+int ecGetAffine(const EcCurve *curve, EcPoint *R, const EcPoint *P);
 
 /**
  * @brief Generate a random number.
  *
  * The method generates a random number and checks if it matches the curve restricitions.
- * Use this number to generate a ECDH public key.
+ * Use this number as ECDH private key.
  *
  * @param curve the NIST curve to use.
  *
@@ -188,6 +215,35 @@
  */
 int ecGenerateRandomNumber(const NistECpCurve *curve, BigNum *d);
 
+/**
+ * @brief Check a public key.
+ *
+ * The method checks if a public key is valid. For NIST curves it uses the
+ * ECC Partial Validation, NIST SP800-56A section 5.6.2.6
+ * 
+ * For other curves it computes the equation and compares the left hand and 
+ * the right handresults. If they are equal the point is on the curve.
+ *
+ * @param curve the curve to use.
+ *
+ * @param pub the public key to check.
+ *
+ * @returns true (!0) if the check was ok, false (0) otherwise.
+ *
+ * @note The function uses some scratch pad variable of the NistECpCurve structure.
+ */
+int ecCheckPubKey(const EcCurve *curve, const EcPoint *pub);
+
+int ecGetCurvesCurve(Curves curveId, EcCurve *curve);
+
+void ecFreeCurvesCurve(EcCurve *curve);
+
+/**
+ * This is a special function for DJB's curve 25519. Actually it's the scalar multiplication
+ * mypublic = basepoint * secret
+ */
+int curve25519_donna(unsigned char *mypublic, const unsigned char *secret, const unsigned char *basepoint);
+
 /*
  * Some additional functions that are not available in bnlib
  */
@@ -199,11 +255,11 @@
 
 int bnSubQMod_ (struct BigNum *rslt, unsigned n1, struct BigNum *mod);
 
-int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod);
+int bnMulMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *n2, struct BigNum *mod, const EcCurve *curve);
 
-int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod);
+int bnMulQMod_ (struct BigNum *rslt, struct BigNum *n1, unsigned n2, struct BigNum *mod, const EcCurve *curve);
 
-int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod);
+int bnSquareMod_ (struct BigNum *rslt, struct BigNum *n1, struct BigNum *mod, const EcCurve *curve);
 
 #ifdef __cplusplus
 }
diff --git a/jni/libzrtp/sources/bnlib/ec/ecdh.c b/jni/libzrtp/sources/bnlib/ec/ecdh.c
index 25ea8cd..8d1bc23 100644
--- a/jni/libzrtp/sources/bnlib/ec/ecdh.c
+++ b/jni/libzrtp/sources/bnlib/ec/ecdh.c
@@ -9,7 +9,7 @@
 #include <ec/ec.h>
 #include <ec/ecdh.h>
 
-int ecdhGeneratePublic(const NistECpCurve *curve, EcPoint *Q, const BigNum *d)
+int ecdhGeneratePublic(const EcCurve *curve, EcPoint *Q, const BigNum *d)
 {
     EcPoint G;
 
@@ -21,10 +21,10 @@
 
     FREE_EC_POINT(&G);
 
-    return 0;
+    return ecCheckPubKey(curve, Q);
 }
 
-int ecdhComputeAgreement(const NistECpCurve *curve, BigNum *agreement, const EcPoint *Q, const BigNum *d)
+int ecdhComputeAgreement(const EcCurve *curve, BigNum *agreement, const EcPoint *Q, const BigNum *d)
 {
     EcPoint t0;
 
diff --git a/jni/libzrtp/sources/bnlib/ec/ecdh.h b/jni/libzrtp/sources/bnlib/ec/ecdh.h
index 0cf083a..7ec32ad 100644
--- a/jni/libzrtp/sources/bnlib/ec/ecdh.h
+++ b/jni/libzrtp/sources/bnlib/ec/ecdh.h
@@ -22,15 +22,17 @@
 /**
  * @brief Takes a secret large random number and computes the public EC point.
  *
- * @param curve is the NIST curve to use.
+ * @param curve is the curve to use.
  *
  * @param Q the functions writes the computed public point in this parameter.
  *
  * @param d is the secret random number.
  *
+ * @return @c true (!0) if public key was computed, @c false otherwise.
+ *
  * @sa ecGenerateRandomNumber
  */
-int ecdhGeneratePublic(const NistECpCurve *curve, EcPoint *Q, const BigNum *d);
+int ecdhGeneratePublic(const EcCurve *curve, EcPoint *Q, const BigNum *d);
 
 /**
  * @brief Computes the key agreement value.
@@ -38,7 +40,7 @@
  * Takes the public EC point of the other party and applies the EC DH algorithm
  * to compute the agreed value.
  *
- * @param curve is the NIST curve to use, must be the same curve as used in
+ * @param curve is the curve to use, must be the same curve as used in
  *              @c ecdhGeneratePublic.
  *
  * @param agreemtn the functions writes the computed agreed value in this parameter.
@@ -47,7 +49,7 @@
  *
  * @param d is the secret random number.
  */
-int ecdhComputeAgreement(const NistECpCurve *curve, BigNum *agreement, const EcPoint *Q, const BigNum *d);
+int ecdhComputeAgreement(const EcCurve *curve, BigNum *agreement, const EcPoint *Q, const BigNum *d);
 
 #ifdef __cplusplus
 }
diff --git a/jni/libzrtp/sources/bnlib/lbn32.c b/jni/libzrtp/sources/bnlib/lbn32.c
index 831b25c..73fedcb 100644
--- a/jni/libzrtp/sources/bnlib/lbn32.c
+++ b/jni/libzrtp/sources/bnlib/lbn32.c
@@ -69,7 +69,7 @@
 #define HAVE_CONFIG_H 0
 #endif
 #if HAVE_CONFIG_H
-#include "bnconfig.h"
+#include <bnconfig.h>
 #endif
 
 /*
diff --git a/jni/libzrtp/sources/bnlib/lbn64.c b/jni/libzrtp/sources/bnlib/lbn64.c
index f14deea..e930652 100644
--- a/jni/libzrtp/sources/bnlib/lbn64.c
+++ b/jni/libzrtp/sources/bnlib/lbn64.c
@@ -69,7 +69,7 @@
 #define HAVE_CONFIG_H 0
 #endif
 #if HAVE_CONFIG_H
-#include "bnconfig.h"
+#include <bnconfig.h>
 #endif
 
 /*
diff --git a/jni/libzrtp/sources/clients/ccrtp/CMakeLists.txt b/jni/libzrtp/sources/clients/ccrtp/CMakeLists.txt
deleted file mode 100755
index aee4b24..0000000
--- a/jni/libzrtp/sources/clients/ccrtp/CMakeLists.txt
+++ /dev/null
@@ -1,121 +0,0 @@
-cmake_minimum_required (VERSION 2.6)
-
-# setup the Thread include and lib
-find_package(Threads)
-if(CMAKE_HAVE_PTHREAD_H)
-  set(HAVE_PTHREAD_H TRUE)
-endif()
-set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT})
-
-if (USES_CCRTP_INCLUDE_DIRS)
-    message(STATUS "  Using local commoncpp dependency")
-else()
-    find_package(PkgConfig)
-    pkg_check_modules(USES_CCRTP libccrtp>=2.0.0)
-endif()
-include_directories(${USES_CCRTP_INCLUDE_DIRS})
-link_directories(${USES_CRTP_LIBRARY_DIRS})
-add_definitions(${USES_CCRTP_CFLAGS})
-set (LIBS ${LIBS} ${USES_CCRTP_LDFLAGS} ${USES_CCRTP_LIBRARIES})
-
-#to make sure includes are first taken - it contains config.h
-include_directories(BEFORE ${CMAKE_BINARY_DIR})
-include_directories (${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../srtp ${CMAKE_CURRENT_SOURCE_DIR}/../../bnlib)
-
-# **** setup the various crypto interface implementations ***
-# Twofish is a special case: its always a standalone modlue and thus
-# not specific to a library.
-# NOTE: the standalone modules live in the 'crypto'
-if (OPENSSL_FOUND)
-    set(crypto_src
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/openssl/zrtpDH.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/openssl/hmac256.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/openssl/sha256.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/openssl/hmac384.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/openssl/sha384.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/openssl/aesCFB.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/openssl/InitializeOpenSSL.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/crypto/twoCFB.cpp)
-endif()
-
-if (CRYPTO_STANDALONE)
-    set(crypto_src
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptcommon/ZrtpRandom.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../common/Thread.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../common/MutexClass.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../common/EventClass.cpp
-        ${zrtp_crypto_src} ${bnlib_src})
-endif()
-
-set(cryptcommon_srcs
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptcommon/twofish.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptcommon/twofish_cfb.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptcommon/aescrypt.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptcommon/aeskey.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptcommon/aestab.c
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptcommon/aes_modes.c)
-
-set(zrtp_ccrtp_src
-    ${CMAKE_CURRENT_SOURCE_DIR}/ZrtpQueue.cpp)
-
-set(zrtpcpp_src ${zrtp_src} ${zrtp_ccrtp_src} ${crypto_src} ${cryptcommon_srcs})
-
-if(BUILD_STATIC AND NOT BUILD_SHARED)
-    set(LIBRARY_BUILD_TYPE STATIC)
-else()
-    set(LIBRARY_BUILD_TYPE SHARED)
-endif()
-
-add_library(${zrtplibName} ${LIBRARY_BUILD_TYPE} ${zrtpcpp_src})
-set_target_properties(${zrtplibName} PROPERTIES VERSION ${VERSION} SOVERSION ${SOVERSION})
-target_link_libraries(${zrtplibName} ${LIBS})
-
-add_dependencies(${zrtplibName} ccrtp)
-
-# **** Setup packing environment ****
-#
-if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
-    include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules/GeneratePackage.cmake)
-
-    GENERATE_PACKAGING(${PACKAGE} ${VERSION})
-endif()
-
-# **** Create the external files for RPM and pkgconfig ****
-#
-set(prefix ${CMAKE_INSTALL_PREFIX})
-set(exec_prefix ${prefix}/bin)
-set(libdir ${prefix}/${LIBDIRNAME})
-set(includedir ${prefix}/include)
-set(PACKAGE pkgconfig)
-
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../libzrtpcpp.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/lib${zrtplibName}.pc @ONLY)
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../libzrtpcpp.spec.cmake ${CMAKE_CURRENT_BINARY_DIR}/lib${zrtplibName}.spec @ONLY)
-
-# **** install files ****
-#
-set(ccrtp_inst
-    ${CMAKE_CURRENT_SOURCE_DIR}/ZrtpQueue.h
-    ${CMAKE_CURRENT_SOURCE_DIR}/zrtpccrtp.h
-    ${CMAKE_CURRENT_SOURCE_DIR}/CcrtpTimeoutProvider.h)
-
-install(FILES
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/libzrtpcpp/ZrtpCodes.h
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/libzrtpcpp/ZrtpConfigure.h
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/libzrtpcpp/ZrtpCallback.h
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/libzrtpcpp/ZrtpCWrapper.h
-        ${CMAKE_CURRENT_SOURCE_DIR}/../../zrtp/libzrtpcpp/ZrtpUserCallback.h ${ccrtp_inst} DESTINATION include/libzrtpcpp)
-
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${zrtplibName}.pc DESTINATION ${LIBDIRNAME}/pkgconfig)
-
-install(TARGETS ${zrtplibName} DESTINATION ${LIBDIRNAME})
-
-if(${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
-
-    ########### Add uninstall target ###############
-    configure_file("${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
-    add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
-
-endif()
-
-
diff --git a/jni/libzrtp/sources/clients/ccrtp/ZrtpQueue.cpp b/jni/libzrtp/sources/clients/ccrtp/ZrtpQueue.cpp
deleted file mode 100644
index 9e838da..0000000
--- a/jni/libzrtp/sources/clients/ccrtp/ZrtpQueue.cpp
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
-  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 <ZrtpQueue.h>
-#include <libzrtpcpp/ZIDCache.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();
-    }
-    ZIDCache* zf = getZidCacheInstance();
-    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) {
-        // 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, rtn);
-    }
-    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/sources/clients/ccrtp/ZrtpQueue.h b/jni/libzrtp/sources/clients/ccrtp/ZrtpQueue.h
deleted file mode 100644
index 7a1ee67..0000000
--- a/jni/libzrtp/sources/clients/ccrtp/ZrtpQueue.h
+++ /dev/null
@@ -1,911 +0,0 @@
-/*
-  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/ZrtpConfigure.h>
-#include <CcrtpTimeoutProvider.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);
-
-    /**
-     * 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/sources/clients/ccrtp/zrtpccrtp.h b/jni/libzrtp/sources/clients/ccrtp/zrtpccrtp.h
deleted file mode 100644
index 3eae183..0000000
--- a/jni/libzrtp/sources/clients/ccrtp/zrtpccrtp.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-  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 <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:
- */
diff --git a/jni/libzrtp/sources/cmake/Modules/FindGcryptConfig.cmake b/jni/libzrtp/sources/cmake/Modules/FindGcryptConfig.cmake
index caeb7c3..1770241 100755
--- a/jni/libzrtp/sources/cmake/Modules/FindGcryptConfig.cmake
+++ b/jni/libzrtp/sources/cmake/Modules/FindGcryptConfig.cmake
@@ -226,12 +226,12 @@
 ###

 macro(gcr_check _prefix _module0)

   # check cached value

-  if (NOT DEFINED __gcr_config_checked_${_prefix} OR __gcr_config_checked_${_prefix} LESS "${GCR_CONFIG_VERSION}" OR NOT ${_prefix}_FOUND)

+  if (NOT DEFINED __gcr_config_checked_${_prefix} OR __gcr_config_checked_${_prefix} LESS ${GCR_CONFIG_VERSION} OR NOT ${_prefix}_FOUND)

     _gcrconfig_parse_options   (_gcr_modules _gcr_is_required "${_module0}" ${ARGN})

     _gcr_check_modules_internal("${_gcr_is_required}" 0 "${_prefix}" ${_gcr_modules})

 

     _gcrconfig_set(__gcr_config_checked_${_prefix} ${GCR_CONFIG_VERSION})

-  endif(NOT DEFINED __gcr_config_checked_${_prefix} OR __gcr_config_checked_${_prefix} LESS "${GCR_CONFIG_VERSION}" OR NOT ${_prefix}_FOUND)

+  endif(NOT DEFINED __gcr_config_checked_${_prefix} OR __gcr_config_checked_${_prefix} LESS ${GCR_CONFIG_VERSION} OR NOT ${_prefix}_FOUND)

 endmacro(gcr_check)

 

 ###

diff --git a/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake b/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake
index 0eef52f..506b224 100644
--- a/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake
+++ b/jni/libzrtp/sources/cmake/Modules/GeneratePackage.cmake
@@ -23,7 +23,7 @@
   # others
   "\\\\.#"
   "/#"
-  "/build/"
+  "/build*"
   "/autom4te\\\\.cache/"
   "/_build/"
   "/doc/html/"
@@ -37,6 +37,9 @@
   "\\\\.la$"
   "\\\\.sh$"
   "Makefile\\\\.in$"
+  "\\\\.directory$"
+  "\\\\._.DS_Store$"
+  "\\\\._buildmac$"
   )
 
   SET(CPACK_PACKAGE_VENDOR "Werner Dittmann")
diff --git a/jni/libzrtp/sources/common/Thread.h b/jni/libzrtp/sources/common/Thread.h
index 3aca167..ca77255 100644
--- a/jni/libzrtp/sources/common/Thread.h
+++ b/jni/libzrtp/sources/common/Thread.h
@@ -62,7 +62,7 @@
 
 #if defined(AS400) || defined(OS400)
 typedef pthread_id_np_t ThreadId_t;
-#elif defined(VMS) 
+#elif defined(VMS) || defined(__NetBSD__)
 typedef pthread_t ThreadId_t;
 #else
 #ifdef USE_BEGIN_THREAD
@@ -274,7 +274,7 @@
 	{
 #if defined(AS400)||defined(OS400)
 		return(( memcmp(p1,p2,sizeof(ThreadId_t))==0)?TRUE:FALSE);
-#elif defined(VMS) 
+#elif defined(VMS) || defined(__NetBSD__)
 		return (( pthread_equal(*p1,*p2) )?TRUE:FALSE );
 #else
 		return ((*p1 == *p2)?TRUE:FALSE);
diff --git a/jni/libzrtp/sources/common/osSpecifics.c b/jni/libzrtp/sources/common/osSpecifics.c
index 9c9a1ee..3345363 100644
--- a/jni/libzrtp/sources/common/osSpecifics.c
+++ b/jni/libzrtp/sources/common/osSpecifics.c
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2012 Werner Dittmann
+  Copyright (C) 2012-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -27,7 +27,7 @@
 #endif
 
 #if defined(_WIN32) || defined(_WIN64)
-# include <winsock2.h>
+# include <WinSock2.h>
 # include <time.h>
 
 uint64_t  zrtpGetTickCount()
diff --git a/jni/libzrtp/sources/common/osSpecifics.h b/jni/libzrtp/sources/common/osSpecifics.h
index 494dc0a..5030688 100644
--- a/jni/libzrtp/sources/common/osSpecifics.h
+++ b/jni/libzrtp/sources/common/osSpecifics.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2012 Werner Dittmann
+  Copyright (C) 2012-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -34,6 +34,23 @@
  * @author Werner Dittmann <Werner.Dittmann@t-online.de>
  */
 
+#ifndef __EXPORT
+  #if (defined _WIN32 || defined __CYGWIN__) && defined(_DLL)
+    #define __EXPORT    __declspec(dllimport)
+    #define __LOCAL
+  #elif __GNUC__ >= 4
+    #define __EXPORT    __attribute__ ((visibility("default")))
+    #define __LOCAL     __attribute__ ((visibility("hidden")))
+  #else
+    #define __EXPORT
+    #define __LOCAL
+  #endif
+#endif
+
+#if defined(_WIN32) || defined(_WIN64)
+# define snprintf _snprintf
+#endif
+
 #if defined(__cplusplus)
 extern "C"
 {
diff --git a/jni/libzrtp/sources/libzrtpcpp-config.h.cmake b/jni/libzrtp/sources/config.h.cmake
similarity index 100%
rename from jni/libzrtp/sources/libzrtpcpp-config.h.cmake
rename to jni/libzrtp/sources/config.h.cmake
diff --git a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp b/jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp
index 7078b72..c19fa82 100644
--- a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp
+++ b/jni/libzrtp/sources/cryptcommon/ZrtpRandom.cpp
@@ -1,8 +1,8 @@
 /*
- *  Copyright (C) 2006-2012 Werner Dittmann
+ *  Copyright (C) 2006-2013 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
+ *  it under the terms of the GNU Lesser General Public License as published by
  *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
diff --git a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.h b/jni/libzrtp/sources/cryptcommon/ZrtpRandom.h
index 3487a27..d3eedf7 100644
--- a/jni/libzrtp/sources/cryptcommon/ZrtpRandom.h
+++ b/jni/libzrtp/sources/cryptcommon/ZrtpRandom.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2012 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/cryptcommon/macSkein.cpp b/jni/libzrtp/sources/cryptcommon/macSkein.cpp
index a6e1633..9da946f 100644
--- a/jni/libzrtp/sources/cryptcommon/macSkein.cpp
+++ b/jni/libzrtp/sources/cryptcommon/macSkein.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2010 Werner Dittmann
+  Copyright (C) 2010-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/cryptcommon/macSkein.h b/jni/libzrtp/sources/cryptcommon/macSkein.h
index 3fdb8f0..ce5d380 100644
--- a/jni/libzrtp/sources/cryptcommon/macSkein.h
+++ b/jni/libzrtp/sources/cryptcommon/macSkein.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2010 Werner Dittmann
+  Copyright (C) 2010-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/cryptcommon/twofish.c b/jni/libzrtp/sources/cryptcommon/twofish.c
index 45b2bb0..03d2770 100644
--- a/jni/libzrtp/sources/cryptcommon/twofish.c
+++ b/jni/libzrtp/sources/cryptcommon/twofish.c
@@ -475,8 +475,17 @@
     (p)[3] = (Twofish_Byte)(((v) >> 24) & 0xff)
  
 #endif 
- 
- 
+
+#ifdef ANDROID
+/**
+ * Dummy function to disable some compiler optimizations.
+ * 
+ * See comment in Twofish_cfb128_encrypt().
+ */
+void Two_debugDummy(Twofish_Byte* in, Twofish_Byte* out, Twofish_Byte* ivec)
+{
+}
+#endif
 /* 
  * Test the platform-specific macros. 
  * This function tests the macros defined so far to make sure the  
diff --git a/jni/libzrtp/sources/cryptcommon/twofish_cfb.c b/jni/libzrtp/sources/cryptcommon/twofish_cfb.c
index 80925f4..241b956 100755
--- a/jni/libzrtp/sources/cryptcommon/twofish_cfb.c
+++ b/jni/libzrtp/sources/cryptcommon/twofish_cfb.c
@@ -20,8 +20,20 @@
     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);
+
+/*
+ * Some GCC version(s) of Android's NDK produce code that leads to a crash (SIGBUS). The
+ * offending line if the line that produces the output by xor'ing the ivec. Somehow the
+ * compiler/optimizer seems to incorrectly setup the pointers. Adding a call to an
+ * external function that uses the pointer disabled or modifies this optimzing
+ * behaviour. This debug functions as such does nothing, it just disables some
+ * optimization. Don't use a local (static) function - the compiler sees that it does
+ * nothing and optimizes again :-) .
+ */
+#ifdef ANDROID
+          Two_debugDummy(in, out, ivec);
+#endif
+          *(size_t*)(out+n) = *(size_t*)(ivec+n) ^= *(size_t*)(in+n);;
       }
       len -= 16;
       out += 16;
@@ -31,8 +43,8 @@
     if (len) {
       Twofish_encrypt(keyCtx, ivec, ivec);
       while (len--) {
-	out[n] = ivec[n] ^= in[n];
-	++n;
+          out[n] = ivec[n] ^= in[n];
+          ++n;
       }
     }
     *num = n;
diff --git a/jni/libzrtp/sources/demo/CMakeLists.txt b/jni/libzrtp/sources/demo/CMakeLists.txt
index e75a63a..c253d9f 100755
--- a/jni/libzrtp/sources/demo/CMakeLists.txt
+++ b/jni/libzrtp/sources/demo/CMakeLists.txt
@@ -1,22 +1,27 @@
 
 #to make sure includes are first taken - it contains config.h
 include_directories(BEFORE ${CMAKE_BINARY_DIR})
-include_directories (${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}
-                     ${CMAKE_CURRENT_SOURCE_DIR}/../zrtp
-                     ${CMAKE_CURRENT_SOURCE_DIR}/../clients/ccrtp)
+include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
+                     ${CMAKE_SOURCE_DIR}/zrtp
+                     ${CMAKE_SOURCE_DIR}/clients/ccrtp)
 
-########### next target ###############
+if (CCRTP)
+    ########### next target ###############
 
-add_executable(zrtptest zrtptest.cpp)
-target_link_libraries(zrtptest zrtpcpp ccrtp commoncpp)
-add_dependencies(zrtptest zrtpcpp)
+    add_executable(zrtptest zrtptest.cpp)
+    target_link_libraries(zrtptest ${zrtplibName})
+    add_dependencies(zrtptest ${zrtplibName})
 
-########### next target ###############
+    ########### next target ###############
 
-add_executable(zrtptestMulti zrtptestMulti.cpp)
-target_link_libraries(zrtptestMulti zrtpcpp ccrtp commoncpp)
-add_dependencies(zrtptestMulti zrtpcpp)
-
+    add_executable(zrtptestMulti zrtptestMulti.cpp)
+    target_link_libraries(zrtptestMulti ${zrtplibName})
+    add_dependencies(zrtptestMulti ${zrtplibName})
+else()
+    add_executable(sdestest sdestest.cpp)
+    target_link_libraries(sdestest ${zrtplibName})
+    add_dependencies(sdestest ${zrtplibName})
+endif()
 ########### next target ###############
 
 #add_executable(wrappertest wrappertest.c)
diff --git a/jni/libzrtp/sources/demo/sdestest.cpp b/jni/libzrtp/sources/demo/sdestest.cpp
new file mode 100644
index 0000000..a329e8d
--- /dev/null
+++ b/jni/libzrtp/sources/demo/sdestest.cpp
@@ -0,0 +1,231 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <crypto/hmac256.h>
+
+/*
+HKDF-Expand(PRK, info, L)
+
+Description in RFC 5869
+
+   HKDF-Expand(PRK, info, L) -> OKM
+
+   Options:
+      Hash     a hash function; HashLen denotes the length of the
+               hash function output in octets
+   Inputs:
+      PRK      a pseudorandom key of at least HashLen octets
+               (usually, the output from the extract step)
+      info     optional context and application specific information
+               (can be a zero-length string)
+      L        length of output keying material in octets
+               (<= 255*HashLen)
+
+   Output:
+      OKM      output keying material (of L octets)
+
+   The output OKM is calculated as follows:
+
+   N = ceil(L/HashLen)
+   T = T(1) | T(2) | T(3) | ... | T(N)
+   OKM = first L octets of T
+
+   where:
+   T(0) = empty string (zero length)
+   T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
+   T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
+   T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
+   ...
+
+   (where the constant concatenated to the end of each T(n) is a
+   single octet.)
+
+
+   A.1.  Test Case 1
+
+   Basic test case with SHA-256
+
+   Hash = SHA-256
+   IKM  = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets)
+   salt = 0x000102030405060708090a0b0c (13 octets)
+   info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets)
+   L    = 42
+
+   PRK  = 0x077709362c2e32df0ddc3f0dc47bba63
+          90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets)
+   OKM  = 0x3cb25f25faacd57a90434f64d0362f2a
+          2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+          34007208d5b887185865 (42 octets)
+
+A.2.  Test Case 2
+
+   Test with SHA-256 and longer inputs/outputs
+
+   Hash = SHA-256
+   IKM  = 0x000102030405060708090a0b0c0d0e0f
+          101112131415161718191a1b1c1d1e1f
+          202122232425262728292a2b2c2d2e2f
+          303132333435363738393a3b3c3d3e3f
+          404142434445464748494a4b4c4d4e4f (80 octets)
+   salt = 0x606162636465666768696a6b6c6d6e6f
+          707172737475767778797a7b7c7d7e7f
+          808182838485868788898a8b8c8d8e8f
+          909192939495969798999a9b9c9d9e9f
+          a0a1a2a3a4a5a6a7a8a9aaabacadaeaf (80 octets)
+   info = 0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf
+          c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+          d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+          e0e1e2e3e4e5e6e7e8e9eaebecedeeef
+          f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff (80 octets)
+   L    = 82
+
+   PRK  = 0x06a6b88c5853361a06104c9ceb35b45c
+          ef760014904671014a193f40c15fc244 (32 octets)
+   OKM  = 0xb11e398dc80327a1c8e7f78c596a4934
+          4f012eda2d4efad8a050cc4c19afa97c
+          59045a99cac7827271cb41c65e590e09
+          da3275600c2f09b8367793a9aca3db71
+          cc30c58179ec3e87c14c01d5c1f3434f
+          1d87 (82 octets)
+
+A.3.  Test Case 3
+
+   Test with SHA-256 and zero-length salt/info
+
+   Hash = SHA-256
+   IKM  = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets)
+   salt = (0 octets)
+   info = (0 octets)
+   L    = 42
+
+   PRK  = 0x19ef24a32c717b167f33a91d6f648bdf
+          96596776afdb6377ac434c1c293ccb04 (32 octets)
+   OKM  = 0x8da4e775a563c18f715f802a063c5a31
+          b8a11f5c5ee1879ec3454e5f3c738d2d
+          9d201395faa4b61a96c8 (42 octets)
+
+*/
+
+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");
+}
+
+
+static uint8_t info_A1[] = {
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9};
+
+static int32_t L_A1 = 42;
+
+static uint8_t PRK_A1[] = {
+    0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63,
+    0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5};
+
+static uint8_t OKM_A1[] = {
+    0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
+    0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
+    0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65}; // (42 octets)
+
+
+static int32_t L_A3 = 42;
+
+static uint8_t PRK_A3[] = {
+    0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf,
+    0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04};   // (32 octets)
+
+static uint8_t OKM_A3[] = {
+    0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31,
+    0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d,
+    0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8};  // (42 octets)
+
+
+    
+void* createSha256HmacContext(uint8_t* key, int32_t keyLength);
+void freeSha256HmacContext(void* ctx);
+void hmacSha256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength );
+
+
+static int expand(uint8_t* prk, uint32_t prkLen, uint8_t* info, int32_t infoLen, int32_t L, uint32_t hashLen, uint8_t* outbuffer)
+{
+    int32_t n;
+    uint8_t *T;
+    void* hmacCtx;
+
+    const uint8_t* data[4];      // Data pointers for HMAC data, max. 3 plus terminating NULL
+    uint32_t dataLen[4];
+    int32_t dataIdx = 0;
+
+    uint8_t counter;
+    int32_t macLength;
+
+    if (prkLen < hashLen)
+        return -1;
+
+    n = (L + (hashLen-1)) / hashLen;
+
+    // T points to buffer that holds concatenated T(1) || T(2) || ... T(N))
+    T = reinterpret_cast<uint8_t*>(malloc(n * hashLen));
+
+    // Prepare the HMAC
+    hmacCtx = createSha256HmacContext(prk, prkLen);
+
+    // Prepare first HMAC. T(0) has zero length, thus we ignore it in first run.
+    // After first run use its output (T(1)) as first data in next HMAC run.
+    for (int i = 1; i <= n; i++) {
+        if (infoLen > 0 && info != NULL) {
+            data[dataIdx] = info;
+            dataLen[dataIdx++] = infoLen;
+        }
+        counter = i & 0xff;
+        data[dataIdx] = &counter;
+        dataLen[dataIdx++] = 1;
+
+        data[dataIdx] = NULL;
+        dataLen[dataIdx++] = 0;
+
+        hmacSha256Ctx(hmacCtx, data, dataLen, T + ((i-1) * hashLen), &macLength);
+
+        dataIdx = 0;
+        data[dataIdx] = T + ((i-1) * hashLen);
+        dataLen[dataIdx++] = hashLen;
+    }
+    freeSha256HmacContext(hmacCtx);
+    memcpy(outbuffer, T, L);
+    free(T);
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    uint8_t buffer[500];
+    expand(PRK_A1, sizeof(PRK_A1), info_A1, sizeof(info_A1), L_A1, SHA256_DIGEST_LENGTH, buffer);
+    if (memcmp(buffer, OKM_A1, L_A1) != 0) {
+        fprintf(stderr, "ERROR: Test result A1 mismatch");
+        hexdump("Computed result of expand A1", buffer, L_A1);
+        hexdump("Expected result of expand A1", OKM_A1, L_A1);
+        return 1;
+    }
+
+    expand(PRK_A3, sizeof(PRK_A3), NULL, 0, L_A3, SHA256_DIGEST_LENGTH, buffer);
+    if (memcmp(buffer, OKM_A3, L_A3) != 0) {
+        fprintf(stderr, "ERROR: Test result A3 mismatch");
+        hexdump("Computed result of expand A3", buffer, L_A3);
+        hexdump("Expected result of expand A3", OKM_A3, L_A3);
+        return 1;
+    }
+
+    printf("Done\n");
+    return 0;
+}
diff --git a/jni/libzrtp/sources/demo/zrtptest.cpp b/jni/libzrtp/sources/demo/zrtptest.cpp
index fc3490d..0595543 100644
--- a/jni/libzrtp/sources/demo/zrtptest.cpp
+++ b/jni/libzrtp/sources/demo/zrtptest.cpp
@@ -16,9 +16,6 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-#include <commoncpp/string.h>
-
-
 #include <cstdlib>
 #include <map>
 #include <zrtpccrtp.h>
@@ -31,40 +28,36 @@
 class PacketsPattern
 {
 public:
-    inline const InetHostAddress&
-    getDestinationAddress() const
-    { return destinationAddress; }
+    inline const InetHostAddress& getReceiverAddress() const { return *receiverAddress; }
+    inline const InetHostAddress& getSenderAddress()   const { return *senderAddress; }
 
-    inline const tpport_t
-    getDestinationPort() const
-    { return destinationPort; }
+    inline void setReceiverAddress(InetHostAddress *addr) const { delete receiverAddress; receiverAddress = addr; }
+    inline void setSenderAddress(InetHostAddress *addr)   const { delete senderAddress; senderAddress = addr; }
 
-    uint32
-    getPacketsNumber() const
-    { return packetsNumber; }
+    inline const tpport_t getReceiverPort() const { return receiverPort; }
+    inline const tpport_t getSenderPort()   const { return senderPort; }
 
-    uint32
-    getSsrc() const
-    { return 0xdeadbeef; }
+    uint32 getPacketsNumber() const  { return packetsNumber; }
 
-    const unsigned char*
-    getPacketData(uint32 i)
-    { return data[i%2]; }
+    uint32 getSsrc() const  { return 0xdeadbeef; }
 
-    const size_t
-    getPacketSize(uint32 i)
-    { return strlen((char*)data[i%2]) + 1 ; }
+    const unsigned char*getPacketData(uint32 i) { return data[i%2]; }
+
+    const size_t getPacketSize(uint32 i) { return strlen((char*)data[i%2]) + 1 ; }
 
 private:
-    static const InetHostAddress destinationAddress;
-    static const uint16 destinationPort = 5002;
+    static const InetHostAddress *receiverAddress;
+    static const InetHostAddress *senderAddress;
+
+    static const uint16 receiverPort = 5002;
+    static const uint16 senderPort = 5004;
     static const uint32 packetsNumber = 10;
     static const uint32 packetsSize = 12;
     static const unsigned char* data[];
 };
 
-const InetHostAddress PacketsPattern::destinationAddress =
-    InetHostAddress("localhost");
+const InetHostAddress *PacketsPattern::receiverAddress = new InetHostAddress("localhost");
+const InetHostAddress *PacketsPattern::senderAddress = new InetHostAddress("localhost");
 
 const unsigned char* PacketsPattern::data[] = {
     (unsigned char*)"0123456789\n",
@@ -76,7 +69,7 @@
 class ExtZrtpSession : public SymmetricZRTPSession {
 //     ExtZrtpSession(InetMcastAddress& ima, tpport_t port) :
 //     RTPSession(ima,port) {}
-//
+// 
 //     ExtZrtpSession(InetHostAddress& ia, tpport_t port) :
 //     RTPSession(ia,port) {}
 
@@ -118,6 +111,13 @@
 };
 
 
+/*
+ * The following classes use:
+ * - localAddress and destination port+2 for the sender classes
+ * - destinationAddress and destination port for the receiver classes.
+ * 
+ */
+
 /**
  * SymmetricZRTPSession in non-security mode (RTPSession compatible).
  *
@@ -135,7 +135,7 @@
     int doTest() {
         // should be valid?
         //RTPSession tx();
-        ExtZrtpSession tx(pattern.getSsrc(), InetHostAddress("localhost"));
+        ExtZrtpSession tx(pattern.getSsrc(), pattern.getSenderAddress(), pattern.getSenderPort());
 //        SymmetricZRTPSession tx(pattern.getSsrc(), InetHostAddress("localhost"));
         tx.setSchedulingTimeout(10000);
         tx.setExpireTimeout(1000000);
@@ -143,8 +143,9 @@
         tx.startRunning();
 
         tx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
-        if (!tx.addDestination(pattern.getDestinationAddress(),
-                               pattern.getDestinationPort()) ) {
+
+        // We are sender:
+        if (!tx.addDestination(pattern.getReceiverAddress(), pattern.getReceiverPort()) ) {
             return 1;
         }
 
@@ -177,8 +178,7 @@
 
     int
     doTest() {
-        ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(),
-                                pattern.getDestinationPort());
+        ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getReceiverAddress(), pattern.getReceiverPort());
 
 //         SymmetricZRTPSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(),
 //                                 pattern.getDestinationPort());
@@ -188,8 +188,7 @@
         rx.startRunning();
         rx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
         // arbitrary number of loops to provide time to start transmitter
-        if (!rx.addDestination(pattern.getDestinationAddress(),
-                               pattern.getDestinationPort()+2) ) {
+        if (!rx.addDestination(pattern.getSenderAddress(), pattern.getSenderPort()) ) {
             return 1;
         }
         for ( int i = 0; i < 5000 ; i++ ) {
@@ -228,8 +227,8 @@
     int doTest() {
         // should be valid?
         //RTPSession tx();
-        ExtZrtpSession tx(pattern.getSsrc(), pattern.getDestinationAddress(),
-                                pattern.getDestinationPort()+2);
+        // Initialize with local address and Local port is detination port +2 - keep RTP/RTCP port pairs
+        ExtZrtpSession tx(pattern.getSsrc(), pattern.getSenderAddress(), pattern.getSenderPort());
         tx.initialize("test_t.zid");
 
         tx.setSchedulingTimeout(10000);
@@ -238,8 +237,7 @@
         tx.startRunning();
 
         tx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
-        if (!tx.addDestination(pattern.getDestinationAddress(),
-                               pattern.getDestinationPort()) ) {
+        if (!tx.addDestination(pattern.getReceiverAddress(), pattern.getReceiverPort()) ) {
             return 1;
         }
         tx.startZrtp();
@@ -271,8 +269,7 @@
 
     int
     doTest() {
-        ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(),
-                                pattern.getDestinationPort());
+        ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getReceiverAddress(), pattern.getReceiverPort());
 
         rx.initialize("test_r.zid");
 
@@ -282,8 +279,7 @@
         rx.startRunning();
         rx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
         // arbitrary number of loops to provide time to start transmitter
-        if (!rx.addDestination(pattern.getDestinationAddress(),
-                               pattern.getDestinationPort()+2) ) {
+        if (!rx.addDestination(pattern.getSenderAddress(), pattern.getSenderPort()) ) {
             return 1;
         }
         rx.startZrtp();
@@ -348,6 +344,8 @@
         warningMap.insert(pair<int32, std::string*>(WarningCRCmismatch, new string("Internal ZRTP packet checksum mismatch - packet dropped")));
         warningMap.insert(pair<int32, std::string*>(WarningSRTPauthError, new string("Dropping packet because SRTP authentication failed!")));
         warningMap.insert(pair<int32, std::string*>(WarningSRTPreplayError, new string("Dropping packet because SRTP replay check failed!")));
+        warningMap.insert(pair<int32, std::string*>(WarningNoExpectedRSMatch, new string("No RS match found - but ZRTP expected a match.")));
+        warningMap.insert(pair<int32, std::string*>(WarningNoExpectedAuxMatch, new string("The auxlliary secrets do not match.")));
 
         severeMap.insert(pair<int32, std::string*>(SevereHelloHMACFailed, new string("Hash HMAC check of Hello failed!")));
         severeMap.insert(pair<int32, std::string*>(SevereCommitHMACFailed, new string("Hash HMAC check of Commit failed!")));
@@ -453,6 +451,8 @@
 
 bool MyUserCallback::initialized = false;
 
+static unsigned char transmAuxSecret[] = {1,2,3,4,5,6,7,8,9,0};
+
 /**
  * SymmetricZRTPSession in security mode and using a callback class.
  *
@@ -471,38 +471,52 @@
 
     ZrtpConfigure config;
 
-    void run()
-    {
+    void run() {
         doTest();
     }
 
-    int doTest()
-    {
+    int doTest() {
         // should be valid?
         //RTPSession tx();
-        ExtZrtpSession tx(/*pattern.getSsrc(),*/ pattern.getDestinationAddress(),
-                                pattern.getDestinationPort()+2);
-//        config.clear();
+        ExtZrtpSession tx(/*pattern.getSsrc(),*/ pattern.getSenderAddress(), pattern.getSenderPort());
+        config.clear();
 //        config.setStandardConfig();
-        config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("DH2k"));
+//         config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("DH2k"));
+//         config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("DH3k"));
+
+        // This ordering prefers NIST
         config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("EC38"));
+        config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("E414"));
+
         config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("EC25"));
+        config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("E255"));
 
-         config.addAlgo(HashAlgorithm, zrtpHashes.getByName("S384"));
+        config.addAlgo(HashAlgorithm, zrtpHashes.getByName("S384"));
+        config.addAlgo(HashAlgorithm, zrtpHashes.getByName("SKN3"));
 
-//          config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("2FS3"));
-//          config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("AES3"));
+        config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("AES3"));
+        config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("2FS3"));
 
         config.addAlgo(SasType, zrtpSasTypes.getByName("B256"));
 
+        config.addAlgo(AuthLength, zrtpAuthLengths.getByName("HS32"));
+        config.addAlgo(AuthLength, zrtpAuthLengths.getByName("HS80"));
+        config.addAlgo(AuthLength, zrtpAuthLengths.getByName("SK32"));
+        config.addAlgo(AuthLength, zrtpAuthLengths.getByName("SK64"));
+
         tx.initialize("test_t.zid", true, &config);
         // At this point the Hello hash is available. See ZRTP specification
         // chapter 9.1 for further information when an how to use the Hello
         // hash.
-        cout << "TX Hello hash: " << tx.getHelloHash() << endl;
-        cout << "TX Hello hash length: " << tx.getHelloHash().length() << endl;
-
+        int numSupportedVersion = tx.getNumberSupportedVersions();
+        cout << "TX Hello hash 0: " << tx.getHelloHash(0) << endl;
+        cout << "TX Hello hash 0 length: " << tx.getHelloHash(0).length() << endl;
+        if (numSupportedVersion > 1) {
+            cout << "TX Hello hash 1: " << tx.getHelloHash(1) << endl;
+            cout << "TX Hello hash 1 length: " << tx.getHelloHash(1).length() << endl;
+        }
         tx.setUserCallback(new MyUserCallback(&tx));
+        tx.setAuxSecret(transmAuxSecret, sizeof(transmAuxSecret));
 
         tx.setSchedulingTimeout(10000);
         tx.setExpireTimeout(1000000);
@@ -510,8 +524,8 @@
         tx.startRunning();
 
         tx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
-        if (!tx.addDestination(pattern.getDestinationAddress(),
-                               pattern.getDestinationPort()) ) {
+
+        if (!tx.addDestination(pattern.getReceiverAddress(), pattern.getReceiverPort()) ) {
             return 1;
         }
         tx.startZrtp();
@@ -535,29 +549,49 @@
     }
 };
 
+static unsigned char recvAuxSecret[] = {1,2,3,4,5,6,7,8,9,9};
 
 class
 ZrtpRecvPacketTransmissionTestCB: public Thread
 {
 public:
-    void
-    run() {
+    ZrtpConfigure config;
+
+    void run() {
         doTest();
     }
 
-    int
-    doTest() {
-        ExtZrtpSession rx( /*pattern.getSsrc()+1,*/ pattern.getDestinationAddress(),
-                                pattern.getDestinationPort());
+    int doTest() {
+        ExtZrtpSession rx( /*pattern.getSsrc()+1,*/ pattern.getReceiverAddress(), pattern.getReceiverPort());
+        config.clear();
+//        config.setStandardConfig();
+//         config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("DH3k"));
 
-        rx.initialize("test_r.zid");
+         config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("E414"));
+         config.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName("EC38"));
+
+         config.addAlgo(HashAlgorithm, zrtpHashes.getByName("S384"));
+         config.addAlgo(HashAlgorithm, zrtpHashes.getByName("SKN3"));
+
+//          config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("2FS3"));
+//          config.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName("AES3"));
+
+        config.addAlgo(SasType, zrtpSasTypes.getByName("B256"));
+
+
+        rx.initialize("test_r.zid", true, &config);
         // At this point the Hello hash is available. See ZRTP specification
         // chapter 9.1 for further information when an how to use the Hello
         // hash.
-        cout << "RX Hello hash: " << rx.getHelloHash() << endl;
-        cout << "RX Hello hash length: " << rx.getHelloHash().length() << endl;
-
+        int numSupportedVersion = rx.getNumberSupportedVersions();
+        cout << "RX Hello hash 0: " << rx.getHelloHash(0) << endl;
+        cout << "RX Hello hash 0 length: " << rx.getHelloHash(0).length() << endl;
+        if (numSupportedVersion > 1) {
+            cout << "RX Hello hash 1: " << rx.getHelloHash(1) << endl;
+            cout << "RX Hello hash 1 length: " << rx.getHelloHash(1).length() << endl;
+        }
         rx.setUserCallback(new MyUserCallback(&rx));
+        rx.setAuxSecret(recvAuxSecret, sizeof(recvAuxSecret));
 
         rx.setSchedulingTimeout(10000);
         rx.setExpireTimeout(1000000);
@@ -565,8 +599,7 @@
         rx.startRunning();
         rx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
         // arbitrary number of loops to provide time to start transmitter
-        if (!rx.addDestination(pattern.getDestinationAddress(),
-                               pattern.getDestinationPort()+2) ) {
+        if (!rx.addDestination(pattern.getSenderAddress(), pattern.getSenderPort()) ) {
             return 1;
         }
         rx.startZrtp();
@@ -598,7 +631,7 @@
 
     /* check args */
     while (1) {
-        c = getopt(argc, argv, "rs");
+        c = getopt(argc, argv, "rsR:S:");
         if (c == -1) {
             break;
         }
@@ -609,6 +642,12 @@
         case 's':
             send = true;
             break;
+        case 'R':
+            pattern.setReceiverAddress(new InetHostAddress(optarg));
+            break;
+        case 'S':
+            pattern.setSenderAddress(new InetHostAddress(optarg));
+            break;
         default:
             cerr << "Wrong Arguments, only -s and -r are accepted" << endl;
         }
diff --git a/jni/libzrtp/sources/demo/zrtptestMulti.cpp b/jni/libzrtp/sources/demo/zrtptestMulti.cpp
index 8fd288b..d7042ed 100644
--- a/jni/libzrtp/sources/demo/zrtptestMulti.cpp
+++ b/jni/libzrtp/sources/demo/zrtptestMulti.cpp
@@ -488,7 +488,8 @@
     if (!multiParams.empty()) {
         tx = new SymmetricZRTPSession(pattern.getDestinationAddress(),
                                       pattern.getDestinationPort()+2+10);
-//            tx->initialize("test_t.zid", true, &config);
+
+        //            tx->initialize("test_t.zid", true, &config);
         tx->initialize("test_t.zid", true);
         tx->setMultiStrParams(multiParams);
 
@@ -499,13 +500,12 @@
     else {
         tx = new SymmetricZRTPSession(pattern.getDestinationAddress(),
                                       pattern.getDestinationPort()+2);
-        //config.addHashAlgo(Sha384);
-//            tx->initialize("test_t.zid", true, &config);
         if (mitm) {                      // Act as trusted MitM - could be enrolled
             tx->setMitmMode(true);
         }
 
         tx->setSignSas(signsas);
+//            tx->initialize("test_t.zid", true, &config);
         tx->initialize("test_t.zid", true);
 
         if (enroll)                     // act as PBX enrollement service
@@ -518,8 +518,13 @@
     // At this point the Hello hash is available. See ZRTP specification
     // chapter 9.1 for further information when an how to use the Hello
     // hash.
-    cout << prefix << "Hello hash: " << tx->getHelloHash() << endl;
-    cout << prefix << "Hello hash length: " << tx->getHelloHash().length() << endl;
+    int numSupportedVersion = tx->getNumberSupportedVersions();
+    cout << "TX Hello hash 0: " << tx->getHelloHash(0) << endl;
+    cout << "TX Hello hash 0 length: " << tx->getHelloHash(0).length() << endl;
+    if (numSupportedVersion > 1) {
+        cout << "TX Hello hash 1: " << tx->getHelloHash(1) << endl;
+        cout << "TX Hello hash 1 length: " << tx->getHelloHash(1).length() << endl;
+    }
     tx->setUserCallback(mcb);
     tx->setSchedulingTimeout(10000);
     tx->setExpireTimeout(1000000);
@@ -583,12 +588,14 @@
         rx = new SymmetricZRTPSession(pattern.getDestinationAddress(),
                                       pattern.getDestinationPort());
         config.setStandardConfig();
+//        config.clear();
+//        config.addAlgo(SasType, zrtpSasTypes.getByName("B256"));
+
         if (enroll)
             config.setTrustedMitM(true);                // allow a trusted MitM to start enrollment process
 
         rx->setSignSas(signsas);
 
-        // config.addHashAlgo(Sha384);
         rx->initialize("test_r.zid", true, &config);
 //            rx->initialize("test_r.zid", true);
 
@@ -599,8 +606,13 @@
     // At this point the Hello hash is available. See ZRTP specification
     // chapter 9.1 for further information when an how to use the Hello
     // hash.
-    cout << prefix << "Hello hash: " << rx->getHelloHash() << endl;
-    cout << prefix << "Hello hash length: " << rx->getHelloHash().length() << endl;
+    int numSupportedVersion = rx->getNumberSupportedVersions();
+    cout << "RX Hello hash 0: " << rx->getHelloHash(0) << endl;
+    cout << "RX Hello hash 0 length: " << rx->getHelloHash(0).length() << endl;
+    if (numSupportedVersion > 1) {
+        cout << "RX Hello hash 1: " << rx->getHelloHash(1) << endl;
+        cout << "RX Hello hash 1 length: " << rx->getHelloHash(1).length() << endl;
+    }
     rx->setUserCallback(mcb);
     rx->setSchedulingTimeout(10000);
     rx->setExpireTimeout(1000000);
diff --git a/jni/libzrtp/sources/directive b/jni/libzrtp/sources/directive
index 6670679..016351a 100644
--- a/jni/libzrtp/sources/directive
+++ b/jni/libzrtp/sources/directive
@@ -1,3 +1 @@
-version: 1.1
 directory: ccrtp
-filename: libzrtpcpp-2.2.1.tar.gz
diff --git a/jni/libzrtp/sources/libzrtpcpp.pc.cmake b/jni/libzrtp/sources/libzrtpcpp.pc.cmake
index f9f5541..655bd30 100644
--- a/jni/libzrtp/sources/libzrtpcpp.pc.cmake
+++ b/jni/libzrtp/sources/libzrtpcpp.pc.cmake
@@ -9,7 +9,7 @@
 Description: GNU ZRTP core library
 Version: @VERSION@
 Requires: @CRYPTOBACKEND@
-Libs:  -L${libdir} -l@zrtplib@
+Libs:  -L${libdir} -l@zrtplibName@
 Cflags: -I${includedir}
 
 
diff --git a/jni/libzrtp/sources/srtp/CryptoContext.cpp b/jni/libzrtp/sources/srtp/CryptoContext.cpp
index a6e8768..89eb699 100644
--- a/jni/libzrtp/sources/srtp/CryptoContext.cpp
+++ b/jni/libzrtp/sources/srtp/CryptoContext.cpp
@@ -388,22 +388,18 @@
 
     int64_t delta = guessed_index - local_index;
     if (delta > 0) {
-        /* Packet not yet received*/
-        return true;
+        return true;           /* Packet not yet received*/
     }
     else {
-        if ( -delta > REPLAY_WINDOW_SIZE ) {
-            /* Packet too old */
-            return false;
+        if ( -delta >= REPLAY_WINDOW_SIZE ) {
+            return false;      /* Packet too old */
         }
         else {
             if ((replay_window >> (-delta)) & 0x1) {
-                /* Packet already received ! */
-                return false;
+                return false;  /* Packet already received ! */
             }
             else {
-                /* Packet not yet received */
-                return true;
+                return true;  /* Packet not yet received */
             }
         }
     }
diff --git a/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp b/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp
index e331be9..952a823 100644
--- a/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp
+++ b/jni/libzrtp/sources/srtp/CryptoContextCtrl.cpp
@@ -341,24 +341,21 @@
         return true;
     }
 
-    int64_t delta = s_l - index;
+    int64_t delta = index - s_l;
     if (delta > 0) {
         /* Packet not yet received*/
         return true;
     }
     else {
-        if( -delta > REPLAY_WINDOW_SIZE ) {
-            /* Packet too old */
-            return false;
+        if( -delta >= REPLAY_WINDOW_SIZE ) {
+            return false;       /* Packet too old */
         }
         else {
             if((replay_window >> (-delta)) & 0x1) {
-                /* Packet already received ! */
-                return false;
+                return false;   /* Packet already received ! */
             }
             else {
-                /* Packet not yet received */
-                return true;
+                return true;    /* Packet not yet received */
             }
         }
     }
@@ -376,7 +373,8 @@
     else {
         replay_window |= ( 1 << delta );
     }
-    s_l = index;
+    if (index > s_l)
+        s_l = index;
 }
 
 CryptoContextCtrl* CryptoContextCtrl::newCryptoContextForSSRC(uint32_t ssrc)
diff --git a/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp b/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp
index cb17b8f..1c743d2 100644
--- a/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp
+++ b/jni/libzrtp/sources/srtp/crypto/gcrypt/InitializeGcrypt.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp b/jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp
index 7346522..abe0a81 100644
--- a/jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp
+++ b/jni/libzrtp/sources/zrtp/ZIDCacheDb.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2008 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -133,4 +133,5 @@
 
 void ZIDCacheDb::cleanup() {
     cacheOps.cleanCache(zidFile, errorBuffer);
+    cacheOps.readLocalZid(zidFile, associatedZid, NULL, errorBuffer);
 }
diff --git a/jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp b/jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp
index 2c02a1e..5975fc2 100644
--- a/jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp
+++ b/jni/libzrtp/sources/zrtp/ZIDCacheFile.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2008 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp b/jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp
index 0bd91f0..b097cbf 100644
--- a/jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp
+++ b/jni/libzrtp/sources/zrtp/ZIDRecordDb.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -29,11 +29,6 @@
     memcpy(record.rs2, record.rs1, RS_LENGTH);
     record.rs2Ttl = record.rs1Ttl;
 
-    // now propagate flags as well
-    if (isRs1Valid()) {
-        setRs2Valid();
-    }
-
     // set new RS1 data
     memcpy(record.rs1, data, RS_LENGTH);
 
@@ -48,6 +43,7 @@
         validThru = time(NULL) + expire;
     }
     record.rs1Ttl = validThru;
+    resetRs2Valid();
     setRs1Valid();
 }
 
diff --git a/jni/libzrtp/sources/zrtp/ZIDRecordFile.cpp b/jni/libzrtp/sources/zrtp/ZIDRecordFile.cpp
index 68a4b9c..fd25dec 100644
--- a/jni/libzrtp/sources/zrtp/ZIDRecordFile.cpp
+++ b/jni/libzrtp/sources/zrtp/ZIDRecordFile.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -29,11 +29,6 @@
     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);
 
@@ -55,6 +50,7 @@
     else {
         memcpy(record.rs1Interval, (unsigned char*)&validThru, TIME_LENGTH);
     }
+    resetRs2Valid();
     setRs1Valid();
 }
 
diff --git a/jni/libzrtp/sources/zrtp/ZRtp.cpp b/jni/libzrtp/sources/zrtp/ZRtp.cpp
index 9fb8e0a..c7d2a46 100755
--- a/jni/libzrtp/sources/zrtp/ZRtp.cpp
+++ b/jni/libzrtp/sources/zrtp/ZRtp.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2009 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -25,6 +25,12 @@
 #include <crypto/sha256.h>
 #include <crypto/hmac384.h>
 #include <crypto/sha384.h>
+
+#include <crypto/skeinMac256.h>
+#include <crypto/skein256.h>
+#include <crypto/skeinMac384.h>
+#include <crypto/skein384.h>
+
 #include <crypto/aesCFB.h>
 #include <crypto/twoCFB.h>
 
@@ -52,7 +58,7 @@
     }
     fprintf(stderr, "\n");
 }
- */
+ * */
 
 /*
  * This method simplifies detection of libzrtpcpp inside Automake, configure
@@ -73,9 +79,10 @@
         callback(cb), dhContext(NULL), DHss(NULL), auxSecret(NULL), auxSecretLength(0), rs1Valid(false),
         rs2Valid(false), msgShaContext(NULL), hash(NULL), cipher(NULL), pubKey(NULL), sasType(NULL), authLength(NULL),
         multiStream(false), multiStreamAvailable(false), peerIsEnrolled(false), mitmSeen(false), pbxSecretTmp(NULL),
-        enrollmentMode(false), configureAlgos(*config), zidRec(NULL) {
+        enrollmentMode(false), configureAlgos(*config), zidRec(NULL), saveZidRecord(true) {
 
     enableMitmEnrollment = config->isTrustedMitM();
+    signatureData = NULL;
     paranoidMode = config->isParanoidMode();
 
     // setup the implicit hash function pointers and length
@@ -86,6 +93,8 @@
     hmacFunctionImpl = hmac_sha256;
     hmacListFunctionImpl = hmac_sha256;
 
+    memcpy(ownZid, myZid, ZID_SIZE);        // save the ZID
+
     /*
      * Generate H0 as a random number (256 bits, 32 bytes) and then
      * the hash chain, refer to chapter 9. Use the implicit hash function.
@@ -95,21 +104,40 @@
     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
+    // configure all supported Hello packet versions
+    zrtpHello_11.configureHello(&configureAlgos);
+    zrtpHello_11.setH3(H3);                    // set H3 in Hello, included in helloHash
+    zrtpHello_11.setZid(ownZid);
+    zrtpHello_11.setVersion((uint8_t*)zrtpVersion_11);
+
+
+    zrtpHello_12.configureHello(&configureAlgos);
+    zrtpHello_12.setH3(H3);                 // set H3 in Hello, included in helloHash
+    zrtpHello_12.setZid(ownZid);
+    zrtpHello_12.setVersion((uint8_t*)zrtpVersion_12);
+
+    if (mitmm) {                            // this session acts for a trusted MitM (PBX)
+        zrtpHello_11.setMitmMode();
+        zrtpHello_12.setMitmMode();
+    }
+    if (sasSignSupport) {                   // the application supports SAS signing
+        zrtpHello_11.setSasSign();
+        zrtpHello_12.setSasSign();
+    }
+
+    // Keep array in ascending order (greater index -> greater version)
+    helloPackets[0].packet = &zrtpHello_11;
+    helloPackets[0].version = zrtpHello_11.getVersionInt();
+    setClientId(id, &helloPackets[0]);      // set id, compute HMAC and final helloHash
+
+    helloPackets[1].packet = &zrtpHello_12;
+    helloPackets[1].version = zrtpHello_12.getVersionInt();
+    setClientId(id, &helloPackets[1]);      // set id, compute HMAC and final helloHash
+ 
+    currentHelloPacket = helloPackets[SUPPORTED_ZRTP_VERSIONS-1].packet;  // start with highest supported version
+    helloPackets[SUPPORTED_ZRTP_VERSIONS].packet = NULL;
     peerHelloVersion[0] = 0;
 
-    memcpy(ownZid, myZid, ZID_SIZE);
-    zrtpHello.setZid(ownZid);
-
-    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);
 }
 
@@ -235,7 +263,7 @@
 }
 
 ZrtpPacketHello* ZRtp::prepareHello() {
-    return &zrtpHello;
+    return currentHelloPacket;
 }
 
 ZrtpPacketHelloAck* ZRtp::prepareHelloAck() {
@@ -249,16 +277,17 @@
  */
 ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) {
 
+    myRole = Initiator;
+
+    if (!hello->isLengthOk()) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     // Save data before detailed checks - may aid in analysing problems
     peerClientId.assign((char*)hello->getClientId(), ZRTP_WORD_SIZE * 4);
     memcpy(peerHelloVersion, hello->getVersion(), ZRTP_WORD_SIZE);
     peerHelloVersion[ZRTP_WORD_SIZE] = 0;
 
-    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, ownZid, ZID_SIZE) == 0) {       // peers have same ZID????
@@ -291,14 +320,15 @@
     sasType = findBestSASType(hello);
 
     if (!multiStream) {
-        pubKey = findBestPubkey(hello);                 // Check for public key algorithm first, sets 'hash' as well
+        pubKey = findBestPubkey(hello);                 // Check for public key algorithm first, must set 'hash' as well
         if (hash == NULL) {
             *errMsg = UnsuppHashType;
             return NULL;
         }
         if (cipher == NULL)                             // public key selection may have set the cipher already
             cipher = findBestCipher(hello, pubKey);
-        authLength = findBestAuthLen(hello);
+        if (authLength == NULL)                         // public key selection may have set the SRTP authLen already
+            authLength = findBestAuthLen(hello);
         multiStreamAvailable = checkMultiStream(hello);
     }
     else {
@@ -440,7 +470,7 @@
 }
 
 /*
- * At this point we will take the role of the Responder. We may have been in
+ * At this point we will take the role of the Responder. We 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
@@ -452,8 +482,21 @@
 
     sendInfo(Info, InfoRespCommitReceived);
 
-    // The following code check the hash chain according chapter 10 to detect
-    // false ZRTP packets.
+    if (!commit->isLengthOk(ZrtpPacketCommit::DhExchange)) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+
+    // Check if ZID in Commit is the same as we got in Hello
+    uint8_t tmpZid[ZID_SIZE];
+    memcpy(tmpZid, commit->getZid(), ZID_SIZE);
+    if (memcmp(peerZid, tmpZid, ZID_SIZE) != 0) {       // ZIDs do not match????
+        sendInfo(Severe, SevereProtocolError);
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
+
+    // The following code checks 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);
@@ -511,8 +554,8 @@
         *errMsg = UnsuppPKExchange;
         return NULL;
     }
-    if (*(int32_t*)(cp->getName()) == *(int32_t*)ec38) {
-        if (*(int32_t*)(hash->getName()) != *(int32_t*)s384) {
+    if (*(int32_t*)(cp->getName()) == *(int32_t*)ec38 || *(int32_t*)(cp->getName()) == *(int32_t*)e414) {
+        if (!(*(int32_t*)(hash->getName()) == *(int32_t*)s384 || *(int32_t*)(hash->getName()) == *(int32_t*)skn3)) {
             *errMsg = UnsuppHashType;
             return NULL;
         }
@@ -528,7 +571,7 @@
     sasType = cp;
 
     // dhContext cannot be NULL - always setup during prepareCommit()
-    // check if we can use the dhContext prepared by 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())) {
@@ -540,7 +583,11 @@
 
     dhContext->getPubKeyBytes(pubKeyBytes);
 
+    // Re-compute auxSecretIDr because we changed roles *IDr with my H3, *IDi with peer's H3
     // Setup a DHPart1 packet.
+    myRole = Responder;
+    computeAuxSecretIds();                 // recompute AUX secret ids because we are now Responder, use different H3
+
     zrtpDH1.setPubKeyType(pubKey->getName());
     zrtpDH1.setMessageType((uint8_t*)DHPart1Msg);
     zrtpDH1.setRs1Id(rs1IDr);
@@ -561,22 +608,20 @@
     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.
+    // We are responder. Release the pre-computed SHA context because it was prepared for Initiator.
+    // Setup and compute for Responder.
     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);
+    // 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*)currentHelloPacket->getHeaderBase(), currentHelloPacket->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);
 
@@ -595,6 +640,10 @@
 
     sendInfo(Info, InfoInitDH1Received);
 
+    if (!dhPart1->isLengthOk()) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     // 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.
@@ -633,8 +682,6 @@
     }
     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.
@@ -667,6 +714,10 @@
 
     sendInfo(Info, InfoRespDH2Received);
 
+    if (!dhPart2->isLengthOk()) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     // 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
@@ -689,7 +740,7 @@
     // 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);
+    computeHvi(dhPart2, currentHelloPacket);
     if (memcmp(hvi, peerHvi, HVI_SIZE) != 0) {
         *errMsg = DHErrorWrongHVI;
         return NULL;
@@ -706,8 +757,8 @@
         return NULL;
     }
     dhContext->computeSecretKey(pvi, DHss);
-    // Hash the Initiator's DH2 into the message Hash (other messages already
-    // prepared, see method prepareDHPart1().
+
+    // 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);
 
@@ -770,6 +821,10 @@
 
     sendInfo(Info, InfoRespCommitReceived);
 
+    if (!commit->isLengthOk(ZrtpPacketCommit::MultiStream)) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     // The following code checks the hash chain according chapter 10 to detect
     // false ZRTP packets.
     // Use implicit hash function
@@ -840,7 +895,7 @@
     // 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*)currentHelloPacket->getHeaderBase(), currentHelloPacket->getLength() * ZRTP_WORD_SIZE);
     hashCtxFunction(msgShaContext, (unsigned char*)commit->getHeaderBase(), commit->getLength() * ZRTP_WORD_SIZE);
 
     closeHashCtx(msgShaContext, messageHash);
@@ -878,6 +933,10 @@
 
     sendInfo(Info, InfoInitConf1Received);
 
+    if (!confirm1->isLengthOk()) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     uint8_t confMac[MAX_DIGEST_LENGTH];
     uint32_t macLen;
 
@@ -903,7 +962,7 @@
         return NULL;
     }
     signatureLength = confirm1->getSignatureLength();
-    if (signSasSeen && signatureLength > 0) {
+    if (signSasSeen && signatureLength > 0 && confirm1->isSignatureLengthOk()) {
         signatureData = confirm1->getSignatureData();
         callback->checkSASSignature(sasHash);
         // TODO: error handling if checkSASSignature returns false.
@@ -956,7 +1015,8 @@
             zrtpConfirm2.setPBXEnrollment();
         }
     }
-    getZidCacheInstance()->saveRecord(zidRec);
+    if (saveZidRecord)
+        getZidCacheInstance()->saveRecord(zidRec);
 
     // Encrypt and HMAC with Initiator's key - we are Initiator here
     hmlen = (zrtpConfirm2.getLength() - 9) * ZRTP_WORD_SIZE;
@@ -994,6 +1054,10 @@
     // don't update SAS, RS
     sendInfo(Info, InfoInitConf1Received);
 
+    if (!confirm1->isLengthOk()) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     uint8_t confMac[MAX_DIGEST_LENGTH];
     uint32_t macLen;
 
@@ -1059,6 +1123,10 @@
 
     sendInfo(Info, InfoRespConf2Received);
 
+    if (!confirm2->isLengthOk()) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     uint8_t confMac[MAX_DIGEST_LENGTH];
     uint32_t macLen;
 
@@ -1088,7 +1156,7 @@
             return NULL;
         }
         signatureLength = confirm2->getSignatureLength();
-        if (signSasSeen && signatureLength > 0) {
+        if (signSasSeen && signatureLength > 0 && confirm2->isSignatureLengthOk() ) {
             signatureData = confirm2->getSignatureData();
             callback->checkSASSignature(sasHash);
             // TODO: error handling if checkSASSignature returns false.
@@ -1106,7 +1174,8 @@
 
         // save new RS1, this inherits the verified flag from old RS1
         zidRec->setNewRs1((const uint8_t*)newRs1);
-        getZidCacheInstance()->saveRecord(zidRec);
+        if (saveZidRecord)
+            getZidCacheInstance()->saveRecord(zidRec);
 
         // Ask for enrollment only if enabled via configuration and the
         // confirm packet contains the enrollment flag. The enrolling user
@@ -1141,7 +1210,10 @@
 }
 
 ZrtpPacketErrorAck* ZRtp::prepareErrorAck(ZrtpPacketError* epkt) {
-    sendInfo(ZrtpError, epkt->getErrorCode() * -1);
+    if (epkt->getLength() < 4)
+        sendInfo(ZrtpError, CriticalSWError * -1);
+    else
+        sendInfo(ZrtpError, epkt->getErrorCode() * -1);
     return &zrtpErrorAck;
 }
 
@@ -1151,7 +1223,8 @@
 }
 
 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)
@@ -1167,6 +1240,10 @@
     if (!mitmSeen || paranoidMode)
         return &zrtpRelayAck;
 
+    if (!srly->isLengthOk()) {
+        *errMsg = CriticalSWError;
+        return NULL;
+    }
     uint8_t* hkey, *ekey;
     // If we are responder then the PBX used it's Initiator keys
     if (myRole == Responder) {
@@ -1287,8 +1364,7 @@
     if (num == 0) {
         return &zrtpHashes.getByName(mandatoryHash);
     }
-    // Build list of configured hash algorithm names, append mandatory algos
-    // if necessary.
+    // Build list of configured hash algorithm names.
     numAlgosConf = configureAlgos.getNumConfiguredAlgos(HashAlgorithm);
     for (i = 0; i < numAlgosConf; i++) {
         algosConf[i] = &configureAlgos.getAlgoAt(HashAlgorithm, i);
@@ -1302,8 +1378,7 @@
         numAlgosOffered++;
     }
 
-    // Lookup offered algos in configured algos. Because of appended
-    // mandatory algorithms at least one match will happen
+    // Lookup offered algos in configured algos.
     for (i = 0; i < numAlgosOffered; i++) {
         for (ii = 0; ii < numAlgosConf; ii++) {
             if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
@@ -1354,85 +1429,101 @@
     return &zrtpSymCiphers.getByName(mandatoryCipher);
 }
 
+// We can have the non-NIST in the list of orderedAlgos even if they are not available
+// in the code (refer to ZrtpConfigure.cpp). If they are not build in they cannot appear
+// in'configureAlgos' and thus not in the intersection lists. Thus a ZRTP build that
+// does not include the non-NIST curves also works without problems.
+//
 AlgorithmEnum* ZRtp::findBestPubkey(ZrtpPacketHello *hello) {
 
-    int i;
-    int ii;
-    int numAlgosIntersect;
-    AlgorithmEnum* algosIntersect[ZrtpConfigure::maxNoOfAlgos+1];
-
-    int numAlgosConf;
-    AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
+    AlgorithmEnum* peerIntersect[ZrtpConfigure::maxNoOfAlgos+1];
+    AlgorithmEnum* ownIntersect[ZrtpConfigure::maxNoOfAlgos+1];
 
     // Build list of own pubkey algorithm names, must follow the order
     // defined in RFC 6189, chapter 4.1.2.
-    const char *orderedAlgos[] = {dh2k, ec25, dh3k, ec38};
+    const char *orderedAlgos[] = {dh2k, e255, ec25, dh3k, e414, ec38};
     int numOrderedAlgos = sizeof(orderedAlgos) / sizeof(const char*);
 
-    int num = hello->getNumPubKeys();
-    if (num == 0) {
-        hash = &zrtpHashes.getByName(mandatoryHash);             // set mandatory hash
+    int numAlgosPeer = hello->getNumPubKeys();
+    if (numAlgosPeer == 0) {
+        hash = findBestHash(hello);                    // find a hash algorithm
         return &zrtpPubKeys.getByName(mandatoryPubKey);
     }
-    // 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) {
+    // Build own list of intersecting algos, keep own order or algorithms
+    // The list must include real public key algorithms only, so skip mult-stream mode, 
+    // preshared and alike.
+    int numAlgosOwn = configureAlgos.getNumConfiguredAlgos(PubKeyAlgorithm);
+    int numOwnIntersect = 0;
+    for (int i = 0; i < numAlgosOwn; i++) {
+        ownIntersect[numOwnIntersect] = &configureAlgos.getAlgoAt(PubKeyAlgorithm, i);
+        if (*(int32_t*)(ownIntersect[numOwnIntersect]->getName()) == *(int32_t*)mult) {
             continue;                               // skip multi-stream mode
         }
-        ii++;
-    }
-    numAlgosConf = ii;
- 
-    // Build list of intersecting algos: own and offered in Hello, intersect list is ordered according to offered algorithms
-    for (numAlgosIntersect = 0, i = 0; i < num; i++) {
-        for (ii = 0; ii < numAlgosConf; ii++) {
-            algosIntersect[numAlgosIntersect] = &zrtpPubKeys.getByName((const char*)hello->getPubKeyType(i));
-            if (*(int32_t*)(algosConf[ii]->getName()) == *(int32_t*)(algosIntersect[numAlgosIntersect]->getName())) {
-                numAlgosIntersect++;
+        for (int ii = 0; ii < numAlgosPeer; ii++) {
+            if (*(int32_t*)(ownIntersect[numOwnIntersect]->getName()) == *(int32_t*)(zrtpPubKeys.getByName((const char*)hello->getPubKeyType(ii)).getName())) {
+                numOwnIntersect++;
+                break;
             }
         }
     }
-    if (numAlgosIntersect == 0) {
-        // If we don't find a common algorithm - use the mandatory algorithms
-        hash = &zrtpHashes.getByName(mandatoryHash);
+    // Build list of peer's intersecting algos: take own list as input and build a 
+    // list of algorithms that we have in common. The order of the list is according
+    // to peer's Hello packet (peer's preferences). 
+    int numPeerIntersect = 0;
+    for (int i = 0; i < numAlgosPeer; i++) {
+        peerIntersect[numPeerIntersect] = &zrtpPubKeys.getByName((const char*)hello->getPubKeyType(i));
+        for (int ii = 0; ii < numOwnIntersect; ii++) {
+            if (*(int32_t*)(ownIntersect[ii]->getName()) == *(int32_t*)(peerIntersect[numPeerIntersect]->getName())) {
+                numPeerIntersect++;
+                break;
+            }
+        }
+    }
+    if (numPeerIntersect == 0) {       // If we don't have a common algorithm - use mandatory algorithms
+        hash = findBestHash(hello);
         return &zrtpPubKeys.getByName(mandatoryPubKey);
     }
+
+    // If we have only one algorithm in common or if the first entry matches - take it.
+    // Otherwise determine which algorithm from the intersection lists is first in the 
+    // list of ordered algorithms and select it (RFC6189, section 4.1.2).
     AlgorithmEnum* useAlgo;
-    if (numAlgosIntersect > 1 && *(int32_t*)(algosConf[0]->getName()) != *(int32_t*)(algosIntersect[0]->getName())) {
+    if (numPeerIntersect > 1 && *(int32_t*)(ownIntersect[0]->getName()) != *(int32_t*)(peerIntersect[0]->getName())) {
         int own, peer;
 
-        const int32_t *name = (int32_t*)algosConf[0]->getName();
+        const int32_t *name = (int32_t*)ownIntersect[0]->getName();
         for (own = 0; own < numOrderedAlgos; own++) {
             if (*name == *(int32_t*)orderedAlgos[own])
                 break;
         }
-        name = (int32_t*)algosIntersect[0]->getName();
+        name = (int32_t*)peerIntersect[0]->getName();
         for (peer = 0; peer < numOrderedAlgos; peer++) {
             if (*name == *(int32_t*)orderedAlgos[peer])
                 break;
         }
         if (own < peer) {
-            useAlgo = algosConf[0];
+            useAlgo = ownIntersect[0];
         }
         else {
-            useAlgo = algosIntersect[0];
+            useAlgo = peerIntersect[0];
         }
         // find fastest of conf vs intersecting
     }
     else {
-        useAlgo = algosIntersect[0];
+        useAlgo = peerIntersect[0];
     }
+    int32_t algoName = *(int32_t*)(useAlgo->getName());
+
     // select a corresponding strong hash if necessary.
-    if (*(int32_t*)(useAlgo->getName()) == *(int32_t*)ec38) {
-        hash = getStrongHashOffered(hello);
-        cipher = getStrongCipherOffered(hello);
+    if (algoName == *(int32_t*)ec38 || algoName == *(int32_t*)e414) {
+        hash = getStrongHashOffered(hello, algoName);
+        cipher = getStrongCipherOffered(hello, algoName);
     }
     else {
-        hash = findBestHash(hello);
+        hash = getHashOffered(hello, algoName);;
+        cipher = getCipherOffered(hello, algoName);
     }
+    authLength = getAuthLenOffered(hello, algoName);
     return useAlgo;
 }
 
@@ -1450,14 +1541,14 @@
     if (num == 0) {
         return &zrtpSasTypes.getByName(mandatorySasType);
     }
-    // Buildlist of configured SAS algorithm names
+    // Build list of configured SAS algorithm names
     numAlgosConf = configureAlgos.getNumConfiguredAlgos(SasType);
     for (i = 0; i < numAlgosConf; i++) {
         algosConf[i] = &configureAlgos.getAlgoAt(SasType, i);
     }
     // Build list of offered known algos in Hello,
     for (numAlgosOffered = 0, i = 0; i < num; i++) {
-        algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i++));
+        algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i));
         if (!algosOffered[numAlgosOffered]->isValid())
             continue;
         numAlgosOffered++;
@@ -1515,27 +1606,109 @@
     return &zrtpAuthLengths.getByName(mandatoryAuthLen_1);
 }
 
-AlgorithmEnum* ZRtp::getStrongHashOffered(ZrtpPacketHello *hello) {
+// The following set of functions implement a 'non-NIST first policy' if nonNist computes 
+// to true. They prefer nonNist algorithms if these are available. Otherwise they use the NIST
+// counterpart or simply call the according findBest*(...) function.
+//
+// Only the findBestPubkey(...) function calls them after it selected the public key algorithm.
+// If the public key algorithm is non-NIST and if the policy is set to PreferNonNist then
+// nonNist becomes true.
+//
+// The functions work according to the RFC6189 spec: the initiator can select every algorithm
+// that both parties support. Thus the Initiator can even select an algorithm the wasn't offered
+// in its own Hello packet but that the Initiator found in the peer's Hello and that is available
+// for it.
+//
+AlgorithmEnum* ZRtp::getStrongHashOffered(ZrtpPacketHello *hello, int32_t algoName) {
 
     int numHash = hello->getNumHashes();
+    bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
+
+    if (nonNist) {
+        for (int i = 0; i < numHash; i++) {
+            int32_t nm = *(int32_t*)(hello->getHashType(i));
+            if (nm == *(int32_t*)skn3) {
+                return &zrtpHashes.getByName((const char*)hello->getHashType(i));
+            }
+        }
+    }
     for (int i = 0; i < numHash; i++) {
-        if (*(int32_t*)(hello->getHashType(i)) == *(int32_t*)s384) {
+        int32_t nm = *(int32_t*)(hello->getHashType(i));
+        if (nm == *(int32_t*)s384 || nm == *(int32_t*)skn3) {
             return &zrtpHashes.getByName((const char*)hello->getHashType(i));
         }
     }
-    return NULL;
+    return NULL;         // returning NULL -> prepareCommit(...) terminates ZRTP, missing strong hash is an error
 }
 
-AlgorithmEnum* ZRtp::getStrongCipherOffered(ZrtpPacketHello *hello) {
+AlgorithmEnum* ZRtp::getStrongCipherOffered(ZrtpPacketHello *hello, int32_t algoName) {
 
     int num = hello->getNumCiphers();
+    bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
+
+    if (nonNist) {
+        for (int i = 0; i < num; i++) {
+            int32_t nm = *(int32_t*)(hello->getCipherType(i));
+            if (nm == *(int32_t*)two3) {
+                return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
+            }
+        }
+    }
     for (int i = 0; i < num; i++) {
-        if (*(int32_t*)(hello->getCipherType(i)) == *(int32_t*)aes3 ||
-            *(int32_t*)(hello->getCipherType(i)) == *(int32_t*)two3) {
+        int32_t nm = *(int32_t*)(hello->getCipherType(i));
+        if (nm == *(int32_t*)aes3 || nm == *(int32_t*)two3) {
             return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
         }
     }
-    return NULL;
+    return NULL;       // returning NULL -> prepareCommit(...) finds the best cipher
+}
+
+AlgorithmEnum* ZRtp::getHashOffered(ZrtpPacketHello *hello, int32_t algoName) {
+
+    int num = hello->getNumHashes();
+    bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
+
+    if (nonNist) {
+        for (int i = 0; i < num; i++) {
+            int32_t nm = *(int32_t*)(hello->getHashType(i));
+            if (nm == *(int32_t*)skn2 || nm == *(int32_t*)skn3) {
+                return &zrtpHashes.getByName((const char*)hello->getHashType(i));
+            }
+        }
+    }
+    return findBestHash(hello);
+}
+
+AlgorithmEnum* ZRtp::getCipherOffered(ZrtpPacketHello *hello, int32_t algoName) {
+
+    int num = hello->getNumCiphers();
+    bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
+
+    if (nonNist) {
+        for (int i = 0; i < num; i++) {
+            int32_t nm = *(int32_t*)(hello->getCipherType(i));
+            if (nm == *(int32_t*)two2 || nm == *(int32_t*)two3) {
+                return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
+            }
+        }
+    }
+    return NULL;       // returning NULL -> prepareCommit(...) finds the best cipher
+}
+
+AlgorithmEnum* ZRtp::getAuthLenOffered(ZrtpPacketHello *hello, int32_t algoName) {
+
+    int num = hello->getNumAuth();
+    bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
+
+    if (nonNist) {
+        for (int i = 0; i < num; i++) {
+            int32_t nm = *(int32_t*)(hello->getAuthLen(i));
+            if (nm == *(int32_t*)sk32 || nm == *(int32_t*)sk64) {
+                return &zrtpAuthLengths.getByName((const char*)hello->getAuthLen(i));
+            }
+        }
+    }
+    return findBestAuthLen(hello);
 }
 
 bool ZRtp::checkMultiStream(ZrtpPacketHello *hello) {
@@ -1558,6 +1731,10 @@
 bool ZRtp::verifyH2(ZrtpPacketCommit *commit) {
     uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH];
 
+    // packet does not have the correct size, treat H2 verfication as failed.
+    if (!commit->isLengthOk(multiStream ? ZrtpPacketCommit::MultiStream : ZrtpPacketCommit::DhExchange))
+        return false;
+
     sha256(commit->getH2(), HASH_IMAGE_SIZE, tmpH3);
     if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) {
         return false;
@@ -1593,6 +1770,7 @@
     uint8_t randBuf[RS_LENGTH];
     uint32_t macLen;
 
+    fprintf(stderr, "Compute shared secrets\n");
     detailInfo.secretsCached = 0;
     if (!zidRec->isRs1Valid()) {
         randomZRTP(randBuf, RS_LENGTH);
@@ -1618,15 +1796,6 @@
         detailInfo.secretsCached |= Rs2;
     }
 
-    /*
-    * For the time being we don't support this type 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);
@@ -1638,6 +1807,28 @@
         hmacFunction((unsigned char*)zidRec->getMiTMData(), RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen);
         detailInfo.secretsCached |= Pbx;
     }
+    computeAuxSecretIds();
+}
+
+void ZRtp::computeAuxSecretIds() {
+    uint8_t randBuf[RS_LENGTH];
+    uint32_t macLen;
+
+    if (auxSecret == NULL) {
+        randomZRTP(randBuf, RS_LENGTH);
+        hmacFunction(randBuf, RS_LENGTH, H3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen);
+        hmacFunction(randBuf, RS_LENGTH, H3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen);
+    }
+    else {
+        if (myRole == Initiator) {  // I'm initiator thus use my H3 for initiator's IDi, peerH3 for respnder's IDr
+            hmacFunction(auxSecret, auxSecretLength, H3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen);
+            hmacFunction(auxSecret, auxSecretLength, peerH3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen);
+        }
+        else {
+            hmacFunction(auxSecret, auxSecretLength, peerH3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen);
+            hmacFunction(auxSecret, auxSecretLength, H3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen);
+        }
+    }
 }
 
 /*
@@ -1684,12 +1875,17 @@
         rsFound = 0x8;
         detailInfo.secretsMatched = Rs2;
     }
-    /* *** Not yet supported
+
     if (memcmp(auxSecretIDr, dhPart->getAuxSecretId(), 8) == 0) {
-    DEBUGOUT((fprintf(stdout, "%c: Match for aux secret found\n", zid[0])));
+        DEBUGOUT((fprintf(stdout, "Initiator: Match for aux secret found\n")));
         setD[1] = auxSecret;
+        detailInfo.secretsMatched |= Aux;
+        detailInfo.secretsMatchedDH |= Aux;
     }
-    */
+    if (auxSecret != NULL && (detailInfo.secretsMatched & Aux) == 0) {
+        sendInfo(Warning, WarningNoExpectedAuxMatch);
+    }
+
     // check if we have a matching PBX secret and place it third (s3)
     if (memcmp(pbxSecretIDr, dhPart->getPbxSecretId(), HMAC_SIZE) == 0) {
         DEBUGOUT((fprintf(stdout, "%c: Match for Other_secret found\n", zid[0])));
@@ -1704,6 +1900,7 @@
         if (rs1Valid || rs2Valid) {            // but valid RS records in cache
             sendInfo(Warning, WarningNoExpectedRSMatch);
             zidRec->resetSasVerified();
+            saveZidRecord = false;             // Don't save RS until user verfied/confirmed SAS
         }
         else {                                 // No valid RS record in cache
             sendInfo(Warning, WarningNoRSMatch);
@@ -1780,7 +1977,7 @@
             data[pos] = (unsigned char*)&sLen[i];
             length[pos++] = sizeof(uint32_t);
             data[pos] = (unsigned char*)setD[i];
-            length[pos++] = RS_LENGTH;
+            length[pos++] = (i != 1) ? RS_LENGTH : auxSecretLength;
         }
         else {                           // no machting secret, set length 0, skip secret
             sLen[i] = 0;
@@ -1842,12 +2039,17 @@
         rsFound |= 0x8;
         detailInfo.secretsMatched = Rs2;
     }
-    /* ***** not yet supported
-    if (memcmp(auxSecretIDi, dhPart->getauxSecretId(), 8) == 0) {
-    DEBUGOUT((fprintf(stdout, "%c: Match for aux secret found\n", ownZidzid[0])));
-        setD[1] = ;
+
+    if (memcmp(auxSecretIDi, dhPart->getAuxSecretId(), 8) == 0) {
+        DEBUGOUT((fprintf(stdout, "Responder: Match for aux secret found\n")));
+        setD[1] = auxSecret;
+        detailInfo.secretsMatched |= Aux;
+        detailInfo.secretsMatchedDH |= Aux;
     }
-    */
+    // If we have an auxSecret but no match from peer - report this.
+    if (auxSecret != NULL && (detailInfo.secretsMatched & Aux) == 0) {
+        sendInfo(Warning, WarningNoExpectedAuxMatch);
+    }
 
     if (memcmp(pbxSecretIDi, dhPart->getPbxSecretId(), 8) == 0) {
         DEBUGOUT((fprintf(stdout, "%c: Match for PBX secret found\n", ownZid[0])));
@@ -1861,6 +2063,7 @@
         if (rs1Valid || rs2Valid) {            // but valid RS records in cache
             sendInfo(Warning, WarningNoExpectedRSMatch);
             zidRec->resetSasVerified();
+            saveZidRecord = false;             // Don't save RS until user verfied/confirmed SAS
         }
         else {                                 // No valid RS record in cache
             sendInfo(Warning, WarningNoRSMatch);
@@ -1939,7 +2142,7 @@
             data[pos] = (unsigned char*)&sLen[i];
             length[pos++] = sizeof(uint32_t);
             data[pos] = (unsigned char*)setD[i];
-            length[pos++] = RS_LENGTH;
+            length[pos++] = (i != 1) ? RS_LENGTH : auxSecretLength;
         }
         else {                           // no machting secret, set length 0, skip secret
             sLen[i] = 0;
@@ -2189,6 +2392,34 @@
         hashCtxFunction = sha384Ctx;
         hashCtxListFunction = sha384Ctx;
         break;
+
+    case 2:
+        hashLength = SKEIN256_DIGEST_LENGTH;
+        hashFunction = skein256;
+        hashListFunction = skein256;
+
+        hmacFunction = macSkein256;
+        hmacListFunction = macSkein256;
+
+        createHashCtx = createSkein256Context;
+        closeHashCtx = closeSkein256Context;
+        hashCtxFunction = skein256Ctx;
+        hashCtxListFunction = skein256Ctx;
+        break;
+
+    case 3:
+        hashLength = SKEIN384_DIGEST_LENGTH;
+        hashFunction = skein384;
+        hashListFunction = skein384;
+
+        hmacFunction = macSkein384;
+        hmacListFunction = macSkein384;
+
+        createHashCtx = createSkein384Context;
+        closeHashCtx = closeSkein384Context;
+        hashCtxFunction = skein384Ctx;
+        hashCtxListFunction = skein384Ctx;
+        break;
     }
 }
 
@@ -2202,6 +2433,7 @@
         return;
 
     zidRec->setSasVerified();
+    saveZidRecord = true;
     getZidCacheInstance()->saveRecord(zidRec);
 }
 
@@ -2211,6 +2443,14 @@
     getZidCacheInstance()->saveRecord(zidRec);
 }
 
+void ZRtp::setRs2Valid() {
+
+    if (zidRec != NULL) {
+        zidRec->setRs2Valid();
+        if (saveZidRecord)
+            getZidCacheInstance()->saveRecord(zidRec);
+    }
+}
 
 void ZRtp::sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) {
 
@@ -2262,33 +2502,32 @@
     }
 }
 
-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());
-    }
+void ZRtp::setClientId(std::string id, HelloPacketVersion* hpv) {
 
-    int32_t len = zrtpHello.getLength() * ZRTP_WORD_SIZE;
+    unsigned char tmp[CLIENT_ID_SIZE +1] = {' '};
+    memcpy(tmp, id.c_str(), id.size() > CLIENT_ID_SIZE ? CLIENT_ID_SIZE : id.size());
+    tmp[CLIENT_ID_SIZE] = 0;
 
-    // Hello packet is ready now, compute its HMAC
+    hpv->packet->setClientId(tmp);
+
+    int32_t len = hpv->packet->getLength() * ZRTP_WORD_SIZE;
+
+    // Hello packets are 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);
+    hmacFunctionImpl(H2, HASH_IMAGE_SIZE, (uint8_t*)hpv->packet->getHeaderBase(), len-(2*ZRTP_WORD_SIZE), hmac, &macLen);
+    hpv->packet->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);
+    hashFunctionImpl((uint8_t*)hpv->packet->getHeaderBase(), len, hpv->helloHash);
 }
 
 void ZRtp::storeMsgTemp(ZrtpPacketBase* pkt) {
-    int32_t length = pkt->getLength() * ZRTP_WORD_SIZE;
+    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;
@@ -2304,12 +2543,18 @@
     return (memcmp(hmac, tempMsgBuffer+len, (HMAC_SIZE)) == 0 ? true : false);
 }
 
-std::string ZRtp::getHelloHash() {
+std::string ZRtp::getHelloHash(int32_t index) {
     std::ostringstream stm;
 
-    uint8_t* hp = helloHash;
+    if (index < 0 || index >= MAX_ZRTP_VERSIONS)
+        return std::string();
 
-    stm << zrtpVersion;
+    uint8_t* hp = helloPackets[index].helloHash;
+
+    char version[5] = {'\0'};
+    strncpy(version, (const char*)helloPackets[index].packet->getVersion(), ZRTP_WORD_SIZE);
+
+    stm << version;
     stm << " ";
     stm.fill('0');
     stm << hex;
@@ -2426,7 +2671,8 @@
     Event_t ev;
 
     ev.type = ZrtpPacket;
-    ev.packet = (uint8_t*)&zrtpConf2Ack;
+    ev.packet = (uint8_t*)zrtpConf2Ack.getHeaderBase();
+    ev.length = sizeof (Conf2AckPacket_t) + 12;  // 12 is fixed ZRTP (RTP) header size
 
     if (stateEngine != NULL) {
         stateEngine->processEvent(&ev);
diff --git a/jni/libzrtp/sources/zrtp/ZrtpCWrapper.cpp b/jni/libzrtp/sources/zrtp/ZrtpCWrapper.cpp
index f8e0c65..7f7c3dd 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpCWrapper.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpCWrapper.cpp
@@ -1,9 +1,9 @@
 /*
     This class maps the ZRTP C calls to ZRTP C++ methods.
-    Copyright (C) 2010  Werner Dittmann
+    Copyright (C) 2010-2013  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
+    it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
 
@@ -164,10 +164,10 @@
         zrtpContext->zrtpEngine->resetSASVerified();
 }
 
-char* zrtp_getHelloHash(ZrtpContext* zrtpContext) {
+char* zrtp_getHelloHash(ZrtpContext* zrtpContext, int32_t index) {
     std::string ret;
     if (zrtpContext && zrtpContext->zrtpEngine)
-        ret = zrtpContext->zrtpEngine->getHelloHash();
+        ret = zrtpContext->zrtpEngine->getHelloHash(index);
     else
         return NULL;
 
@@ -324,6 +324,13 @@
     return 0;
 }
 
+int32_t zrtp_getNumberSupportedVersions(ZrtpContext* zrtpContext) {
+    return zrtpContext->zrtpEngine->getNumberSupportedVersions();
+}
+
+int32_t zrtp_getCurrentProtocolVersion(ZrtpContext* zrtpContext) {
+    return zrtpContext->zrtpEngine->getCurrentProtocolVersion();
+}
 /*
  * The following methods wrap the ZRTP Configure functions
  */
diff --git a/jni/libzrtp/sources/zrtp/ZrtpCallbackWrapper.cpp b/jni/libzrtp/sources/zrtp/ZrtpCallbackWrapper.cpp
index ca2dce6..fed2c04 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpCallbackWrapper.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpCallbackWrapper.cpp
@@ -1,9 +1,9 @@
 /*
     This class maps the ZRTP C++ callback methods to C callback methods.
-    Copyright (C) 2010  Werner Dittmann
+    Copyright (C) 2010-2013  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
+    it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpConfigure.cpp b/jni/libzrtp/sources/zrtp/ZrtpConfigure.cpp
index bb71269..6a22983 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpConfigure.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpConfigure.cpp
@@ -1,3 +1,24 @@
+/*

+  Copyright (C) 2006-2013 Werner Dittmann

+

+  This program 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 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 <crypto/aesCFB.h>

 #include <crypto/twoCFB.h>

 #include <libzrtpcpp/ZrtpConfigure.h>

@@ -135,6 +156,8 @@
 HashEnum::HashEnum() : EnumBase(HashAlgorithm) {

     insert(s256, 0, "SHA-256", NULL, NULL, None);

     insert(s384, 0, "SHA-384", NULL, NULL, None);

+    insert(skn2, 0, "Skein-256", NULL, NULL, None);

+    insert(skn3, 0, "Skein-384", NULL, NULL, None);

 }

 

 HashEnum::~HashEnum() {}

@@ -156,10 +179,14 @@
  */

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

     insert(dh2k, 0, "DH-2048", NULL, NULL, None);

-    insert(ec25, 0, "ECDH-256", NULL, NULL, None);

+    insert(ec25, 0, "NIST ECDH-256", NULL, NULL, None);

     insert(dh3k, 0, "DH-3072", NULL, NULL, None);

-    insert(ec38, 0, "ECDH-384", NULL, NULL, None);

-    insert(mult, 0, "Multi-stream", NULL, NULL, None);

+    insert(ec38, 0, "NIST ECDH-384", NULL, NULL, None);

+    insert(mult, 0, "Multi-stream",  NULL, NULL, None);

+#ifdef SUPPORT_NON_NIST

+    insert(e255, 0, "ECDH-255", NULL, NULL, None);

+    insert(e414, 0, "ECDH-414", NULL, NULL, None);

+#endif

 }

 

 PubKeyEnum::~PubKeyEnum() {}

@@ -198,7 +225,8 @@
 /*

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

  */

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

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

+selectionPolicy(Standard){}

 

 ZrtpConfigure::~ZrtpConfigure() {}

 

diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketClearAck.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketClearAck.cpp
index 85f1484..5a96f52 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketClearAck.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketClearAck.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketCommit.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketCommit.cpp
index af4bb09..b582777 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketCommit.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketCommit.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketConf2Ack.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketConf2Ack.cpp
index f35dc82..67a51ee 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketConf2Ack.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketConf2Ack.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketConfirm.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketConfirm.cpp
index f558759..6f13cae 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketConfirm.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketConfirm.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -66,6 +66,17 @@
     return true;
 }
 
+bool ZrtpPacketConfirm::isSignatureLengthOk() {
+    int32_t actualLen = getLength();
+    int32_t expectedLen = 19;                  // Confirm packet fixed part is 19 ZRTP words
+    int32_t sigLen = getSignatureLength();
+
+    if (sigLen > 0) {                          // We have a signature
+        expectedLen += sigLen + 1;             // +1 for the signature length field
+    }
+    return (expectedLen == actualLen);
+}
+
 int32_t ZrtpPacketConfirm::getSignatureLength() {
     int32_t sl = confirmHeader->sigLength & 0xff;
     if (confirmHeader->filler[1] == 1) {                              // do we have a 9th bit
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketDHPart.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketDHPart.cpp
index 8c59233..1a89e16 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketDHPart.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketDHPart.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -59,6 +59,12 @@
     else if (*(int32_t*)pkt == *(int32_t*)ec38) {
         dhLength = 96;
     }
+    else if (*(int32_t*)pkt == *(int32_t*)e255) {
+        dhLength = 32;
+    }
+    else if (*(int32_t*)pkt == *(int32_t*)e414) {
+        dhLength = 104;
+    }
     else
         return;
 
@@ -74,18 +80,24 @@
 
     int16_t len = getLength();
     DEBUGOUT((fprintf(stdout, "DHPart length: %d\n", len)));
-    if (len == 85) {
+    if (len == 85) {         // Dh2k
         dhLength = 256;
     }
-    else if (len == 117) {
+    else if (len == 117) {   // Dh3k
         dhLength = 384;
     }
-    else if (len == 37) {
+    else if (len == 37) {    // EC256
         dhLength = 64;
     }
-    else if (len == 45) {
+    else if (len == 45) {    // EC384
         dhLength = 96;
     }
+    else if (len == 29) {    // E255
+        dhLength = 32;
+    }
+    else if (len == 47) {    // E414
+        dhLength = 104;
+    }
     else {
         pv = NULL;
         return;
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketError.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketError.cpp
index a9d881e..94d4dc1 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketError.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketError.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketErrorAck.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketErrorAck.cpp
index 3a30977..d0d0f33 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketErrorAck.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketErrorAck.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketHello.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketHello.cpp
index 6635fa3..bc885ef 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketHello.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketHello.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2012 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -19,6 +19,7 @@
  * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
  */
 
+#include <ctype.h>
 #include <libzrtpcpp/ZrtpPacketHello.h>
 
 
@@ -62,8 +63,6 @@
     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);
@@ -102,14 +101,25 @@
     zrtpHeader = (zrtpPacketHeader_t *)&((HelloPacket_t *)data)->hdr;	// the standard header
     helloHeader = (Hello_t *)&((HelloPacket_t *)data)->hello;
 
+    // Force the isLengthOk() check to fail when we process the packet.
+    if (getLength() < HELLO_FIXED_PART_LEN) {
+        computedLength = 0;
+        return;
+    }
+
     uint32_t t = *((uint32_t*)&helloHeader->flags);
     uint32_t temp = zrtpNtohl(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;
 
     // +2 : the MAC at the end of the packet
     computedLength = nHash + nCipher + nAuth + nPubkey + nSas + sizeof(HelloPacket_t)/ZRTP_WORD_SIZE + 2;
@@ -125,3 +135,14 @@
 ZrtpPacketHello::~ZrtpPacketHello() {
     DEBUGOUT((fprintf(stdout, "Deleting Hello packet: alloc: %x\n", allocated)));
 }
+
+int32_t ZrtpPacketHello::getVersionInt() {
+    uint8_t* vp = getVersion();
+    int32_t version = 0;
+
+    if (isdigit(*vp) && isdigit(*vp+2)) {
+        version = (*vp - '0') * 10;
+        version += *(vp+2) - '0';
+    }
+    return version;
+}
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketHelloAck.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketHelloAck.cpp
index 2d752b7..2849f2d 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketHelloAck.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketHelloAck.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketPing.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketPing.cpp
index 9a1f90f..b79e4ac 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketPing.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketPing.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2009 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -30,7 +30,7 @@
     setZrtpId();
     setLength((sizeof(PingPacket_t) / ZRTP_WORD_SIZE) - 1);
     setMessageType((uint8_t*)PingMsg);
-    setVersion((uint8_t*)zrtpVersion);
+    setVersion((uint8_t*)zrtpVersion_11);  // TODO: fix version string after clarification
 }
 
 ZrtpPacketPing::ZrtpPacketPing(uint8_t *data) {
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketPingAck.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketPingAck.cpp
index 2331640..0bee991 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketPingAck.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketPingAck.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2009 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -30,7 +30,7 @@
     setZrtpId();
     setLength((sizeof(PingAckPacket_t) / ZRTP_WORD_SIZE) - 1);
     setMessageType((uint8_t*)PingAckMsg);
-    setVersion((uint8_t*)zrtpVersion);
+    setVersion((uint8_t*)zrtpVersion_11);  // TODO: fix version string after clarification
 }
 
 ZrtpPacketPingAck::ZrtpPacketPingAck(uint8_t *data) {
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketRelayAck.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketRelayAck.cpp
index 6ff0c7a..a531e2f 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketRelayAck.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketRelayAck.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-20011 Werner Dittmann
+  Copyright (C) 2006-20013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpPacketSASrelay.cpp b/jni/libzrtp/sources/zrtp/ZrtpPacketSASrelay.cpp
index d132e28..c8b7f54 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpPacketSASrelay.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpPacketSASrelay.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/ZrtpQueue.cpp b/jni/libzrtp/sources/zrtp/ZrtpQueue.cpp
index 9e838da..fef847e 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpQueue.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpQueue.cpp
@@ -119,12 +119,15 @@
 void ZrtpQueue::startZrtp() {
     if (zrtpEngine != NULL) {
         zrtpEngine->startZrtpEngine();
+        zrtpUnprotect = 0;
         started = true;
     }
 }
 
 void ZrtpQueue::stopZrtp() {
     if (zrtpEngine != NULL) {
+        if (zrtpUnprotect < 50 && !zrtpEngine->isMultiStream())
+            zrtpEngine->setRs2Valid();
         delete zrtpEngine;
         zrtpEngine = NULL;
         started = false;
@@ -158,6 +161,10 @@
     // 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 (rtn < (int32)(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);
@@ -679,9 +686,9 @@
     clientIdString = id;
 }
 
-std::string ZrtpQueue::getHelloHash()  {
+std::string ZrtpQueue::getHelloHash(int32_t index)  {
     if (zrtpEngine != NULL)
-        return zrtpEngine->getHelloHash();
+        return zrtpEngine->getHelloHash(index);
     else
         return std::string();
 }
@@ -811,6 +818,21 @@
     return 0;
 }
 
+int32_t ZrtpQueue::getNumberSupportedVersions() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getNumberSupportedVersions();
+
+    return 0;
+}
+
+int32_t ZrtpQueue::getCurrentProtocolVersion() {
+    if (zrtpEngine != NULL)
+        return zrtpEngine->getCurrentProtocolVersion();
+
+    return 0;
+}
+
+
 IncomingZRTPPkt::IncomingZRTPPkt(const unsigned char* const block, size_t len) :
         IncomingRTPPkt(block,len) {
 }
diff --git a/jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp b/jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp
index a987032..a6756af 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpSdesStream.cpp
@@ -1,7 +1,28 @@
+/*
+  Copyright (C) 2012-2013 Werner Dittmann
+
+  This program 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 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 <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
+#include <string>
+#include <sstream>
+
 #include <libzrtpcpp/ZrtpSdesStream.h>
 #include <libzrtpcpp/ZrtpTextData.h>
 #include <libzrtpcpp/ZrtpConfigure.h>
@@ -11,17 +32,16 @@
 #include <srtp/CryptoContext.h>
 #include <srtp/CryptoContextCtrl.h>
 #include <cryptcommon/ZrtpRandom.h>
+#include <crypto/hmac384.h>
+
 
 #if defined(_WIN32) || defined(_WIN64)
 # define snprintf _snprintf
 #endif
 
-/*
- * These functions support 256 bit encryption algorithms.
- */
-#define MAX_KEY_LEN           32
-#define MAX_SALT_LEN          14
-
+// SRTP authentication tag length is 80 bits = 10 bytes
+#define ZRTP_TUNNEL_AUTH_LEN  10
+#define ZRTP_TUNNEL_LABEL     10
 /*
  * The ABNF grammar for the crypto attribute is defined below (from RFC 4568):
  *
@@ -85,6 +105,19 @@
 
 static const int minElementsKeyParam = 1;
 
+typedef struct _cryptoMix {
+    const char* name;
+    int32_t hashLength;
+    ZrtpSdesStream::sdesHmacTypeMix hashType;
+} cryptoMix;
+
+static const size_t MIX_HMAC_STRING_MIN_LEN = sizeof("HMAC-SHA-384");
+
+static cryptoMix knownMixAlgos[] = {
+    {"HMAC-SHA-384", 384, ZrtpSdesStream::MIX_HMAC_SHA},
+    {NULL, 0, ZrtpSdesStream::MIX_NONE}
+};
+
 typedef struct _suite {
     ZrtpSdesStream::sdesSuites suite;
     const char *name;
@@ -101,17 +134,18 @@
 /* NOTE: the b64len of a 128 bit suite is 40, a 256bit suite uses 64 characters */
 static suiteParam knownSuites[] = {
     {ZrtpSdesStream::AES_CM_128_HMAC_SHA1_32, "AES_CM_128_HMAC_SHA1_32", 128, 112, 160,
-     hs32, aes1, 40, (uint64_t)1<<48, 1<<31
+     hs32, "AES-128", 40, (uint64_t)1<<48, (uint64_t)1<<31
     },
     {ZrtpSdesStream::AES_CM_128_HMAC_SHA1_80, "AES_CM_128_HMAC_SHA1_80", 128, 112, 160,
-     hs80, aes1, 40, (uint64_t)1<<48, 1<<31
+     hs80, "AES-128", 40, (uint64_t)1<<48, (uint64_t)1<<31
     },
     {(ZrtpSdesStream::sdesSuites)0, NULL, 0, 0, 0, 0, 0, 0, 0, 0}
 };
 
 ZrtpSdesStream::ZrtpSdesStream(const sdesSuites s) :
     state(STREAM_INITALIZED), suite(s), recvSrtp(NULL), recvSrtcp(NULL), sendSrtp(NULL),
-    sendSrtcp(NULL), srtcpIndex(0) {
+    sendSrtcp(NULL), srtcpIndex(0), recvZrtpTunnel(0), sendZrtpTunnel(0), cryptoMixHashLength(0), 
+    cryptoMixHashType(MIX_NONE)  {
 }
 
 ZrtpSdesStream::~ZrtpSdesStream() {
@@ -130,6 +164,12 @@
 
     delete recvSrtcp;
     recvSrtp = NULL;
+
+    delete recvZrtpTunnel;
+    recvZrtpTunnel = NULL;
+
+    delete sendZrtpTunnel;
+    sendZrtpTunnel = NULL;
 }
 
 bool ZrtpSdesStream::createSdes(char *cryptoString, size_t *maxLen, bool sipInvite) {
@@ -152,13 +192,13 @@
         state = OUT_PROFILE_READY;
     }
     else {
+        createSrtpContexts(sipInvite);
         state = SDES_SRTP_ACTIVE;
     }
     return s;
-
 }
 
-bool ZrtpSdesStream::parseSdes(char *cryptoString, size_t length, bool sipInvite) {
+bool ZrtpSdesStream::parseSdes(const char *cryptoString, size_t length, bool sipInvite) {
 
     if (sipInvite) {
         if (state != OUT_PROFILE_READY)
@@ -179,6 +219,7 @@
         // Check if answerer used same tag and suite as the offerer
         if (tmpTag != tag || suite != tmpSuite)
             return false;
+        createSrtpContexts(sipInvite);
         state = SDES_SRTP_ACTIVE;
     }
     else {
@@ -217,6 +258,36 @@
     return rc;
 }
 
+
+bool ZrtpSdesStream::outgoingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength) {
+
+    if (state != SDES_SRTP_ACTIVE || sendZrtpTunnel == NULL) {
+        *newLength = length;
+        return true;
+    }
+    bool rc = SrtpHandler::protect(sendZrtpTunnel, packet, length, newLength);
+    if (rc)
+        ;//protect++;
+    return rc;
+}
+
+int ZrtpSdesStream::incomingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength) {
+    if (state != SDES_SRTP_ACTIVE || recvZrtpTunnel == NULL) {    // SRTP inactive, just return with newLength set
+        *newLength = length;
+        return 1;
+    }
+    int32_t rc = SrtpHandler::unprotect(recvZrtpTunnel, packet, length, newLength);
+    if (rc == 1) {
+//            unprotect++
+    }
+    else {
+//            unprotectFailed++;
+    }
+    return rc;
+}
+
+
+
 bool ZrtpSdesStream::outgoingRtcp(uint8_t *packet, size_t length, size_t *newLength) {
 #if 0
 SrtpHandler::protectCtrl(CryptoContextCtrl* pcc, uint8_t* buffer, size_t length, size_t* newLength, uint32_t *srtcpIndex)
@@ -235,8 +306,70 @@
     return knownSuites[suite].cipher;
 }
 
-const char* ZrtpSdesStream::getAuthAlgo(){
-    return knownSuites[suite].tagLength;
+const char* ZrtpSdesStream::getAuthAlgo() {
+    if (strcmp(knownSuites[suite].tagLength, hs80) == 0)
+        return "HMAC-SHA1 80 bit";
+    else
+        return "HMAC-SHA1 32 bit";
+}
+
+int ZrtpSdesStream::getCryptoMixAttribute(char *algoNames, size_t length) {
+
+    if (length < MIX_HMAC_STRING_MIN_LEN)
+        return 0;
+
+    // In case we support more than one MIX profile select the correct one if the
+    // application called setCryptoMixAttribute(...) and we already selected the one to use.
+    if (cryptoMixHashType != MIX_NONE) {
+        for (cryptoMix* cp = knownMixAlgos; cp->name != NULL; cp++) {
+            if (cp->hashLength == cryptoMixHashLength && cp->hashType == cryptoMixHashType) {
+                strcpy(algoNames, cp->name);
+                return strlen(cp->name);
+            }
+        }
+    }
+    // TODO: enhance here to support multiple algorithms (concatenate strings into the buffer until buffer full)
+    else {
+        strcpy(algoNames, knownMixAlgos[0].name);
+        return strlen(algoNames);
+    }
+    return 0;
+}
+
+bool ZrtpSdesStream::setCryptoMixAttribute(const char *algoNames) {
+
+    int len = strlen(algoNames);
+    if (len <= 0)
+        return false;
+
+    std::string algoIn(algoNames);
+    algoIn += ' ';
+
+    // split input name string and lookup if we support one of the offered algorithms
+    // We take the first match.
+    std::string delimiters = " ";
+    size_t current;
+    size_t next = -1;
+
+    do {
+        current = next + 1;
+        next = algoIn.find_first_of(delimiters, current);
+        if (next == std::string::npos)
+            break;
+
+        std::string tmps = algoIn.substr(current, next - current );
+        const char* nm = tmps.c_str();
+
+        for (cryptoMix* cp = knownMixAlgos; cp->name != NULL; cp++) {
+            if (strncmp(cp->name, nm, strlen(cp->name)) == 0) {
+                cryptoMixHashLength = cp->hashLength;
+                cryptoMixHashType = cp->hashType;
+                return true;
+            }
+        }
+    } while (true);
+
+    return false;
 }
 
 #ifdef WEAKRANDOM
@@ -284,15 +417,213 @@
     return codelength;
 }
 
+void* createSha384HmacContext(uint8_t* key, int32_t keyLength);
+void freeSha384HmacContext(void* ctx);
+void hmacSha384Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength );
+
+static int expand(uint8_t* prk, uint32_t prkLen, uint8_t* info, int32_t infoLen, int32_t L, uint32_t hashLen, uint8_t* outbuffer)
+{
+    int32_t n;
+    uint8_t *T;
+    void* hmacCtx;
+
+    const uint8_t* data[4];      // 3 data pointers for HMAC data plus terminating NULL
+    uint32_t dataLen[4];
+    int32_t dataIdx = 0;
+
+    uint8_t counter;
+    int32_t macLength;
+
+    if (prkLen < hashLen)
+        return -1;
+
+    n = (L + (hashLen-1)) / hashLen;
+
+    // T points to buffer that holds concatenated T(1) || T(2) || ... T(N))
+    T = reinterpret_cast<uint8_t*>(malloc(n * hashLen));
+
+    if (hashLen == 384/8)
+        hmacCtx = createSha384HmacContext(prk, prkLen);
+    else
+        return -1;
+
+    // Prepare first HMAC. T(0) has zero length, thus we ignore it in first run.
+    // After first run use its output (T(1)) as first data in next HMAC run.
+    for (int i = 1; i <= n; i++) {
+        if (infoLen > 0 && info != NULL) {
+            data[dataIdx] = info;
+            dataLen[dataIdx++] = infoLen;
+        }
+        counter = i & 0xff;
+        data[dataIdx] = &counter;
+        dataLen[dataIdx++] = 1;
+
+        data[dataIdx] = NULL;
+        dataLen[dataIdx++] = 0;
+
+        if (hashLen == 384/8)
+            hmacSha384Ctx(hmacCtx, data, dataLen, T + ((i-1) * hashLen), &macLength);
+
+        // Use output of previous hash run as first input of next hash run
+        dataIdx = 0;
+        data[dataIdx] = T + ((i-1) * hashLen);
+        dataLen[dataIdx++] = hashLen;
+    }
+    freeSha384HmacContext(hmacCtx);
+    memcpy(outbuffer, T, L);
+    free(T);
+    return 0;
+}
+
+void ZrtpSdesStream::computeMixedKeys(bool sipInvite) {
+    uint8_t salt[MAX_SALT_LEN*2];
+    uint8_t ikm[MAX_KEY_LEN*2];
+
+    // Concatenate the existing salt and key data. Depending on our role we have to change
+    // the order of the data.
+    if (sipInvite) {             // We are offerer, use local created data as mso and mko, so they go first
+        memcpy(salt, &localKeySalt[localKeyLenBytes], localSaltLenBytes);
+        memcpy(&salt[localSaltLenBytes], &remoteKeySalt[remoteKeyLenBytes], remoteSaltLenBytes);
+
+        memcpy(ikm, localKeySalt, localKeyLenBytes);
+        memcpy(&ikm[localKeyLenBytes], remoteKeySalt, remoteKeyLenBytes);
+    }
+    else {
+        memcpy(salt, &remoteKeySalt[remoteKeyLenBytes], remoteSaltLenBytes);
+        memcpy(&salt[remoteSaltLenBytes], &localKeySalt[localKeyLenBytes], localSaltLenBytes);
+
+        memcpy(ikm, remoteKeySalt, remoteKeyLenBytes);
+        memcpy(&ikm[remoteKeyLenBytes], localKeySalt, localKeyLenBytes);
+    }
+    uint32_t saltLen = localSaltLenBytes + remoteSaltLenBytes;
+    uint32_t keyLen = localKeyLenBytes + remoteKeyLenBytes;
+    uint32_t L = saltLen + keyLen;
+
+    uint8_t prk[MAX_DIGEST_LENGTH];
+    uint32_t prkLen;
+
+    switch(cryptoMixHashType) {
+        case MIX_HMAC_SHA:
+            if (cryptoMixHashLength == 384)
+                hmac_sha384(salt, saltLen, ikm, keyLen, prk, &prkLen);
+            else
+                return;
+            break;
+
+        case MIX_MAC_SKEIN:
+            return;
+
+        default:
+            return;
+    }
+
+    uint8_t T[(MAX_SALT_LEN + MAX_KEY_LEN)*2] = {0};
+    expand(prk, prkLen, NULL, 0, L, cryptoMixHashLength/8, T);
+
+    // We have a new set of SRTP key data now, replace the old with the new.
+    int32_t offset = 0;
+    if (sipInvite) {    // We are offerer, replace local created data with mso and mko, remote with msa, mka
+        memcpy(&localKeySalt[localKeyLenBytes], T, localSaltLenBytes);
+        offset += localSaltLenBytes;
+        memcpy(&remoteKeySalt[remoteKeyLenBytes], &T[offset], remoteSaltLenBytes);
+        offset += remoteSaltLenBytes;
+
+        memcpy(localKeySalt, &T[offset], localKeyLenBytes);
+        offset += localKeyLenBytes;
+        memcpy(remoteKeySalt, &T[offset], remoteKeyLenBytes);
+    }
+    else {            // We are answerer, replace remote data with mso and mko, local data with msa, mka
+        memcpy(&remoteKeySalt[remoteKeyLenBytes], T, remoteSaltLenBytes);
+        offset += remoteSaltLenBytes;
+        memcpy(&localKeySalt[localKeyLenBytes], &T[offset], localSaltLenBytes);
+        offset += localSaltLenBytes;
+
+        memcpy(remoteKeySalt, &T[offset], remoteKeyLenBytes);
+        offset += remoteKeyLenBytes;
+        memcpy(localKeySalt, &T[offset], localKeyLenBytes);
+    }
+}
+
+void ZrtpSdesStream::createSrtpContexts(bool sipInvite) {
+
+    if (cryptoMixHashType != MIX_NONE) {
+        computeMixedKeys(sipInvite);
+    }
+
+    sendSrtp = new CryptoContext(0,                     // SSRC (used for lookup)
+                                 0,                     // Roll-Over-Counter (ROC)
+                                 0L,                    // keyderivation << 48,
+                                 localCipher,                // encryption algo
+                                 localAuthn,                 // authtentication algo
+                                 localKeySalt,               // Master Key
+                                 localKeyLenBytes,           // Master Key length
+                                 &localKeySalt[localKeyLenBytes], // Master Salt
+                                 localSaltLenBytes,          // Master Salt length
+                                 localKeyLenBytes,           // encryption keylen
+                                 localAuthKeyLen,            // authentication key len (HMAC key lenght)
+                                 localSaltLenBytes,          // session salt len
+                                 localTagLength);            // authentication tag len
+    sendSrtp->deriveSrtpKeys(0L);
+
+    sendZrtpTunnel = new CryptoContext(0,                     // SSRC (used for lookup)
+                                 0,                     // Roll-Over-Counter (ROC)
+                                 0L,                    // keyderivation << 48,
+                                 localCipher,                // encryption algo
+                                 localAuthn,                 // authtentication algo
+                                 localKeySalt,               // Master Key
+                                 localKeyLenBytes,           // Master Key length
+                                 &localKeySalt[localKeyLenBytes], // Master Salt
+                                 localSaltLenBytes,          // Master Salt length
+                                 localKeyLenBytes,           // encryption keylen
+                                 localAuthKeyLen,            // authentication key len (HMAC key lenght)
+                                 localSaltLenBytes,          // session salt len
+                                 ZRTP_TUNNEL_AUTH_LEN);      // authentication tag len
+
+    sendZrtpTunnel->setLabelbase(ZRTP_TUNNEL_LABEL);
+    sendZrtpTunnel->deriveSrtpKeys(0L);
+    memset(localKeySalt, 0, sizeof(localKeySalt));
+
+    recvSrtp = new CryptoContext(0,                     // SSRC (used for lookup)
+                                 0,                     // Roll-Over-Counter (ROC)
+                                 0L,                    // keyderivation << 48,
+                                 remoteCipher,                // encryption algo
+                                 remoteAuthn,                 // authtentication algo
+                                 remoteKeySalt,               // Master Key
+                                 remoteKeyLenBytes,           // Master Key length
+                                 &remoteKeySalt[remoteKeyLenBytes], // Master Salt
+                                 remoteSaltLenBytes,          // Master Salt length
+                                 remoteKeyLenBytes,           // encryption keylen
+                                 remoteAuthKeyLen,            // authentication key len (HMAC key lenght)
+                                 remoteSaltLenBytes,          // session salt len
+                                 remoteTagLength);            // authentication tag len
+    recvSrtp->deriveSrtpKeys(0L);
+
+    recvZrtpTunnel = new CryptoContext(0,                     // SSRC (used for lookup)
+                                 0,                     // Roll-Over-Counter (ROC)
+                                 0L,                    // keyderivation << 48,
+                                 remoteCipher,                // encryption algo
+                                 remoteAuthn,                 // authtentication algo
+                                 remoteKeySalt,               // Master Key
+                                 remoteKeyLenBytes,           // Master Key length
+                                 &remoteKeySalt[remoteKeyLenBytes], // Master Salt
+                                 remoteSaltLenBytes,          // Master Salt length
+                                 remoteKeyLenBytes,           // encryption keylen
+                                 remoteAuthKeyLen,            // authentication key len (HMAC key lenght)
+                                 remoteSaltLenBytes,          // session salt len
+                                 ZRTP_TUNNEL_AUTH_LEN);       // authentication tag len
+
+    recvZrtpTunnel->setLabelbase(ZRTP_TUNNEL_LABEL);
+    recvZrtpTunnel->deriveSrtpKeys(0L);
+    memset(remoteKeySalt, 0, sizeof(remoteKeySalt));
+}
+
 bool ZrtpSdesStream::createSdesProfile(char *cryptoString, size_t *maxLen) {
 
-    uint8_t keySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4] = {0};  /* Some buffer for random data, multiple of 4 */
     char b64keySalt[(MAX_KEY_LEN + MAX_SALT_LEN) * 2] = {'\0'};
     uint32_t sidx;
     int32_t b64Len;
 
-    /* Lookup crypto suite parameters */
-    for (sidx = 0; knownSuites[sidx].name != NULL; sidx++) {
+    for (sidx = 0; knownSuites[sidx].name != NULL; sidx++) {  // Lookup crypto suite parameters
         if (knownSuites[sidx].suite == suite)
             break;
     }
@@ -300,45 +631,29 @@
         return false;
     }
     suiteParam *pSuite = &knownSuites[sidx];
-    _random(keySalt, sizeof(keySalt));
+    _random(localKeySalt, sizeof(localKeySalt));
 
     AlgorithmEnum& auth = zrtpAuthLengths.getByName(pSuite->tagLength);
-    int authn = SrtpAuthenticationSha1Hmac;
-    int authKeyLen = pSuite->authKeyLength / 8;
-    int tagLength = auth.getKeylen() / 8;
+    localAuthn = SrtpAuthenticationSha1Hmac;
+    localAuthKeyLen = pSuite->authKeyLength / 8;
+    localTagLength = auth.getKeylen() / 8;
 
     // If SDES will support other encryption algos - get it here based on
     // the algorithm name in suite
-    int cipher = SrtpEncryptionAESCM;
+    localCipher = SrtpEncryptionAESCM;
 
-    int keyLenBytes = pSuite->keyLength / 8;
-    int saltLenBytes = pSuite->saltLength / 8;
-
-    sendSrtp = new CryptoContext(0,                     // SSRC (used for lookup)
-                                 0,                     // Roll-Over-Counter (ROC)
-                                 0L,                    // keyderivation << 48,
-                                 cipher,                // encryption algo
-                                 authn,                 // authtentication algo
-                                 keySalt,               // Master Key
-                                 keyLenBytes,           // Master Key length
-                                 &keySalt[keyLenBytes], // Master Salt
-                                 saltLenBytes,          // Master Salt length
-                                 keyLenBytes,           // encryption keylen
-                                 authKeyLen,            // authentication key len (HMAC key lenght)
-                                 saltLenBytes,          // session salt len
-                                 tagLength);            // authentication tag len
-    sendSrtp->deriveSrtpKeys(0L);
+    localKeyLenBytes = pSuite->keyLength / 8;
+    localSaltLenBytes = pSuite->saltLength / 8;
 
     if (tag == -1)
         tag = 1;
 
-    /* Get B64 code for master key and master salt */
-    b64Len = b64Encode(keySalt, keyLenBytes + saltLenBytes, b64keySalt, sizeof(b64keySalt));
+    // Get B64 code for master key and master salt and then construct the SDES crypto string
+    b64Len = b64Encode(localKeySalt, localKeyLenBytes + localSaltLenBytes, b64keySalt, sizeof(b64keySalt));
     b64keySalt[b64Len] = '\0';
     memset(cryptoString, 0, *maxLen);
     *maxLen = snprintf(cryptoString, *maxLen-1, "%d %s inline:%s", tag, pSuite->name, b64keySalt);
 
-    memset(keySalt, 0, sizeof(keySalt));
     return true;
 }
 
@@ -346,7 +661,6 @@
     int elements,  i;
     int charsScanned;
     int mkiLength = 0;
-    uint8_t keySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4] = {0};
     uint32_t sidx;
 
     char cryptoString[MAX_CRYPT_STRING_LEN+1] = {'\0'};
@@ -362,28 +676,22 @@
         length = strlen(cryptoStr);
 
     if (length > MAX_CRYPT_STRING_LEN) {
-//        fprintf(stderr, "parseCreateSdesProfile() crypto string too long: %ld, maximum: %d\n", length, MAX_CRYPT_STRING_LEN);
         return false;
     }
-    /* make own copy, null terminated */
-    memcpy(cryptoString, cryptoStr, length);
+    memcpy(cryptoString, cryptoStr, length);   // make own copy, null terminated
 
     *outTag = -1;
     elements = sscanf(cryptoString, parseCrypto, outTag, suiteName, keyParams, &charsScanned);
 
-    /* Do we have enough elements in the string */
-    if (elements < minElementsCrypto) {
-//        fprintf(stderr, "parseCreateSdesProfile() to few elements in crypto string: %d, expected: %d\n", elements, minElementsCrypto);
+    if (elements < minElementsCrypto) {        // Do we have enough elements in the string
         return false;
     }
 
-    /* Lookup crypto suite */
-    for (sidx = 0; knownSuites[sidx].name != NULL; sidx++) {
+    for (sidx = 0; knownSuites[sidx].name != NULL; sidx++) {  // Lookup crypto suite
         if (!strcmp(knownSuites[sidx].name, suiteName))
             break;
     }
     if (sidx >= sizeof(knownSuites)/sizeof(struct _suite)) {
-//        fprintf(stderr, "parseCreateSdesProfile() unsupported crypto suite: %s\n", suiteName);
         return false;
     }
     suiteParam *pSuite = &knownSuites[sidx];
@@ -392,57 +700,30 @@
     /* Now scan the key parameters */
     elements = sscanf(keyParams, parseKeyParam, keySaltB64, lifetime, mkiVal, &mkiLength);
 
-    /* Currently only one we only accept key||salt B64 string, no other parameters */
-    if (elements != minElementsKeyParam) {
-//         fprintf(stderr, "parseCreateSdesProfile() wrong number of parameters in key parameters: %d, expected: %d\n",
-//                      elements, minElementsKeyParam);
+    if (elements != minElementsKeyParam) {     // Currently we only accept key||salt B64 string, no other parameters 
         return false;
     }
 
-    int keyLenBytes = pSuite->keyLength / 8;
-    int saltLenBytes = pSuite->saltLength / 8;
+    remoteKeyLenBytes = pSuite->keyLength / 8;
+    remoteSaltLenBytes = pSuite->saltLength / 8;
 
-    /* Check if key||salt B64 string hast the correct length */
-    if (strlen(keySaltB64) != pSuite->b64length) {
-//         fprintf(stderr, "parseCreateSdesProfile() B64 key||salt string length does not match: %ld, expected: %d\n",
-//                     strlen(keySaltB64), pSuite->b64length);
+    if (strlen(keySaltB64) != pSuite->b64length) {  // Check if key||salt B64 string hast the correct length
         return false;
     }
+    i = b64Decode(keySaltB64, pSuite->b64length, remoteKeySalt, remoteKeyLenBytes + remoteSaltLenBytes);
 
-    i = b64Decode(keySaltB64, pSuite->b64length, keySalt, keyLenBytes + saltLenBytes);
-
-    /* Did the B64 decode deliver enough data for key||salt */
-    if (i != (keyLenBytes + saltLenBytes)) {
-//         fprintf(stderr, "parseCreateSdesProfile() B64 key||salt binary data length does not match: %d, expected: %d\n",
-//                     i, keyLenBytes + saltLenBytes);
+    if (i != (remoteKeyLenBytes + remoteSaltLenBytes)) {  // Did the B64 decode delivered enough data for key||salt
         return false;
     }
 
     AlgorithmEnum& auth = zrtpAuthLengths.getByName(pSuite->tagLength);
-    int authn = SrtpAuthenticationSha1Hmac;
-    int authKeyLen = pSuite->authKeyLength / 8;
-    int tagLength = auth.getKeylen() / 8;
+    remoteAuthn = SrtpAuthenticationSha1Hmac;
+    remoteAuthKeyLen = pSuite->authKeyLength / 8;
+    remoteTagLength = auth.getKeylen() / 8;
 
     // If SDES will support other encryption algos - get it here based on
     // the algorithm name in suite
-    int cipher = SrtpEncryptionAESCM;
-
-    recvSrtp = new CryptoContext(0,                     // SSRC (used for lookup)
-                                 0,                     // Roll-Over-Counter (ROC)
-                                 0L,                    // keyderivation << 48,
-                                 cipher,                // encryption algo
-                                 authn,                 // authtentication algo
-                                 keySalt,               // Master Key
-                                 keyLenBytes,           // Master Key length
-                                 &keySalt[keyLenBytes], // Master Salt
-                                 saltLenBytes,          // Master Salt length
-                                 keyLenBytes,           // encryption keylen
-                                 authKeyLen,            // authentication key len (HMAC key lenght)
-                                 saltLenBytes,          // session salt len
-                                 tagLength);            // authentication tag len
-    recvSrtp->deriveSrtpKeys(0L);
-
-    memset(keySalt, 0, sizeof(keySalt));
+    remoteCipher = SrtpEncryptionAESCM;
 
     return true;
 }
\ No newline at end of file
diff --git a/jni/libzrtp/sources/zrtp/ZrtpStateClass.cpp b/jni/libzrtp/sources/zrtp/ZrtpStateClass.cpp
index 74dfb04..2c46a4f 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpStateClass.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpStateClass.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2008 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -46,14 +46,9 @@
 };
 
 
-ZrtpStateClass::ZrtpStateClass(ZRtp *p) {
-    parent = p;
-    secSubstate = Normal;
+ZrtpStateClass::ZrtpStateClass(ZRtp *p) : parent(p), commitPkt(NULL), multiStream(false), secSubstate(Normal), sentVersion(0) {
     engine = new ZrtpStates(states, numberOfStates, Initial);
 
-    commitPkt = NULL;
-    multiStream = false;
-
     // Set up timers according to ZRTP spec
     T1.start = 50;
     T1.maxResend = 20;
@@ -99,10 +94,10 @@
         if (!inState(WaitErrorAck)) {
             uint16_t totalLength = *(uint16_t*)(pkt+2);
             totalLength = zrtpNtohs(totalLength) * ZRTP_WORD_SIZE;
-            totalLength += 12 + sizeof(uint32_t);           // !2 bytes is fixed header, uint32_t is CRC
+            totalLength += 12 + sizeof(uint32_t);           // 12 bytes is fixed header, uint32_t is CRC
 
             if (totalLength != ev->length) {
-                fprintf(stderr, "Total length does not match received length: %d - %ld\n", totalLength, ev->length);
+                fprintf(stderr, "Total length does not match received length: %d - %ld\n", totalLength, (long int)(ev->length & 0xffff));
                 sendErrorPacket(MalformedPacket);
                 parent->synchLeave();
                 return;
@@ -128,7 +123,9 @@
         else if (first == 'p' && middle == ' ' && last == ' ') {
             ZrtpPacketPing ppkt(pkt);
             ZrtpPacketPingAck* ppktAck = parent->preparePingAck(&ppkt);
-            parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck));
+            if (ppktAck != NULL) {          // ACK only to valid PING packet, otherwise ignore it
+                parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck));
+            }
             parent->synchLeave();
             return;
         }
@@ -157,10 +154,11 @@
     DEBUGOUT((cout << "Checking for match in Initial.\n"));
 
     if (event->type == ZrtpInitial) {
-	ZrtpPacketHello* hello = parent->prepareHello();
+        ZrtpPacketHello* hello = parent->prepareHello();
+        sentVersion = hello->getVersionInt();
 
-	// remember packet for easy resend in case timer triggers
-	sentPacket = static_cast<ZrtpPacketBase *>(hello);
+        // remember packet for easy resend in case timer triggers
+        sentPacket = static_cast<ZrtpPacketBase *>(hello);
 
         if (!parent->sendPacketZRTP(sentPacket)) {
             sendFailed();                 // returns to state Initial
@@ -170,7 +168,7 @@
             timerFailed(SevereNoTimer);      // returns to state Initial
             return;
         }
-	nextState(Detect);
+        nextState(Detect);
     }
 }
 
@@ -238,6 +236,8 @@
          * - 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)
+         * 
+         * When we receive an HelloAck this also means that out partner accepted our protocol version.
          */
         if (first == 'h' && last =='k') {
             cancelTimer();
@@ -247,7 +247,8 @@
         }
         /*
          * Hello:
-         * - send HelloAck packet to acknowledge the received Hello packet 
+         * - send HelloAck packet to acknowledge the received Hello packet if versions match.
+         *   Otherweise negotiate ZRTP versions.
          * - 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.
@@ -256,7 +257,58 @@
          * - Don't clear sentPacket, points to Hello
          */
         if (first == 'h' && last ==' ') {
+            ZrtpPacketHello hpkt(pkt);
+
             cancelTimer();
+
+            /*
+             * Check and negotiate the ZRTP protocol version first.
+             *
+             * This selection mechanism relies on the fact that we sent the highest supported protocol version in
+             * the initial Hello packet with as stated in RFC6189, section 4.1.1
+             */
+            int32_t recvVersion = hpkt.getVersionInt();
+            if (recvVersion > sentVersion) {   // We don't support this version, stay in state with timer active
+                if (startTimer(&T1) <= 0) {
+                    timerFailed(SevereNoTimer);      // returns to state Initial
+                }
+                return;
+            }
+
+            /*
+             * The versions don't match. Start negotiating versions. This negotiation stays in the Detect state.
+             * Only if the received version matches our own sent version we start to send a HelloAck.
+             */
+            if (recvVersion != sentVersion) {
+                ZRtp::HelloPacketVersion* hpv = parent->helloPackets;
+
+                int32_t index;
+                for (index = 0; hpv->packet && hpv->packet != parent->currentHelloPacket; hpv++, index++)   // Find current sent Hello
+                    ;
+
+                for(; index >= 0 && hpv->version > recvVersion; hpv--, index--)   // find a supported version less-equal to received version
+                    ;
+
+                if (index < 0) {
+                    sendErrorPacket(UnsuppZRTPVersion);
+                    return;
+                }
+                parent->currentHelloPacket = hpv->packet;
+                sentVersion = parent->currentHelloPacket->getVersionInt();
+
+                // remember packet for easy resend in case timer triggers
+                sentPacket = static_cast<ZrtpPacketBase *>(parent->currentHelloPacket);
+
+                if (!parent->sendPacketZRTP(sentPacket)) {
+                    sendFailed();                 // returns to state Initial
+                    return;
+                }
+                if (startTimer(&T1) <= 0) {
+                    timerFailed(SevereNoTimer);      // returns to state Initial
+                    return;
+                }
+                return;
+            }
             ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck();
 
             if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
@@ -265,7 +317,6 @@
             }
             // 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);
@@ -292,7 +343,7 @@
             nextState(Detect);
         }
     }
-    // If application call zrtpStart() to restart discovery
+    // If application calls zrtpStart() to restart discovery
     else if (event->type == ZrtpInitial) {
         cancelTimer();
         if (!parent->sendPacketZRTP(sentPacket)) {
@@ -360,36 +411,36 @@
      */
     if (event->type == ZrtpPacket) {
         pkt = event->packet;
-	msg = (char *)pkt + 4;
+        msg = (char *)pkt + 4;
 
-	first = tolower(*msg);
-	last = tolower(*(msg+7));
+        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();
+         * - 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);
+            nextState(CommitSent);
             if (!parent->sendPacketZRTP(sentPacket)) {
                 sendFailed();             // returns to state Initial
                 return;
             }
             if (startTimer(&T2) <= 0) {
                 timerFailed(SevereNoTimer);  // returns to state Initial
-	    }
-	    return;
+            }
+            return;
         }
         /*
          * Hello:
@@ -421,7 +472,7 @@
          * - switch to state WaitDHPart2 and wait for peer's DHPart2
          * - don't start timer, we are responder
          */
-        if (first == 'c') {
+        if (first == 'c' && last == ' ') {
             cancelTimer();
             ZrtpPacketCommit cpkt(pkt);
 
@@ -459,7 +510,7 @@
     }
     /*
      * Timer:
-     * - resend Hello packet, stay in state, restart timer until repeat 
+     * - 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
@@ -561,7 +612,7 @@
          * - Initiator role, thus start timer T2 to monitor timeout for Commit
          */
 
-        if (first == 'h') {
+        if (first == 'h' && last == ' ') {
             // Parse peer's packet data into a Hello packet
             ZrtpPacketHello hpkt(pkt);
             ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode);
@@ -611,7 +662,7 @@
 
     DEBUGOUT((cout << "Checking for match in WaitCommit.\n"));
 
-    char *msg, first;
+    char *msg, first, last;
     uint8_t *pkt;
     uint32_t errorCode = 0;
 
@@ -620,12 +671,13 @@
         msg = (char *)pkt + 4;
 
         first = tolower(*msg);
+        last = tolower(*(msg+7));
         /*
          * Hello:
          * - resend HelloAck
          * - stay in WaitCommit
          */
-        if (first == 'h') {
+        if (first == 'h' && last == ' ') {
             if (!parent->sendPacketZRTP(sentPacket)) {
                 sendFailed();       // returns to state Initial
             }
@@ -638,7 +690,7 @@
          * - switch state to WaitDHPart2 or WaitConfirm2 if multi stream mode
          * - don't start timer, we are responder
          */
-        if (first == 'c') {
+        if (first == 'c' && last == ' ') {
             ZrtpPacketCommit cpkt(pkt);
 
             if (!multiStream) {
@@ -706,7 +758,7 @@
 
     DEBUGOUT((cout << "Checking for match in CommitSend.\n"));
 
-    char *msg, first, last;
+    char *msg, first, middle, last, secondLast;
     uint8_t *pkt;
     uint32_t errorCode = 0;
 
@@ -715,7 +767,9 @@
         msg = (char *)pkt + 4;
 
         first = tolower(*msg);
+        middle = tolower(*(msg+4));
         last = tolower(*(msg+7));
+        secondLast = tolower(*(msg+6));
 
         /*
          * HelloAck or Hello:
@@ -723,7 +777,7 @@
          *   ignore it
          * - no switch in state, leave timer as it is
          */
-        if (first == 'h' && (last =='k' || last == ' ')) {
+        if (first == 'h' && middle == 'o' && (last =='k' || last == ' ')) {
             return;
         }
 
@@ -748,6 +802,11 @@
             }
             cancelTimer();         // this cancels the Commit timer T2
 
+            if (!zpCo.isLengthOk(multiStream ? ZrtpPacketCommit::MultiStream : ZrtpPacketCommit::DhExchange)) {
+                sendErrorPacket(CriticalSWError);
+                return;
+            }
+
             // 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
@@ -800,7 +859,7 @@
          * - switch to WaitConfirm1
          * - start timer to resend DHPart2 if necessary, we are Initiator
          */
-        if (first == 'd') {
+        if (first == 'd' && secondLast == '1') {
             cancelTimer();
             sentPacket = NULL;
             ZrtpPacketDHPart dpkt(pkt);
@@ -832,6 +891,11 @@
             return;
         }
 
+        /*
+         * Confirm1 and multi-stream mode
+         * - switch off resending commit
+         * - prepare Confirm2
+         */
         if (multiStream && (first == 'c' && last == '1')) {
             cancelTimer();
             ZrtpPacketConfirm cpkt(pkt);
@@ -902,7 +966,7 @@
 
     DEBUGOUT((cout << "Checking for match in DHPart2.\n"));
 
-    char *msg, first;
+    char *msg, first, secondLast, last;
     uint8_t *pkt;
     uint32_t errorCode = 0;
 
@@ -911,12 +975,14 @@
         msg = (char *)pkt + 4;
 
         first = tolower(*msg);
+        last = tolower(*(msg+7));
+        secondLast = tolower(*(msg+6));
         /*
          * Commit:
          * - resend DHPart1
          * - stay in state
          */
-        if (first == 'c') {
+        if (first == 'c' && last == ' ') {
             if (!parent->sendPacketZRTP(sentPacket)) {
                 return sendFailed();       // returns to state Initial
             }
@@ -928,7 +994,7 @@
          * - switch to WaitConfirm2
          * - No timer, we are responder
          */
-        if (first == 'd') {
+        if (first == 'd' && secondLast == '2') {
             ZrtpPacketDHPart dpkt(pkt);
             ZrtpPacketConfirm* confirm = parent->prepareConfirm1(&dpkt, &errorCode);
 
@@ -1069,7 +1135,7 @@
 
     DEBUGOUT((cout << "Checking for match in WaitConfirm2.\n"));
 
-    char *msg, first, last;
+    char *msg, first, secondLast, last;
     uint8_t *pkt;
     uint32_t errorCode = 0;
 
@@ -1078,6 +1144,7 @@
         msg = (char *)pkt + 4;
 
         first = tolower(*msg);
+        secondLast = tolower(*(msg+6));
         last = tolower(*(msg+7));
 
         /*
@@ -1085,7 +1152,7 @@
          * - resend Confirm1 packet
          * - stay in state
          */
-        if (first == 'd' || (multiStream && (first == 'c' && last == ' '))) {
+        if ((first == 'd' && secondLast == '2') || (multiStream && (first == 'c' && last == ' '))) {
             if (!parent->sendPacketZRTP(sentPacket)) {
                 sendFailed();             // returns to state Initial
             }
@@ -1151,7 +1218,7 @@
 
     DEBUGOUT((cout << "Checking for match in WaitConfAck.\n"));
 
-    char *msg, first;
+    char *msg, first, last;
     uint8_t *pkt;
 
     if (event->type == ZrtpPacket) {
@@ -1159,12 +1226,13 @@
         msg = (char *)pkt + 4;
 
         first = tolower(*msg);
+        last = tolower(*(msg+7));
          /*
          * ConfAck:
          * - Switch off resending Confirm2
          * - switch to SecureState
          */
-        if (first == 'c') {
+        if (first == 'c' && last == 'k') {
             cancelTimer();
             sentPacket = NULL;
             // Receiver was already enabled after sending Confirm2 packet
@@ -1208,44 +1276,45 @@
 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);
-    }
+//     char *msg, first, last, middle;
+//     uint8_t *pkt;
+// 
+//     if (event->type == ZrtpPacket) {
+// 	pkt = event->packet;
+// 	msg = (char *)pkt + 4;
+// 
+// 	first = tolower(*msg);
+//     middle = tolower(*(msg+4));
+// 	last = tolower(*(msg+7));
+// 
+// 	/*
+// 	 * ClearAck:
+// 	 * - stop resending GoClear,
+// 	 * - switch to state AckDetected, wait for peer's Hello
+// 	 */
+// 	if (first == 'c' && middle == 'r' && 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);
+//     }
 }
 
 
@@ -1349,7 +1418,7 @@
         }
         /*
          * GoClear received, handle it. TODO fix go clear handling
-         */
+         *
         if (first == 'g' && last == 'r') {
             ZrtpPacketGoClear gpkt(pkt);
             ZrtpPacketClearAck* clearAck = parent->prepareClearAck(&gpkt);
@@ -1359,12 +1428,18 @@
             }
         // TODO Timeout to resend clear ack until user user confirmation
         }
+        */
     }
     else if (event->type == Timer) {
         // Ignore stray timeout in this state
         ;
     }
-    else  {  // unknown Event type for this state (covers Error and ZrtpClose)
+    // unknown Event type for this state (covers Error and ZrtpClose)
+    else  {
+        // If in secure state ingnore error events to avoid Error packet injection
+        // attack - found by Dmitry Monakhov (dmonakhov@openvz.org)
+        if (event->type == ErrorPkt)
+            return;
         sentPacket = NULL;
         parent->srtpSecretsOff(ForSender);
         parent->srtpSecretsOff(ForReceiver);
diff --git a/jni/libzrtp/sources/zrtp/ZrtpTextData.cpp b/jni/libzrtp/sources/zrtp/ZrtpTextData.cpp
index 93e2ccf..ecf5b6d 100644
--- a/jni/libzrtp/sources/zrtp/ZrtpTextData.cpp
+++ b/jni/libzrtp/sources/zrtp/ZrtpTextData.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2008 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -22,8 +22,9 @@
 #include <libzrtpcpp/ZrtpConfigure.h>
 //                             1
 //                    1234567890123456
-char clientId[] =    "GNU ZRTP 3.0.0  "; // 16 chars max.
-char zrtpVersion[] = "1.10";             // must be 4 chars
+char clientId[] =    "GNU ZRTP 4.1.1  "; // 16 chars max.
+char zrtpVersion_11[] = "1.10";          // must be 4 chars
+char zrtpVersion_12[] = "1.20";          // must be 4 chars
 /**
  *
  */
@@ -69,6 +70,8 @@
 
 char s256[] = "S256";
 char s384[] = "S384";
+char skn2[] = "SKN2";
+char skn3[] = "SKN3";
 const char* mandatoryHash = s256;
 
 char aes3[] = "AES3";
@@ -83,6 +86,8 @@
 char ec25[] = "EC25";
 char dh3k[] = "DH3k";
 char ec38[] = "EC38";
+char e255[] = "E255";
+char e414[] = "E414";
 char mult[] = "Mult";
 const char* mandatoryPubKey = dh3k;
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp b/jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp
index 43a3306..f3042f8 100644
--- a/jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/aesCFB.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2012 by Werner Dittmann
+  Copyright (C) 2012-2013 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
@@ -29,8 +29,7 @@
  * files in the program, then also delete it here.
  */
 
-/** Copyright (C) 2012
- *
+/**
  * @author  Werner Dittmann <Werner.Dittmann@t-online.de>
  */
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/aesCFB.h b/jni/libzrtp/sources/zrtp/crypto/aesCFB.h
index b121893..7223bdf 100644
--- a/jni/libzrtp/sources/zrtp/crypto/aesCFB.h
+++ b/jni/libzrtp/sources/zrtp/crypto/aesCFB.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/InitializeGcrypt.cpp b/jni/libzrtp/sources/zrtp/crypto/gcrypt/InitializeGcrypt.cpp
index cb17b8f..1c743d2 100644
--- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/InitializeGcrypt.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/gcrypt/InitializeGcrypt.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptAesCFB.cpp b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptAesCFB.cpp
index 19acb6e..066035f 100644
--- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptAesCFB.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptAesCFB.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptZrtpDH.cpp b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptZrtpDH.cpp
index 0b6e213..bc8897a 100644
--- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptZrtpDH.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptZrtpDH.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006, 2009 Werner Dittmann
+  Copyright (C) 2006, 2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac256.cpp b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac256.cpp
index a53a674..a0ecc65 100644
--- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac256.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcrypthmac256.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha256.cpp b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha256.cpp
index 1015c44..b20bfe6 100644
--- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha256.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha256.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha384.cpp b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha384.cpp
index c7d7c57..c26a23c 100644
--- a/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha384.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/gcrypt/gcryptsha384.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/hmac256.cpp b/jni/libzrtp/sources/zrtp/crypto/hmac256.cpp
index 955c40b..1e3ceb7 100644
--- a/jni/libzrtp/sources/zrtp/crypto/hmac256.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/hmac256.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2012 Werner Dittmann
+  Copyright (C) 2012-2013 Werner Dittmann
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -124,7 +124,7 @@
     hmacSha256Init(&ctx, key, keyLength);
     hmacSha256Update(&ctx, data, dataLength);
     hmacSha256Final(&ctx, mac);
-    *macLength = SHA256_BLOCK_SIZE;
+    *macLength = SHA256_DIGEST_SIZE;
 }
 
 void hmac_sha256(uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunckLength[],
@@ -140,7 +140,7 @@
         dataChunckLength ++;
     }
     hmacSha256Final(&ctx, mac);
-    *macLength = SHA256_BLOCK_SIZE;
+    *macLength = SHA256_DIGEST_SIZE;
 }
 
 void* createSha256HmacContext(uint8_t* key, int32_t keyLength)
@@ -159,7 +159,7 @@
     hmacSha256Reset(pctx);
     hmacSha256Update(pctx, data, dataLength);
     hmacSha256Final(pctx, mac);
-    *macLength = SHA256_BLOCK_SIZE;
+    *macLength = SHA256_DIGEST_SIZE;
 }
 
 void hmacSha256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[],
@@ -174,7 +174,7 @@
         dataLength++;
     }
     hmacSha256Final(pctx, mac);
-    *macLength = SHA256_BLOCK_SIZE;
+    *macLength = SHA256_DIGEST_SIZE;
 }
 
 void freeSha256HmacContext(void* ctx)
diff --git a/jni/libzrtp/sources/zrtp/crypto/hmac384.cpp b/jni/libzrtp/sources/zrtp/crypto/hmac384.cpp
index 40b4487..c7a7abd 100644
--- a/jni/libzrtp/sources/zrtp/crypto/hmac384.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/hmac384.cpp
@@ -124,7 +124,7 @@
     hmacSha384Init(&ctx, key, keyLength);
     hmacSha384Update(&ctx, data, dataLength);
     hmacSha384Final(&ctx, mac);
-    *macLength = SHA384_BLOCK_SIZE;
+    *macLength = SHA384_DIGEST_SIZE;
 }
 
 void hmac_sha384( uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunckLength[],
@@ -140,7 +140,7 @@
         dataChunckLength ++;
     }
     hmacSha384Final(&ctx, mac);
-    *macLength = SHA384_BLOCK_SIZE;
+    *macLength = SHA384_DIGEST_SIZE;
 }
 
 void* createSha384HmacContext(uint8_t* key, int32_t keyLength)
@@ -159,7 +159,7 @@
     hmacSha384Reset(pctx);
     hmacSha384Update(pctx, data, dataLength);
     hmacSha384Final(pctx, mac);
-    *macLength = SHA384_BLOCK_SIZE;
+    *macLength = SHA384_DIGEST_SIZE;
 }
 
 void hmacSha384Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[],
@@ -174,7 +174,7 @@
         dataLength++;
     }
     hmacSha384Final(pctx, mac);
-    *macLength = SHA384_BLOCK_SIZE;
+    *macLength = SHA384_DIGEST_SIZE;
 }
 
 void freeSha384HmacContext(void* ctx)
diff --git a/jni/libzrtp/sources/zrtp/crypto/openssl/InitializeOpenSSL.cpp b/jni/libzrtp/sources/zrtp/crypto/openssl/InitializeOpenSSL.cpp
index 17961c3..2c5c8de 100755
--- a/jni/libzrtp/sources/zrtp/crypto/openssl/InitializeOpenSSL.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/openssl/InitializeOpenSSL.cpp
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.
 
@@ -18,19 +18,16 @@
 
 #include <stdio.h>
 #include <openssl/evp.h>
-#include <libzrtpcpp-config.h>
+#include <config.h>
 
-#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
-#undef  _MSWINDOWS_
-#define _MSWINDOWS_
+#ifdef _MSWINDOWS_
 #include <windows.h>
 #endif
-
 #if defined SOLARIS && !defined HAVE_PTHREAD_H
 #include <synch.h>
 #include <thread.h>
 #endif
-#if !defined(_MSWINDOWS_) && !defined SOLARIS
+#if !defined _MSWINDOWS_ && !defined SOLARIS
 #include <pthread.h>
 #endif
 
@@ -74,7 +71,6 @@
 }
 
 #ifdef _MSWINDOWS_
-#define __LOCKING
 
 static HANDLE *lock_cs;
 
@@ -112,8 +108,7 @@
 #endif /* OPENSSL_SYS_WIN32 */
 
 
-#if defined SOLARIS && !defined HAVE_PTHREAD_H && !defined(_MSWINDOWS)
-#define __LOCKING
+#if defined SOLARIS && !defined HAVE_PTHREAD_H
 
 static mutex_t *lock_cs;
 static long *lock_count;
@@ -180,7 +175,6 @@
 #endif /* SOLARIS */
 
 
-#ifndef __LOCKING
 static pthread_mutex_t* lock_cs;
 static long* lock_count;
 
@@ -239,4 +233,4 @@
     return(ret);
 }
 */
-#endif
+
diff --git a/jni/libzrtp/sources/zrtp/crypto/sha2.c b/jni/libzrtp/sources/zrtp/crypto/sha2.c
index fccd1d2..22761f3 100644
--- a/jni/libzrtp/sources/zrtp/crypto/sha2.c
+++ b/jni/libzrtp/sources/zrtp/crypto/sha2.c
@@ -754,7 +754,7 @@
     }
 }
 
-INT_RETURN sha2(unsigned char hval[], unsigned long size,
+INT_RETURN sha2_all(unsigned char hval[], unsigned long size,
                                 const unsigned char data[], unsigned long len)
 {   sha2_ctx    cx[1];
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/sha2.h b/jni/libzrtp/sources/zrtp/crypto/sha2.h
index 91d0745..1ad3889 100644
--- a/jni/libzrtp/sources/zrtp/crypto/sha2.h
+++ b/jni/libzrtp/sources/zrtp/crypto/sha2.h
@@ -140,7 +140,7 @@
 INT_RETURN  sha2_begin(unsigned long size, sha2_ctx ctx[1]);
 VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]);
 VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]);
-INT_RETURN  sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len);
+INT_RETURN  sha2_all(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len);
 
 #endif
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/sha256.h b/jni/libzrtp/sources/zrtp/crypto/sha256.h
index 959a620..36127b9 100644
--- a/jni/libzrtp/sources/zrtp/crypto/sha256.h
+++ b/jni/libzrtp/sources/zrtp/crypto/sha256.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/sha384.h b/jni/libzrtp/sources/zrtp/crypto/sha384.h
index 6cb7a70..d4ccce5 100644
--- a/jni/libzrtp/sources/zrtp/crypto/sha384.h
+++ b/jni/libzrtp/sources/zrtp/crypto/sha384.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/skein256.cpp b/jni/libzrtp/sources/zrtp/crypto/skein256.cpp
new file mode 100644
index 0000000..94cff63
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skein256.cpp
@@ -0,0 +1,100 @@
+/*
+  Copyright (C) 2013 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.
+ */
+
+/**
+ * @author: Werner Dittmann
+ */
+
+#include <cryptcommon/skeinApi.h>
+#include <zrtp/crypto/skein256.h>
+
+#include <stdlib.h>
+
+void skein256(unsigned char *data, unsigned int dataLength, unsigned char *digest )
+{
+    SkeinCtx_t ctx;
+
+    skeinCtxPrepare(&ctx, SKEIN_SIZE);
+    skeinInit(&ctx, SKEIN256_DIGEST_LENGTH*8);
+    skeinUpdate(&ctx, data, dataLength);
+
+    skeinFinal(&ctx, digest);
+}
+
+void skein256(unsigned char *dataChunks[], unsigned int dataChunckLength[], unsigned char *digest)
+{
+    SkeinCtx_t ctx;
+
+    skeinCtxPrepare(&ctx, SKEIN_SIZE);
+    skeinInit(&ctx, SKEIN256_DIGEST_LENGTH*8);
+    while(*dataChunks) {
+        skeinUpdate(&ctx, *dataChunks, *dataChunckLength);
+        dataChunks++;
+        dataChunckLength++;
+    }
+    skeinFinal(&ctx, digest);
+}
+
+void* createSkein256Context()
+{
+    SkeinCtx_t *ctx = reinterpret_cast<SkeinCtx_t *>(malloc(sizeof(SkeinCtx_t )));
+    skeinCtxPrepare(ctx, SKEIN_SIZE);
+    skeinInit(ctx, SKEIN256_DIGEST_LENGTH*8);
+    return (void*)ctx;
+}
+
+void closeSkein256Context(void* ctx, unsigned char* digest)
+{
+    SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx);
+
+    if (digest != NULL) {
+        skeinFinal(hd, digest);
+    }
+    free(hd);
+}
+
+void skein256Ctx(void* ctx, unsigned char* data, unsigned int dataLength)
+{
+    SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx);
+
+    skeinUpdate(hd, data, dataLength);
+}
+
+void skein256Ctx(void* ctx, unsigned char* dataChunks[], unsigned int dataChunkLength[])
+{
+    SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx);
+
+    while (*dataChunks) {
+        skeinUpdate(hd, *dataChunks, *dataChunkLength);
+        dataChunks++;
+        dataChunkLength++;
+    }
+}
diff --git a/jni/libzrtp/sources/zrtp/crypto/skein256.h b/jni/libzrtp/sources/zrtp/crypto/skein256.h
new file mode 100644
index 0000000..6d4e722
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skein256.h
@@ -0,0 +1,146 @@
+/*
+  Copyright (C) 2013 Werner Dittmann
+
+  This program 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 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 Skein256 digest.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _SKEIN256_H
+#define _SKEIN256_H
+
+/**
+ * @file skein256.h
+ * @brief Functions that provide Skein256 support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SKEIN256_DIGEST_LENGTH
+#define SKEIN256_DIGEST_LENGTH  32
+#endif
+#define SKEIN_SIZE Skein512
+
+
+/**
+ * Compute Skein256 digest.
+ *
+ * This functions takes one data chunk and computes its Skein256 digest. This 
+ * function creates and deletes an own Skein256 context to perform the Skein256
+ * 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 (Skein256_DIGEST_LENGTH).
+ */
+void skein256(unsigned char *data,
+            unsigned int data_length,
+            unsigned char *digest);
+
+/**
+ * Compute Skein256 digest over several data cunks.
+ *
+ * This functions takes several data chunks and computes the Skein256 digest.
+ * This function creates and deletes an own Skein256 context to perform the
+ * Skein256 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 (Skein256_DIGEST_LENGTH).
+ */
+void skein256(unsigned char *data[],
+            unsigned int data_length[],
+            unsigned char *digest);
+/**
+ * Create and initialize a Skein256 context.
+ *
+ * An application uses this context to hash several data into one Skein256
+ * digest. See also skein256Ctx(...) and closeSha256Context(...).
+ *
+ * @return Returns a pointer to the initialized Skein256 context
+ */
+void* createSkein256Context();
+
+/**
+ * Compute a digest and close the SHa256 digest.
+ *
+ * An application uses this function to compute the Skein256 digest and to
+ * close the Skein256 context.
+ *
+ * @param ctx
+ *    Points to the Skein256 context.
+ * @param digest
+ *    If this pointer is not NULL then it must point to a byte array that
+ *    is big enough to hold the Skein256 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 closeSkein256Context(void* ctx,
+                        unsigned char* digest);
+
+/**
+ * Update the Skein256 context with data.
+ *
+ * This functions updates the Skein256 context with some data.
+ * See also CloseSha256Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the Skein256 context.
+ * @param data
+ *    Points to the data to update the context.
+ * @param dataLength
+ *    The length of the data in bytes.
+ */
+void skein256Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength);
+
+/**
+ * Update the Skein256 context with several data chunks.
+ *
+ * This functions updates the Skein256 context with some data.
+ * See also CloseSha256Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the Skein256 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 skein256Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[]);
+
+/**
+ * @}
+ */
+#endif
+
diff --git a/jni/libzrtp/sources/zrtp/crypto/skein384.cpp b/jni/libzrtp/sources/zrtp/crypto/skein384.cpp
new file mode 100644
index 0000000..1dbe608
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skein384.cpp
@@ -0,0 +1,103 @@
+/*
+  Copyright (C) 2013 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.
+ */
+
+/**
+ * @author: Werner Dittmann
+ */
+
+#include <cryptcommon/skeinApi.h>
+#include <zrtp/crypto/skein384.h>
+
+#include <stdlib.h>
+
+#define SKEIN_SIZE Skein512
+#define SKEIN384_DIGEST_LENGTH  48
+
+void skein384(unsigned char *data, unsigned int dataLength, unsigned char *digest )
+{
+    SkeinCtx_t ctx;
+
+    skeinCtxPrepare(&ctx, SKEIN_SIZE);
+    skeinInit(&ctx, SKEIN384_DIGEST_LENGTH*8);
+    skeinUpdate(&ctx, data, dataLength);
+
+    skeinFinal(&ctx, digest);
+}
+
+void skein384(unsigned char *dataChunks[], unsigned int dataChunckLength[], unsigned char *digest)
+{
+    SkeinCtx_t ctx;
+
+    skeinCtxPrepare(&ctx, SKEIN_SIZE);
+    skeinInit(&ctx, SKEIN384_DIGEST_LENGTH*8);
+    while(*dataChunks) {
+        skeinUpdate(&ctx, *dataChunks, *dataChunckLength);
+        dataChunks++;
+        dataChunckLength++;
+    }
+    skeinFinal(&ctx, digest);
+}
+
+void* createSkein384Context()
+{
+    SkeinCtx_t *ctx = reinterpret_cast<SkeinCtx_t *>(malloc(sizeof(SkeinCtx_t )));
+    skeinCtxPrepare(ctx, SKEIN_SIZE);
+    skeinInit(ctx, SKEIN384_DIGEST_LENGTH*8);
+    return (void*)ctx;
+}
+
+void closeSkein384Context(void* ctx, unsigned char* digest)
+{
+    SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx);
+
+    if (digest != NULL) {
+        skeinFinal(hd, digest);
+    }
+    free(hd);
+}
+
+void skein384Ctx(void* ctx, unsigned char* data, unsigned int dataLength)
+{
+    SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx);
+
+    skeinUpdate(hd, data, dataLength);
+}
+
+void skein384Ctx(void* ctx, unsigned char* dataChunks[], unsigned int dataChunkLength[])
+{
+    SkeinCtx_t* hd = reinterpret_cast<SkeinCtx_t*>(ctx);
+
+    while (*dataChunks) {
+        skeinUpdate(hd, *dataChunks, *dataChunkLength);
+        dataChunks++;
+        dataChunkLength++;
+    }
+}
diff --git a/jni/libzrtp/sources/zrtp/crypto/skein384.h b/jni/libzrtp/sources/zrtp/crypto/skein384.h
new file mode 100644
index 0000000..61fd64e
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skein384.h
@@ -0,0 +1,146 @@
+/*
+  Copyright (C) 2013 Werner Dittmann
+
+  This program 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 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 Skein384 digest.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _SKEIN384_H
+#define _SKEIN384_H
+
+/**
+ * @file skein384.h
+ * @brief Functions that provide Skein384 support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SKEIN384_DIGEST_LENGTH
+#define SKEIN384_DIGEST_LENGTH  48
+#endif
+#define SKEIN_SIZE Skein512
+
+
+/**
+ * Compute Skein384 digest.
+ *
+ * This functions takes one data chunk and computes its Skein384 digest. This 
+ * function creates and deletes an own Skein384 context to perform the Skein384
+ * 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 (Skein384_DIGEST_LENGTH).
+ */
+void skein384(unsigned char *data,
+            unsigned int data_length,
+            unsigned char *digest);
+
+/**
+ * Compute Skein384 digest over several data cunks.
+ *
+ * This functions takes several data chunks and computes the Skein384 digest.
+ * This function creates and deletes an own Skein384 context to perform the
+ * Skein384 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 (Skein384_DIGEST_LENGTH).
+ */
+void skein384(unsigned char *data[],
+            unsigned int data_length[],
+            unsigned char *digest);
+/**
+ * Create and initialize a Skein384 context.
+ *
+ * An application uses this context to hash several data into one Skein384
+ * digest. See also skein384Ctx(...) and closeSha384Context(...).
+ *
+ * @return Returns a pointer to the initialized Skein384 context
+ */
+void* createSkein384Context();
+
+/**
+ * Compute a digest and close the SHa384 digest.
+ *
+ * An application uses this function to compute the Skein384 digest and to
+ * close the Skein384 context.
+ *
+ * @param ctx
+ *    Points to the Skein384 context.
+ * @param digest
+ *    If this pointer is not NULL then it must point to a byte array that
+ *    is big enough to hold the Skein384 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 closeSkein384Context(void* ctx,
+                        unsigned char* digest);
+
+/**
+ * Update the Skein384 context with data.
+ *
+ * This functions updates the Skein384 context with some data.
+ * See also CloseSha384Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the Skein384 context.
+ * @param data
+ *    Points to the data to update the context.
+ * @param dataLength
+ *    The length of the data in bytes.
+ */
+void skein384Ctx(void* ctx, unsigned char* data, 
+               unsigned int dataLength);
+
+/**
+ * Update the Skein384 context with several data chunks.
+ *
+ * This functions updates the Skein384 context with some data.
+ * See also CloseSha384Context(...) how to get the digest.
+ *
+ * @param ctx
+ *    Points to the Skein384 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 skein384Ctx(void* ctx, unsigned char* dataChunks[],
+               unsigned int dataChunkLength[]);
+
+/**
+ * @}
+ */
+#endif
+
diff --git a/jni/libzrtp/sources/zrtp/crypto/skeinMac256.cpp b/jni/libzrtp/sources/zrtp/crypto/skeinMac256.cpp
new file mode 100644
index 0000000..b4234e5
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skeinMac256.cpp
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2013 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.
+ */
+
+/*
+ * Authors: Werner Dittmann
+ */
+
+#include <cryptcommon/macSkein.h>
+#include <zrtp/crypto/skeinMac256.h>
+
+void macSkein256(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength)
+{
+    macSkein(key, keyLength, data, dataLength, mac, SKEIN256_DIGEST_LENGTH*8, SKEIN_SIZE);
+    *macLength = SKEIN256_DIGEST_LENGTH;
+}
+
+
+void macSkein256( uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunkLength[], uint8_t* mac, uint32_t* macLength )
+{
+    macSkein(key, keyLength, (const uint8_t**)dataChunks, dataChunkLength, mac, SKEIN256_DIGEST_LENGTH*8, SKEIN_SIZE);
+    *macLength = SKEIN256_DIGEST_LENGTH;
+}
+
+void* createMacSkein256Context(uint8_t* key, int32_t keyLength)
+{
+    return createSkeinMacContext(key, keyLength, SKEIN256_DIGEST_LENGTH*8, SKEIN_SIZE);
+}
+
+void macSkein256Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, uint8_t* mac, int32_t* macLength)
+{
+
+    macSkeinCtx(ctx, data, dataLength, mac);
+    *macLength = SKEIN256_DIGEST_LENGTH;
+}
+
+void macSkein256Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength )
+{
+    macSkeinCtx(ctx, data, dataLength, mac);
+    *macLength = SKEIN256_DIGEST_LENGTH;
+}
+
+void freeMacSkein256Context(void* ctx)
+{
+    freeSkeinMacContext(ctx);
+}
\ No newline at end of file
diff --git a/jni/libzrtp/sources/zrtp/crypto/skeinMac256.h b/jni/libzrtp/sources/zrtp/crypto/skeinMac256.h
new file mode 100644
index 0000000..e87a1e1
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skeinMac256.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2013 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 Skein256 HMAC.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef HMAC_SKEIN256_H
+#define HMAC_SKEIN256_H
+
+/**
+ * @file skeinMac256.h
+ * @brief Function that provide Skein256 HMAC support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SKEIN256_DIGEST_LENGTH
+#define SKEIN256_DIGEST_LENGTH 32
+#endif
+
+#define SKEIN_SIZE Skein512
+
+/**
+ * Compute Skein256 HMAC.
+ *
+ * This functions takes one data chunk and computes its Skein256 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 (SKEIN256_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+void macSkein256( uint8_t* key, uint32_t key_length, uint8_t* data, int32_t data_length, uint8_t* mac, uint32_t* mac_length );
+
+/**
+ * Compute Skein256 HMAC over several data cunks.
+ *
+ * This functions takes several data chunk and computes the Skein256 HAMAC.
+ *
+ * @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 (SKEIN256_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+
+void macSkein256( 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/sources/zrtp/crypto/skeinMac384.cpp b/jni/libzrtp/sources/zrtp/crypto/skeinMac384.cpp
new file mode 100644
index 0000000..57c7ad1
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skeinMac384.cpp
@@ -0,0 +1,76 @@
+/*
+  Copyright (C) 2013 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.
+ */
+
+/*
+ * Authors: Werner Dittmann
+ */
+
+#define SKEIN_SIZE Skein512
+#define SKEIN384_DIGEST_LENGTH  48
+
+#include <cryptcommon/macSkein.h>
+#include <zrtp/crypto/skeinMac384.h>
+
+void macSkein384(uint8_t *key, uint32_t keyLength, uint8_t* data, int32_t dataLength, uint8_t* mac, uint32_t* macLength)
+{
+    macSkein(key, keyLength, data, dataLength, mac, SKEIN384_DIGEST_LENGTH*8, SKEIN_SIZE);
+    *macLength = SKEIN384_DIGEST_LENGTH;
+}
+
+
+void macSkein384( uint8_t* key, uint32_t keyLength, uint8_t* dataChunks[], uint32_t dataChunkLength[], uint8_t* mac, uint32_t* macLength )
+{
+    macSkein(key, keyLength, (const uint8_t**)dataChunks, dataChunkLength, mac, SKEIN384_DIGEST_LENGTH*8, SKEIN_SIZE);
+    *macLength = SKEIN384_DIGEST_LENGTH;
+}
+
+void* createMacSkein384Context(uint8_t* key, int32_t keyLength)
+{
+    return createSkeinMacContext(key, keyLength, SKEIN384_DIGEST_LENGTH*8, SKEIN_SIZE);
+}
+
+void macSkein384Ctx(void* ctx, const uint8_t* data, uint32_t dataLength, uint8_t* mac, int32_t* macLength)
+{
+
+    macSkeinCtx(ctx, data, dataLength, mac);
+    *macLength = SKEIN384_DIGEST_LENGTH;
+}
+
+void macSkein384Ctx(void* ctx, const uint8_t* data[], uint32_t dataLength[], uint8_t* mac, int32_t* macLength )
+{
+    macSkeinCtx(ctx, data, dataLength, mac);
+    *macLength = SKEIN384_DIGEST_LENGTH;
+}
+
+void freeMacSkein384Context(void* ctx)
+{
+    freeSkeinMacContext(ctx);
+}
\ No newline at end of file
diff --git a/jni/libzrtp/sources/zrtp/crypto/skeinMac384.h b/jni/libzrtp/sources/zrtp/crypto/skeinMac384.h
new file mode 100644
index 0000000..2065899
--- /dev/null
+++ b/jni/libzrtp/sources/zrtp/crypto/skeinMac384.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2013 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 Skein384 HMAC.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef HMAC_SKEIN384_H
+#define HMAC_SKEIN384_H
+
+/**
+ * @file skeinMac384.h
+ * @brief Function that provide Skein384 HMAC support
+ * 
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SKEIN384_DIGEST_LENGTH
+#define SKEIN384_DIGEST_LENGTH 48
+#endif
+
+#define SKEIN_SIZE Skein512
+
+/**
+ * Compute Skein384 HMAC.
+ *
+ * This functions takes one data chunk and computes its Skein384 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 (SKEIN384_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+void macSkein384( uint8_t* key, uint32_t key_length, uint8_t* data, int32_t data_length, uint8_t* mac, uint32_t* mac_length );
+
+/**
+ * Compute Skein384 HMAC over several data cunks.
+ *
+ * This functions takes several data chunk and computes the Skein384 HAMAC.
+ *
+ * @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 (SKEIN384_DIGEST_LENGTH).
+ * @param mac_length
+ *    Point to an integer that receives the length of the computed HMAC.
+ */
+
+void macSkein384( 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/sources/zrtp/crypto/twoCFB.h b/jni/libzrtp/sources/zrtp/crypto/twoCFB.h
index e063a35..595d19d 100755
--- a/jni/libzrtp/sources/zrtp/crypto/twoCFB.h
+++ b/jni/libzrtp/sources/zrtp/crypto/twoCFB.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp b/jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp
index e602dd3..d718f24 100644
--- a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp
+++ b/jni/libzrtp/sources/zrtp/crypto/zrtpDH.cpp
@@ -62,7 +62,7 @@
 typedef struct _dhCtx {
     BigNum privKey;
     BigNum pubKey;
-    NistECpCurve curve;
+    EcCurve curve;
     EcPoint pubPoint;
 } dhCtx;
 
@@ -202,6 +202,12 @@
     else if (*(int32_t*)type == *(int32_t*)ec38) {
         pkType = EC38;
     }
+    else if (*(int32_t*)type == *(int32_t*)e255) {
+        pkType = E255;
+    }
+    else if (*(int32_t*)type == *(int32_t*)e414) {
+        pkType = E414;
+    }
     else {
         return;
     }
@@ -246,6 +252,16 @@
         ecGetCurveNistECp(NIST384P, &tmpCtx->curve);
         ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey);
         break;
+
+    case E255:
+        ecGetCurvesCurve(Curve25519, &tmpCtx->curve);
+        ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey);
+        break;
+
+    case E414:
+        ecGetCurvesCurve(Curve3617, &tmpCtx->curve);
+        ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey);
+        break;
     }
 }
 
@@ -267,6 +283,11 @@
     case EC38:
         ecFreeCurveNistECp(&tmpCtx->curve);
         break;
+
+    case E255:
+    case E414:
+        ecFreeCurvesCurve(&tmpCtx->curve);
+        break;
     }
 }
 
@@ -300,7 +321,7 @@
         return length;
     }
 
-    if (pkType == EC25 || pkType == EC38) {
+    if (pkType == EC25 || pkType == EC38 || pkType == E414) {
         int32_t len = getPubKeySize() / 2;
         EcPoint pub;
 
@@ -319,6 +340,23 @@
 
         return length;
     }
+    if (pkType == E255) {
+        int32_t len = getPubKeySize();
+        EcPoint pub;
+
+        bnBegin(&sec);
+        INIT_EC_POINT(&pub);
+
+        bnInsertLittleBytes(pub.x, pubKeyBytes, 0, len);
+
+        /* Generate agreement for responder: sec = pub * privKey */
+        ecdhComputeAgreement(&tmpCtx->curve, &sec, &pub, &tmpCtx->privKey);
+        bnExtractLittleBytes(&sec, secret, 0, length);
+        bnEnd(&sec);
+        FREE_EC_POINT(&pub);
+
+        return length;
+    }
     return -1;
 }
 
@@ -338,7 +376,10 @@
 
     case EC25:
     case EC38:
-        return ecdhGeneratePublic(&tmpCtx->curve, &tmpCtx->pubPoint, &tmpCtx->privKey);
+    case E255:
+    case E414:
+        while (!ecdhGeneratePublic(&tmpCtx->curve, &tmpCtx->pubPoint, &tmpCtx->privKey))
+            ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey);
     }
     return 0;
 }
@@ -359,6 +400,13 @@
     case EC38:
         return 48;
         break;
+
+    case E255:
+        return 32;
+        break;
+    case E414:
+        return 52;
+        break;
     }
     return 0;
 }
@@ -369,9 +417,11 @@
     if (pkType == DH2K || pkType == DH3K)
         return bnBytes(&tmpCtx->pubKey);
 
-    if (pkType == EC25 || pkType == EC38)
-        return bnBytes(tmpCtx->curve.p) * 2;
+    if (pkType == EC25 || pkType == EC38 || pkType == E414)
+        return bnBytes(tmpCtx->curve.p) * 2;   // *2 -> x and y coordinate
 
+    if (pkType == E255)
+        return bnBytes(tmpCtx->curve.p);
     return 0;
 
 }
@@ -391,13 +441,18 @@
         return size;
     }
 
-    if (pkType == EC25 || pkType == EC38) {
+    if (pkType == EC25 || pkType == EC38 || pkType == E414) {
         int32_t len = getPubKeySize() / 2;
 
         bnExtractBigBytes(tmpCtx->pubPoint.x, buf, 0, len);
         bnExtractBigBytes(tmpCtx->pubPoint.y, buf+len, 0, len);
         return len * 2;
     }
+    if (pkType == E255) {
+        int32_t len = getPubKeySize();
+        bnExtractLittleBytes(tmpCtx->pubPoint.x, buf, 0, len);
+        return len;
+    }
     return 0;
 }
 
@@ -405,49 +460,22 @@
 {
 
     /* ECC validation (partial), NIST SP800-56A, section 5.6.2.6 */
-    if (pkType == EC25 || pkType == EC38) {
+    if (pkType == EC25 || pkType == EC38 || pkType == E414) {
 
-        struct BigNum t1, t2;
         dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
         EcPoint pub;
-        int ret = 0;
 
         INIT_EC_POINT(&pub);
         int32_t len = getPubKeySize() / 2;
 
-        bnBegin(&t1);
-        bnBegin(&t2);
-
         bnInsertBigBytes(pub.x, pubKeyBytes, 0, len);
         bnInsertBigBytes(pub.y, pubKeyBytes+len, 0, len);
 
-        /* Represent point at infinity by (0, 0), make sure it's not that */
-        if (bnCmpQ(pub.x, 0) == 0 && bnCmpQ(pub.y, 0) == 0) {
-            goto fail;
-        }
-        /* Check that coordinates are within range */
-        if (bnCmpQ(pub.x, 0) < 0 || bnCmp(pub.x, tmpCtx->curve.p) >= 0) {
-            goto fail;
-        }
-        if (bnCmpQ(pub.y, 0) < 0 || bnCmp(pub.y, tmpCtx->curve.p) >= 0) {
-            goto fail;
-        }
-        /* Check that point satisfies EC equation y^2 = x^3 - 3x + b, mod P */
-        bnSquareMod_(&t1, pub.y, tmpCtx->curve.p);
-        bnSquareMod_(&t2, pub.x, tmpCtx->curve.p);
-        bnSubQMod_(&t2, 3, tmpCtx->curve.p);
-        bnMulMod_(&t2, &t2, pub.x, tmpCtx->curve.p);
-        bnAddMod_(&t2, tmpCtx->curve.b, tmpCtx->curve.p);
-        if (bnCmp (&t1, &t2) != 0) {
-            goto fail;
-        }
-        ret = 1;
+        return ecCheckPubKey(&tmpCtx->curve, &pub);
+    }
 
-    fail:
-        FREE_EC_POINT(&pub);
-        bnEnd(&t1);
-        bnEnd(&t2);
-        return ret;
+    if (pkType == E255) {
+        return 1;
     }
 
     BigNum pubKeyOther;
@@ -481,16 +509,16 @@
     switch (pkType) {
     case DH2K:
         return dh2k;
-        break;
     case DH3K:
         return dh3k;
-        break;
     case EC25:
         return ec25;
-        break;
     case EC38:
         return ec38;
-        break;
+    case E255:
+        return e255;
+    case E414:
+        return e414;
     }
     return NULL;
 }
diff --git a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.h b/jni/libzrtp/sources/zrtp/crypto/zrtpDH.h
index acf0e92..d2a3a40 100644
--- a/jni/libzrtp/sources/zrtp/crypto/zrtpDH.h
+++ b/jni/libzrtp/sources/zrtp/crypto/zrtpDH.h
@@ -59,6 +59,8 @@
 const int32_t DH3K = 1;
 const int32_t EC25 = 2;
 const int32_t EC38 = 3;
+const int32_t E255 = 4;
+const int32_t E414 = 5;
 
 
 /**
diff --git a/jni/libzrtp/sources/clients/ccrtp/CcrtpTimeoutProvider.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/CcrtpTimeoutProvider.h
similarity index 100%
rename from jni/libzrtp/sources/clients/ccrtp/CcrtpTimeoutProvider.h
rename to jni/libzrtp/sources/zrtp/libzrtpcpp/CcrtpTimeoutProvider.h
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h
index 8f471a6..2ba1de6 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCache.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -161,9 +161,9 @@
     /**
      * @brief Clean the cache.
      *
-     * This method cleans the cache and discards all information about remote peers.
-     * The method does not delete the local (own) ZID. To delete local ZID information
-     * the user must delete the database base.
+     * The function drops and re-creates all tables in the database. This removes all stored
+     * data. The application must not call this while a ZRTP call is active. Also the application
+     * <b>must</b> get the local ZID again.
      *
      */
     virtual void cleanup() =0;
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h
index 6b1d70b..7aa6dd0 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheDb.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h
index 9d43fde..7b264e8 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDCacheFile.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h
index f3d804e..c46fc24 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecord.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -19,7 +19,7 @@
 #define _ZIDRECORD_H_
 
 #include <stdint.h>
-
+#include <common/osSpecifics.h>
 /**
  * @file ZIDRecord.h
  * @brief ZID cache record management
@@ -32,19 +32,6 @@
  * @{
  */
 
-#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
-
 /**
  * These length are fixed for ZRTP. See RFC 6189.
  */
@@ -65,6 +52,12 @@
 
 public:
     /**
+     * @brief Destructor.
+     * Define a virtual destructor to enable cleanup in derived classes.
+     */
+    virtual ~ZIDRecord() {};
+
+    /**
      * Set the @c ZID in the record.
      *
      * Set the ZID in this record before calling read or save.
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h
index 28287d9..111b4ed 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordDb.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordFile.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordFile.h
index 579a430..74cc8a0 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordFile.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZIDRecordFile.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZRtp.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZRtp.h
index 417a892..a20b599 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZRtp.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZRtp.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2012 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -51,6 +51,15 @@
 #define MAX_DIGEST_LENGTH       64
 #define IMPL_MAX_DIGEST_LENGTH  64
 
+// max. number of parallel supported ZRTP protocol versions.
+#define MAX_ZRTP_VERSIONS       2
+
+// currently only 1.10 supported
+#define SUPPORTED_ZRTP_VERSIONS       1
+
+// Integer representation of highest supported ZRTP protocol version
+#define HIGHEST_ZRTP_VERION    12
+
 class __EXPORT ZrtpStateClass;
 class ZrtpDH;
 
@@ -108,6 +117,14 @@
         const char *authLength;
     } zrtpInfo;
 
+    /**
+     * Faster access to Hello packets with different versions.
+     */
+    typedef struct _HelloPacketVersion {
+        int32_t version;
+        ZrtpPacketHello* packet;
+        uint8_t helloHash[IMPL_MAX_DIGEST_LENGTH];
+    } HelloPacketVersion;
 
     /**
      * Constructor intializes all relevant data but does not start the
@@ -219,17 +236,25 @@
     /**
      * Get the ZRTP Hello Hash data.
      *
-     * Use this method to get the ZRTP Hello Hash data. The method
+     * 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.
+     * 
+     * The index defines which Hello packet to use. Each supported ZRTP procol version
+     * uses a different Hello packet and thus computes different hashes.
      *
      * Refer to ZRTP specification, chapter 8.
+     * 
+     * @param index
+     *     Hello hash of the Hello packet identfied by index. Index must be 0 <= index < MAX_ZRTP_VERSIONS.
      *
      * @return
-     *    a std:string containing the Hello hash value as hex-digits. The
-     *    hello hash is available immediately after class instantiation.
+     *    a std::string formatted according to RFC6189 section 8 without the leading 'a=zrtp-hash:'
+     *    SDP attribute identifier. The hello hash is available immediately after class instantiation.
+     * 
+     * @see getNumberSupportedVersions()
      */
-    std::string getHelloHash();
+    std::string getHelloHash(int index);
 
     /**
      * Get the peer's ZRTP Hello Hash data.
@@ -490,6 +515,28 @@
       */
      std::string getPeerProtcolVersion();
 
+     /**
+      * Get number of supported ZRTP protocol versions.
+      *
+      * @return the number of supported ZRTP protocol versions.
+      */
+     int32_t getNumberSupportedVersions() {return SUPPORTED_ZRTP_VERSIONS;}
+
+     /**
+      * Get negotiated ZRTP protocol version.
+      *
+      * @return the integer representation of the negotiated ZRTP protocol version.
+      */
+     int32_t getCurrentProtocolVersion() {return currentHelloPacket->getVersionInt();}
+
+     /**
+      * Validate the RS2 data if necessary.
+      *
+      * The cache functions stores the RS2 data but does not set its valid flag. The
+      * application may decide to set this flag.
+      */
+     void setRs2Valid();
+
 private:
      friend class ZrtpStateClass;
 
@@ -612,7 +659,6 @@
     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
@@ -770,7 +816,9 @@
     /**
      * Pre-initialized packets.
      */
-    ZrtpPacketHello    zrtpHello;
+    ZrtpPacketHello    zrtpHello_11;
+    ZrtpPacketHello    zrtpHello_12;   // Prepare for ZRTP protocol version 1.2
+
     ZrtpPacketHelloAck zrtpHelloAck;
     ZrtpPacketConf2Ack zrtpConf2Ack;
     ZrtpPacketClearAck zrtpClearAck;
@@ -786,12 +834,24 @@
     ZrtpPacketSASrelay zrtpSasRelay;
     ZrtpPacketRelayAck zrtpRelayAck;
 
+    HelloPacketVersion helloPackets[MAX_ZRTP_VERSIONS + 1];
+    int32_t highestZrtpVersion;
+
+    /// Pointer to Hello packet sent to partner, initialized in ZRtp, modified by ZrtpStateClass
+    ZrtpPacketHello* currentHelloPacket;
+
     /**
      * ZID cache record
      */
     ZIDRecord *zidRec;
 
     /**
+     * Save record
+     * 
+     * If false don't save record until user vrified and confirmed the SAS.
+     */
+    bool saveZidRecord;
+    /**
      * Random IV data to encrypt the confirm data, 128 bit for AES
      */
     uint8_t randomIV[16];
@@ -938,20 +998,75 @@
     bool checkMultiStream(ZrtpPacketHello* hello);
 
     /**
-     * Checks if Hello packet contains a strong (384bit) hash and returns it.
+     * Checks if Hello packet contains a strong (384bit) hash based on selection policy.
+     * 
+     * The function currently implements the nonNist policy only:
+     * If the public key algorithm is a non-NIST ECC algorithm this function prefers
+     * non-NIST HASH algorithms (Skein etc).
+     * 
+     * If Hello packet does not contain a strong hash then this functions returns @c NULL.
      *
+     * @param hello The Hello packet.
+     * @param algoName name of selected PK algorithm
      * @return @c hash algorithm if found in Hello packet, @c NULL otherwise.
      */
-    AlgorithmEnum* getStrongHashOffered(ZrtpPacketHello *hello);
+    AlgorithmEnum* getStrongHashOffered(ZrtpPacketHello *hello, int32_t algoName);
 
     /**
-     * Checks if Hello packet offers a strong (256bit) symmetric cipher.
+     * Checks if Hello packet offers a strong (256bit) symmetric cipher based on selection policy.
      *
-     * The method returns the first strong cipher offered in the Hello packet.
+     * The function currently implements the nonNist policy only:
+     * If the public key algorithm is a non-NIST ECC algorithm this function prefers
+     * non-NIST symmetric cipher algorithms (Twofish etc).
+     *
+     * If Hello packet does not contain a symmetric cipher then this functions returns @c NULL.
+
+     * @param hello The Hello packet.
+     * @param algoName name of selected PK algorithm
+     * @return @c hash algorithm if found in Hello packet, @c NULL otherwise.
      *
      * @return @c cipher algorithm if found in Hello packet, @c NULL otherwise.
      */
-    AlgorithmEnum* getStrongCipherOffered(ZrtpPacketHello *hello);
+    AlgorithmEnum* getStrongCipherOffered(ZrtpPacketHello *hello, int32_t algoName);
+
+    /**
+     * Checks if Hello packet contains a hash based on selection policy.
+     *
+     * The function currently implements the nonNist policy only:
+     * If the public key algorithm is a non-NIST ECC algorithm this function prefers
+     * non-NIST HASH algorithms (Skein etc).
+     *
+     * @param hello The Hello packet.
+     * @param algoName name of selected PK algorithm
+     * @return @c hash algorithm found in Hello packet.
+     */
+    AlgorithmEnum* getHashOffered(ZrtpPacketHello *hello, int32_t algoName);
+
+    /**
+     * Checks if Hello packet offers a symmetric cipher based on selection policy.
+     *
+     * The function currently implements the nonNist policy only:
+     * If the public key algorithm is a non-NIST ECC algorithm this function prefers
+     * non-NIST symmetric cipher algorithms (Twofish etc).
+     *
+     * @param hello The Hello packet.
+     * @param algoName name of selected PK algorithm
+     * @return non-NIST @c cipher algorithm if found in Hello packet, @c NULL otherwise
+     */
+    AlgorithmEnum* getCipherOffered(ZrtpPacketHello *hello, int32_t algoName);
+
+    /**
+     * Checks if Hello packet offers a SRTP authentication length based on selection policy.
+     *
+     * The function currently implements the nonNist policy only:
+     * If the public key algorithm is a non-NIST ECC algorithm this function prefers
+     * non-NIST algorithms (Skein etc).
+     *
+     * @param hello The Hello packet.
+     * @param algoName algoName name of selected PK algorithm
+     * @return @c authLen algorithm found in Hello packet
+     */
+    AlgorithmEnum* getAuthLenOffered(ZrtpPacketHello *hello, int32_t algoName);
 
     /**
      * Save the computed MitM secret to the ZID record of the peer
@@ -965,6 +1080,8 @@
 
     void computeSharedSecretSet(ZIDRecord *zidRec);
 
+    void computeAuxSecretIds();
+
     void computeSRTPKeys();
 
     void KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLength,
@@ -1345,8 +1462,10 @@
       *
       * @param id
       *     The client's id
+      * @param hpv
+      *     Pointer to hello packet version structure.
       */
-     void setClientId(std::string id);
+     void setClientId(std::string id, HelloPacketVersion* hpv);
 };
 
 /**
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCWrapper.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCWrapper.h
index 19aebb0..0ad5b95 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCWrapper.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCWrapper.h
@@ -1,9 +1,9 @@
 /*
     This file defines the GNU ZRTP C-to-C++ wrapper.
-    Copyright (C) 2010  Werner Dittmann
+    Copyright (C) 2013  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
+    it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
 
@@ -565,7 +565,7 @@
      * @returns
      *      Pointer to the ZrtpContext
      */
-    ZrtpContext* zrtp_CreateWrapper();
+    ZrtpContext* zrtp_CreateWrapper(void);
 
     /**
      * Initialize the ZRTP protocol engine.
@@ -782,21 +782,28 @@
      *
      * 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.
+     * hex-digits. 
+
+     * The index defines which Hello packet to use. Each supported ZRTP procol version
+     * uses a different Hello packet and thus computes different hashes.
      *
-     * <b>NOTE: An application may call this method if it needs this information.
-     * Usually it is not necessary.</b>
+     * Refer to ZRTP specification, chapter 8.
+     *
+     * @param index
+     *     Hello hash of the Hello packet identfied by index. Index must be 0 <= index < zrtp_getNumberSupportedVersions().
      *
      * @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
+     *    a pointer to a C-string that contains the Hello hash formatted according to RFC6189 section 8 
+     *    without the leading 'a=zrtp-hash:' SDP attribute identifier. 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.
+     *
+     * @see zrtp_getNumberSupportedVersions()
      */
-    char* zrtp_getHelloHash(ZrtpContext* zrtpContext);
+    char* zrtp_getHelloHash(ZrtpContext* zrtpContext, int32_t index);
 
     /**
      * Get the peer's ZRTP Hello Hash data.
@@ -1070,7 +1077,27 @@
     int32_t zrtp_getPeerZid(ZrtpContext* zrtpContext, uint8_t* data);
 
 
-    /**
+     /**
+      * Get number of supported ZRTP protocol versions.
+      *
+      * @param zrtpContext
+      *    Pointer to the opaque ZrtpContext structure.
+      *
+      * @return the number of supported ZRTP protocol versions.
+      */
+     int32_t zrtp_getNumberSupportedVersions(ZrtpContext* zrtpContext);
+
+     /**
+      * Get negotiated ZRTP protocol versions.
+      *
+      * @param zrtpContext
+      *    Pointer to the opaque ZrtpContext structure.
+      *
+      * @return the integer representation of the negotiated ZRTP protocol version.
+      */
+     int32_t zrtp_getCurrentProtocolVersion(ZrtpContext* zrtpContext);
+
+     /**
      * This enumerations list all configurable algorithm types.
      */
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallback.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallback.h
index 957c4dd..0ad18a9 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallback.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallback.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -28,19 +28,7 @@
 #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
+#include <common/osSpecifics.h>
 
 /**
  * This enum defines which role a ZRTP peer has.
@@ -58,6 +46,7 @@
  * </ul>
  */
 typedef enum  {
+    NoRole = 0,     ///< ZRTP role not yet set
     Responder = 1,  ///< This client is in ZRTP Responder mode
     Initiator       ///< This client is in ZRTP Initiator mode
 } Role;
@@ -129,9 +118,10 @@
      * ZRTP calls this method to send a ZRTP packet via the RTP session.
      *
      * @param data
-     *    Points to ZRTP packet to send.
+     *    Points to ZRTP packet to send. The packet already contains a 4 bytes
+     *    storage at the end to store CRC.
      * @param length
-     *    The length in bytes of the data
+     *    The length in bytes of the data, including the CRC storage.
      * @return
      *    zero if sending failed, one if packet was send
      */
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallbackWrapper.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallbackWrapper.h
index dd739e0..098ec06 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallbackWrapper.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCallbackWrapper.h
@@ -1,9 +1,9 @@
 /*
     This class maps the ZRTP C++ callback methods to C callback methods.
-    Copyright (C) 2010 Werner Dittmann
+    Copyright (C) 2010-2013 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
+    it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCodes.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCodes.h
index b35d47b..1a7dd5f 100755
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCodes.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCodes.h
@@ -1,10 +1,10 @@
 /** @file ZrtpCodes.h
  */
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the Lesser GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -90,14 +90,15 @@
  * Sub-codes for Warning
  */
 enum WarningCodes {
-    WarningDHAESmismatch = 1,       //!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096
+    WarningDHAESmismatch = 1,       //!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096 - not used DH4096 was discarded
     WarningGoClearReceived,         //!< Received a GoClear message
-    WarningDHShort,                 //!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096
+    WarningDHShort,                 //!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096- not used DH4096 was discarded
     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
+    WarningNoExpectedRSMatch,       //!< Valid retained shared secrets availabe but no matches found - must verify SAS
+    WarningNoExpectedAuxMatch       //!< Our AUX secret was set but the other peer's AUX secret does not match ours
 };
 
 /**
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpConfigure.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpConfigure.h
index 896a85f..bb78cef 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpConfigure.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpConfigure.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2009 - 2010 Werner Dittmann
+  Copyright (C) 2009 - 2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -315,6 +315,14 @@
     ~ZrtpConfigure();
 
     /**
+     * Define the algorithm selection policies.
+     */
+    typedef enum _policies {
+        Standard = 1,
+        PreferNonNist = 2
+    } Policy;
+
+    /**
      * Set the maximum number of algorithms per algorithm type that an application can
      * configure.
      */
@@ -510,6 +518,9 @@
     /// Helper function to print some internal data
     void printConfiguredAlgos(AlgoTypes algoTyp);
 
+    Policy getSelectionPolicy()         {return selectionPolicy;}
+    void setSelectionPolicy(Policy pol) {selectionPolicy = pol;}
+
   private:
     std::vector<AlgorithmEnum* > hashes;
     std::vector<AlgorithmEnum* > symCiphers;
@@ -532,6 +543,8 @@
 
     void printConfiguredAlgos(std::vector<AlgorithmEnum* >& a);
 
+    Policy selectionPolicy;
+
   protected:
 
   public:
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCrc32.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCrc32.h
index ad57edd..49eec83 100755
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCrc32.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpCrc32.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketBase.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketBase.h
index 11b7930..a5826c7 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketBase.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketBase.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -38,12 +38,8 @@
 #include <string.h>
 #include <stdlib.h>
 
-#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
-#include <winsock2.h>
-#else
-#include <netinet/in.h>
-#endif
 #include <common/osSpecifics.h>
+
 #include <libzrtpcpp/zrtpPacket.h>
 #include <libzrtpcpp/ZrtpTextData.h>
 #include <libzrtpcpp/ZrtpConfigure.h>
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketClearAck.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketClearAck.h
index 992f6d8..91ca4c4 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketClearAck.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketClearAck.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketCommit.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketCommit.h
index b23b23d..4b6e1eb 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketCommit.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketCommit.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -31,6 +31,11 @@
 
 #include <libzrtpcpp/ZrtpPacketBase.h>
 
+// PRSH here only for completeness. We don't support PRSH in the other ZRTP parts.
+#define COMMIT_DH_EX      29
+#define COMMIT_MULTI      25
+#define COMMIT_PRSH       27
+
 /**
  * Implement the Commit packet.
  *
@@ -48,6 +53,11 @@
     Commit_t* commitHeader;     ///< Points to Commit message part
 
  public:
+    typedef enum _commitType {
+        DhExchange =  1,
+        MultiStream = 2
+    } commitType;
+
     /// Creates a Commit packet with default data
     ZrtpPacketCommit();
 
@@ -90,6 +100,10 @@
     /// Get pointer to MAC field during multi-stream mode, a fixed length byte array
     uint8_t* getHMACMulti()   { return commitHeader->hmac-4*ZRTP_WORD_SIZE; };
 
+    /// Check if packet length makes sense.
+    bool isLengthOk(commitType type)   {int32_t len = getLength(); 
+                                        return ((type == DhExchange) ? len == COMMIT_DH_EX : len == COMMIT_MULTI);}
+
     /// Set hash algorithm type field, fixed length character field
     void setHashType(uint8_t* text)    { memcpy(commitHeader->hash, text, ZRTP_WORD_SIZE); };
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConf2Ack.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConf2Ack.h
index a7c2567..a6f85f5 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConf2Ack.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConf2Ack.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConfirm.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConfirm.h
index e3ff85b..283861d 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConfirm.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketConfirm.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -84,6 +84,11 @@
         /// get the signature length in words
         int32_t getSignatureLength();
 
+        /// Check if packet length makes sense. Confirm packets are 19 words at minumum
+        bool isLengthOk()             {return (getLength() >= 19); }
+
+        bool isSignatureLengthOk();
+
         /// set SAS verified flag
         void setSASFlag()            { confirmHeader->flags |= 0x4; }
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketDHPart.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketDHPart.h
index d0ea4ba..08737a5 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketDHPart.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketDHPart.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -79,6 +79,9 @@
     /// Get pointer to HMAC, fixed length byte array
     uint8_t* getHMAC()           { return pv+dhLength; };
 
+    /// Check if packet length makes sense. DHPart packets are 29 words at minumum, using E255
+    bool isLengthOk()            {return (getLength() >= 29);}
+
     /// Setpublic key value, variable length byte array
     void setPv(uint8_t* text)         { memcpy(pv, text, dhLength); };
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketError.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketError.h
index ca00ee0..679a803 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketError.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketError.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketErrorAck.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketErrorAck.h
index e64c8a6..cfd435c 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketErrorAck.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketErrorAck.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2007 - 2010 Werner Dittmann
+  Copyright (C) 2007-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHello.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHello.h
index c9a38bd..f5394af 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHello.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHello.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2012 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -85,6 +85,9 @@
     /// Get version number from Hello message, fixed ASCII character array
     uint8_t* getVersion()  { return helloHeader->version; };
 
+     /// Get version number from Hello message as integer, only relvant digits converted
+    int32_t getVersionInt();
+
     /// Get client id from Hello message, fixed ASCII character array
     uint8_t* getClientId() { return helloHeader->clientId; };
 
@@ -95,7 +98,7 @@
     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 ); }
+    void setVersion(const 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)); }
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHelloAck.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHelloAck.h
index 345a071..d3e138e 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHelloAck.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketHelloAck.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPing.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPing.h
index 840df62..32fb2f9 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPing.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPing.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2009 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPingAck.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPingAck.h
index b795ffb..eb2924f 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPingAck.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketPingAck.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2009 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketRelayAck.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketRelayAck.h
index 93437e6..7fe373b 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketRelayAck.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketRelayAck.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2007 - 2010 Werner Dittmann
+  Copyright (C) 2007-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketSASrelay.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketSASrelay.h
index 04721fa..22739ff 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketSASrelay.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpPacketSASrelay.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2011 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -73,11 +73,14 @@
         const uint8_t* getSasAlgo() {return sasRelayHeader->sas; }
 
         /// Get pointer to new SAS hash data, fixed byte array
-        const uint8_t* getTrustedSas() { return sasRelayHeader->trustedSasHash; }
+        const uint8_t* getTrustedSas()    { return sasRelayHeader->trustedSasHash; }
 
         /// get the signature length in words
         uint32_t getSignatureLength();
 
+        /// Check if packet length makes sense. SAS rely packets are 19 words at minumum, they are similar to Confirm
+        bool isLengthOk()                 {return (getLength() >= 19);}
+
         /// set SAS verified flag
         void setSASFlag()            { sasRelayHeader->flags |= 0x4; }
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpQueue.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpQueue.h
index 7a1ee67..512d8c8 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpQueue.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpQueue.h
@@ -368,20 +368,28 @@
      */
     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.
+     * 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.
+     * 
+     * The index defines which Hello packet to use. Each supported ZRTP procol version
+     * uses a different Hello packet and thus computes different hashes.
+     *
+     * Refer to ZRTP specification, chapter 8.
+     *
+     * @param index
+     *     Hello hash of the Hello packet identfied by index. Index must be 0 <= index < getNumberSupportedVersions().
      *
      * @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.
+     *    a std::string formatted according to RFC6189 section 8 without the leading 'a=zrtp-hash:'
+     *    SDP attribute identifier. The hello hash is available immediatly after class instantiation.
+     * 
+     * @see getNumberSupportedVersions()
      */
-    std::string getHelloHash();
+    std::string getHelloHash(int32_t index);
 
     /**
      * Get the peer's ZRTP Hello Hash data.
@@ -743,6 +751,20 @@
      */
     int32 getPeerZid(uint8* data);
 
+    /**
+      * Get number of supported ZRTP protocol versions.
+      *
+      * @return the number of supported ZRTP protocol versions.
+      */
+     int32_t getNumberSupportedVersions();
+
+     /**
+      * Get negotiated ZRTP protocol version.
+      *
+      * @return the integer representation of the negotiated ZRTP protocol version.
+      */
+     int32_t getCurrentProtocolVersion();
+
 protected:
     friend class TimeoutProvider<std::string, ost::ZrtpQueue*>;
 
@@ -851,6 +873,7 @@
     int16 senderZrtpSeqNo;
     ost::Mutex synchLock;   // Mutex for ZRTP (used by ZrtpStateClass)
     uint32 peerSSRC;
+    uint64 zrtpUnprotect;
     bool started;
     bool mitmMode;
     bool signSas;
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h
index 7d36f2b..d7d2265 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpSdesStream.h
@@ -1,13 +1,107 @@
+/*
+  Copyright (C) 2012-2013 Werner Dittmann
+
+  This program 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 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 _ZRTPSDESSTREAM_H_
+#define _ZRTPSDESSTREAM_H_
+/**
+ * @file ZrtpSdesStream.h
+ * @brief The ZRTP main engine
+ * @defgroup GNU_ZRTP The GNU ZRTP C++ implementation
+ * @{
+ *
+ * This class implements SDES and provides a simple to use API for applications.
+ *
+ * This SDES implementation currently supports only two SDES algorithms and it does
+ * not support optional parameters such as lifetime or MKI parameters. Also session
+ * parameters are not supported. Most applications that use SDES don't use these
+ * optional parameters.
+ *
+ * It is not necessary to explicitly start the SDES stream. The class initiates
+ * the SRTP after it created and parsed all necessary SDES crypto strings.
+ *
+ * Because SDES works together with the signaling protocol, for example SIP, it is
+ * important to adhere to a defined flow. The following pseudo code snippet depicts
+ * such a flow. Applications shall follow this flow.
+ *
+ *<pre>
+ *
+ *     Inviter                           Answerer
+ *    (Offerer)
+ *
+ * ZrtpSdesStream inv;                 ZrtpSdesStream answ;
+ *
+ * // create/get own SDES data
+ * inv.createSdes(...);
+ * inv.getCryptoMixAttribute(...)
+ *
+ * // prepare SIP/SDP offer, send
+ * // it to answerer
+ *                                    // receive SIP/SDP, get
+ *                                    // SDES data, parse/set it
+ *                                    answ.setCryptoMixAttribute(...)
+ *                                    answ.parseSdes(...)
+ *
+ *                                    // create/get own SDES data
+ *                                    answ.getCryptoMixAttribute(...)
+ *                                    answ.createSdes(...)
+ *
+ *                                    // prepare SIP/SDP answer,
+ *                                    // send to offerer
+ * // receive SIP/SDP answer, get
+ * // SDES data, parse, set mix algo
+ * // if availabe
+ * inv.setCryptoMixAttribute(...)
+ * inv.parseSdes(...)
+ *
+ * ...                                ...
+ *
+ * inv.outgoingRtp(...)
+ *                                    answ.incomingRtp(...)
+ *
+ *                                    answ.outgoingRtp(...)
+ * inv.incomingRtp(...)
+ *</pre>
+ *
+ * To use SDES without the new crypto mix feature just do not use the crypto mix functions.
+ * An application may always send crypto mix attributes. If the answerer does not support this
+ * feature it does not send back a selected algorithm and the offerer cannot set an algorithm.
+ * Thus the crypto mix feature is not used.
+ * 
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <common/osSpecifics.h>
 
 class CryptoContext;
 class CryptoContextCtrl;
 
+/*
+ * These functions support 256 bit encryption algorithms.
+ */
+#define MAX_KEY_LEN           32
+#define MAX_SALT_LEN          14
+#define MAX_DIGEST_LENGTH     64
+
 /**
  * Maximum length of a raw crypto string.
  */
 #define MAX_CRYPT_STRING_LEN 200
 
-class ZrtpSdesStream {
+class __EXPORT ZrtpSdesStream {
 
 public:
 
@@ -15,12 +109,12 @@
      * Supported SDES crypto suites.
      */
     typedef enum {
-        AES_CM_128_HMAC_SHA1_32 = 1,
+        AES_CM_128_HMAC_SHA1_32 = 0,
         AES_CM_128_HMAC_SHA1_80
     } sdesSuites;
 
     /**
-     * SDES stream stated
+     * SDES stream state
      */
     typedef enum {
         STREAM_INITALIZED = 1,
@@ -29,15 +123,18 @@
         SDES_SRTP_ACTIVE
     } sdesZrtpStates;
 
+    typedef enum {
+        MIX_NONE = 0,
+        MIX_HMAC_SHA,
+        MIX_MAC_SKEIN
+    } sdesHmacTypeMix;
+
     /**
      * @brief Create and SDES/ZRTP stream.
      *
      * This method creates an SDES stream with capabilities to handle RTP,
      * RTCP, SRTP, and SRTCP packets.
      *
-     * It is not necessary to explicitly start the SDES stream. The method initiates
-     * the SRTP after it created and parsed all necessary SDES crypto strings.
-     *
      * @param suite defines which crypto suite to use for this stream. The values are
      *              @c AES_CM_128_HMAC_SHA1_80 or @c AES_CM_128_HMAC_SHA1_32.
      */
@@ -67,19 +164,16 @@
      * @c zrtp-hash from the SDP parameters and forwards it to @c libzrtp. The
      * answering application's SRTP environment is now ready.
      *
-     * @param cryptoString points to a char output buffer that receives the
-     *                     crypto  string in the raw format, without the any
-     *                     signaling prefix, for example @c a=crypto: in case
-     *                     of SDP signaling. The function terminates the
-     *                     crypto string with a @c nul byte
+     * @param cryptoString output buffer that receives the crypto  string in raw
+     *                     format, without the any signaling prefix, for example
+     *                     @c a=crypto:. The function terminates the crypto string
+     *                     with a @c nul byte
      *
      * @param maxLen length of the crypto string buffer. On return it contains the
      *               actual length of the crypto string.
      *
-     * @param sipInvite if this is set to @c true (not zero) then the method
-     *                  takes the necessary actions to create the crypto eonvironment
-     *                  for the inviting SIP application. It it is zero then it handles
-     *                  the invited case (answerer).
+     * @param sipInvite the inviter (offerer) must set this to @c true, the answerer must
+     *                  set it to @c false.
      *
      * @return @c true if data could be created, @c false otherwise.
      */
@@ -88,36 +182,67 @@
     /**
      * @brief Parses an SDES crypto string for the SDES/ZRTP stream.
      *
-     * Parses a received crypto string that the application received in a SIP INVITE
+     * Parses a SDES crypto string that the application received in a SIP INVITE
      * or SIP 200 OK.
      *
-     * An INVITE-ing application shall call this function right after it received
+     * An INVITE-ing (offerer) application shall call this function right after it received
      * the 200 OK from the answering application and must call this function with the
-     * @c sipInvite parameter set to @c true. This usually at the same point when
-     * it gets the  @c zrtp-hash from the SDP parameters.
-     * This application's SRTP environment is now ready.
+     * @c sipInvite parameter set to @c true. The offerer's SRTP is now ready for use.
      *
      * The answering application calls this function after it received the INVITE and
      * extracted the crypto string from the SDP and must call this function with the
-     * @c sipInvite parameter set to @c false. This is usually the same point when
-     * it gets the @c zrtp-hash from the SDP parameters.
+     * @c sipInvite parameter set to @c false.
      *
-     * @param cryptoString points to the crypto sting in raw format,
-     *                     without any signaling prefix, for example @c
-     *                     a=crypto: in case of SDP signaling.
+     * @param cryptoString the received crypto sting in raw format,
+     *                     without any signaling prefix, for example @c a=crypto:
      *
      * @param length length of the crypto string to parse. If the length is
      *               @c zero then the function uses @c strlen to compute
      *               the length.
      *
-     * @param sipInvite if this is set to @c true then the method
-     *                  takes the necessary actions to create the crypto eonvironment
-     *                  for the inviting SIP application. It it is zero then it handles
-     *                  the invited case (answerer).
+     * @param sipInvite the inviter (offerer) must set this to @c true, the answerer must
+     *                  set it to @c false.
      *
      * @return @c true if data could be created, @c false otherwise.
      */
-    bool parseSdes(char *cryptoString, size_t length, bool sipInvite);
+    bool parseSdes(const char *cryptoString, size_t length, bool sipInvite);
+
+    /**
+     * @brief Get Crypto Mix attribute string
+     *
+     * The offerer calls this method to get a string of @b all supported crypto mix algorithms
+     * and shall send this list to the answerer.
+     *
+     * The answerer calls this function only @b after it received the crypto mix string and @b after
+     * calling @c setCryptoMixAttribute(...). The method returns only one (the selected)
+     * crypto mix algorithm and the answerer must send this to the offerer, for example in 200 OK.
+     *
+     * @param algoNames buffer to store the nul terminated crypto mix algorithm names.
+     *                  The buffer must be long enough to hold at least the name of the mandatory
+     *                  algorithm HMAC-SHA-384.
+     *
+     * @param length length of buffer
+     *
+     * @return Length of algorithm names (excluding nul byte) or zero if crypto mix not supported or
+     *         enabled.
+     */
+    int getCryptoMixAttribute(char *algoNames, size_t length);
+
+    /**
+     * @brief Set Crypto Mix attribute string
+     *
+     * The method checks if it the string contains an supported algorithm and selects one algorithm.
+     *
+     * The offerer calls this method @b after it received the selected algorithm in the answer.
+     *
+     * The answerer must call this method @b before it calls the @c getCryptoMixAttribute() method.
+     *
+     * @param algoNames buffer that contains the received crypto mix algorithm names.
+     *                  The buffer must be nul terminated.
+     *
+     * @return @c false if none of the offered algorithms is supported.
+     */
+    bool setCryptoMixAttribute(const char *algoNames);
 
     /*
      * ******** Outgoing RTP/RTCP packet handling
@@ -151,7 +276,7 @@
     /**
      * @brief Process an outgoing RTCP packet
      *
-     * This function works in the same way as @c sdesZrtpProcessRtp.
+     * This function works in the same way as @c outgoingRtp.
      *
      * @param packet the buffer that contains the RTCP packet. After processing, the
      *               encrypted packet is stored in the same buffer. The buffer must
@@ -185,7 +310,7 @@
      * @param packet the buffer that contains the RTP/SRTP packet. After processing,
      *               the decrypted packet is stored in the same buffer.
      *
-     * @param length length of the RTCP packet
+     * @param length length of the RTP packet
      *
      * @param newLength to an integer that get the new length of the packet excluding SRTCP data.
      *
@@ -199,7 +324,7 @@
     /**
      * @brief Process an incoming RTCP or SRTCP packet
      *
-     * This function works in the same way as @c sdesZrtpProcessSrtp.
+     * This function works in the same way as @c incomingRtp.
      *
      * @param packet the buffer that contains the RTCP/SRTCP packet. After processing,
      *               the decrypted packet is stored in the same buffer.
@@ -216,21 +341,64 @@
     int incomingSrtcp(uint8_t *packet, size_t length, size_t *newLength);
 
     /**
-     * Return state of SDES stream.
+     * @brief Process an outgoing ZRTP packet.
+     * 
+     * Works like @c outgoingRtp, refer to that documentation.
+     * 
+     * @param packet the buffer that contains the ZRTP packet.
+     *
+     * @param length length of the ZRTP packet
+     *
+     * @param newLength to an integer that get the new length of the packet including SRTP data.
+     *
+     * @return
+     *  - @c true if encryption is successful, app shall send packet to the recipient.
+     *  - @c false if there was an error during encryption, don't send the packet.
+     */
+    bool outgoingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength);
+
+    /**
+     * @brief Process an incoming ZRTP packet
+     *
+     * Works like @c incomingRtp, refer to that documentation.
+     *
+     * @param packet the buffer that contains the ZRTP/SRTP packet. After processing,
+     *               the decrypted packet is stored in the same buffer.
+     *
+     * @param length length of the RTP packet
+     *
+     * @param newLength to an integer that get the new length of the packet excluding SRTCP data.
+     *
+     * @return
+     *       - 1: success,
+     *       - -1: SRTP authentication failed,
+     *       - -2: SRTP replay check failed
+     */
+    int incomingZrtpTunnel(uint8_t *packet, size_t length, size_t *newLength);
+
+        /**
+     * @brief Return state of SDES stream.
      *
      * @return state of stream.
      */
     sdesZrtpStates getState() {return state;}
 
     /**
-     * Return name of active cipher algorithm.
+     * @brief Return SDES crypto mixer HMAC type.
+     *
+     * @return HMAC type
+     */
+    sdesHmacTypeMix getHmacTypeMix() {return cryptoMixHashType;}
+
+    /**
+     * @brief Return name of active cipher algorithm.
      *
      * @return point to name of cipher algorithm.
      */
     const char* getCipher();
 
     /**
-     * Return name of active SRTP authentication algorithm.
+     * @brief Return name of active SRTP authentication algorithm.
      *
      * @return point to name of authentication algorithm.
      */
@@ -244,11 +412,9 @@
     /**
      * @brief Create an SRTP crypto context and the according SDES crypto string.
      *
-     * This lower layer method creates an SRTP profile an the according SDES
-     * crypto string. It selects a valid crypto suite, generates the key and salt
-     * data, converts these into base 64 and returns the crypto string in raw format
-     * without any signaling prefixes. The method also creates the internal
-     * SRTP/SRTCP crypto contexts for outgoing data.
+     * This lower layer method creates an SDES crypto string. It selects a valid
+     * crypto suite, generates the key and salt data, converts these into base 64
+     * and returns the crypto string in raw format without any signaling prefixes.
      *
      * The output string has the following format:
      * @verbatim
@@ -291,8 +457,7 @@
      *
      * The method parses an offered SDES crypto string and checks if it is
      * valid. Next it checks if the string contains a supported crypto suite
-     * and if the key and salt lengths match the selected crypto suite. The method
-     * also creates the internal SRTP/SRTCP crypto contexts for incoming data.
+     * and if the key and salt lengths match the selected crypto suite.
      *
      * Applications usually don't use this method directly. Applications shall
      * use the SDES stream functions.
@@ -324,6 +489,28 @@
      */
     bool parseCreateSdesProfile(const char *cryptoString, size_t length, sdesSuites *parsedSuite, int32_t *tag);
 
+    /**
+     * @brief Create the SRTP contexts after all SDES creation and parsing is done.
+     * 
+     * @param sipInvite if this is set to @c true (not zero) then the method
+     *                  computes the key data for the inviting SIP application (offerer) and
+     *                  for the answerer otherwise.
+     */
+    void createSrtpContexts(bool sipInvite);
+
+    /**
+     * @brief Compute the mixed keys if SDES mixing attribute is set.
+     *
+     * The method takes the parsed or created SDES key material and computes the mixed keys and salt.
+     * It replaces the existing key material with the new data.
+     *
+     * @param sipInvite if this is set to @c true (not zero) then the method
+     *                  computes the key data for the inviting SIP application (offerer) and
+     *                  for the answerer otherwise.
+     */
+    void computeMixedKeys(bool sipInvite);
+
+
     sdesZrtpStates state;
     sdesSuites     suite;
     int32_t        tag;
@@ -333,4 +520,28 @@
     CryptoContextCtrl *sendSrtcp;          //!< The SRTCP context for this stream
     uint32_t srtcpIndex;                   //!< the local SRTCP index
 
+    CryptoContext     *recvZrtpTunnel;     //!< The SRTP context for sender ZRTP tunnel
+    CryptoContext     *sendZrtpTunnel;     //!< The SRTP context for receiver ZRTP tunnel
+
+    int32_t cryptoMixHashLength;
+    sdesHmacTypeMix cryptoMixHashType;
+
+    // Variables for crypto that this client creates and sends to the other client, filled during SDES create
+    uint8_t localKeySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4];  //!< Some buffer for key and salt, multiple of 4
+    int localKeyLenBytes;
+    int localSaltLenBytes;
+    int localCipher;
+    int localAuthn;
+    int localAuthKeyLen;
+    int localTagLength;
+
+    // Variables for crypto that this client receives from the other client, filled during SDES parse
+    uint8_t remoteKeySalt[((MAX_KEY_LEN + MAX_SALT_LEN + 3)/4)*4];  //!< Some buffer for key and salt, multiple of 4
+    int remoteKeyLenBytes;
+    int remoteSaltLenBytes;
+    int remoteCipher;
+    int remoteAuthn;
+    int remoteAuthKeyLen;
+    int remoteTagLength;
 };
+#endif
\ No newline at end of file
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStateClass.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStateClass.h
index c1887c9..5c16313 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStateClass.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStateClass.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -161,6 +161,11 @@
      */
     bool subEvWaitRelayAck();
 
+    /**
+     * Hello packet version sent to other partner
+     */
+    int32_t sentVersion;
+
 public:
     /// Create a ZrtpStateClass
     ZrtpStateClass(ZRtp *p);
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStates.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStates.h
index 44662a0..e90a543 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStates.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpStates.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2007 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpTextData.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpTextData.h
index 91b26c1..0be1e56 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpTextData.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpTextData.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
@@ -37,8 +37,12 @@
  *
  * @author Werner Dittmann <Werner.Dittmann@t-online.de>
  */
+
+extern char zrtpBuildInfo[];
+
 extern char clientId[];
-extern char zrtpVersion[];
+extern char zrtpVersion_11[];
+extern char zrtpVersion_12[];
 
 /**
  *
@@ -87,6 +91,8 @@
 
 extern char s256[];
 extern char s384[];
+extern char skn2[];
+extern char skn3[];
 extern const char* mandatoryHash;
 
 extern char aes3[];
@@ -102,6 +108,8 @@
 extern char dh3k[];
 extern char ec25[];
 extern char ec38[];
+extern char e255[];
+extern char e414[];
 
 extern char mult[];
 
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpUserCallback.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpUserCallback.h
index 3e4871c..d3c9f9d 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpUserCallback.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/ZrtpUserCallback.h
@@ -1,8 +1,8 @@
 /*

-  Copyright (C) 2006-2008 Werner Dittmann

+  Copyright (C) 2006-2013 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

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

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

   (at your option) any later version.

 

diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h
index b49622e..8f33462 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpCacheDbBackend.h
@@ -1,6 +1,19 @@
 /*
- *
- */
+  Copyright (C) 2006-2013 Werner Dittmann
+
+  This program 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 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_CACHE_DB_BACKEND_H_
 #define _ZRTP_CACHE_DB_BACKEND_H_
@@ -279,11 +292,11 @@
 
 
     /**
-     * Clean the cache.
-     *
-     * This method cleans the cache and discards all information about remote peers.
-     * The method does not delete the local (own) ZID. To delete local ZID information
-     * the user must delete the database base.
+     * @brief Clean the cache.
+     * 
+     * The function drops and re-creates all tables in the database. This removes all stored
+     * data. The application must not call this while a ZRTP call is active. Also the application
+     * <b>must</b> get the local ZID again.
      *
      * @param db Pointer to an internal structure that the database
      *           implementation requires.
diff --git a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpPacket.h b/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpPacket.h
index 18ba7a1..f01fb52 100644
--- a/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpPacket.h
+++ b/jni/libzrtp/sources/zrtp/libzrtpcpp/zrtpPacket.h
@@ -1,8 +1,8 @@
 /*
-  Copyright (C) 2006-2010 Werner Dittmann
+  Copyright (C) 2006-2013 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
+  it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
diff --git a/jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c b/jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c
index d73c88d..7dc9cdf 100644
--- a/jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c
+++ b/jni/libzrtp/sources/zrtp/zrtpCacheSqliteBackend.c
@@ -1,4 +1,22 @@
 /*
+  Copyright (C) 2012-2013 Werner Dittmann
+
+  This program 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 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 <stdio.h>
@@ -6,6 +24,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <time.h>
+#include <sqlite3.h>
 
 #include <crypto/zrtpDH.h>
 
@@ -55,6 +74,8 @@
 /* *****************************************************************************
  * SQL statements to process the zrtpIdOwn table.
  */
+static const char *dropZrtpIdOwn =      "DROP TABLE zrtpIdOwn;";
+
 /* SQLite doesn't care about the VARCHAR length. */
 static char *createZrtpIdOwn = "CREATE TABLE zrtpIdOwn(localZid CHAR(18), type INTEGER, accountInfo VARCHAR(1000));";
 
@@ -575,11 +596,29 @@
 
 static int closeCache(void *vdb)
 {
+
     sqlite3 *db = (sqlite3*)vdb;
     sqlite3_close(db);
     return SQLITE_OK;
 }
 
+static int clearCache(void *vdb, char *errString)
+{
+
+    sqlite3 *db = (sqlite3*)vdb;
+    sqlite3_stmt * stmt;
+    int rc;
+
+    rc = SQLITE_PREPARE(db, dropZrtpIdOwn, strlen(dropZrtpIdOwn)+1, &stmt, NULL);
+    rc = sqlite3_step(stmt);
+    sqlite3_finalize(stmt);
+
+    rc = createTables(db, errString);
+    if (rc)
+        return rc;
+    return SQLITE_OK;
+}
+
 static int insertZidNameRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid,
                                const char *accountInfo, zidNameRecord_t *zidName, char* errString)
 {
@@ -735,6 +774,7 @@
 {
     ops->openCache = openCache;
     ops->closeCache = closeCache;
+    ops->cleanCache = clearCache;
 
     ops->readLocalZid = readLocalZid;