summaryrefslogtreecommitdiff
path: root/src/libzrtpcpp
diff options
context:
space:
mode:
authorMark Purcell <msp@debian.org>2013-07-09 15:55:55 +0100
committerMark Purcell <msp@debian.org>2013-07-09 15:55:55 +0100
commit669109e369a1be69ff7c4108eb545eff4c5c26d9 (patch)
tree73c117a2e7dd22a7a6ee315101f6357ab43386ec /src/libzrtpcpp
libzrtpcpp (2.3.4-1) unstable; urgency=medium
* New upstream release - Fixes "CVE-2013-2221 CVE-2013-2222 CVE-2013-2223" (Closes: #714650) # imported from the archive
Diffstat (limited to 'src/libzrtpcpp')
-rw-r--r--src/libzrtpcpp/Base32.h228
-rwxr-xr-xsrc/libzrtpcpp/CMakeLists.txt9
-rw-r--r--src/libzrtpcpp/TimeoutProvider.h303
-rw-r--r--src/libzrtpcpp/ZIDFile.h157
-rw-r--r--src/libzrtpcpp/ZIDRecord.h307
-rw-r--r--src/libzrtpcpp/ZRtp.h1292
-rw-r--r--src/libzrtpcpp/ZrtpCWrapper.h1339
-rw-r--r--src/libzrtpcpp/ZrtpCallback.h367
-rw-r--r--src/libzrtpcpp/ZrtpCallbackWrapper.h101
-rwxr-xr-xsrc/libzrtpcpp/ZrtpCodes.h164
-rw-r--r--src/libzrtpcpp/ZrtpConfigure.h551
-rwxr-xr-xsrc/libzrtpcpp/ZrtpCrc32.h75
-rw-r--r--src/libzrtpcpp/ZrtpPacketBase.h147
-rw-r--r--src/libzrtpcpp/ZrtpPacketClearAck.h54
-rw-r--r--src/libzrtpcpp/ZrtpPacketCommit.h134
-rw-r--r--src/libzrtpcpp/ZrtpPacketConf2Ack.h60
-rw-r--r--src/libzrtpcpp/ZrtpPacketConfirm.h125
-rw-r--r--src/libzrtpcpp/ZrtpPacketDHPart.h120
-rw-r--r--src/libzrtpcpp/ZrtpPacketError.h68
-rw-r--r--src/libzrtpcpp/ZrtpPacketErrorAck.h56
-rw-r--r--src/libzrtpcpp/ZrtpPacketGoClear.h72
-rw-r--r--src/libzrtpcpp/ZrtpPacketHello.h191
-rw-r--r--src/libzrtpcpp/ZrtpPacketHelloAck.h59
-rw-r--r--src/libzrtpcpp/ZrtpPacketPing.h67
-rw-r--r--src/libzrtpcpp/ZrtpPacketPingAck.h74
-rw-r--r--src/libzrtpcpp/ZrtpPacketRelayAck.h56
-rw-r--r--src/libzrtpcpp/ZrtpPacketSASrelay.h113
-rw-r--r--src/libzrtpcpp/ZrtpQueue.h917
-rw-r--r--src/libzrtpcpp/ZrtpStateClass.h324
-rw-r--r--src/libzrtpcpp/ZrtpStates.h90
-rw-r--r--src/libzrtpcpp/ZrtpTextData.h124
-rw-r--r--src/libzrtpcpp/ZrtpUserCallback.h234
-rwxr-xr-xsrc/libzrtpcpp/crypto/TwoCFB.cpp79
-rw-r--r--src/libzrtpcpp/crypto/ZrtpDH.h168
-rw-r--r--src/libzrtpcpp/crypto/aesCFB.h87
-rw-r--r--src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp130
-rw-r--r--src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp77
-rw-r--r--src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp349
-rw-r--r--src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp68
-rw-r--r--src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp68
-rw-r--r--src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp89
-rw-r--r--src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp89
-rw-r--r--src/libzrtpcpp/crypto/hmac256.h96
-rw-r--r--src/libzrtpcpp/crypto/hmac384.h96
-rw-r--r--src/libzrtpcpp/crypto/openssl/AesCFB.cpp89
-rwxr-xr-xsrc/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp242
-rw-r--r--src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp426
-rw-r--r--src/libzrtpcpp/crypto/openssl/hmac256.cpp67
-rw-r--r--src/libzrtpcpp/crypto/openssl/hmac384.cpp67
-rw-r--r--src/libzrtpcpp/crypto/openssl/sha256.cpp97
-rw-r--r--src/libzrtpcpp/crypto/openssl/sha384.cpp97
-rw-r--r--src/libzrtpcpp/crypto/sha256.h144
-rw-r--r--src/libzrtpcpp/crypto/sha384.h144
-rwxr-xr-xsrc/libzrtpcpp/crypto/twoCFB.h87
-rw-r--r--src/libzrtpcpp/crypto/twofish.c1733
-rwxr-xr-xsrc/libzrtpcpp/crypto/twofish.h265
-rwxr-xr-xsrc/libzrtpcpp/crypto/twofish_cfb.c82
-rw-r--r--src/libzrtpcpp/zrtpPacket.h342
-rw-r--r--src/libzrtpcpp/zrtpccrtp.h76
59 files changed, 13332 insertions, 0 deletions
diff --git a/src/libzrtpcpp/Base32.h b/src/libzrtpcpp/Base32.h
new file mode 100644
index 0000000..fbe2983
--- /dev/null
+++ b/src/libzrtpcpp/Base32.h
@@ -0,0 +1,228 @@
+#ifndef BASE32_H
+#define BASE32_H
+
+/*
+ *
+ * Copyright (c) 2002 Bryce "Zooko" Wilcox-O'Hearn Permission is hereby
+ * granted, free of charge, to any person obtaining a copy of this software to
+ * deal in this software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of this software, and to permit persons to whom this software
+ * is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THIS SOFTWARE.
+ *
+ * Converted to C++ by:
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+/**
+ * @file Base32.h
+ * @brief C++ implmentation of the Base32 encoding and decoding
+ *
+ * ZRTP uses the base 32 encoding and decoding to generate the Short
+ * Authentication String (SAS).
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <iostream>
+#include <cstdlib>
+
+#include <string.h>
+#include <assert.h>
+#include <stddef.h>
+
+using namespace std;
+
+extern int divceil(int a, int b);
+
+class Base32 {
+
+ public:
+
+ /**
+ * A Constructor that decodes from base32 into binary.
+ *
+ * The constructor decodes the base32 encoded data back into binary
+ * data. Use <code>getDecoded(...)</code> to get the binary data.
+ *
+ * @param encoded
+ * The string that contains the base32 encoded data.
+ */
+ Base32(const string encoded);
+
+ /**
+ * A Constructor that decodes from base32 into binary.
+ *
+ * This constructor decodes the base32 encoded data back into
+ * binary data. Only the specified number of bits are decoded
+ * (should be a multiple of 5). Use
+ * <code>getDecoded(...)</code> to get the binary data.
+ *
+ * @param encoded
+ * The string that contains the base32 encoded data.
+ * @param noOfBits
+ * How many bits to decode into binary data.
+ */
+ Base32(const string encoded, int noOfBits);
+
+ /**
+ * A Constructor that encodes binary data.
+ *
+ * The constructor converts the first specified number of bits of
+ * the binary data into a base32 presentation. Use
+ * <code>getEncoded</code> to get the encoded data.
+ *
+ * @param data
+ * A pointer to the first bits (byte) of binary data
+ * @param noOfBits
+ * How many bits to use for encoding. Should be a
+ * multiple of 5.
+ */
+ Base32(const unsigned char* data, int noOfBits);
+
+ ~Base32();
+
+ /**
+ * Get the decoded binary data and its length.
+ *
+ * The method returns the decoded binary data if the appropriate
+ * Constructor was used. Otherwise we return <code>NULL</code>
+ * pointer and length zero.
+ *
+ * <em>Note:</em> This method returns a pointer to the decoded
+ * binary data. The Base32 object manages this pointer, thus you
+ * may need to copy the data to a save place before deleting this
+ * object. If the object is deleted this pointer is no longer
+ * valid.
+ *
+ * @param length
+ * A reference to an integer.
+ * @return
+ * A pointer to the decoded binary data.
+ */
+ const unsigned char* getDecoded(int &length);
+
+ /**
+ * Get the encoded base32 string.
+ *
+ * The method returns a string that contains the base32 encoded
+ * data if the appropriate constructor was used. Otherwise we
+ * return an empty string.
+ *
+ * @return
+ * The string containing the base32 encoded data.
+ */
+ const string getEncoded() { return encoded; };
+
+ /**
+ * Compute the number of base32 encoded characters given the
+ * number of bits.
+ *
+ * @param lengthInBits
+ * The length of the data in bits
+ * @return
+ * The length of the base-32 encoding of the data in characters
+ */
+ static size_t const b2alen(const size_t lengthInBits) {
+ return divceil(lengthInBits, 5); };
+
+ private:
+
+ /**
+ * Decodes a string with base32 presentation into binary data.
+ *
+ * a2b_l() will return a result big enough to hold lengthinbits bits. So
+ * for example if cs is 4 characters long (encoding at least 15 and up to
+ * 20 bits) and lengthinbits is 16, then a2b_l() will return a string of
+ * length 2 (since 2 bytes is sufficient to store 16 bits). If cs is 4
+ * characters long and lengthinbits is 20, then a2b_l() will return a
+ * string of length 3 (since 3 bytes is sufficient to store 20 bits). Note
+ * that `b2a_l()' does not mask off unused least-significant bits, so for
+ * example if cs is 4 characters long and lengthinbits is 17, then you
+ * must ensure that all three of the unused least-significant bits of cs
+ * are zero bits or you will get the wrong result. This precondition is
+ * tested by assertions if assertions are enabled. (Generally you just
+ * require the encoder to ensure this consistency property between the
+ * least significant zero bits and value of `lengthinbits', and reject
+ * strings that have a length-in-bits which isn't a multiple of 8 and yet
+ * don't have trailing zero bits, as improperly encoded.)
+ *
+ * @param cs
+ * The data to be decoded
+ * @param size
+ * The length of the input data buffer. Usually divceil(length in bits, 5).
+ * @param lengthinbits
+ * The number of bits of data in <code>cs</code> to be decoded
+ */
+ void a2b_l(const string cs, size_t size, const size_t lengthinbits);
+
+ /**
+ * Encodes binary to to base32 presentation.
+ *
+ * b2a_l() will generate a base-32 encoded string big enough to encode
+ * lengthinbits bits. So for example if os is 2 bytes long and
+ * lengthinbits is 15, then b2a_l() will generate a 3-character- long
+ * base-32 encoded string (since 3 quintets is sufficient to encode 15
+ * bits). If os is 2 bytes long and lengthinbits is 16 (or None), then
+ * b2a_l() will generate a 4-character string. Note that `b2a_l()' does
+ * not mask off unused least-significant bits, so for example if os is 2
+ * bytes long and lengthinbits is 15, then you must ensure that the unused
+ * least-significant bit of os is a zero bit or you will get the wrong
+ * result. This precondition is tested by assertions if assertions are
+ * enabled.
+ *
+ * Warning: if you generate a base-32 encoded string with `b2a_l()', and
+ * then someone else tries to decode it by calling `a2b()' instead of
+ * `a2b_l()', then they will (probably) get a different string than the
+ * one you encoded! So only use `b2a_l()' when you are sure that the
+ * encoding and decoding sides know exactly which `lengthinbits' to use.
+ * If you do not have a way for the encoder and the decoder to agree upon
+ * the lengthinbits, then it is best to use `b2a()' and `a2b()'. The only
+ * drawback to using `b2a()' over `b2a_l()' is that when you have a number
+ * of bits to encode that is not a multiple of 8, `b2a()' can sometimes
+ * generate a base-32 encoded string that is one or two characters longer
+ * than necessary.
+ *
+ * @param cs
+ * Pointer to binary data.
+ * @param len
+ * Length of the binary data buffer. Usually (noOfBits+7)/8.
+ * @param noOfBits
+ * The number of bits of data in encoded into `cs'
+ */
+ void b2a_l(const unsigned char* cs, int len, const size_t noOfBits);
+
+ /**
+ * Holds the pointer to decoded binary data
+ */
+ unsigned char *binaryResult;
+
+ /**
+ * Length of decoding result
+ */
+ int resultLength;
+
+ /**
+ * The string containing the base32 encoded data.
+ */
+ string encoded;
+
+ unsigned char smallBuffer[128];
+};
+
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/CMakeLists.txt b/src/libzrtpcpp/CMakeLists.txt
new file mode 100755
index 0000000..099a233
--- /dev/null
+++ b/src/libzrtpcpp/CMakeLists.txt
@@ -0,0 +1,9 @@
+
+if(enable_ccrtp)
+ set(ccrtp_inst ZrtpQueue.h zrtpccrtp.h ZrtpUserCallback.h TimeoutProvider.h)
+endif()
+
+install(FILES
+ ZrtpCodes.h ZrtpConfigure.h ZrtpCallback.h ZrtpCWrapper.h
+ ${ccrtp_inst} DESTINATION include/libzrtpcpp)
+
diff --git a/src/libzrtpcpp/TimeoutProvider.h b/src/libzrtpcpp/TimeoutProvider.h
new file mode 100644
index 0000000..9f0edf7
--- /dev/null
+++ b/src/libzrtpcpp/TimeoutProvider.h
@@ -0,0 +1,303 @@
+/*
+ Copyright (C) 2006, 2005, 2004 Erik Eliasson, Johan Bilien, Werner Dittmann
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#ifndef TIMEOUTPROVIDER_H
+#define TIMEOUTPROVIDER_H
+
+/**
+ * Provides a way to request timeouts after a number of milli seconds.
+ *
+ * A command is associated to each timeout.
+ *
+ * Modified to use the common c++ library functions and the STL
+ * list by Werner Dittmann.
+ *
+ * @author Erik Eliasson, eliasson@it.kth.se, 2003
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <list>
+#include <sys/time.h>
+
+#include <commoncpp/config.h>
+#include <commoncpp/thread.h>
+
+/**
+ * Represents a request of a "timeout" (delivery of a command to a
+ * "timeout receiver" after at least a specified time period).
+ *
+ * Slightly modified to use gettimeofday directly.
+ *
+ * NOTE: This class is only used internaly.
+ * @author Erik Eliasson
+ * @author Werner Dittmann
+ */
+template <class TOCommand, class TOSubscriber>
+class TPRequest
+{
+
+public:
+
+ TPRequest( TOSubscriber tsi, int timeoutMs, const TOCommand &command):
+ subscriber(tsi)
+ {
+ struct timeval tv;
+ gettimeofday(&tv, NULL );
+
+ when_ms = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000;
+ when_ms += timeoutMs;
+ this->command = command;
+ }
+
+ /**
+ * @param t ms since Epoch
+ */
+ bool happensBefore(uint64 t)
+ {
+ if (when_ms < t) {
+ return true;
+ }
+ if (when_ms > t) {
+ return false;
+ }
+ return false; // if equal it does not "happens_before"
+
+ }
+
+ bool happensBefore(const TPRequest *req){
+ return happensBefore(req->when_ms);
+ }
+
+ /**
+ * Number of milli seconds until timeout from when this method is
+ * called
+ */
+ int getMsToTimeout ()
+ {
+ struct timeval tv;
+ gettimeofday(&tv, NULL );
+
+ uint64 now = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000;
+
+ if (happensBefore(now)) {
+ return 0;
+ }
+ else {
+ return (int)(when_ms - now);
+ }
+ }
+
+ TOCommand getCommand()
+ {
+ return command;
+ }
+
+ TOSubscriber getSubscriber()
+ {
+ return subscriber;
+ }
+
+ /**
+ * Two timeout requests are considered equeal if they have
+ * the same subscriber AND command AND time when they
+ * occur. If one of the time is zero then this is a
+ * wildcard and matches always.
+ */
+ bool operator==(const TPRequest<TOCommand, TOSubscriber> &req)
+ {
+ if (req.subscriber == subscriber &&
+ req.command == command &&
+ req.when_ms == when_ms) {
+ return true;
+ }
+ return false;
+ }
+
+private:
+ TOSubscriber subscriber;
+ uint64 when_ms; // Time since Epoch in ms when the timeout
+ // will happen
+
+ TOCommand command; // Command that will be delivered to the
+ // receiver (subscriber) of the timeout.
+};
+
+/**
+ * Class to generate objects giving timeout functionality.
+ *
+ * @author Erik Eliasson
+ * @author Werner Dittmann
+ */
+template<class TOCommand, class TOSubscriber>
+ class TimeoutProvider : public ost::Thread, ost::Event {
+
+public:
+
+ /**
+ * Timeout Provide Constructor
+ */
+ TimeoutProvider(): requests(), synchLock(), stop(false) { }
+
+ /**
+ * Destructor also terminates the Timeout thread.
+ */
+ ~TimeoutProvider() {
+ terminate();
+ }
+
+ /**
+ * Terminates the Timeout provider thread.
+ */
+ void stopThread(){
+ stop = true;
+ signal(); // signal event to waiting thread
+ }
+
+ /**
+ * Request a timeout trigger.
+ *
+ * @param time_ms Number of milli-seconds until the timeout is
+ * wanted. Note that a small additional period of time is
+ * added that depends on execution speed.
+ * @param subscriber The receiver of the callback when the command has timed
+ * out. This argument must not be NULL.
+ * @param command Specifies the String command to be passed back in the
+ * callback.
+ */
+ void requestTimeout(int32_t time_ms, TOSubscriber subscriber, const TOCommand &command)
+ {
+ TPRequest<TOCommand, TOSubscriber>* request =
+ new TPRequest<TOCommand, TOSubscriber>(subscriber, time_ms, command);
+
+ synchLock.enter();
+
+ if (requests.size()==0) {
+ requests.push_front(request);
+ signal();
+ synchLock.leave();
+ return;
+ }
+ if (request->happensBefore(requests.front())) {
+ requests.push_front(request);
+ signal();
+ synchLock.leave();
+ return;
+ }
+ if (requests.back()->happensBefore(request)){
+ requests.push_back(request);
+ signal();
+ synchLock.leave();
+ return;
+ }
+
+ typename std::list<TPRequest<TOCommand, TOSubscriber>* >::iterator i;
+ for(i = requests.begin(); i != requests.end(); i++ ) {
+ if( request->happensBefore(*i)) {
+ requests.insert(i, request);
+ break;
+ }
+ }
+ signal();
+ synchLock.leave();
+ }
+
+ /**
+ * Removes timeout requests that belong to a subscriber and command.
+ *
+ * @see requestTimeout
+ */
+ void cancelRequest(TOSubscriber subscriber, const TOCommand &command)
+ {
+ synchLock.enter();
+ typename std::list<TPRequest<TOCommand, TOSubscriber>* >::iterator i;
+ for(i = requests.begin(); i != requests.end(); ) {
+ if( (*i)->getCommand() == command &&
+ (*i)->getSubscriber() == subscriber) {
+ i = requests.erase(i);
+ continue;
+ }
+ i++;
+ }
+ synchLock.leave();
+ }
+
+protected:
+
+ void run()
+ {
+ do {
+ synchLock.enter();
+ int32_t time = 3600000;
+ int32_t size = 0;
+ if ((size = requests.size()) > 0) {
+ time = requests.front()->getMsToTimeout();
+ }
+ if (time == 0 && size > 0) {
+ if (stop){ // This must be checked so that we will
+ // stop even if we have timeouts to deliver.
+ synchLock.leave();
+ return;
+ }
+ TPRequest<TOCommand, TOSubscriber>* req = requests.front();
+ TOSubscriber subs = req->getSubscriber();
+ TOCommand command = req->getCommand();
+
+ requests.pop_front();
+
+ synchLock.leave(); // call the command with free Mutex
+ subs->handleTimeout(command);
+ continue;
+ }
+ synchLock.leave();
+ if (stop) { // If we were told to stop while delivering
+ // a timeout we will exit here
+ return;
+ }
+ reset(); // ready to receive triggers again
+ wait(time);
+ if (stop) { // If we are told to exit while waiting we
+ // will exit
+ return;
+ }
+ } while(true);
+ }
+
+private:
+
+ // The timeouts are ordered in the order of which they
+ // will expire. Nearest in future is first in list.
+ std::list<TPRequest<TOCommand, TOSubscriber> *> requests;
+
+ ost::Mutex synchLock; // Protects the internal data structures
+
+ bool stop; // Flag to tell the worker thread
+ // to terminate. Set to true and
+ // wake the worker thread to
+ // terminate it.
+};
+
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/ZIDFile.h b/src/libzrtpcpp/ZIDFile.h
new file mode 100644
index 0000000..0637c27
--- /dev/null
+++ b/src/libzrtpcpp/ZIDFile.h
@@ -0,0 +1,157 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+
+#include <libzrtpcpp/ZIDRecord.h>
+
+#ifndef _ZIDFILE_H_
+#define _ZIDFILE_H_
+/**
+ * @file ZIDFile.h
+ * @brief ZID file management
+ *
+ * A ZID file stores (caches) some data that helps ZRTP to achives its
+ * key continuity feature. See @c ZIDRecord for further info which data
+ * the ZID file contains.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+/**
+ * This class implements a ZID (ZRTP Identifiers) file.
+ *
+ * The ZID file holds information about peers.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZIDFile {
+
+private:
+
+ FILE* zidFile;
+ unsigned char associatedZid[IDENTIFIER_LEN];
+ /**
+ * The private ZID file constructor.
+ *
+ */
+ ZIDFile(): zidFile(NULL) {};
+ ~ZIDFile();
+ void createZIDFile(char* name);
+ void checkDoMigration(char* name);
+
+public:
+
+ /**
+ * Get the an instance of ZIDFile.
+ *
+ * This method just creates an instance an store a pointer to it
+ * in a static variable. The ZIDFile is a singleton, thus only
+ * <em>one</em> ZID file can be open at one time.
+ *
+ * @return
+ * A pointer to the global ZIDFile singleton instance.
+ */
+ static ZIDFile* getInstance();
+ /**
+ * Open the named ZID file and return a ZID file class.
+ *
+ * This static function either opens an existing ZID file or
+ * creates a new ZID file with the given name. The ZIDFile is a
+ * singleton, thus only <em>one</em> ZID file can be open at one
+ * time.
+ *
+ * To open another ZID file you must close the active ZID file
+ * first.
+ *
+ * @param name
+ * The name of the ZID file to open or create
+ * @return
+ * 1 if file could be opened/created, 0 if the ZID instance
+ * already has an open file, -1 if open/creation of file failed.
+ */
+ int open(char *name);
+
+ /**
+ * Check if ZIDFile has an active (open) file.
+ *
+ * @return
+ * True if ZIDFile has an active file, false otherwise
+ */
+ bool isOpen() { return (zidFile != NULL); };
+
+ /**
+ * Close the ZID file.
+ * Closes the ZID file, and prepares to open a new ZID file.
+ */
+ void close();
+
+ /**
+ * Get a ZID record from the active ZID file.
+ *
+ * The method get the identifier data from the ZID record parameter,
+ * locates the record in the ZID file and fills in the RS1, RS2, and
+ * other data.
+ *
+ * If no matching record exists in the ZID file the method creates
+ * it and fills it with default values.
+ *
+ * @param zidRecord
+ * The ZID record that contains the identifier data. The method
+ * fills in data .
+ * @return
+ * Currently always 1 to indicate sucess
+ */
+ unsigned int getRecord(ZIDRecord* zidRecord);
+
+ /**
+ * Save a ZID record into the active ZID file.
+ *
+ * This method saves the content of a ZID record into the ZID file. Before
+ * you can save the ZID record you must have performed a getRecord()
+ * first.
+ *
+ * @param zidRecord
+ * The ZID record to save.
+ * @return
+ * 1 on success
+ */
+ unsigned int saveRecord(ZIDRecord *zidRecord);
+
+ /**
+ * Get the ZID associated with this ZID file.
+ *
+ * @return
+ * Pointer to the ZID
+ */
+ const unsigned char* getZid() { return associatedZid; };
+};
+
+/**
+ * @}
+ */
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/ZIDRecord.h b/src/libzrtpcpp/ZIDRecord.h
new file mode 100644
index 0000000..eb2d190
--- /dev/null
+++ b/src/libzrtpcpp/ZIDRecord.h
@@ -0,0 +1,307 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZIDRECORD_H_
+#define _ZIDRECORD_H_
+
+
+/**
+ * @file ZIDRecord.h
+ * @brief ZID record management
+ *
+ * A ZID record stores (caches) ZID (ZRTP ID) specific data that helps ZRTP
+ * to achives its key continuity feature. Please refer to the ZRTP
+ * specification to get detailed information about the ZID.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+#define IDENTIFIER_LEN 12
+#define RS_LENGTH 32
+#define TIME_LENGTH 8 // 64 bit, can hold time on 64 bit systems
+
+/**
+ * This is the recod structure of version 1 ZID records.
+ *
+ * This is not longer in use - only during migration.
+ */
+typedef struct zidrecord1 {
+ char recValid; //!< if 1 record is valid, if 0: invalid
+ char ownZid; //!< if >1 record contains own ZID, usually 1st record
+ char rs1Valid; //!< if 1 RS1 contains valid data
+ char rs2Valid; //!< if 1 RS2 contains valid data
+ unsigned char identifier[IDENTIFIER_LEN]; ///< the peer's ZID or own ZID
+ unsigned char rs1Data[RS_LENGTH], rs2Data[RS_LENGTH]; ///< the peer's RS data
+} zidrecord1_t;
+
+/**
+ * This is the recod structure of version 2 ZID records.
+ */
+typedef struct zidrecord2 {
+ char version; ///< version number of file format, this is #2
+ char flags; ///< bit field holding various flags, see below
+ char filler1; ///< round up to next 32 bit
+ char filler2; ///< round up to next 32 bit
+ unsigned char identifier[IDENTIFIER_LEN]; ///< the peer's ZID or own ZID
+ unsigned char rs1Interval[TIME_LENGTH]; ///< expiration time of RS1; -1 means indefinite
+ unsigned char rs1Data[RS_LENGTH]; ///< the peer's RS2 data
+ unsigned char rs2Interval[TIME_LENGTH]; ///< expiration time of RS2; -1 means indefinite
+ unsigned char rs2Data[RS_LENGTH]; ///< the peer's RS2 data
+ unsigned char mitmKey[RS_LENGTH]; ///< MiTM key if available
+} zidrecord2_t;
+
+
+#ifndef __EXPORT
+ #if __GNUC__ >= 4
+ #define __EXPORT __attribute__ ((visibility("default")))
+ #define __LOCAL __attribute__ ((visibility("hidden")))
+ #elif defined _WIN32 || defined __CYGWIN__
+ #define __EXPORT __declspec(dllimport)
+ #define __LOCAL
+ #else
+ #define __EXPORT
+ #define __LOCAL
+ #endif
+#endif
+
+static const int Valid = 0x1;
+static const int SASVerified = 0x2;
+static const int RS1Valid = 0x4;
+static const int RS2Valid = 0x8;
+static const int MITMKeyAvailable = 0x10;
+static const int OwnZIDRecord = 0x20;
+
+/**
+ * This class implements the ZID record.
+ *
+ * The ZID record holds data about a peer. According to ZRTP specification
+ * we use a ZID to identify a peer. ZRTP uses the RS (Retained Secret) data
+ * to construct shared secrets.
+ * <p>
+ * NOTE: ZIDRecord has ZIDFile as friend. ZIDFile knows about the private
+ * data of ZIDRecord - please keep both classes synchronized.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZIDRecord {
+ friend class ZIDFile;
+
+private:
+ zidrecord2_t record;
+ unsigned long position;
+
+ /*
+ * The default constructor is private
+ */
+ ZIDRecord() {
+ record.version = 2;
+ }
+
+ /**
+ * Functions for I/O availabe for ZID file handling
+ *
+ * These functions are private, thus only friends may use it.
+ */
+ void setPosition(long pos) {position = pos;}
+ long getPosition() {return position; }
+
+ zidrecord2_t* getRecordData() {return &record; }
+ int getRecordLength() {return sizeof(zidrecord2_t); }
+
+ bool isValid() { return ((record.flags & Valid) == Valid); }
+ void setValid() { record.flags |= Valid; }
+
+public:
+ /**
+ * Create a ZID Record with given ZID data
+ *
+ * The method creates a new ZID record and initializes its ZID
+ * data field. All other fields are set to null.
+ *
+ * An application can use this pre-initialized record to look
+ * up the associated record in the ZID file. If the record is
+ * available, the ZID record fields are filled with the stored
+ * data.
+ *
+ * @param idData
+ * Pointer to the fixed length ZID data
+ * @see ZIDFile::getRecord
+ */
+ ZIDRecord(const unsigned char *idData) {
+ memset(&record, 0, sizeof(zidrecord2_t));
+ memcpy(record.identifier, idData, IDENTIFIER_LEN);
+ record.version = 2;
+ }
+
+ /**
+ * Set @c valid flag in RS1
+ */
+ void setRs1Valid() { record.flags |= RS1Valid; }
+
+ /**
+ * reset @c valid flag in RS1
+ */
+ void resetRs1Valid() { record.flags &= ~RS1Valid; }
+
+ /**
+ * Check @c valid flag in RS1
+ */
+ bool isRs1Valid() { return ((record.flags & RS1Valid) == RS1Valid); }
+
+ /**
+ * Set @c valid flag in RS2
+ */
+ void setRs2Valid() { record.flags |= RS2Valid; }
+
+ /**
+ * Reset @c valid flag in RS2
+ */
+ void resetRs2Valid() { record.flags &= ~RS2Valid; }
+
+ /**
+ * Check @c valid flag in RS2
+ */
+ bool isRs2Valid() { return ((record.flags & RS2Valid) == RS2Valid); }
+
+ /**
+ * Set MITM key available
+ */
+ void setMITMKeyAvailable() { record.flags |= MITMKeyAvailable; }
+
+ /**
+ * Reset MITM key available
+ */
+ void resetMITMKeyAvailable() { record.flags &= ~MITMKeyAvailable; }
+
+ /**
+ * Check MITM key available is set
+ */
+ bool isMITMKeyAvailable() { return ((record.flags & MITMKeyAvailable) == MITMKeyAvailable); }
+
+ /**
+ * Mark this as own ZID record
+ */
+ void setOwnZIDRecord() { record.flags = OwnZIDRecord; }
+ /**
+ * Reset own ZID record marker
+ */
+ void resetOwnZIDRecord(){ record.flags = 0; }
+
+ /**
+ * Check own ZID record marker
+ */
+ bool isOwnZIDRecord() { return (record.flags == OwnZIDRecord); } // no other flag allowed if own ZID
+
+ /**
+ * Set SAS for this ZID as verified
+ */
+ void setSasVerified() { record.flags |= SASVerified; }
+ /**
+ * Reset SAS for this ZID as verified
+ */
+ void resetSasVerified() { record.flags &= ~SASVerified; }
+
+ /**
+ * Check if SAS for this ZID was verified
+ */
+ bool isSasVerified() { return ((record.flags & SASVerified) == SASVerified); }
+
+ /**
+ * Return the ZID for this record
+ */
+ const uint8_t* getIdentifier() {return record.identifier; }
+
+ /**
+ * Check if RS1 is still valid
+ *
+ * Returns true if RS1 is still valid, false otherwise.
+ *
+ * @return
+ * Returns true is RS1 is not expired (valid), false otherwise.
+ */
+ const bool isRs1NotExpired();
+
+ /**
+ * Returns pointer to RS1 data.
+ */
+ const unsigned char* getRs1() { return record.rs1Data; }
+
+ /**
+ * Check if RS2 is still valid
+ *
+ * Returns true if RS2 is still valid, false otherwise.
+ *
+ * @return
+ * Returns true is RS2 is not expired (valid), false otherwise.
+ */
+ const bool isRs2NotExpired();
+
+ /**
+ * Returns pointer to RS1 data.
+ */
+ const unsigned char* getRs2() { return record.rs2Data; }
+
+ /**
+ * Sets new RS1 data and associated expiration value.
+ *
+ * If the expiration value is >0 or -1 the method stores the new
+ * RS1. Before it stores the new RS1 it shifts the exiting RS1
+ * into RS2 (together with its expiration time). Then it computes
+ * the expiration time of the and stores the result together with
+ * the new RS1.
+ *
+ * If the expiration value is -1 then this RS will never expire.
+ *
+ * If the expiration value is 0 then the expiration value of a
+ * stored RS1 is cleared and no new RS1 value is stored. Also RS2
+ * is left unchanged.
+ *
+ * @param data
+ * Points to the new RS1 data.
+ * @param expire
+ * The expiration interval in seconds. Default is -1.
+ *
+ */
+ void setNewRs1(const unsigned char* data, int32_t expire =-1);
+
+ /**
+ * Set MiTM key data.
+ *
+ */
+ void setMiTMData(const unsigned char* data);
+
+ /**
+ * Get MiTM key data.
+ *
+ */
+ const unsigned char* getMiTMData() {return record.mitmKey; }
+};
+
+#endif // ZIDRECORD
+
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/ZRtp.h b/src/libzrtpcpp/ZRtp.h
new file mode 100644
index 0000000..4e03f28
--- /dev/null
+++ b/src/libzrtpcpp/ZRtp.h
@@ -0,0 +1,1292 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTP_H_
+#define _ZRTP_H_
+/**
+ * @file ZRtp.h
+ * @brief The ZRTP main engine
+ * @defgroup GNU_ZRTP The GNU ZRTP C++ implementation
+ * @{
+ */
+
+#include <cstdlib>
+
+#include <libzrtpcpp/ZrtpPacketHello.h>
+#include <libzrtpcpp/ZrtpPacketHelloAck.h>
+#include <libzrtpcpp/ZrtpPacketCommit.h>
+#include <libzrtpcpp/ZrtpPacketDHPart.h>
+#include <libzrtpcpp/ZrtpPacketConfirm.h>
+#include <libzrtpcpp/ZrtpPacketConf2Ack.h>
+#include <libzrtpcpp/ZrtpPacketGoClear.h>
+#include <libzrtpcpp/ZrtpPacketClearAck.h>
+#include <libzrtpcpp/ZrtpPacketError.h>
+#include <libzrtpcpp/ZrtpPacketErrorAck.h>
+#include <libzrtpcpp/ZrtpPacketPing.h>
+#include <libzrtpcpp/ZrtpPacketPingAck.h>
+#include <libzrtpcpp/ZrtpPacketSASrelay.h>
+#include <libzrtpcpp/ZrtpPacketRelayAck.h>
+#include <libzrtpcpp/ZrtpCallback.h>
+#include <libzrtpcpp/ZIDRecord.h>
+
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
+// Prepare to support digest algorithms up to 512 bit (64 bytes)
+#define MAX_DIGEST_LENGTH 64
+#define IMPL_MAX_DIGEST_LENGTH 64
+
+class __EXPORT ZrtpStateClass;
+class ZrtpDH;
+
+/**
+ * The main ZRTP class.
+ *
+ * This is the main class of the RTP/SRTP independent part of the GNU
+ * ZRTP. It handles the ZRTP HMAC, DH, and other data management. The
+ * user of this class needs to know only a few methods and needs to
+ * provide only a few external functions to connect to a Timer
+ * mechanism and to send data via RTP and SRTP. Refer to the
+ * ZrtpCallback class to get detailed information regading the
+ * callback methods required by GNU RTP.
+ *
+ * The class ZrtpQueue is the GNU ccRTP specific implementation that
+ * extends standard ccRTP RTP provide ZRTP support. Refer to the
+ * documentation of ZrtpQueue to get more information about the usage
+ * of ZRtp and associated classes.
+ *
+ * The main entry into the ZRTP class is the processExtensionHeader()
+ * method.
+ *
+ * This class does not directly handle the protocol states, timers,
+ * and packet resend. The protocol state engine is responsible for
+ * these actions.
+ *
+ * Example how to use ZRtp:
+ *<pre>
+ * zrtpEngine = new ZRtp((uint8_t*)ownZid, (ZrtpCallback*)this, idString);
+ * zrtpEngine->startZrtpEngine();
+ *</pre>
+ * @see ZrtpCallback
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZRtp {
+
+ public:
+
+ /**
+ * Constructor intializes all relevant data but does not start the
+ * engine.
+ */
+ ZRtp(uint8_t* myZid, ZrtpCallback* cb, std::string id,
+ ZrtpConfigure* config, bool mitmm= false, bool sasSignSupport= false);
+
+ /**
+ * Destructor cleans up.
+ */
+ ~ZRtp();
+
+ /**
+ * Kick off the ZRTP protocol engine.
+ *
+ * This method calls the ZrtpStateClass#evInitial() state of the state
+ * engine. After this call we are able to process ZRTP packets
+ * from our peer and to process them.
+ */
+ void startZrtpEngine();
+
+ /**
+ * Stop ZRTP security.
+ *
+ */
+ void stopZrtp();
+
+ /**
+ * Process RTP extension header.
+ *
+ * This method expects to get a pointer to the extension header of
+ * a RTP packet. The method checks if this is really a ZRTP
+ * packet. If this check fails the method returns 0 (false) in
+ * case this is not a ZRTP packet. We return a 1 if we processed
+ * the ZRTP extension header and the caller may process RTP data
+ * after the extension header as usual. The method return -1 the
+ * call shall dismiss the packet and shall not forward it to
+ * further RTP processing.
+ *
+ * @param extHeader
+ * A pointer to the first byte of the extension header. Refer to
+ * RFC3550.
+ * @param peerSSRC
+ * The peer's SSRC.
+ * @return
+ * Code indicating further packet handling, see description above.
+ */
+ void processZrtpMessage(uint8_t *extHeader, uint32_t peerSSRC);
+
+ /**
+ * Process a timeout event.
+ *
+ * We got a timeout from the timeout provider. Forward it to the
+ * protocol state engine.
+ *
+ */
+ void processTimeout();
+
+ /**
+ * Check for and handle GoClear ZRTP packet header.
+ *
+ * This method checks if this is a GoClear packet. If not, just return
+ * false. Otherwise handle it according to the specification.
+ *
+ * @param extHeader
+ * A pointer to the first byte of the extension header. Refer to
+ * RFC3550.
+ * @return
+ * False if not a GoClear, true otherwise.
+ */
+ bool handleGoClear(uint8_t *extHeader);
+
+ /**
+ * Set the auxilliary secret.
+ *
+ * Use this method to set the auxilliary secret data. Refer to ZRTP
+ * specification, chapter 4.3 ff
+ *
+ * @param data
+ * Points to the secret data.
+ * @param length
+ * Length of the auxilliary secrect in bytes
+ */
+ void setAuxSecret(uint8_t* data, int32_t length);
+
+ /**
+ * Check current state of the ZRTP state engine
+ *
+ * @param state
+ * The state to check.
+ * @return
+ * Returns true id ZRTP engine is in the given state, false otherwise.
+ */
+ bool inState(int32_t state);
+
+ /**
+ * Set SAS as verified.
+ *
+ * Call this method if the user confirmed (verfied) the SAS. ZRTP
+ * remembers this together with the retained secrets data.
+ */
+ void SASVerified();
+
+ /**
+ * Reset the SAS verfied flag for the current active user's retained secrets.
+ *
+ */
+ void resetSASVerified();
+
+ /**
+ * Get the ZRTP Hello Hash data.
+ *
+ * Use this method to get the ZRTP Hello Hash data. The method
+ * returns the data as a string containing the ZRTP protocol version and
+ * hex-digits.
+ *
+ * Refer to ZRTP specification, chapter 8.
+ *
+ * @return
+ * a std:string containing the Hello hash value as hex-digits. The
+ * hello hash is available immediately after class instantiation.
+ */
+ std::string getHelloHash();
+
+ /**
+ * Get the peer's ZRTP Hello Hash data.
+ *
+ * Use this method to get the peer's ZRTP Hello Hash data. The method
+ * returns the data as a string containing the ZRTP protocol version and
+ * hex-digits.
+ *
+ * The peer's hello hash is available only after ZRTP received a hello. If
+ * no data is available the function returns an empty string.
+ *
+ * Refer to ZRTP specification, chapter 8.
+ *
+ * @return
+ * a std:string containing the Hello version and the hello hash as hex digits.
+ */
+ std::string getPeerHelloHash();
+
+ /**
+ * Get Multi-stream parameters.
+ *
+ * Use this method to get the Multi-stream that were computed during
+ * the ZRTP handshake. An application may use these parameters to
+ * enable multi-stream processing for an associated SRTP session.
+ *
+ * Refer to chapter 4.4.2 in the ZRTP specification for further details
+ * and restriction how and when to use multi-stream mode.
+ *
+ * @return
+ * a string that contains the multi-stream parameters. The application
+ * must not modify the contents of this string, it is opaque data. The
+ * application may hand over this string to a new ZrtpQueue instance
+ * to enable multi-stream processing for this ZrtpQueue.
+ * If ZRTP was not started or ZRTP is not yet in secure state the method
+ * returns an empty string.
+ */
+ std::string getMultiStrParams();
+
+ /**
+ * Set Multi-stream parameters.
+ *
+ * Use this method to set the parameters required to enable Multi-stream
+ * processing of ZRTP. The multi-stream parameters must be set before the
+ * application starts the ZRTP protocol engine.
+ *
+ * Refer to chapter 4.4.2 in the ZRTP specification for further details
+ * of multi-stream mode.
+ *
+ * @param parameters
+ * A string that contains the multi-stream parameters that this
+ * new ZrtpQueue instanace shall use. See also
+ * <code>getMultiStrParams()</code>
+ */
+ void setMultiStrParams(std::string parameters);
+
+ /**
+ * Check if this ZRTP session is a Multi-stream session.
+ *
+ * Use this method to check if this ZRTP instance uses multi-stream.
+ * Refer to chapters 4.2 and 4.4.2 in the ZRTP.
+ *
+ * @return
+ * True if multi-stream is used, false otherwise.
+ */
+ bool isMultiStream();
+
+ /**
+ * Check if the other ZRTP client supports Multi-stream.
+ *
+ * Use this method to check if the other ZRTP client supports
+ * Multi-stream mode.
+ *
+ * @return
+ * True if multi-stream is available, false otherwise.
+ */
+ bool isMultiStreamAvailable();
+
+ /**
+ * Accept a PBX enrollment request.
+ *
+ * If a PBX service asks to enroll the PBX trusted MitM key and the user
+ * accepts this request, for example by pressing an OK button, the client
+ * application shall call this method and set the parameter
+ * <code>accepted</code> to true. If the user does not accept the request
+ * set the parameter to false.
+ *
+ * @param accepted
+ * True if the enrollment request is accepted, false otherwise.
+ */
+ void acceptEnrollment(bool accepted);
+
+ /**
+ * Check the state of the enrollment mode.
+ *
+ * If true then we will set the enrollment flag (E) in the confirm
+ * packets and perform the enrollment actions. A MitM (PBX) enrollment service
+ * started this ZRTP session. Can be set to true only if mitmMode is also true.
+ *
+ * @return status of the enrollmentMode flag.
+ */
+ bool isEnrollmentMode();
+
+ /**
+ * Set the state of the enrollment mode.
+ *
+ * If true then we will set the enrollment flag (E) in the confirm
+ * packets and perform the enrollment actions. A MitM (PBX) enrollment
+ * service must sets this mode to true.
+ *
+ * Can be set to true only if mitmMode is also true.
+ *
+ * @param enrollmentMode defines the new state of the enrollmentMode flag
+ */
+ void setEnrollmentMode(bool enrollmentMode);
+
+ /**
+ * Check if a peer's cache entry has a vaild MitM key.
+ *
+ * If true then the other peer ha a valid MtiM key, i.e. the peer has performed
+ * the enrollment procedure. A PBX ZRTP Back-2-Back application can use this function
+ * to check which of the peers is enrolled.
+ *
+ * @return True if the other peer has a valid Mitm key (is enrolled).
+ */
+ bool isPeerEnrolled();
+
+ /**
+ * Send the SAS relay packet.
+ *
+ * The method creates and sends a SAS relay packet according to the ZRTP
+ * specifications. Usually only a MitM capable user agent (PBX) uses this
+ * function.
+ *
+ * @param sh the full SAS hash value, 32 bytes
+ * @param render the SAS rendering algorithm
+ */
+ bool sendSASRelayPacket(uint8_t* sh, std::string render);
+
+ /**
+ * Get the commited SAS rendering algorithm for this ZRTP session.
+ *
+ * @return the commited SAS rendering algorithm
+ */
+ std::string getSasType();
+
+ /**
+ * Get the computed SAS hash for this ZRTP session.
+ *
+ * A PBX ZRTP back-to-Back function uses this function to get the SAS
+ * hash of an enrolled client to construct the SAS relay packet for
+ * the other client.
+ *
+ * @return a pointer to the byte array that contains the full
+ * SAS hash.
+ */
+ uint8_t* getSasHash();
+
+ /**
+ * Set signature data.
+ *
+ * This functions stores signature data and transmitts it during ZRTP
+ * processing to the other party as part of the Confirm packets. Refer to
+ * chapters 5.7 and 7.2.
+ *
+ * The signature data must be set before ZRTP the application calls
+ * <code>start()</code>.
+ *
+ * @param data
+ * The signature data including the signature type block. The method
+ * copies this data into the Confirm packet at signature type block.
+ * @param length
+ * The length of the signature data in bytes. This length must be
+ * multiple of 4.
+ * @return
+ * True if the method stored the data, false otherwise.
+ */
+ bool setSignatureData(uint8_t* data, int32_t length);
+
+ /**
+ * Get signature data.
+ *
+ * This functions returns a pointer to the signature data that was receivied
+ * during ZRTP processing. Refer to chapters 5.7 and 7.2.
+ *
+ * The returned pointer points to volatile data that is valid only during the
+ * <code>checkSASSignature()</code> callback funtion. The application must copy
+ * the signature data if it will be used after the callback function returns.
+ *
+ * The signature data can be retrieved after ZRTP enters secure state.
+ * <code>start()</code>.
+ *
+ * @return
+ * Pointer to signature data.
+ */
+ const uint8_t* getSignatureData();
+
+ /**
+ * Get length of signature data in number of bytes.
+ *
+ * This functions returns the length of signature data that was receivied
+ * during ZRTP processing. Refer to chapters 5.7 and 7.2.
+ *
+ * @return
+ * Length in bytes of the received signature data. The method returns
+ * zero if no signature data is avilable.
+ */
+ int32_t getSignatureLength();
+
+ /**
+ * Emulate a Conf2Ack packet.
+ *
+ * This method emulates a Conf2Ack packet. According to ZRTP specification
+ * the first valid SRTP packet that the Initiator receives must switch
+ * on secure mode. Refer to chapter 4 in the specificaton
+ *
+ */
+ void conf2AckSecure();
+
+ /**
+ * Get other party's ZID (ZRTP Identifier) data
+ *
+ * This functions returns the other party's ZID that was receivied
+ * during ZRTP processing.
+ *
+ * The ZID data can be retrieved after ZRTP receive the first Hello
+ * packet from the other party. The application may call this method
+ * for example during SAS processing in showSAS(...) user callback
+ * method.
+ *
+ * @param data
+ * Pointer to a data buffer. This buffer must have a size of
+ * at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
+ * @return
+ * Number of bytes copied into the data buffer - must be equivalent
+ * to 96 bit, usually 12 bytes.
+ */
+ int32_t getPeerZid(uint8_t* data);
+
+private:
+ friend class ZrtpStateClass;
+
+ /**
+ * The state engine takes care of protocol processing.
+ */
+ ZrtpStateClass* stateEngine;
+
+ /**
+ * This is my ZID that I send to the peer.
+ */
+ uint8_t zid[IDENTIFIER_LEN];
+
+ /**
+ * The peer's ZID
+ */
+ uint8_t peerZid[IDENTIFIER_LEN];
+
+ /**
+ * The callback class provides me with the interface to send
+ * data and to deal with timer management of the hosting system.
+ */
+ ZrtpCallback* callback;
+
+ /**
+ * My active Diffie-Helman context
+ */
+ ZrtpDH* dhContext;
+
+ /**
+ * The computed DH shared secret
+ */
+ uint8_t* DHss;
+
+ /**
+ * My computed public key
+ */
+ uint8_t pubKeyBytes[400];
+ /**
+ * Length off public key
+ */
+// int32_t pubKeyLen;
+ /**
+ * My Role in the game
+ */
+ Role myRole;
+
+ /**
+ * The human readable SAS value
+ */
+ std::string SAS;
+
+ /**
+ * The SAS hash for signaling and alike. Refer to chapters
+ * 4.5 and 7 how sasHash, sasValue and the SAS string are derived.
+ */
+ uint8_t sasHash[MAX_DIGEST_LENGTH];
+ /**
+ * The ids for the retained and other shared secrets
+ */
+ uint8_t rs1IDr[MAX_DIGEST_LENGTH];
+ uint8_t rs2IDr[MAX_DIGEST_LENGTH];
+ uint8_t auxSecretIDr[MAX_DIGEST_LENGTH];
+ uint8_t pbxSecretIDr[MAX_DIGEST_LENGTH];
+
+ uint8_t rs1IDi[MAX_DIGEST_LENGTH];
+ uint8_t rs2IDi[MAX_DIGEST_LENGTH];
+ uint8_t auxSecretIDi[MAX_DIGEST_LENGTH];
+ uint8_t pbxSecretIDi[MAX_DIGEST_LENGTH];
+
+ /**
+ * pointers to aux secret storage and length of aux secret
+ */
+ uint8_t* auxSecret;
+ int32_t auxSecretLength;
+
+ /**
+ * Record if valid rs1 and/or rs1 were found in the
+ * retaind secret cache.
+ */
+ bool rs1Valid;
+ bool rs2Valid;
+ /**
+ * My hvi
+ */
+ uint8_t hvi[MAX_DIGEST_LENGTH];
+
+ /**
+ * The peer's hvi
+ */
+ uint8_t peerHvi[8*ZRTP_WORD_SIZE];
+
+ /**
+ * Context to compute the SHA256 hash of selected messages.
+ * Used to compute the s0, refer to chapter 4.4.1.4
+ */
+ void* msgShaContext;
+ /**
+ * Commited Hash, Cipher, and public key algorithms
+ */
+ AlgorithmEnum* hash;
+ AlgorithmEnum* cipher;
+ AlgorithmEnum* pubKey;
+ /**
+ * The selected SAS type.
+ */
+ AlgorithmEnum* sasType;
+
+ /**
+ * The selected SAS type.
+ */
+ AlgorithmEnum* authLength;
+
+ /**
+ * The Hash images as defined in chapter 5.1.1 (H0 is a random value,
+ * not stored here). Need full SHA 256 lenght to store hash value but
+ * only the leftmost 128 bits are used in computations and comparisons.
+ */
+ uint8_t H0[IMPL_MAX_DIGEST_LENGTH];
+ uint8_t H1[IMPL_MAX_DIGEST_LENGTH];
+ uint8_t H2[IMPL_MAX_DIGEST_LENGTH];
+ uint8_t H3[IMPL_MAX_DIGEST_LENGTH];
+ uint8_t helloHash[IMPL_MAX_DIGEST_LENGTH];
+
+ uint8_t peerHelloHash[IMPL_MAX_DIGEST_LENGTH];
+ uint8_t peerHelloVersion[ZRTP_WORD_SIZE + 1]; // +1 for nul byte
+
+ // We get the peer's H? from the message where length is defined as 8 words
+ uint8_t peerH0[8*ZRTP_WORD_SIZE];
+ uint8_t peerH1[8*ZRTP_WORD_SIZE];
+ uint8_t peerH2[8*ZRTP_WORD_SIZE];
+ uint8_t peerH3[8*ZRTP_WORD_SIZE];
+
+ /**
+ * The SHA256 hash over selected messages
+ */
+ uint8_t messageHash[MAX_DIGEST_LENGTH];
+
+ /**
+ * The s0
+ */
+ uint8_t s0[MAX_DIGEST_LENGTH];
+
+ /**
+ * The new Retained Secret
+ */
+ uint8_t newRs1[MAX_DIGEST_LENGTH];
+
+ /**
+ * The GoClear HMAC keys and confirm HMAC key
+ */
+ uint8_t hmacKeyI[MAX_DIGEST_LENGTH];
+ uint8_t hmacKeyR[MAX_DIGEST_LENGTH];
+
+ /**
+ * The Initiator's srtp key and salt
+ */
+ uint8_t srtpKeyI[MAX_DIGEST_LENGTH];
+ uint8_t srtpSaltI[MAX_DIGEST_LENGTH];
+
+ /**
+ * The Responder's srtp key and salt
+ */
+ uint8_t srtpKeyR[MAX_DIGEST_LENGTH];
+ uint8_t srtpSaltR[MAX_DIGEST_LENGTH];
+
+ /**
+ * The keys used to encrypt/decrypt the confirm message
+ */
+ uint8_t zrtpKeyI[MAX_DIGEST_LENGTH];
+ uint8_t zrtpKeyR[MAX_DIGEST_LENGTH];
+
+ /**
+ * Pointers to negotiated hash and HMAC functions
+ */
+ void (*hashFunction)(unsigned char *data,
+ unsigned int data_length,
+ unsigned char *digest);
+
+ void (*hashListFunction)(unsigned char *data[],
+ unsigned int data_length[],
+ unsigned char *digest);
+
+ void (*hmacFunction)(uint8_t* key, uint32_t key_length,
+ uint8_t* data, int32_t data_length,
+ uint8_t* mac, uint32_t* mac_length);
+
+ void (*hmacListFunction)( uint8_t* key, uint32_t key_length,
+ uint8_t* data[], uint32_t data_length[],
+ uint8_t* mac, uint32_t* mac_length );
+
+ void* (*createHashCtx)();
+
+ void (*closeHashCtx)(void* ctx, unsigned char* digest);
+
+ void (*hashCtxFunction)(void* ctx, unsigned char* data,
+ unsigned int dataLength);
+
+ void (*hashCtxListFunction)(void* ctx, unsigned char* dataChunks[],
+ unsigned int dataChunkLength[]);
+
+ int32_t hashLength;
+
+ // Funtion pointers to implicit hash and hmac functions
+ void (*hashFunctionImpl)(unsigned char *data,
+ unsigned int data_length,
+ unsigned char *digest);
+
+ void (*hashListFunctionImpl)(unsigned char *data[],
+ unsigned int data_length[],
+ unsigned char *digest);
+
+ void (*hmacFunctionImpl)(uint8_t* key, uint32_t key_length,
+ uint8_t* data, int32_t data_length,
+ uint8_t* mac, uint32_t* mac_length);
+
+ void (*hmacListFunctionImpl)( uint8_t* key, uint32_t key_length,
+ uint8_t* data[], uint32_t data_length[],
+ uint8_t* mac, uint32_t* mac_length );
+
+ int32_t hashLengthImpl;
+
+ /**
+ * The ZRTP Session Key
+ * Refer to chapter 5.4.1.4
+ */
+ uint8_t zrtpSession[MAX_DIGEST_LENGTH];
+
+ /**
+ * True if this ZRTP instance uses multi-stream mode.
+ */
+ bool multiStream;
+
+ /**
+ * True if the other ZRTP client supports multi-stream mode.
+ */
+ bool multiStreamAvailable;
+
+ /**
+ * Enable MitM (PBX) enrollment
+ *
+ * If set to true then ZRTP honors the PBX enrollment flag in
+ * Commit packets and calls the appropriate user callback
+ * methods. If the parameter is set to false ZRTP ignores the PBX
+ * enrollment flags.
+ */
+ bool enableMitmEnrollment;
+
+ /**
+ * True if a valid trusted MitM key of the other peer is available, i.e. enrolled.
+ */
+ bool peerIsEnrolled;
+
+ /**
+ * Set to true if the Hello packet contained the M-flag (MitM flag).
+ * We use this later to check some stuff for SAS Relay processing
+ */
+ bool mitmSeen;
+
+ /**
+ * Temporarily store computed pbxSecret, if user accepts enrollment then
+ * it will copied to our ZID record of the PBX (MitM)
+ */
+ uint8_t* pbxSecretTmp;
+ uint8_t pbxSecretTmpBuffer[MAX_DIGEST_LENGTH];
+
+ /**
+ * If true then we will set the enrollment flag (E) in the confirm
+ * packets. Set to true if the PBX enrollment service started this ZRTP
+ * session. Can be set to true only if mitmMode is also true.
+ */
+ bool enrollmentMode;
+
+ /**
+ * Configuration data which algorithms to use.
+ */
+ ZrtpConfigure configureAlgos;
+ /**
+ * Pre-initialized packets.
+ */
+ ZrtpPacketHello zrtpHello;
+ ZrtpPacketHelloAck zrtpHelloAck;
+ ZrtpPacketConf2Ack zrtpConf2Ack;
+ ZrtpPacketClearAck zrtpClearAck;
+ ZrtpPacketGoClear zrtpGoClear;
+ ZrtpPacketError zrtpError;
+ ZrtpPacketErrorAck zrtpErrorAck;
+ ZrtpPacketDHPart zrtpDH1;
+ ZrtpPacketDHPart zrtpDH2;
+ ZrtpPacketCommit zrtpCommit;
+ ZrtpPacketConfirm zrtpConfirm1;
+ ZrtpPacketConfirm zrtpConfirm2;
+ ZrtpPacketPingAck zrtpPingAck;
+ ZrtpPacketSASrelay zrtpSasRelay;
+ ZrtpPacketRelayAck zrtpRelayAck;
+
+ /**
+ * Random IV data to encrypt the confirm data, 128 bit for AES
+ */
+ uint8_t randomIV[16];
+
+ uint8_t tempMsgBuffer[1024];
+ int32_t lengthOfMsgData;
+
+ /**
+ * Variables to store signature data. Includes the signature type block
+ */
+ const uint8_t* signatureData; // will be set when needed
+ int32_t signatureLength; // overall length in bytes
+
+ /**
+ * Is true if the other peer signaled SAS signature support in its Hello packet.
+ */
+ bool signSasSeen;
+
+ uint32_t peerSSRC; // peer's SSRC, required to setup PingAck packet
+
+ /**
+ * Enable or disable paranoid mode.
+ *
+ * The Paranoid mode controls the behaviour and handling of the SAS verify flag. If
+ * Panaoid mode is set to flase then ZRtp applies the normal handling. If Paranoid
+ * mode is set to true then the handling is:
+ *
+ * <ul>
+ * <li> Force the SAS verify flag to be false at srtpSecretsOn() callback. This gives
+ * the user interface (UI) the indication to handle the SAS as <b>not verified</b>.
+ * See implementation note below.</li>
+ * <li> Don't set the SAS verify flag in the <code>Confirm</code> packets, thus the other
+ * also must report the SAS as <b>not verified</b>.</li>
+ * <li> ignore the <code>SASVerified()</code> function, thus do not set the SAS to verified
+ * in the ZRTP cache. </li>
+ * <li> Disable the <b>Trusted PBX MitM</b> feature. Just send the <code>SASRelay</code> packet
+ * but do not process the relayed data. This protects the user from a malicious
+ * "trusted PBX".</li>
+ * </ul>
+ * ZRtp performs alls other steps during the ZRTP negotiations as usual, in particular it
+ * computes, compares, uses, and stores the retained secrets. This avoids unnecessary warning
+ * messages. The user may enable or disable the Paranoid mode on a call-by-call basis without
+ * breaking the key continuity data.
+ *
+ * <b>Implementation note:</b></br>
+ * An application shall always display the SAS code if the SAS verify flag is <code>false</code>.
+ * The application shall also use mechanisms to remind the user to compare the SAS code, for
+ * example useing larger fonts, different colours and other display features.
+ */
+ bool paranoidMode;
+
+ /**
+ * Find the best Hash algorithm that is offered in Hello.
+ *
+ * Find the best, that is the strongest, Hash algorithm that our peer
+ * offers in its Hello packet.
+ *
+ * @param hello
+ * The Hello packet.
+ * @return
+ * The Enum that identifies the best offered Hash algortihm. Return
+ * <code>NumSupportedHashes</code> to signal that no matching Hash algorithm
+ * was found at all.
+ */
+ AlgorithmEnum* findBestHash(ZrtpPacketHello *hello);
+
+ /**
+ * Find the best symmetric cipher algorithm that is offered in Hello.
+ *
+ * Find the best, that is the strongest, cipher algorithm that our peer
+ * offers in its Hello packet.
+ *
+ * @param hello
+ * The Hello packet.
+ * @param pk
+ * The id of the selected public key algorithm
+ * @return
+ * The Enum that identifies the best offered Cipher algortihm. Return
+ * <code>NumSupportedSymCiphers</code> to signal that no matching Cipher algorithm
+ * was found at all.
+ */
+ AlgorithmEnum* findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk);
+
+ /**
+ * Find the best Public Key algorithm that is offered in Hello.
+ *
+ * Find the best, that is the strongest, public key algorithm that our peer
+ * offers in its Hello packet.
+ *
+ * @param hello
+ * The Hello packet.
+ * @return
+ * The Enum that identifies the best offered Public Key algortihm. Return
+ * <code>NumSupportedPubKeys</code> to signal that no matching Public Key algorithm
+ * was found at all.
+ */
+ AlgorithmEnum* findBestPubkey(ZrtpPacketHello *hello);
+
+ /**
+ * Find the best SAS algorithm that is offered in Hello.
+ *
+ * Find the best, that is the strongest, SAS algorithm that our peer
+ * offers in its Hello packet.
+ *
+ * @param hello
+ * The Hello packet.
+ * @return
+ * The Enum that identifies the best offered SAS algortihm. Return
+ * <code>NumSupportedSASTypes</code> to signal that no matching SAS algorithm
+ * was found at all.
+ */
+ AlgorithmEnum* findBestSASType(ZrtpPacketHello* hello);
+
+ /**
+ * Find the best authentication length that is offered in Hello.
+ *
+ * Find the best, that is the strongest, authentication length that our peer
+ * offers in its Hello packet.
+ *
+ * @param hello
+ * The Hello packet.
+ * @return
+ * The Enum that identifies the best offered authentication length. Return
+ * <code>NumSupportedAuthLenghts</code> to signal that no matching length
+ * was found at all.
+ */
+ AlgorithmEnum* findBestAuthLen(ZrtpPacketHello* hello);
+
+ /**
+ * Check if MultiStream mode is offered in Hello.
+ *
+ * Find the best, that is the strongest, authentication length that our peer
+ * offers in its Hello packet.
+ *
+ * @param hello
+ * The Hello packet.
+ * @return
+ * True if multi stream mode is available, false otherwise.
+ */
+ bool checkMultiStream(ZrtpPacketHello* hello);
+
+ /**
+ * Save the computed MitM secret to the ZID record of the peer
+ */
+ void writeEnrollmentPBX();
+
+ /**
+ * Compute my hvi value according to ZRTP specification.
+ */
+ void computeHvi(ZrtpPacketDHPart* dh, ZrtpPacketHello *hello);
+
+ void computeSharedSecretSet(ZIDRecord& zidRec);
+
+ void computeSRTPKeys();
+
+ void KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLength,
+ uint8_t* context, int32_t contextLength, int32_t L, uint8_t* output);
+
+ void generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec);
+
+ void generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec);
+
+ void generateKeysMultiStream();
+
+ void computePBXSecret();
+
+ void setNegotiatedHash(AlgorithmEnum* hash);
+
+ /*
+ * The following methods are helper functions for ZrtpStateClass.
+ * ZrtpStateClass calls them to prepare packets, send data, report
+ * problems, etc.
+ */
+ /**
+ * Send a ZRTP packet.
+ *
+ * The state engines calls this method to send a packet via the RTP
+ * stack.
+ *
+ * @param packet
+ * Points to the ZRTP packet.
+ * @return
+ * zero if sending failed, one if packet was send
+ */
+ int32_t sendPacketZRTP(ZrtpPacketBase *packet);
+
+ /**
+ * Activate a Timer using the host callback.
+ *
+ * @param tm
+ * The time in milliseconds.
+ * @return
+ * zero if activation failed, one if timer was activated
+ */
+ int32_t activateTimer(int32_t tm);
+
+ /**
+ * Cancel the active Timer using the host callback.
+ *
+ * @return
+ * zero if activation failed, one if timer was activated
+ */
+ int32_t cancelTimer();
+
+ /**
+ * Prepare a Hello packet.
+ *
+ * Just take the preinitialized Hello packet and return it. No
+ * further processing required.
+ *
+ * @return
+ * A pointer to the initialized Hello packet.
+ */
+ ZrtpPacketHello* prepareHello();
+
+ /**
+ * Prepare a HelloAck packet.
+ *
+ * Just take the preinitialized HelloAck packet and return it. No
+ * further processing required.
+ *
+ * @return
+ * A pointer to the initialized HelloAck packet.
+ */
+ ZrtpPacketHelloAck* prepareHelloAck();
+
+ /**
+ * Prepare a Commit packet.
+ *
+ * We have received a Hello packet from our peer. Check the offers
+ * it makes to us and select the most appropriate. Using the
+ * selected values prepare a Commit packet and return it to protocol
+ * state engine.
+ *
+ * @param hello
+ * Points to the received Hello packet
+ * @param errMsg
+ * Points to an integer that can hold a ZRTP error code.
+ * @return
+ * A pointer to the prepared Commit packet
+ */
+ ZrtpPacketCommit* prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg);
+
+ /**
+ * Prepare a Commit packet for Multi Stream mode.
+ *
+ * Using the selected values prepare a Commit packet and return it to protocol
+ * state engine.
+ *
+ * @param hello
+ * Points to the received Hello packet
+ * @return
+ * A pointer to the prepared Commit packet for multi stream mode
+ */
+ ZrtpPacketCommit* prepareCommitMultiStream(ZrtpPacketHello *hello);
+
+ /**
+ * Prepare the DHPart1 packet.
+ *
+ * This method prepares a DHPart1 packet. The input to the method is always
+ * a Commit packet received from the peer. Also we a in the role of the
+ * Responder.
+ *
+ * When we receive a Commit packet we get the selected ciphers, hashes, etc
+ * and cross-check if this is ok. Then we need to initialize a set of DH
+ * keys according to the selected cipher. Using this data we prepare our DHPart1
+ * packet.
+ */
+ ZrtpPacketDHPart* prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMsg);
+
+ /**
+ * Prepare the DHPart2 packet.
+ *
+ * This method prepares a DHPart2 packet. The input to the method is always
+ * a DHPart1 packet received from the peer. Our peer sends the DH1Part as
+ * response to our Commit packet. Thus we are in the role of the
+ * Initiator.
+ *
+ */
+ ZrtpPacketDHPart* prepareDHPart2(ZrtpPacketDHPart* dhPart1, uint32_t* errMsg);
+
+ /**
+ * Prepare the Confirm1 packet.
+ *
+ * This method prepare the Confirm1 packet. The input to this method is the
+ * DHPart2 packect received from our peer. The peer sends the DHPart2 packet
+ * as response of our DHPart1. Here we are in the role of the Responder
+ *
+ */
+ ZrtpPacketConfirm* prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* errMsg);
+
+ /**
+ * Prepare the Confirm1 packet in multi stream mode.
+ *
+ * This method prepares the Confirm1 packet. The state engine call this method
+ * if multi stream mode is selected and a Commit packet was received. The input to
+ * this method is the Commit.
+ * Here we are in the role of the Responder
+ *
+ */
+ ZrtpPacketConfirm* prepareConfirm1MultiStream(ZrtpPacketCommit* commit, uint32_t* errMsg);
+
+ /**
+ * Prepare the Confirm2 packet.
+ *
+ * This method prepare the Confirm2 packet. The input to this method is the
+ * Confirm1 packet received from our peer. The peer sends the Confirm1 packet
+ * as response of our DHPart2. Here we are in the role of the Initiator
+ */
+ ZrtpPacketConfirm* prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* errMsg);
+
+ /**
+ * Prepare the Confirm2 packet in multi stream mode.
+ *
+ * This method prepares the Confirm2 packet. The state engine call this method if
+ * multi stream mode is active and in state CommitSent. The input to this method is
+ * the Confirm1 packet received from our peer. The peer sends the Confirm1 packet
+ * as response of our Commit packet in multi stream mode.
+ * Here we are in the role of the Initiator
+ */
+ ZrtpPacketConfirm* prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, uint32_t* errMsg);
+
+ /**
+ * Prepare the Conf2Ack packet.
+ *
+ * This method prepare the Conf2Ack packet. The input to this method is the
+ * Confirm2 packet received from our peer. The peer sends the Confirm2 packet
+ * as response of our Confirm1. Here we are in the role of the Initiator
+ */
+ ZrtpPacketConf2Ack* prepareConf2Ack(ZrtpPacketConfirm* confirm2, uint32_t* errMsg);
+
+ /**
+ * Prepare the ErrorAck packet.
+ *
+ * This method prepares the ErrorAck packet. The input to this method is the
+ * Error packet received from the peer.
+ */
+ ZrtpPacketErrorAck* prepareErrorAck(ZrtpPacketError* epkt);
+
+ /**
+ * Prepare the Error packet.
+ *
+ * This method prepares the Error packet. The input to this method is the
+ * error code to be included into the message.
+ */
+ ZrtpPacketError* prepareError(uint32_t errMsg);
+
+ /**
+ * Prepare a ClearAck packet.
+ *
+ * This method checks if the GoClear message is valid. If yes then switch
+ * off SRTP processing, stop sending of RTP packets (pause transmit) and
+ * inform the user about the fact. Only if user confirms the GoClear message
+ * normal RTP processing is resumed.
+ *
+ * @return
+ * NULL if GoClear could not be authenticated, a ClearAck packet
+ * otherwise.
+ */
+ ZrtpPacketClearAck* prepareClearAck(ZrtpPacketGoClear* gpkt);
+
+ /**
+ * Prepare the ErrorAck packet.
+ *
+ * This method prepares the ErrorAck packet. The input to this method is the
+ * Error packet received from the peer.
+ */
+ ZrtpPacketPingAck* preparePingAck(ZrtpPacketPing* ppkt);
+
+ /**
+ * Prepare the RelayAck packet.
+ *
+ * This method prepares the RelayAck packet. The input to this method is the
+ * SASrelay packet received from the peer.
+ */
+ ZrtpPacketRelayAck* prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* errMsg);
+
+ /**
+ * Prepare a GoClearAck packet w/o HMAC
+ *
+ * Prepare a GoCLear packet without a HMAC but with a short error message.
+ * This type of GoClear is used if something went wrong during the ZRTP
+ * negotiation phase.
+ *
+ * @return
+ * A goClear packet without HMAC
+ */
+ ZrtpPacketGoClear* prepareGoClear(uint32_t errMsg = 0);
+
+ /**
+ * Compare the hvi values.
+ *
+ * Compare a received Commit packet with our Commit packet and returns
+ * which Commit packt is "more important". See chapter 5.2 to get further
+ * information how to compare Commit packets.
+ *
+ * @param commit
+ * Pointer to the peer's commit packet we just received.
+ * @return
+ * <0 if our Commit packet is "less important"
+ * >0 if our Commit is "more important"
+ * 0 shouldn't happen because we compare crypto hashes
+ */
+ int32_t compareCommit(ZrtpPacketCommit *commit);
+
+ /**
+ * Verify the H2 hash image.
+ *
+ * Verifies the H2 hash contained in a received commit message.
+ * This functions just verifies H2 but does not store it.
+ *
+ * @param commit
+ * Pointer to the peer's commit packet we just received.
+ * @return
+ * true if H2 is ok and verified
+ * false if H2 could not be verified
+ */
+ bool verifyH2(ZrtpPacketCommit *commit);
+
+ /**
+ * Send information messages to the hosting environment.
+ *
+ * The ZRTP implementation uses this method to send information messages
+ * to the host. Along with the message ZRTP provides a severity indicator
+ * that defines: Info, Warning, Error, Alert. Refer to the MessageSeverity
+ * enum in the ZrtpCallback class.
+ *
+ * @param severity
+ * This defines the message's severity
+ * @param subCode
+ * The subcode identifying the reason.
+ * @see ZrtpCodes#MessageSeverity
+ */
+ void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+ /**
+ * ZRTP state engine calls this if the negotiation failed.
+ *
+ * ZRTP calls this method in case ZRTP negotiation failed. The parameters
+ * show the severity as well as some explanatory text.
+ *
+ * @param severity
+ * This defines the message's severity
+ * @param subCode
+ * The subcode identifying the reason.
+ * @see ZrtpCodes#MessageSeverity
+ */
+ void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+ /**
+ * ZRTP state engine calls this method if the other side does not support ZRTP.
+ *
+ * If the other side does not answer the ZRTP <em>Hello</em> packets then
+ * ZRTP calls this method,
+ *
+ */
+ void zrtpNotSuppOther();
+
+ /**
+ * Signal SRTP secrets are ready.
+ *
+ * This method calls a callback method to inform the host that the SRTP
+ * secrets are ready.
+ *
+ * @param part
+ * Defines for which part (sender or receiver) to switch on security
+ * @return
+ * Returns false if something went wrong during initialization of SRTP
+ * context. Propagate error back to state engine.
+ */
+ bool srtpSecretsReady(EnableSecurity part);
+
+ /**
+ * Switch off SRTP secrets.
+ *
+ * This method calls a callback method to inform the host that the SRTP
+ * secrets shall be cleared.
+ *
+ * @param part
+ * Defines for which part (sender or receiver) to clear
+ */
+ void srtpSecretsOff(EnableSecurity part);
+
+ /**
+ * ZRTP state engine calls these methods to enter or leave its
+ * synchronization mutex.
+ */
+ void synchEnter();
+
+ void synchLeave();
+
+ /**
+ * Helper function to store ZRTP message data in a temporary buffer
+ *
+ * This functions first clears the temporary buffer, then stores
+ * the packet's data to it. We use this to check the packet's HMAC
+ * after we received the HMAC key in to following packet.
+ *
+ * @param data
+ * Pointer to the packet's ZRTP message
+ */
+ void storeMsgTemp(ZrtpPacketBase* pkt);
+
+ /**
+ * Helper function to check a ZRTP message HMAC
+ *
+ * This function gets a HMAC key and uses it to compute a HMAC
+ * with this key and the stored data of a previous received ZRTP
+ * message. It compares the computed HMAC and the HMAC stored in
+ * the received message and returns the result.
+ *
+ * @param key
+ * Pointer to the HMAC key.
+ * @return
+ * Returns true if the computed HMAC and the stored HMAC match,
+ * false otherwise.
+ */
+ bool checkMsgHmac(uint8_t* key);
+
+ /**
+ * Set the client ID for ZRTP Hello message.
+ *
+ * The user of ZRTP must set its id to identify itself in the
+ * ZRTP HELLO message. The maximum length is 16 characters. Shorter
+ * id string are allowed, they will be filled with blanks. A longer id
+ * is truncated to 16 characters.
+ *
+ * The identifier is set in the Hello packet of ZRTP. Thus only after
+ * setting the identifier ZRTP can compute the HMAC and the final
+ * helloHash.
+ *
+ * @param id
+ * The client's id
+ */
+ void setClientId(std::string id);
+};
+
+/**
+ * @}
+ */
+#endif // ZRTP
+
diff --git a/src/libzrtpcpp/ZrtpCWrapper.h b/src/libzrtpcpp/ZrtpCWrapper.h
new file mode 100644
index 0000000..0126545
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpCWrapper.h
@@ -0,0 +1,1339 @@
+/*
+ This file defines the GNU ZRTP C-to-C++ wrapper.
+ Copyright (C) 2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef ZRTPCWRAPPER_H
+#define ZRTPCWRAPPER_H
+
+/**
+ *
+ * @file ZrtpCWrapper.h
+ * @brief The GNU ZRTP C-to-C++ wrapper.
+ *
+ * To avoid any include of C++ header files some structure, defines, and
+ * enumerations are repeated in this file. Refer to the inline comments if
+ * you modify the file.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ *
+ * @see ZRtp
+ */
+
+#include <stdint.h>
+
+/**
+ * Defines to specify the role a ZRTP peer has.
+ *
+ * According to the ZRTP specification the role determines which keys to
+ * use to encrypt or decrypt SRTP data.
+ *
+ * <ul>
+ * <li> The Initiator encrypts SRTP data using the <em>keyInitiator</em> and the
+ * <em>saltInitiator</em> data, the Responder uses these data to decrypt.
+ * </li>
+ * <li> The Responder encrypts SRTP data using the <em>keyResponder</em> and the
+ * <em>saltResponder</em> data, the Initiator uses these data to decrypt.
+ * </li>
+ * </ul>
+ */
+/*
+ * Keep the following defines in sync with Role enumeration in ZrtpCallback.h
+ */
+#define Responder 1 /*!< This client is in ZRTP Responder mode */
+#define Initiator 2 /*!< This client is in ZRTP Initiator mode */
+
+#define CRC_SIZE 4 /*!< Size of CRC code of a ZRTP packet */
+#define ZRTP_MAGIC 0x5a525450 /*!< The magic code that identifies a ZRTP packet */
+#define MAX_ZRTP_SIZE 3072 /*!< The biggest ZRTP packet ever possible */
+
+/*
+ * IMPORTANT: keep the following enums in synch with ZrtpCodes. We copy them here
+ * to avoid any C++ header includes and defines. The protocol states are located
+ * ZrtpStateClass.h .
+ */
+/**
+ * This enum defines the information message severity.
+ *
+ * The ZRTP implementation issues information messages to inform the user
+ * about ongoing processing, unusual behavior, or alerts in case of severe
+ * problems. Each main severity code a number of sub-codes exist that
+ * specify the exact nature of the problem.
+ *
+ * An application gets message severity codes and the associated sub-codes
+ * via the ZrtpUserCallback#showMessage method.
+ *
+ * The severity levels and their meaning are:
+ *
+ * <dl>
+ * <dt>Info</dt> <dd>keeps the user informed about ongoing processing and
+ * security setup. The enumeration InfoCodes defines the subcodes.
+ * </dd>
+ * <dt>Warning</dt> <dd>is an information about some security issues, e.g. if
+ * an AES 256 encryption is request but only DH 3072 as public key scheme
+ * is supported. ZRTP will establish a secure session (SRTP). The
+ * enumeration WarningCodes defines the sub-codes.
+ * </dd>
+ * <dt>Severe</dt> <dd>is used if an error occured during ZRTP protocol usage.
+ * In case of <em>Severe</em> ZRTP will <b>not</b> establish a secure session.
+ * The enumeration SevereCodes defines the sub-codes.
+ * </dd>
+ * <dt>Zrtp</dt> <dd>shows a ZRTP security problem. Refer to the enumeration
+ * ZrtpErrorCodes for sub-codes. GNU ZRTP of course will <b>not</b>
+ * establish a secure session.
+ * </dd>
+ * </dl>
+ *
+ */
+enum zrtp_MessageSeverity {
+ zrtp_Info = 1, /*!< Just an info message */
+ zrtp_Warning, /*!< A Warning message - security can be established */
+ zrtp_Severe, /*!< Severe error, security will not be established */
+ zrtp_ZrtpError /*!< ZRTP error, security will not be established */
+};
+
+/**
+ * Sub-codes for Info
+ */
+enum zrtp_InfoCodes {
+ zrtp_InfoHelloReceived = 1, /*!< Hello received, preparing a Commit */
+ zrtp_InfoCommitDHGenerated, /*!< Commit: Generated a public DH key */
+ zrtp_InfoRespCommitReceived, /*!< Responder: Commit received, preparing DHPart1 */
+ zrtp_InfoDH1DHGenerated, /*!< DH1Part: Generated a public DH key */
+ zrtp_InfoInitDH1Received, /*!< Initiator: DHPart1 received, preparing DHPart2 */
+ zrtp_InfoRespDH2Received, /*!< Responder: DHPart2 received, preparing Confirm1 */
+ zrtp_InfoInitConf1Received, /*!< Initiator: Confirm1 received, preparing Confirm2 */
+ zrtp_InfoRespConf2Received, /*!< Responder: Confirm2 received, preparing Conf2Ack */
+ zrtp_InfoRSMatchFound, /*!< At least one retained secrets matches - security OK */
+ zrtp_InfoSecureStateOn, /*!< Entered secure state */
+ zrtp_InfoSecureStateOff /*!< No more security for this session */
+};
+
+/**
+ * Sub-codes for Warning
+ */
+enum zrtp_WarningCodes {
+ zrtp_WarningDHAESmismatch = 1, /*!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096 */
+ zrtp_WarningGoClearReceived, /*!< Received a GoClear message */
+ zrtp_WarningDHShort, /*!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096 */
+ zrtp_WarningNoRSMatch, /*!< No retained shared secrets available - must verify SAS */
+ zrtp_WarningCRCmismatch, /*!< Internal ZRTP packet checksum mismatch - packet dropped */
+ zrtp_WarningSRTPauthError, /*!< Dropping packet because SRTP authentication failed! */
+ zrtp_WarningSRTPreplayError, /*!< Dropping packet because SRTP replay check failed! */
+ zrtp_WarningNoExpectedRSMatch /*!< Valid retained shared secrets availabe but no matches found - must verify SAS */
+};
+
+/**
+ * Sub-codes for Severe
+ */
+enum zrtp_SevereCodes {
+ zrtp_SevereHelloHMACFailed = 1, /*!< Hash HMAC check of Hello failed! */
+ zrtp_SevereCommitHMACFailed, /*!< Hash HMAC check of Commit failed! */
+ zrtp_SevereDH1HMACFailed, /*!< Hash HMAC check of DHPart1 failed! */
+ zrtp_SevereDH2HMACFailed, /*!< Hash HMAC check of DHPart2 failed! */
+ zrtp_SevereCannotSend, /*!< Cannot send data - connection or peer down? */
+ zrtp_SevereProtocolError, /*!< Internal protocol error occured! */
+ zrtp_SevereNoTimer, /*!< Cannot start a timer - internal resources exhausted? */
+ zrtp_SevereTooMuchRetries /*!< Too much retries during ZRTP negotiation - connection or peer down? */
+};
+
+/**
+ * Error codes according to the ZRTP specification chapter 6.9
+ *
+ * GNU ZRTP uses these error codes in two ways: to fill the appropriate
+ * field ing the ZRTP Error packet and as sub-code in
+ * ZrtpUserCallback#showMessage(). GNU ZRTP uses thes error codes also
+ * to report received Error packts, in this case the sub-codes are their
+ * negative values.
+ *
+ * The enumeration member comments are copied from the ZRTP specification.
+ */
+enum zrtp_ZrtpErrorCodes {
+ zrtp_MalformedPacket = 0x10, /*!< Malformed packet (CRC OK, but wrong structure) */
+ zrtp_CriticalSWError = 0x20, /*!< Critical software error */
+ zrtp_UnsuppZRTPVersion = 0x30, /*!< Unsupported ZRTP version */
+ zrtp_HelloCompMismatch = 0x40, /*!< Hello components mismatch */
+ zrtp_UnsuppHashType = 0x51, /*!< Hash type not supported */
+ zrtp_UnsuppCiphertype = 0x52, /*!< Cipher type not supported */
+ zrtp_UnsuppPKExchange = 0x53, /*!< Public key exchange not supported */
+ zrtp_UnsuppSRTPAuthTag = 0x54, /*!< SRTP auth. tag not supported */
+ zrtp_UnsuppSASScheme = 0x55, /*!< SAS scheme not supported */
+ zrtp_NoSharedSecret = 0x56, /*!< No shared secret available, DH mode required */
+ zrtp_DHErrorWrongPV = 0x61, /*!< DH Error: bad pvi or pvr ( == 1, 0, or p-1) */
+ zrtp_DHErrorWrongHVI = 0x62, /*!< DH Error: hvi != hashed data */
+ zrtp_SASuntrustedMiTM = 0x63, /*!< Received relayed SAS from untrusted MiTM */
+ zrtp_ConfirmHMACWrong = 0x70, /*!< Auth. Error: Bad Confirm pkt HMAC */
+ zrtp_NonceReused = 0x80, /*!< Nonce reuse */
+ zrtp_EqualZIDHello = 0x90, /*!< Equal ZIDs in Hello */
+ zrtp_GoCleatNotAllowed = 0x100, /*!< GoClear packet received, but not allowed */
+ zrtp_IgnorePacket = 0x7fffffff /*!< Internal state, not reported */
+};
+
+/**
+ * Information codes for the Enrollment user callbacks.
+ */
+enum zrtp_InfoEnrollment {
+ zrtp_EnrollmentRequest, //!< Aks user to confirm or deny an Enrollemnt request
+ zrtp_EnrollmentCanceled, //!< User did not confirm the PBX enrollement
+ zrtp_EnrollmentFailed, //!< Enrollment process failed, no PBX secret available
+ zrtp_EnrollmentOk //!< Enrollment process for this PBX was ok
+};
+
+/* The ZRTP protocol states */
+enum zrtpStates {
+ Initial, /*!< Initial state after starting the state engine */
+ Detect, /*!< State sending Hello, try to detect answer message */
+ AckDetected, /*!< HelloAck received */
+ AckSent, /*!< HelloAck sent after Hello received */
+ WaitCommit, /*!< Wait for a Commit message */
+ CommitSent, /*!< Commit message sent */
+ WaitDHPart2, /*!< Wait for a DHPart2 message */
+ WaitConfirm1, /*!< Wait for a Confirm1 message */
+ WaitConfirm2, /*!< Wait for a confirm2 message */
+ WaitConfAck, /*!< Wait for Conf2Ack */
+ WaitClearAck, /*!< Wait for clearAck - not used */
+ SecureState, /*!< This is the secure state - SRTP active */
+ WaitErrorAck, /*!< Wait for ErrorAck message */
+ numberOfStates /*!< Gives total number of protocol states */
+};
+
+/*! The algorihms that we support in SRTP and that ZRTP can negotiate. */
+typedef enum {
+ zrtp_Aes = 1, /*!< Use AES as symmetrical cipher algorithm */
+ zrtp_TwoFish, /*!< Use TwoFish as symmetrical cipher algorithm */
+ zrtp_Sha1, /*!< Use Sha1 as authentication algorithm */
+ zrtp_Skein /*!< Use Skein as authentication algorithm */
+} zrtp_SrtpAlgorithms;
+
+/**
+ * This structure contains pointers to the SRTP secrets and the role info.
+ *
+ * About the role and what the meaning of the role is refer to the
+ * of the enum Role. The pointers to the secrets are valid as long as
+ * the ZRtp object is active. To use these data after the ZRtp object's
+ * lifetime you may copy the data into a save place.
+ */
+typedef struct c_srtpSecrets
+{
+ zrtp_SrtpAlgorithms symEncAlgorithm;/*!< symmetrical cipher algorithm */
+ const uint8_t* keyInitiator; /*!< Initiator's key */
+ int32_t initKeyLen; /*!< Initiator's key length */
+ const uint8_t* saltInitiator; /*!< Initiator's salt */
+ int32_t initSaltLen; /*!< Initiator's salt length */
+ const uint8_t* keyResponder; /*!< Responder's key */
+ int32_t respKeyLen; /*!< Responder's key length */
+ const uint8_t* saltResponder; /*!< Responder's salt */
+ int32_t respSaltLen; /*!< Responder's salt length */
+ zrtp_SrtpAlgorithms authAlgorithm; /*!< SRTP authentication algorithm */
+ int32_t srtpAuthTagLen; /*!< SRTP authentication length */
+ char* sas; /*!< The SAS string */
+ int32_t role; /*!< ZRTP role of this client */
+} C_SrtpSecret_t;
+
+/*
+ * Keep the following defines in sync with enum EnableSecurity in ZrtpCallback.h
+ */
+#define ForReceiver 1 /*!< Enable security for SRTP receiver */
+#define ForSender 2 /*!< Enable security for SRTP sender */
+
+#ifdef __cplusplus
+#pragma GCC visibility push(default)
+extern "C"
+{
+#endif
+
+ typedef struct ZRtp ZRtp;
+ typedef struct ZrtpCallbackWrapper ZrtpCallbackWrapper;
+ typedef struct ZrtpConfigure ZrtpConfigure;
+
+
+ typedef struct zrtpContext
+ {
+ ZRtp* zrtpEngine; /*!< Holds the real ZRTP engine */
+ ZrtpCallbackWrapper* zrtpCallback; /*!< Help class Callback wrapper */
+ ZrtpConfigure* configure; /*!< Optional configuration data */
+ void* userData; /*!< User data, set by application */
+ } ZrtpContext;
+
+ /**
+ * This structure defines the callback functions required by GNU ZRTP.
+ *
+ * The RTP stack specific part must implement the callback methods.
+ * The generic part of GNU ZRTP uses these mehtods
+ * to communicate with the specific part, for example to send data
+ * via the RTP/SRTP stack, to set timers and cancel timer and so on.
+ *
+ * The generiy part of GNU ZRTP needs only a few callback methods to
+ * be implemented by the specific part.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+ /**
+ * The following methods define the GNU ZRTP callback interface.
+ * For detailed documentation refer to file ZrtpCallback.h, each C
+ * method has "zrtp_" prepended to the C++ name.
+ *
+ * @see ZrtpCallback
+ */
+ typedef struct zrtp_Callbacks
+ {
+ /**
+ * Send a ZRTP packet via RTP.
+ *
+ * ZRTP calls this method to send a ZRTP packet via the RTP session.
+ * The ZRTP packet will have to be created using the provided ZRTP message.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param data
+ * Points to ZRTP message to send.
+ * @param length
+ * The length in bytes of the data
+ * @return
+ * zero if sending failed, one if packet was sent
+ */
+ int32_t (*zrtp_sendDataZRTP) (ZrtpContext* ctx, const uint8_t* data, int32_t length ) ;
+
+ /**
+ * Activate timer.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param time
+ * The time in ms for the timer
+ * @return
+ * zero if activation failed, one if timer was activated
+ */
+ int32_t (*zrtp_activateTimer) (ZrtpContext* ctx, int32_t time ) ;
+
+ /**
+ * Cancel the active timer.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * zero if cancel action failed, one if timer was canceled
+ */
+ int32_t (*zrtp_cancelTimer)(ZrtpContext* ctx) ;
+
+ /**
+ * Send information messages to the hosting environment.
+ *
+ * The ZRTP implementation uses this method to send information
+ * messages to the host. Along with the message ZRTP provides a
+ * severity indicator that defines: Info, Warning, Error,
+ * Alert. Refer to the <code>MessageSeverity</code> enum above.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param severity
+ * This defines the message's severity
+ * @param subCode
+ * The subcode identifying the reason.
+ * @see ZrtpCodes#MessageSeverity
+ */
+ void (*zrtp_sendInfo) (ZrtpContext* ctx, int32_t severity, int32_t subCode ) ;
+
+ /**
+ * SRTP crypto data ready for the sender or receiver.
+ *
+ * The ZRTP implementation calls this method right after all SRTP
+ * secrets are computed and ready to be used. The parameter points
+ * to a structure that contains pointers to the SRTP secrets and a
+ * <code>enum Role</code>. The called method (the implementation
+ * of this abstract method) must either copy the pointers to the SRTP
+ * data or the SRTP data itself to a save place. The SrtpSecret_t
+ * structure is destroyed after the callback method returns to the
+ * ZRTP implementation.
+ *
+ * The SRTP data themselves are obtained in the ZRtp object and are
+ * valid as long as the ZRtp object is active. TheZRtp's
+ * destructor clears the secrets. Thus the called method needs to
+ * save the pointers only, ZRtp takes care of the data.
+ *
+ * The implementing class may enable SRTP processing in this
+ * method or delay it to srtpSecertsOn().
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param secrets A pointer to a SrtpSecret_t structure that
+ * contains all necessary data.
+ *
+ * @param part for which part (Sender or Receiver) this data is
+ * valid.
+ *
+ * @return Returns false if something went wrong during
+ * initialization of SRTP context, for example memory shortage.
+ */
+ int32_t (*zrtp_srtpSecretsReady) (ZrtpContext* ctx, C_SrtpSecret_t* secrets, int32_t part ) ;
+
+ /**
+ * Switch off the security for the defined part.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param part Defines for which part (sender or receiver) to
+ * switch on security
+ */
+ void (*zrtp_srtpSecretsOff) (ZrtpContext* ctx, int32_t part ) ;
+
+ /**
+ * Switch on the security.
+ *
+ * ZRTP calls this method after it has computed the SAS and check
+ * if it is verified or not. In addition ZRTP provides information
+ * about the cipher algorithm and key length for the SRTP session.
+ *
+ * This method must enable SRTP processing if it was not enabled
+ * during sertSecretsReady().
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param c The name of the used cipher algorithm and mode, or
+ * NULL
+ *
+ * @param s The SAS string
+ *
+ * @param verified if <code>verified</code> is true then SAS was
+ * verified by both parties during a previous call.
+ */
+ void (*zrtp_rtpSecretsOn) (ZrtpContext* ctx, char* c, char* s, int32_t verified ) ;
+
+ /**
+ * This method handles GoClear requests.
+ *
+ * According to the ZRTP specification the user must be informed about
+ * a GoClear request because the ZRTP implementation switches off security
+ * if it could authenticate the GoClear packet.
+ *
+ * <b>Note:</b> GoClear is not yet implemented in GNU ZRTP.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void (*zrtp_handleGoClear)(ZrtpContext* ctx) ;
+
+ /**
+ * Handle ZRTP negotiation failed.
+ *
+ * ZRTP calls this method in case ZRTP negotiation failed. The
+ * parameters show the severity as well as the reason.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param severity
+ * This defines the message's severity
+ * @param subCode
+ * The subcode identifying the reason.
+ * @see ZrtpCodes#MessageSeverity
+ */
+ void (*zrtp_zrtpNegotiationFailed) (ZrtpContext* ctx, int32_t severity, int32_t subCode ) ;
+
+ /**
+ * ZRTP calls this method if the other side does not support ZRTP.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * If the other side does not answer the ZRTP <em>Hello</em> packets then
+ * ZRTP calls this method,
+ *
+ */
+ void (*zrtp_zrtpNotSuppOther)(ZrtpContext* ctx) ;
+
+ /**
+ * Enter synchronization mutex.
+ *
+ * GNU ZRTP requires one mutex to synchronize its
+ * processing. Because mutex implementations depend on the
+ * underlying infrastructure, for example operating system or
+ * thread implementation, GNU ZRTP delegates mutex handling to the
+ * specific part of its implementation.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void (*zrtp_synchEnter)(ZrtpContext* ctx) ;
+
+ /**
+ * Leave synchronization mutex.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void (*zrtp_synchLeave)(ZrtpContext* ctx) ;
+
+ /**
+ * Inform about a PBX enrollment request.
+ *
+ * Please refer to chapter 8.3 ff to get more details about PBX
+ * enrollment and SAS relay.
+ *
+ * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param info Give some information to the user about the PBX
+ * requesting an enrollment.
+ */
+ void (*zrtp_zrtpAskEnrollment) (ZrtpContext* ctx, int32_t info) ;
+
+ /**
+ * Inform about PBX enrollment result.
+ *
+ * Informs the use about the acceptance or denial of an PBX enrollment
+ * request
+ *
+ * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param info Give some information to the user about the result
+ * of an enrollment.
+ */
+ void (*zrtp_zrtpInformEnrollment) (ZrtpContext* ctx, int32_t info ) ;
+
+ /**
+ * Request a SAS signature.
+ *
+ * After ZRTP was able to compute the Short Authentication String
+ * (SAS) it calls this method. The client may now use an
+ * approriate method to sign the SAS. The client may use
+ * ZrtpQueue#setSignatureData() to store the signature data and
+ * enable signature transmission to the other peer. Refer to
+ * chapter 8.2 of ZRTP specification.
+ *
+ * <b>Note:</b> SAS signing is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param sas
+ * Pointer to the 32 byte SAS hash to sign.
+ *
+ */
+ void (*zrtp_signSAS)(ZrtpContext* ctx, uint8_t* sas) ;
+
+ /**
+ * ZRTPQueue calls this method to request a SAS signature check.
+ *
+ * After ZRTP received a SAS signature in one of the Confirm packets it
+ * call this method. The client may use <code>getSignatureLength()</code>
+ * and <code>getSignatureData()</code>of ZrtpQueue to get the signature
+ * data and perform the signature check. Refer to chapter 8.2 of ZRTP
+ * specification.
+ *
+ * If the signature check fails the client may return false to ZRTP. In
+ * this case ZRTP signals an error to the other peer and terminates
+ * the ZRTP handshake.
+ *
+ * <b>Note:</b> SAS signing is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param ctx
+ * Pointer to the opaque ZrtpContext structure.
+ * @param sas
+ * Pointer to the 32 byte SAS hash that was signed by the other peer.
+ * @return
+ * true if the signature was ok, false otherwise.
+ *
+ */
+ int32_t (*zrtp_checkSASSignature) (ZrtpContext* ctx, uint8_t* sas ) ;
+ } zrtp_Callbacks;
+
+ /**
+ * Create the GNU ZRTP C wrapper.
+ *
+ * This wrapper implements the C interface to the C++ based GNU ZRTP.
+ * @returns
+ * Pointer to the ZrtpContext
+ */
+ ZrtpContext* zrtp_CreateWrapper();
+
+ /**
+ * Initialize the ZRTP protocol engine.
+ *
+ * This method initialized the GNU ZRTP protocol engine. An application
+ * calls this method to actually create the ZRTP protocol engine and
+ * initialize its configuration data. This method does not start the
+ * protocol engine.
+ *
+ * If an application requires a specific algorithm configuration then it
+ * must set the algorithm configuration data before it initializes the
+ * ZRTP protocol engine.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param cb
+ * The callback structure that holds the addresses of the callback
+ * methods.
+ * @param id
+ * A C string that holds the ZRTP client id, only the first 16 chars
+ * are used.
+ * @param zidFilename
+ * The name of the ZID file. This file holds some parameters and
+ * other data like additional shared secrets.
+ * @param userData
+ * A pointer to user data. The wrapper just stores this pointer in
+ * the ZrtpContext and the application may use it for its purposes.
+ * @param mitmMode
+ * A trusted Mitm (PBX) must set this to true. The ZRTP engine sets
+ * the M Flag in the Hello packet to announce a trusted MitM.
+ * @returns
+ * Pointer to the ZrtpContext
+ *
+ * @see zrtp_InitializeConfig
+ */
+ void zrtp_initializeZrtpEngine(ZrtpContext* zrtpContext,
+ zrtp_Callbacks *cb,
+ const char* id,
+ const char* zidFilename,
+ void* userData,
+ int32_t mitmMode);
+
+ /**
+ * Destroy the ZRTP wrapper and its underlying objects.
+ */
+ void zrtp_DestroyWrapper (ZrtpContext* zrtpContext);
+
+ /**
+ * Computes the ZRTP checksum over a received ZRTP packet buffer and
+ * compares the result with received checksum.
+ *
+ * @param buffer
+ * Pointer to ZRTP packet buffer
+ * @param length
+ * Length of the packet buffer excluding received CRC data
+ * @param crc
+ * The received CRC data.
+ * @returns
+ * True if CRC matches, false otherwise.
+ */
+ int32_t zrtp_CheckCksum(uint8_t* buffer, uint16_t length, uint32_t crc);
+
+ /**
+ * Computes the ZRTP checksum over a newly created ZRTP packet buffer.
+ *
+ * @param buffer
+ * Pointer to the created ZRTP packet buffer
+ * @param length
+ * Length of the packet buffer
+ * @returns
+ * The computed CRC.
+ */
+ uint32_t zrtp_GenerateCksum(uint8_t* buffer, uint16_t length);
+
+ /**
+ * Prepares the ZRTP checksum for appending to ZRTP packet.
+ * @param crc
+ * The computed CRC data.
+ * @returns
+ * Prepared CRC data in host order
+ */
+ uint32_t zrtp_EndCksum(uint32_t crc);
+
+ /**
+ * Kick off the ZRTP protocol engine.
+ *
+ * This method calls the ZrtpStateClass#evInitial() state of the state
+ * engine. After this call we are able to process ZRTP packets
+ * from our peer and to process them.
+ *
+ * <b>NOTE: application shall never call this method directly but use the
+ * appropriate method provided by the RTP implementation. </b>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_startZrtpEngine(ZrtpContext* zrtpContext);
+
+ /**
+ * Stop ZRTP security.
+ *
+ * <b>NOTE: An application shall never call this method directly but use the
+ * appropriate method provided by the RTP implementation. </b>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_stopZrtpEngine(ZrtpContext* zrtpContext);
+
+ /**
+ * Process RTP extension header.
+ *
+ * This method expects to get a pointer to the message part of
+ * a ZRTP packet.
+ *
+ * <b>NOTE: An application shall never call this method directly. Only
+ * the module that implements the RTP binding shall use this method</b>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param extHeader
+ * A pointer to the first byte of the ZRTP message part.
+ * @param peerSSRC
+ * The peer's SSRC.
+ * @return
+ * Code indicating further packet handling, see description above.
+ */
+ void zrtp_processZrtpMessage(ZrtpContext* zrtpContext, uint8_t *extHeader, uint32_t peerSSRC);
+
+ /**
+ * Process a timeout event.
+ *
+ * We got a timeout from the timeout provider. Forward it to the
+ * protocol state engine.
+ *
+ * <b>NOTE: application shall never call this method directly. Only
+ * the module that implements the RTP binding shall use this method</b>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_processTimeout(ZrtpContext* zrtpContext);
+
+ /*
+ * Check for and handle GoClear ZRTP packet header.
+ *
+ * This method checks if this is a GoClear packet. If not, just return
+ * false. Otherwise handle it according to the specification.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param extHeader
+ * A pointer to the first byte of the extension header. Refer to
+ * RFC3550.
+ * @return
+ * False if not a GoClear, true otherwise.
+ *
+ int32_t zrtp_handleGoClear(ZrtpContext* zrtpContext, uint8_t *extHeader);
+ */
+
+ /**
+ * Set the auxilliary secret.
+ *
+ * Use this method to set the auxilliary secret data. Refer to ZRTP
+ * specification, chapter 4.3 ff
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param data
+ * Points to the secret data.
+ * @param length
+ * Length of the auxilliary secrect in bytes
+ */
+ void zrtp_setAuxSecret(ZrtpContext* zrtpContext, uint8_t* data, int32_t length);
+
+ /**
+ * Check current state of the ZRTP state engine
+ *
+ * <b>NOTE: application usually don't call this method. Only
+ * the m-odule that implements the RTP binding shall use this method</b>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param state
+ * The state to check.
+ * @return
+ * Returns true if ZRTP engine is in the given state, false otherwise.
+ */
+ int32_t zrtp_inState(ZrtpContext* zrtpContext, int32_t state);
+
+ /**
+ * Set SAS as verified.
+ *
+ * Call this method if the user confirmed (verfied) the SAS. ZRTP
+ * remembers this together with the retained secrets data.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_SASVerified(ZrtpContext* zrtpContext);
+
+ /**
+ * Reset the SAS verfied flag for the current active user's retained secrets.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_resetSASVerified(ZrtpContext* zrtpContext);
+
+ /**
+ * Get the ZRTP Hello Hash data.
+ *
+ * Use this method to get the ZRTP Hello Hash data. The method
+ * returns the data as a string containing the ZRTP protocol version and
+ * hex-digits. Refer to ZRTP specification, chapter 8.
+ *
+ * <b>NOTE: An application may call this method if it needs this information.
+ * Usually it is not necessary.</b>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * a pointer to a C-string that contains the Hello hash value as
+ * hex-digits. The hello hash is available immediately after
+ * @c zrtp_CreateWrapper .
+ * The caller must @c free() if it does not use the
+ * hello hash C-string anymore.
+ */
+ char* zrtp_getHelloHash(ZrtpContext* zrtpContext);
+
+ /**
+ * Get the peer's ZRTP Hello Hash data.
+ *
+ * Use this method to get the peer's ZRTP Hello Hash data. The method
+ * returns the data as a string containing the ZRTP protocol version and
+ * hex-digits.
+ *
+ * The peer's hello hash is available only after ZRTP received a hello. If
+ * no data is available the function returns an empty string.
+ *
+ * Refer to ZRTP specification, chapter 8.
+ *
+ * @return
+ * a std:string containing the Hello version and the hello hash as hex digits.
+ */
+ char* zrtp_getPeerHelloHash(ZrtpContext* zrtpContext);
+
+ /**
+ * Get Multi-stream parameters.
+ *
+ * Use this method to get the Multi-stream parameters that were computed
+ * during the ZRTP handshake. An application may use these parameters to
+ * enable multi-stream processing for an associated SRTP session.
+ *
+ * The application must not modify the contents of returned char array, it
+ * is opaque data. The application may hand over this string to a new ZRTP
+ * instance to enable multi-stream processing for this new session.
+ *
+ * Refer to chapter 4.4.2 in the ZRTP specification for further details
+ * and restriction how and when to use multi-stream mode.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param length
+ * Pointer to an integer that receives the length of the char array
+ * @return
+ * a char array that contains the multi-stream parameters.
+ * If ZRTP was not started or ZRTP is not yet in secure state the method
+ * returns NULL and a length of 0.
+ */
+ char* zrtp_getMultiStrParams(ZrtpContext* zrtpContext, int32_t *length);
+
+ /**
+ * Set Multi-stream parameters.
+ *
+ * Use this method to set the parameters required to enable Multi-stream
+ * processing of ZRTP. The multi-stream parameters must be set before the
+ * application starts the ZRTP protocol engine.
+ *
+ * Refer to chapter 4.4.2 in the ZRTP specification for further details
+ * of multi-stream mode.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param length
+ * The integer that contains the length of the char array
+ * @param parameters
+ * A char array that contains the multi-stream parameters that this
+ * new ZRTP instance shall use. See also
+ * <code>getMultiStrParams()</code>
+ */
+ void zrtp_setMultiStrParams(ZrtpContext* zrtpContext, char* parameters, int32_t length);
+
+ /**
+ * Check if this ZRTP session is a Multi-stream session.
+ *
+ * Use this method to check if this ZRTP instance uses multi-stream.
+ * Refer to chapters 4.2 and 4.4.2 in the ZRTP.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * True if multi-stream is used, false otherwise.
+ */
+ int32_t zrtp_isMultiStream(ZrtpContext* zrtpContext);
+
+ /**
+ * Check if the other ZRTP client supports Multi-stream.
+ *
+ * Use this method to check if the other ZRTP client supports
+ * Multi-stream mode.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * True if multi-stream is available, false otherwise.
+ */
+ int32_t zrtp_isMultiStreamAvailable(ZrtpContext* zrtpContext);
+
+ /**
+ * Accept a PBX enrollment request.
+ *
+ * If a PBX service asks to enroll the PBX trusted MitM key and the user
+ * accepts this request, for example by pressing an OK button, the client
+ * application shall call this method and set the parameter
+ * <code>accepted</code> to true. If the user does not accept the request
+ * set the parameter to false.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param accepted
+ * True if the enrollment request is accepted, false otherwise.
+ */
+ void zrtp_acceptEnrollment(ZrtpContext* zrtpContext, int32_t accepted);
+
+ /**
+ * Check the state of the enrollment mode.
+ *
+ * If true then we will set the enrollment flag (E) in the confirm
+ * packets and performs the enrollment actions. A MitM (PBX) enrollment service
+ * started this ZRTP session. Can be set to true only if mitmMode is also true.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return status of the enrollmentMode flag.
+ */
+ int32_t zrtp_isEnrollmentMode(ZrtpContext* zrtpContext);
+
+ /**
+ * Check the state of the enrollment mode.
+ *
+ * If true then we will set the enrollment flag (E) in the confirm
+ * packets and perform the enrollment actions. A MitM (PBX) enrollment
+ * service must sets this mode to true.
+ *
+ * Can be set to true only if mitmMode is also true.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param enrollmentMode defines the new state of the enrollmentMode flag
+ */
+ void zrtp_setEnrollmentMode(ZrtpContext* zrtpContext, int32_t enrollmentMode);
+
+ /**
+ * Check if a peer's cache entry has a vaild MitM key.
+ *
+ * If true then the other peer ha a valid MtiM key, i.e. the peer has performed
+ * the enrollment procedure. A PBX ZRTP Back-2-Back application can use this function
+ * to check which of the peers is enrolled.
+ *
+ * @return True if the other peer has a valid Mitm key (is enrolled).
+ */
+ int32_t isPeerEnrolled(ZrtpContext* zrtpContext);
+
+ /**
+ * Send the SAS relay packet.
+ *
+ * The method creates and sends a SAS relay packet according to the ZRTP
+ * specifications. Usually only a MitM capable user agent (PBX) uses this
+ * function.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param sh the full SAS hash value
+ * @param render the SAS rendering algorithm
+ */
+ int32_t zrtp_sendSASRelayPacket(ZrtpContext* zrtpContext, uint8_t* sh, char* render);
+
+ /**
+ * Get the commited SAS rendering algorithm for this ZRTP session.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return the commited SAS rendering algorithm
+ */
+ const char* zrtp_getSasType(ZrtpContext* zrtpContext);
+
+ /**
+ * Get the computed SAS hash for this ZRTP session.
+ *
+ * A PBX ZRTP back-to-Back function uses this function to get the SAS
+ * hash of an enrolled client to construct the SAS relay packet for
+ * the other client.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return a pointer to the byte array that contains the full
+ * SAS hash.
+ */
+ uint8_t* zrtp_getSasHash(ZrtpContext* zrtpContext);
+
+ /**
+ * Set signature data
+ *
+ * This functions stores signature data and transmitts it during ZRTP
+ * processing to the other party as part of the Confirm packets. Refer to
+ * chapters 5.7 and 7.2.
+ *
+ * The signature data must be set before ZRTP the application calls
+ * <code>start()</code>.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param data
+ * The signature data including the signature type block. The method
+ * copies this data into the Confirm packet at signature type block.
+ * @param length
+ * The length of the signature data in bytes. This length must be
+ * multiple of 4.
+ * @return
+ * True if the method stored the data, false otherwise.
+ */
+ int32_t zrtp_setSignatureData(ZrtpContext* zrtpContext, uint8_t* data, int32_t length);
+
+ /**
+ * Get signature data
+ *
+ * This functions returns signature data that was receivied during ZRTP
+ * processing. Refer to chapters 5.7 and 7.2.
+ *
+ * The signature data can be retrieved after ZRTP enters secure state.
+ * <code>start()</code>.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * Number of bytes copied into the data buffer
+ */
+ const uint8_t* zrtp_getSignatureData(ZrtpContext* zrtpContext);
+
+ /**
+ * Get length of signature data
+ *
+ * This functions returns the length of signature data that was receivied
+ * during ZRTP processing. Refer to chapters 5.7 and 7.2.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * Length in bytes of the received signature data. The method returns
+ * zero if no signature data avilable.
+ */
+ int32_t zrtp_getSignatureLength(ZrtpContext* zrtpContext);
+
+ /**
+ * Emulate a Conf2Ack packet.
+ *
+ * This method emulates a Conf2Ack packet. According to ZRTP specification
+ * the first valid SRTP packet that the Initiator receives must switch
+ * on secure mode. Refer to chapter 4 in the specificaton
+ *
+ * <b>NOTE: application shall never call this method directly. Only
+ * the module that implements the RTP binding shall use this method</b>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_conf2AckSecure(ZrtpContext* zrtpContext);
+
+ /**
+ * Get other party's ZID (ZRTP Identifier) data
+ *
+ * This functions returns the other party's ZID that was receivied
+ * during ZRTP processing.
+ *
+ * The ZID data can be retrieved after ZRTP receive the first Hello
+ * packet from the other party. The application may call this method
+ * for example during SAS processing in showSAS(...) user callback
+ * method.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param data
+ * Pointer to a data buffer. This buffer must have a size of
+ * at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
+ * @return
+ * Number of bytes copied into the data buffer - must be equivalent
+ * to 12 bytes.
+ */
+ int32_t zrtp_getPeerZid(ZrtpContext* zrtpContext, uint8_t* data);
+
+
+ /**
+ * This enumerations list all configurable algorithm types.
+ */
+
+ /* Keep in synch with enumeration in ZrtpConfigure.h */
+
+ typedef enum zrtp_AlgoTypes {
+ zrtp_HashAlgorithm = 1, zrtp_CipherAlgorithm, zrtp_PubKeyAlgorithm, zrtp_SasType, zrtp_AuthLength
+ } Zrtp_AlgoTypes;
+
+ /**
+ * Initialize the GNU ZRTP Configure data.
+ *
+ * Initializing and setting a ZRTP configuration is optional. GNU ZRTP
+ * uses a sensible default if an application does not define its own
+ * ZRTP configuration.
+ *
+ * If an application initialize th configure data it must set the
+ * configuration data.
+ *
+ * The ZRTP specification, chapters 5.1.2 through 5.1.6 defines the
+ * algorithm names and their meaning.
+ *
+ * The current ZRTP implementation implements all mandatory algorithms
+ * plus a set of the optional algorithms. An application shall use
+ * @c zrtp_getAlgorithmNames to get the names of the available algorithms.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @returns
+ * Pointer to the ZrtpConfCtx
+ *
+ * @see zrtp_getAlgorithmNames
+ */
+ int32_t zrtp_InitializeConfig (ZrtpContext* zrtpContext);
+
+ /**
+ * Get names of all available algorithmes of a given algorithm type.
+ *
+ * The algorithm names are as specified in the ZRTP specification, chapters
+ * 5.1.2 through 5.1.6 .
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param type
+ * The algorithm type.
+ * @returns
+ * A NULL terminated array of character pointers.
+ */
+ char** zrtp_getAlgorithmNames(ZrtpContext* zrtpContext, Zrtp_AlgoTypes type);
+
+ /**
+ * Free storage used to store the algorithm names.
+ *
+ * If an application does not longer require the algoritm names it should
+ * free the space.
+ *
+ * @param names
+ * The NULL terminated array of character pointers.
+ */
+ void zrtp_freeAlgorithmNames(char** names);
+
+ /**
+ * Convenience function that sets a pre-defined standard configuration.
+ *
+ * The standard configuration consists of the following algorithms:
+ * <ul>
+ * <li> Hash: SHA256 </li>
+ * <li> Symmetric Cipher: AES 128, AES 256 </li>
+ * <li> Public Key Algorithm: DH2048, DH3027, MultiStream </li>
+ * <li> SAS type: libase 32 </li>
+ * <li> SRTP Authentication lengths: 32, 80 </li>
+ *</ul>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_setStandardConfig(ZrtpContext* zrtpContext);
+
+ /**
+ * Convenience function that sets the mandatory algorithms only.
+ *
+ * Mandatory algorithms are:
+ * <ul>
+ * <li> Hash: SHA256 </li>
+ * <li> Symmetric Cipher: AES 128 </li>
+ * <li> Public Key Algorithm: DH3027, MultiStream </li>
+ * <li> SAS type: libase 32 </li>
+ * <li> SRTP Authentication lengths: 32, 80 </li>
+ *</ul>
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_setMandatoryOnly(ZrtpContext* zrtpContext);
+
+ /**
+ * Clear all configuration data.
+ *
+ * The functions clears all configuration data.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ */
+ void zrtp_confClear(ZrtpContext* zrtpContext);
+
+ /**
+ * Add an algorithm to configuration data.
+ *
+ * Adds the specified algorithm to the configuration data.
+ * If no free configuration data slot is available the
+ * function does not add the algorithm and returns -1. The
+ * methods appends the algorithm to the existing algorithms.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The name of the algorithm to add.
+ * @return
+ * Number of free configuration data slots or -1 on error
+ */
+ int32_t zrtp_addAlgo(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char* algo);
+
+ /**
+ * Add an algorithm to configuration data at given index
+ *
+ * Adds the specified algorithm to the configuration data vector
+ * at a given index. If the index is larger than the actual size
+ * of the configuration vector the method just appends the algorithm.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The name of the algorithm to add.
+ * @param index
+ * The index where to add the algorihm
+ * @return
+ * Number of free configuration data slots or -1 on error
+ */
+ int32_t zrtp_addAlgoAt(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char* algo, int32_t index);
+
+ /**
+ * Remove a algorithm from configuration data.
+ *
+ * Removes the specified algorithm from configuration data. If
+ * the algorithm was not configured previously the function does
+ * not modify the configuration data and returns the number of
+ * free configuration data slots.
+ *
+ * If an application removes all algorithms then ZRTP does not
+ * include any algorithm into the hello message and falls back
+ * to a predefined mandatory algorithm.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The name of the algorithm to remove.
+ * @return
+ * Number of free configuration slots.
+ */
+ int32_t zrtp_removeAlgo(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char* algo);
+
+ /**
+ * Returns the number of configured algorithms.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @return
+ * The number of configured algorithms (used configuration
+ * data slots)
+ */
+ int32_t zrtp_getNumConfiguredAlgos(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType);
+
+ /**
+ * Returns the identifier of the algorithm at index.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param index
+ * The index in the list of the algorihm type
+ * @return
+ * A pointer to the algorithm name. If the index
+ * does not point to a configured slot then the function
+ * returns NULL.
+ *
+ */
+ const char* zrtp_getAlgoAt(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, int32_t index);
+
+ /**
+ * Checks if the configuration data of the algorihm type already contains
+ * a specific algorithms.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The name of the algorithm to check
+ * @return
+ * True if the algorithm was found, false otherwise.
+ *
+ */
+ int32_t zrtp_containsAlgo(ZrtpContext* zrtpContext, Zrtp_AlgoTypes algoType, const char* algo);
+
+ /**
+ * Enables or disables trusted MitM processing.
+ *
+ * For further details of trusted MitM processing refer to ZRTP
+ * specification, chapter 7.3
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param yesNo
+ * If set to true then trusted MitM processing is enabled.
+ */
+ void zrtp_setTrustedMitM(ZrtpContext* zrtpContext, int32_t yesNo);
+
+ /**
+ * Check status of trusted MitM processing.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * Returns true if trusted MitM processing is enabled.
+ */
+ int32_t zrtp_isTrustedMitM(ZrtpContext* zrtpContext);
+
+ /**
+ * Enables or disables SAS signature processing.
+ *
+ * For further details of trusted MitM processing refer to ZRTP
+ * specification, chapter 7.2
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @param yesNo
+ * If true then certificate processing is enabled.
+ */
+ void zrtp_setSasSignature(ZrtpContext* zrtpContext, int32_t yesNo);
+
+ /**
+ * Check status of SAS signature processing.
+ *
+ * @param zrtpContext
+ * Pointer to the opaque ZrtpContext structure.
+ * @return
+ * Returns true if certificate processing is enabled.
+ */
+ int32_t zrtp_isSasSignature(ZrtpContext* zrtpContext);
+
+#ifdef __cplusplus
+}
+#pragma GCC visibility pop
+#endif
+
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/ZrtpCallback.h b/src/libzrtpcpp/ZrtpCallback.h
new file mode 100644
index 0000000..957c4dd
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpCallback.h
@@ -0,0 +1,367 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCALLBACK_H_
+#define _ZRTPCALLBACK_H_
+
+/**
+ * @file ZrtpCallback.h
+ * @brief Callback interface between ZRTP and the RTP stack implementation
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <string>
+#include <stdint.h>
+#include <libzrtpcpp/ZrtpCodes.h>
+
+#ifndef __EXPORT
+ #if __GNUC__ >= 4
+ #define __EXPORT __attribute__ ((visibility("default")))
+ #define __LOCAL __attribute__ ((visibility("hidden")))
+ #elif defined _WIN32 || defined __CYGWIN__
+ #define __EXPORT __declspec(dllimport)
+ #define __LOCAL
+ #else
+ #define __EXPORT
+ #define __LOCAL
+ #endif
+#endif
+
+/**
+ * This enum defines which role a ZRTP peer has.
+ *
+ * According to the ZRTP specification the role determines which keys to
+ * use to encrypt or decrypt SRTP data.
+ *
+ * <ul>
+ * <li> The Initiator encrypts SRTP data using the <em>keyInitiator</em> and the
+ * <em>saltInitiator</em> data, the Responder uses these data to decrypt.
+ * </li>
+ * <li> The Responder encrypts SRTP data using the <em>keyResponder</em> and the
+ * <em>saltResponder</em> data, the Initiator uses these data to decrypt.
+ * </li>
+ * </ul>
+ */
+typedef enum {
+ Responder = 1, ///< This client is in ZRTP Responder mode
+ Initiator ///< This client is in ZRTP Initiator mode
+} Role;
+
+/// The algorihms that we support in SRTP and that ZRTP can negotiate.
+typedef enum {
+ None,
+ Aes = 1, ///< Use AES as symmetrical cipher algorithm
+ TwoFish, ///< Use TwoFish as symmetrical cipher algorithm
+ Sha1, ///< Use Sha1 as authentication algorithm
+ Skein ///< Use Skein as authentication algorithm
+} SrtpAlgorithms;
+
+/**
+ * This structure contains pointers to the SRTP secrets and the role info.
+ *
+ * About the role and what the meaning of the role is refer to the
+ * of the enum Role. The pointers to the secrets are valid as long as
+ * the ZRtp object is active. To use these data after the ZRtp object's
+ * lifetime you may copy the data into a save place. The destructor
+ * of ZRtp clears the data.
+ */
+typedef struct srtpSecrets {
+ SrtpAlgorithms symEncAlgorithm; ///< symmetrical cipher algorithm
+ const uint8_t* keyInitiator; ///< Initiator's key
+ int32_t initKeyLen; ///< Initiator's key length
+ const uint8_t* saltInitiator; ///< Initiator's salt
+ int32_t initSaltLen; ///< Initiator's salt length
+ const uint8_t* keyResponder; ///< Responder's key
+ int32_t respKeyLen; ///< Responder's key length
+ const uint8_t* saltResponder; ///< Responder's salt
+ int32_t respSaltLen; ///< Responder's salt length
+ SrtpAlgorithms authAlgorithm; ///< SRTP authentication algorithm
+ int32_t srtpAuthTagLen; ///< SRTP authentication length
+ std::string sas; ///< The SAS string
+ Role role; ///< ZRTP role of this client
+} SrtpSecret_t;
+
+enum EnableSecurity {
+ ForReceiver = 1, ///< Enable security for SRTP receiver
+ ForSender = 2 ///< Enable security for SRTP sender
+};
+
+/**
+ * This abstract class defines the callback functions required by GNU ZRTP.
+ *
+ * This class is a pure abstract class, aka Interface in Java, that
+ * defines the callback interface that the specific part of a GNU ZRTP
+ * must implement. The generic part of GNU ZRTP uses these mehtods
+ * to communicate with the specific part, for example to send data
+ * via the RTP/SRTP stack, to set timers and cancel timer and so on.
+ *
+ * The generiy part of GNU ZRTP needs only a few callback methods to
+ * be implemented by the specific part.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpCallback {
+
+protected:
+ friend class ZRtp;
+
+ virtual ~ZrtpCallback() {};
+
+ /**
+ * Send a ZRTP packet via RTP.
+ *
+ * ZRTP calls this method to send a ZRTP packet via the RTP session.
+ *
+ * @param data
+ * Points to ZRTP packet to send.
+ * @param length
+ * The length in bytes of the data
+ * @return
+ * zero if sending failed, one if packet was send
+ */
+ virtual int32_t sendDataZRTP(const uint8_t* data, int32_t length) =0;
+
+ /**
+ * Activate timer.
+ *
+ * @param time
+ * The time in ms for the timer
+ * @return
+ * zero if activation failed, one if timer was activated
+ */
+ virtual int32_t activateTimer(int32_t time) =0;
+
+ /**
+ * Cancel the active timer.
+ *
+ * @return
+ * zero if cancel action failed, one if timer was canceled
+ */
+ virtual int32_t cancelTimer() =0;
+
+ /**
+ * Send information messages to the hosting environment.
+ *
+ * The ZRTP implementation uses this method to send information
+ * messages to the host. Along with the message ZRTP provides a
+ * severity indicator that defines: Info, Warning, Error,
+ * Alert. Refer to the <code>MessageSeverity</code> enum above.
+ *
+ * @param severity
+ * This defines the message's severity
+ * @param subCode
+ * The subcode identifying the reason.
+ * @see ZrtpCodes#MessageSeverity
+ */
+ virtual void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) =0;
+
+ /**
+ * SRTP crypto data ready for the sender or receiver.
+ *
+ * The ZRTP implementation calls this method right after all SRTP
+ * secrets are computed and ready to be used. The parameter points
+ * to a structure that contains pointers to the SRTP secrets and a
+ * <code>enum Role</code>. The called method (the implementation
+ * of this abstract method) must either copy the pointers to the SRTP
+ * data or the SRTP data itself to a save place. The SrtpSecret_t
+ * structure is destroyed after the callback method returns to the
+ * ZRTP implementation.
+ *
+ * The SRTP data themselfs are ontained in the ZRtp object and are
+ * valid as long as the ZRtp object is active. TheZRtp's
+ * destructor clears the secrets. Thus the called method needs to
+ * save the pointers only, ZRtp takes care of the data.
+ *
+ * The implementing class may enable SRTP processing in this
+ * method or delay it to srtpSecertsOn().
+ *
+ * @param secrets A pointer to a SrtpSecret_t structure that
+ * contains all necessary data.
+ *
+ * @param part for which part (Sender or Receiver) this data is
+ * valid.
+ *
+ * @return Returns false if something went wrong during
+ * initialization of SRTP context, for example memory shortage.
+ */
+ virtual bool srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part) =0;
+
+ /**
+ * Switch off the security for the defined part.
+ *
+ * @param part Defines for which part (sender or receiver) to
+ * switch on security
+ */
+ virtual void srtpSecretsOff(EnableSecurity part) =0;
+
+ /**
+ * Switch on the security.
+ *
+ * ZRTP calls this method after it has computed the SAS and check
+ * if it is verified or not. In addition ZRTP provides information
+ * about the cipher algorithm and key length for the SRTP session.
+ *
+ * This method must enable SRTP processing if it was not enabled
+ * during sertSecretsReady().
+ *
+ * @param c The name of the used cipher algorithm and mode, or
+ * NULL
+ *
+ * @param s The SAS string
+ *
+ * @param verified if <code>verified</code> is true then SAS was
+ * verified by both parties during a previous call.
+ */
+ virtual void srtpSecretsOn(std::string c, std::string s, bool verified) =0;
+
+ /**
+ * This method handles GoClear requests.
+ *
+ * According to the ZRTP specification the user must be informed about
+ * a GoClear request because the ZRTP implementation switches off security
+ * if it could authenticate the GoClear packet.
+ *
+ * <b>Note:</b> GoClear is not yet implemented in GNU ZRTP.
+ *
+ */
+ virtual void handleGoClear() =0;
+
+ /**
+ * Handle ZRTP negotiation failed.
+ *
+ * ZRTP calls this method in case ZRTP negotiation failed. The
+ * parameters show the severity as well as the reason.
+ *
+ * @param severity
+ * This defines the message's severity
+ * @param subCode
+ * The subcode identifying the reason.
+ * @see ZrtpCodes#MessageSeverity
+ */
+ virtual void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) =0;
+
+ /**
+ * ZRTP calls this method if the other side does not support ZRTP.
+ *
+ * If the other side does not answer the ZRTP <em>Hello</em> packets then
+ * ZRTP calls this method,
+ *
+ */
+ virtual void zrtpNotSuppOther() =0;
+
+ /**
+ * Enter synchronization mutex.
+ *
+ * GNU ZRTP requires one mutes to synchronize its
+ * processing. Because mutex implementations depend on the
+ * underlying infrastructure, for example operating system or
+ * thread implementation, GNU ZRTP delegates mutex handling to the
+ * spcific part of its implementation.
+ */
+ virtual void synchEnter() =0;
+
+ /**
+ * Leave synchronization mutex.
+ */
+ virtual void synchLeave() =0;
+
+ /**
+ * Inform about a PBX enrollment request.
+ *
+ * Please refer to chapter 8.3 ff to get more details about PBX
+ * enrollment and SAS relay.
+ *
+ * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param info Give some information to the user about the PBX
+ * requesting an enrollment.
+ */
+ virtual void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info) =0;
+
+ /**
+ * Inform about PBX enrollment result.
+ *
+ * Informs the use about the acceptance or denial of an PBX enrollment
+ * request
+ *
+ * <b>Note:</b> PBX enrollement is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param info information to the user about the result
+ * of an enrollment.
+ */
+ virtual void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info) =0;
+
+ /**
+ * Request a SAS signature.
+ *
+ * After ZRTP was able to compute the Short Authentication String
+ * (SAS) it calls this method. The client may now use an
+ * approriate method to sign the SAS. The client may use
+ * ZrtpQueue#setSignatureData() to store the signature data an
+ * enable signature transmission to the other peer. Refer to
+ * chapter 8.2 of ZRTP specification.
+ *
+ * <b>Note:</b> SAS signing is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param sasHash
+ * The SAS hash to sign.
+ *
+ */
+ virtual void signSAS(uint8_t* sasHash) =0;
+
+ /**
+ * ZRTPQueue calls this method to request a SAS signature check.
+ *
+ * After ZRTP received a SAS signature in one of the Confirm packets it
+ * call this method. The client may use <code>getSignatureLength()</code>
+ * and <code>getSignatureData()</code>of ZrtpQueue to get the signature
+ * data and perform the signature check. Refer to chapter 8.2 of ZRTP
+ * specification.
+ *
+ * If the signature check fails the client may return false to ZRTP. In
+ * this case ZRTP signals an error to the other peer and terminates
+ * the ZRTP handshake.
+ *
+ * <b>Note:</b> SAS signing is not yet fully supported by GNU
+ * ZRTP.
+ *
+ * @param sasHash
+ * The SAS hash that was signed by the other peer.
+ * @return
+ * true if the signature was ok, false otherwise.
+ *
+ */
+ virtual bool checkSASSignature(uint8_t* sasHash) =0;
+};
+
+#endif // ZRTPCALLBACK
+
+/**
+ * @}
+ */
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/ZrtpCallbackWrapper.h b/src/libzrtpcpp/ZrtpCallbackWrapper.h
new file mode 100644
index 0000000..dd739e0
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpCallbackWrapper.h
@@ -0,0 +1,101 @@
+/*
+ This class maps the ZRTP C++ callback methods to C callback methods.
+ Copyright (C) 2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef ZRTPCALLBACKWRAPPER_H
+#define ZRTPCALLBACKWRAPPER_H
+
+#include <stdlib.h>
+
+#include <libzrtpcpp/ZrtpCallback.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+#include <libzrtpcpp/ZrtpCWrapper.h>
+
+/**
+ *
+ * @file ZrtpCallbackWrapper.h
+ * @brief C-Wrapper helper
+ *
+ * This is a helper class for for the C wrapper and implements
+ * the GNU ZRTP callback interface. For detailed documentation about
+ * the callback method refer to file <code>ZrtpCallback</code>
+ * @ingroup GNU_ZRTP
+ * @{
+ *
+ * @see ZrtpCallback
+ * @see ZrtpCWrapper
+ */
+class __EXPORT ZrtpCallbackWrapper : public ZrtpCallback
+{
+public:
+ /**
+ * Construct a class that implements ZrtpCallback and uses a C structure
+ * to call C functions that implement the callbacks.
+ *
+ * @param cb
+ * The C callback structure that hold the addresses of the C methods
+ * that implement the actual callback functions.
+ * @param ctx
+ * Pointer to the ZrtpContext
+ */
+ ZrtpCallbackWrapper(zrtp_Callbacks* cb, ZrtpContext* ctx);
+
+ int32_t sendDataZRTP ( const unsigned char* data, int32_t length );
+
+ int32_t activateTimer ( int32_t time );
+
+ int32_t cancelTimer();
+
+ void sendInfo ( GnuZrtpCodes::MessageSeverity severity, int32_t subCode );
+
+ bool srtpSecretsReady ( SrtpSecret_t* secrets, EnableSecurity part );
+
+ void srtpSecretsOff ( EnableSecurity part );
+
+ void srtpSecretsOn ( std::string c, std::string s, bool verified );
+
+ void handleGoClear();
+
+ void zrtpNegotiationFailed ( GnuZrtpCodes::MessageSeverity severity, int32_t subCode );
+
+ void zrtpNotSuppOther();
+
+ void synchEnter();
+
+ void synchLeave();
+
+ void zrtpAskEnrollment (GnuZrtpCodes::InfoEnrollment info );
+
+ void zrtpInformEnrollment (GnuZrtpCodes::InfoEnrollment info );
+
+ void signSAS (uint8_t* sasHash );
+
+ bool checkSASSignature (uint8_t* sasHash );
+
+private:
+ void init();
+ zrtp_Callbacks *c_callbacks;
+ ZrtpContext* zrtpCtx;
+
+};
+
+/**
+ * @}
+ */
+
+#endif // ZRTPCALLBACKWRAPPER_H
diff --git a/src/libzrtpcpp/ZrtpCodes.h b/src/libzrtpcpp/ZrtpCodes.h
new file mode 100755
index 0000000..a1bb6fc
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpCodes.h
@@ -0,0 +1,164 @@
+/** @file ZrtpCodes.h
+ */
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCODES_H_
+#define _ZRTPCODES_H_
+/**
+ * @file ZrtpCodes.h
+ * @brief The ZRTP info, warning, and error codes
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+namespace GnuZrtpCodes {
+/**
+ * \namespace GnuZrtpCodes
+ *
+ * This enum defines the information message severity.
+ *
+ * The ZRTP implementation issues information messages to inform the user
+ * about ongoing processing, unusual behavior, or alerts in case of severe
+ * problems. Each main severity code a number of sub-codes exist that
+ * specify the exact nature of the problem.
+ *
+ * An application gets message severity codes and the associated sub-codes
+ * via the ZrtpUserCallback#showMessage method.
+ *
+ * The severity levels and their meaning are:
+ *
+ * <dl>
+ * <dt>Info</dt> <dd>keeps the user informed about ongoing processing and
+ * security setup. The enumeration InfoCodes defines the subcodes.
+ * </dd>
+ * <dt>Warning</dt> <dd>is an information about some security issues, e.g. if
+ * an AES 256 encryption is request but only DH 3072 as public key scheme
+ * is supported. ZRTP will establish a secure session (SRTP). The
+ * enumeration WarningCodes defines the sub-codes.
+ * </dd>
+ * <dt>Severe</dt> <dd>is used if an error occured during ZRTP protocol usage.
+ * In case of <em>Severe</em> ZRTP will <b>not</b> establish a secure session.
+ * The enumeration SevereCodes defines the sub-codes.
+ * </dd>
+ * <dt>Zrtp</dt> <dd>shows a ZRTP security problem. Refer to the enumeration
+ * ZrtpErrorCodes for sub-codes. GNU ZRTP of course will <b>not</b>
+ * establish a secure session.
+ * </dd>
+ * </dl>
+ *
+ */
+enum MessageSeverity {
+ Info = 1,
+ Warning,
+ Severe,
+ ZrtpError
+};
+
+/**
+ * Sub-codes for Info
+ */
+enum InfoCodes {
+ InfoHelloReceived = 1, //!< Hello received, preparing a Commit
+ InfoCommitDHGenerated, //!< Commit: Generated a public DH key
+ InfoRespCommitReceived, //!< Responder: Commit received, preparing DHPart1
+ InfoDH1DHGenerated, //!< DH1Part: Generated a public DH key
+ InfoInitDH1Received, //!< Initiator: DHPart1 received, preparing DHPart2
+ InfoRespDH2Received, //!< Responder: DHPart2 received, preparing Confirm1
+ InfoInitConf1Received, //!< Initiator: Confirm1 received, preparing Confirm2
+ InfoRespConf2Received, //!< Responder: Confirm2 received, preparing Conf2Ack
+ InfoRSMatchFound, //!< At least one retained secrets matches - security OK
+ InfoSecureStateOn, //!< Entered secure state
+ InfoSecureStateOff //!< No more security for this session
+};
+
+/**
+ * Sub-codes for Warning
+ */
+enum WarningCodes {
+ WarningDHAESmismatch = 1, //!< Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096
+ WarningGoClearReceived, //!< Received a GoClear message
+ WarningDHShort, //!< Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096
+ WarningNoRSMatch, //!< No retained shared secrets available - must verify SAS
+ WarningCRCmismatch, //!< Internal ZRTP packet checksum mismatch - packet dropped
+ WarningSRTPauthError, //!< Dropping packet because SRTP authentication failed!
+ WarningSRTPreplayError, //!< Dropping packet because SRTP replay check failed!
+ WarningNoExpectedRSMatch //!< Valid retained shared secrets availabe but no matches found - must verify SAS
+};
+
+/**
+ * Sub-codes for Severe
+ */
+enum SevereCodes {
+ SevereHelloHMACFailed = 1, //!< Hash HMAC check of Hello failed!
+ SevereCommitHMACFailed, //!< Hash HMAC check of Commit failed!
+ SevereDH1HMACFailed, //!< Hash HMAC check of DHPart1 failed!
+ SevereDH2HMACFailed, //!< Hash HMAC check of DHPart2 failed!
+ SevereCannotSend, //!< Cannot send data - connection or peer down?
+ SevereProtocolError, //!< Internal protocol error occured!
+ SevereNoTimer, //!< Cannot start a timer - internal resources exhausted?
+ SevereTooMuchRetries //!< Too much retries during ZRTP negotiation - connection or peer down?
+};
+
+/**
+ * Error codes according to the ZRTP specification chapter 6.9
+ *
+ * GNU ZRTP uses these error codes in two ways: to fill the appropriate
+ * field ing the ZRTP Error packet and as sub-code in
+ * ZrtpUserCallback#showMessage(). GNU ZRTP uses thes error codes also
+ * to report received Error packts, in this case the sub-codes are their
+ * negative values.
+ *
+ * The enumeration member comments are copied from the ZRTP specification.
+ */
+enum ZrtpErrorCodes {
+ MalformedPacket = 0x10, //!< Malformed packet (CRC OK, but wrong structure)
+ CriticalSWError = 0x20, //!< Critical software error
+ UnsuppZRTPVersion = 0x30, //!< Unsupported ZRTP version
+ HelloCompMismatch = 0x40, //!< Hello components mismatch
+ UnsuppHashType = 0x51, //!< Hash type not supported
+ UnsuppCiphertype = 0x52, //!< Cipher type not supported
+ UnsuppPKExchange = 0x53, //!< Public key exchange not supported
+ UnsuppSRTPAuthTag = 0x54, //!< SRTP auth. tag not supported
+ UnsuppSASScheme = 0x55, //!< SAS scheme not supported
+ NoSharedSecret = 0x56, //!< No shared secret available, DH mode required
+ DHErrorWrongPV = 0x61, //!< DH Error: bad pvi or pvr ( == 1, 0, or p-1)
+ DHErrorWrongHVI = 0x62, //!< DH Error: hvi != hashed data
+ SASuntrustedMiTM = 0x63, //!< Received relayed SAS from untrusted MiTM
+ ConfirmHMACWrong = 0x70, //!< Auth. Error: Bad Confirm pkt HMAC
+ NonceReused = 0x80, //!< Nonce reuse
+ EqualZIDHello = 0x90, //!< Equal ZIDs in Hello
+ GoCleatNotAllowed = 0x100, //!< GoClear packet received, but not allowed
+ IgnorePacket = 0x7fffffff
+};
+
+/**
+ * Information codes for the Enrollment user callbacks.
+ */
+enum InfoEnrollment {
+ EnrollmentRequest, //!< Aks user to confirm or deny an Enrollemnt request
+ EnrollmentCanceled, //!< User did not confirm the PBX enrollement
+ EnrollmentFailed, //!< Enrollment process failed, no PBX secret available
+ EnrollmentOk //!< Enrollment process for this PBX was ok
+};
+
+}
+
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/ZrtpConfigure.h b/src/libzrtpcpp/ZrtpConfigure.h
new file mode 100644
index 0000000..33a824f
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpConfigure.h
@@ -0,0 +1,551 @@
+/*
+ Copyright (C) 2009 - 2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPCONFIGURE_H_
+#define _ZRTPCONFIGURE_H_
+
+/**
+ * @file ZrtpConfigure.h
+ * @brief The ZRTP configure functions
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <list>
+#include <string>
+#include <vector>
+#include <string.h>
+
+#include <libzrtpcpp/ZrtpCallback.h>
+
+/**
+ * This enumerations list all configurable algorithm types.
+ */
+
+enum AlgoTypes {
+ Invalid = 0, HashAlgorithm = 1, CipherAlgorithm, PubKeyAlgorithm, SasType, AuthLength
+};
+
+typedef void(*encrypt_t)(uint8_t*, int32_t, uint8_t*, uint8_t*, int32_t);
+typedef void(*decrypt_t)(uint8_t*, int32_t, const uint8_t*, uint8_t*, int32_t);
+
+/**
+ * The algorithm enumration class.
+ *
+ * This simple class is just a container of an algorithm's name and
+ * its associated algorithm type. We use this class together with the
+ * EnumBase class to implement a Java-like enum class functionality
+ * (not fully, but OK for our use case).
+ *
+ * An application shall use the get / check methods to retrieve information.
+ */
+class AlgorithmEnum {
+public:
+ /**
+ * Create an AlgorithmEnum object.
+ *
+ * @param type
+ * Defines the algorithm type
+ * @param name
+ * Set the names of the algorithm. The name is copied
+ * and the call may reuse the space.
+ * @param klen
+ * The key length for this algorihm in byte, for example 16 or 32
+ * @param ra
+ * A human readable short string that describes the algorihm.
+ * @param en
+ * Pointer to the encryption function of this algorithn
+ * @param de
+ * Pointer to the decryption funtions of this algorithm.
+ * @param alId
+ * The algorithm id used by SRTP to identify an algorithm type, for
+ * example Skein, Sha1, Aes, ...
+ *
+ * @see AlgoTypes
+ */
+ AlgorithmEnum(const AlgoTypes type, const char* name, int32_t klen,
+ const char* ra, encrypt_t en, decrypt_t de, SrtpAlgorithms alId);
+
+ /**
+ * AlgorithmEnum destructor
+ */
+ ~AlgorithmEnum();
+
+ /**
+ * Get the algorihm's name
+ *
+ * @returns
+ * Algorithm's name as null terminated C-string. The
+ * application must not free this memory.
+ */
+ const char* getName();
+
+ /**
+ * Get the algorihm's readable name
+ *
+ * @returns
+ * Algorithm's readable name as null terminated C-string. The
+ * application must not free this memory.
+ */
+ const char* getReadable();
+
+ /**
+ * Get the algorihm's key length.
+ *
+ * @returns
+ * An integer definig the key length in bytes.
+ */
+ int getKeylen();
+
+ /**
+ * Get the algorihm's integer id.
+ *
+ * @returns
+ * An integer that defines the algorithm.
+ */
+ SrtpAlgorithms getAlgoId();
+ /**
+ * Get the algorihm's key length.
+ *
+ * @returns
+ * An integer definig the key length in bytes.
+ */
+ encrypt_t getEncrypt();
+
+ /**
+ * Get the algorihm's key length.
+ *
+ * @returns
+ * An integer definig the key length in bytes.
+ */
+ decrypt_t getDecrypt();
+
+ /**
+ * Get the algorithm type of this AlgorithmEnum object.
+ *
+ * @returns
+ * The algorithm type.
+ *
+ * @see AlgoTypes
+ */
+ AlgoTypes getAlgoType();
+
+ /**
+ * Check if this AlgorithmEnum object is valid
+ *
+ * @returns
+ * @c true if the object is valid, @c false otherwise
+ */
+ bool isValid();
+
+private:
+ AlgoTypes algoType;
+ std::string algoName;
+ int32_t keyLen;
+ std::string readable;
+ encrypt_t encrypt;
+ decrypt_t decrypt;
+ SrtpAlgorithms algoId;
+};
+
+/**
+ * EnumBase provides methods to store and access algorithm enumerations of
+ * a specific algorithm type.
+ *
+ * An application shall use the get / check methods to retrieve information
+ * from the preset Algorithm Enumerations.
+ *
+ * @see AlgoTypes
+ * @see zrtpHashes
+ * @see zrtpSymCiphers
+ * @see zrtpPubKeys
+ * @see zrtpSasTypes
+ * @see zrtpAuthLengths
+ */
+class EnumBase {
+public:
+ /**
+ * Get an AlgorithmEnum by its name
+ *
+ * @param name
+ * The name of the AlgorithmEnum to search.
+ * @returns
+ * The AlgorithmEnum if found or an invalid AlgorithmEnum if the name
+ * was not found
+ */
+ AlgorithmEnum& getByName(const char* name);
+
+ /**
+ * Return all names of all currently stored AlgorithmEnums
+ *
+ * @return
+ * A C++ std::list of C++ std::strings that contain the names.
+ */
+ std::list<std::string>* getAllNames();
+
+ /**
+ * Get the number of currently stored AlgorithmEnums
+ *
+ * @return
+ * The number of currently stored AlgorithmEnums
+ */
+ int getSize();
+
+ /**
+ * Get the AlgoTypes to which this EnumBase belongs.
+ *
+ * @return
+ * The AlgoTypes of this EnumBase.
+ * @see AlgoTypes.
+ */
+ AlgoTypes getAlgoType();
+
+ /**
+ * Return the AlgorithmEnum by its ordinal number
+ *
+ * @param ord
+ * The ordinal number of the AlgorithmEnum.
+ * @return
+ * The AlgorithmEnum if found, an invalid Algorithm otherwise.
+ */
+ AlgorithmEnum& getByOrdinal(int ord);
+
+ /**
+ * Get the ordinal number of an AlgorithmEnum
+ *
+ * @param algo
+ * Return toe ordinal numer of this AlgorithmEnum.
+ *
+ * @return
+ * Return the ordinal number of this AlgorithmEnum if found,
+ * -1 otherwise.
+ */
+ int getOrdinal(AlgorithmEnum& algo);
+
+protected:
+ EnumBase(AlgoTypes algo);
+ ~EnumBase();
+ void insert(const char* name);
+ void insert(const char* name, int32_t klen,
+ const char* ra, encrypt_t en, decrypt_t de, SrtpAlgorithms alId);
+
+private:
+ AlgoTypes algoType;
+ std::vector <AlgorithmEnum* > algos;
+};
+
+/**
+ * The enumaration subclasses that contain the supported algorithm enumerations.
+ */
+class HashEnum : public EnumBase {
+public:
+ HashEnum();
+ ~HashEnum();
+};
+
+class SymCipherEnum : public EnumBase {
+public:
+ SymCipherEnum();
+ ~SymCipherEnum();
+};
+
+class PubKeyEnum : public EnumBase {
+public:
+ PubKeyEnum();
+ ~PubKeyEnum();
+};
+
+class SasTypeEnum : public EnumBase {
+public:
+ SasTypeEnum();
+ ~SasTypeEnum();
+};
+
+class AuthLengthEnum : public EnumBase {
+public:
+ AuthLengthEnum();
+ ~AuthLengthEnum();
+};
+
+extern HashEnum zrtpHashes;
+extern SymCipherEnum zrtpSymCiphers;
+extern PubKeyEnum zrtpPubKeys;
+extern SasTypeEnum zrtpSasTypes;
+extern AuthLengthEnum zrtpAuthLengths;
+
+/**
+ * ZRTP configuration data.
+ *
+ * This class contains data and functions to set ZRTP configuration data.
+ * An application may use this class to set configuration information for
+ * ZRTP. ZRTP uses this configuration information to announce various
+ * algorithms via its Hello message. An application may use this class to
+ * restrict or allow use of algorithms.
+ *
+ * The constructor does not set any algorithms, thus it is an empty
+ * configuration. An application may use this empty configuration and
+ * hand it over to ZRTP. In this case ZRTP does not announce any algorithms
+ * in its Hello message and uses mandatory algorithms only.
+ *
+ * An application can configure implemented algorithms only.
+ */
+class __EXPORT ZrtpConfigure {
+public:
+ ZrtpConfigure(); /* Creates Configuration data */
+ ~ZrtpConfigure();
+
+ /**
+ * Set the maximum number of algorithms per algorithm type that an application can
+ * configure.
+ */
+ static const int maxNoOfAlgos = 7;
+ /**
+ * Convenience function that sets a pre-defined standard configuration.
+ *
+ * The standard configuration consists of the following algorithms:
+ * <ul>
+ * <li> Hash: SHA256 </li>
+ * <li> Symmetric Cipher: AES 128, AES 256 </li>
+ * <li> Public Key Algorithm: DH2048, DH3027, MultiStream </li>
+ * <li> SAS type: libase 32 </li>
+ * <li> SRTP Authentication lengths: 32, 80 </li>
+ *</ul>
+ */
+ void setStandardConfig();
+
+ /**
+ * Convenience function that sets the mandatory algorithms only.
+ *
+ * Mandatory algorithms are:
+ * <ul>
+ * <li> Hash: SHA256 </li>
+ * <li> Symmetric Cipher: AES 128 </li>
+ * <li> Public Key Algorithm: DH3027, MultiStream </li>
+ * <li> SAS type: libase 32 </li>
+ * <li> SRTP Authentication lengths: 32, 80 </li>
+ *</ul>
+ */
+ void setMandatoryOnly();
+
+ /**
+ * Clear all configuration data.
+ *
+ * The functions clears all configuration data.
+ */
+ void clear();
+
+ /**
+ * Add an algorithm to configuration data.
+ *
+ * Adds the specified algorithm to the configuration data.
+ * If no free configuration data slot is available the
+ * function does not add the algorithm and returns -1. The
+ * methods appends the algorithm to the existing algorithms.
+ *
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The enumeration of the algorithm to add.
+ * @return
+ * Number of free configuration data slots or -1 on error
+ */
+ int32_t addAlgo(AlgoTypes algoType, AlgorithmEnum& algo);
+
+ /**
+ * Add an algorithm to configuration data at given index.
+ *
+ * Adds the specified algorithm to the configuration data vector
+ * at a given index. If the index is larger than the actual size
+ * of the configuration vector the method just appends the algorithm.
+ *
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The enumeration of the algorithm to add.
+ * @param index
+ * The index where to add the algorihm
+ * @return
+ * Number of free configuration data slots or -1 on error
+ */
+ int32_t addAlgoAt(AlgoTypes algoType, AlgorithmEnum& algo, int32_t index);
+
+ /**
+ * Remove a algorithm from configuration data.
+ *
+ * Removes the specified algorithm from configuration data. If
+ * the algorithm was not configured previously the function does
+ * not modify the configuration data and returns the number of
+ * free configuration data slots.
+ *
+ * If an application removes all algorithms then ZRTP does not
+ * include any algorithm into the hello message and falls back
+ * to a predefined mandatory algorithm.
+ *
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The enumeration of the algorithm to remove.
+ * @return
+ * Number of free configuration slots.
+ */
+ int32_t removeAlgo(AlgoTypes algoType, AlgorithmEnum& algo);
+
+ /**
+ * Returns the number of configured algorithms.
+ *
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @return
+ * The number of configured algorithms (used configuration
+ * data slots)
+ */
+ int32_t getNumConfiguredAlgos(AlgoTypes algoType);
+
+ /**
+ * Returns the identifier of the algorithm at index.
+ *
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param index
+ * The index in the list of the algorihm type
+ * @return
+ * A pointer the the algorithm enumeration. If the index
+ * does not point to a configured slot then the function
+ * returns NULL.
+ *
+ */
+ AlgorithmEnum& getAlgoAt(AlgoTypes algoType, int32_t index);
+
+ /**
+ * Checks if the configuration data of the algorihm type already contains
+ * a specific algorithms.
+ *
+ * @param algoType
+ * Specifies which algorithm type to select
+ * @param algo
+ * The algorithm to check
+ * @return
+ * True if the algorithm was found, false otherwise.
+ *
+ */
+ bool containsAlgo(AlgoTypes algoType, AlgorithmEnum& algo);
+
+ /**
+ * Enables or disables trusted MitM processing.
+ *
+ * For further details of trusted MitM processing refer to ZRTP
+ * specification, chapter 7.3
+ *
+ * @param yesNo
+ * If set to true then trusted MitM processing is enabled.
+ */
+ void setTrustedMitM(bool yesNo);
+
+ /**
+ * Check status of trusted MitM processing.
+ *
+ * @return
+ * Returns true if trusted MitM processing is enabled.
+ */
+ bool isTrustedMitM();
+
+ /**
+ * Enables or disables SAS signature processing.
+ *
+ * For further details of trusted MitM processing refer to ZRTP
+ * specification, chapter 7.2
+ *
+ * @param yesNo
+ * If set to true then certificate processing is enabled.
+ */
+ void setSasSignature(bool yesNo);
+
+ /**
+ * Check status of SAS signature processing.
+ *
+ * @return
+ * Returns true if certificate processing is enabled.
+ */
+ bool isSasSignature();
+
+ /**
+ * Enables or disables paranoid mode.
+ *
+ * For further explanation of paranoid mode refer to the documentation
+ * of ZRtp class.
+ *
+ * @param yesNo
+ * If set to true then paranoid mode is enabled.
+ */
+ void setParanoidMode(bool yesNo);
+
+ /**
+ * Check status of paranoid mode.
+ *
+ * @return
+ * Returns true if paranoid mode is enabled.
+ */
+ bool isParanoidMode();
+
+ /// Helper function to print some internal data
+ void printConfiguredAlgos(AlgoTypes algoTyp);
+
+ private:
+ std::vector<AlgorithmEnum* > hashes;
+ std::vector<AlgorithmEnum* > symCiphers;
+ std::vector<AlgorithmEnum* > publicKeyAlgos;
+ std::vector<AlgorithmEnum* > sasTypes;
+ std::vector<AlgorithmEnum* > authLengths;
+
+ bool enableTrustedMitM;
+ bool enableSasSignature;
+ bool enableParanoidMode;
+
+
+ AlgorithmEnum& getAlgoAt(std::vector<AlgorithmEnum* >& a, int32_t index);
+ int32_t addAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo);
+ int32_t addAlgoAt(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo, int32_t index);
+ int32_t removeAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo);
+ int32_t getNumConfiguredAlgos(std::vector<AlgorithmEnum* >& a);
+ bool containsAlgo(std::vector<AlgorithmEnum* >& a, AlgorithmEnum& algo);
+ std::vector<AlgorithmEnum* >& getEnum(AlgoTypes algoType);
+
+ void printConfiguredAlgos(std::vector<AlgorithmEnum* >& a);
+
+ protected:
+
+ public:
+};
+
+/**
+ * @}
+ */
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/ZrtpCrc32.h b/src/libzrtpcpp/ZrtpCrc32.h
new file mode 100755
index 0000000..ad57edd
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpCrc32.h
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCRC32_H_
+#define _ZRTPCRC32_H_
+
+/**
+ *
+ * @file ZrtpCrc32.h
+ * @brief Methods to compute the CRC32 checksum for ZRTP packets
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ *
+ * @see ZrtpCallback
+ */
+
+/**
+ * Check if a buffer matches a given CRC32 checksum.
+ *
+ * @param buffer
+ * Pointer to the data buffer.
+ * @param length
+ * Length in bytes of the data buffer.
+ * @param crc32
+ * The CRC32 checksum.
+ *
+ * @return
+ * @c true if the CRC32 checksum matches the computed checksum of the
+ * buffer, @c false otherwise.
+ */
+bool zrtpCheckCksum(uint8_t *buffer, uint16_t length, uint32_t crc32);
+
+/**
+ * Generate a CRC32 checksum of a data buffer
+ *
+ * @param buffer
+ * Pointer to the buffer.
+ * @param length
+ * Lenght of the buffer in bytes.
+ *
+ * @return
+ * A preliminary CRC32 checksum
+ */
+uint32_t zrtpGenerateCksum(uint8_t *buffer, uint16_t length);
+
+/**
+ * Close CRC32 computation.
+ *
+ * @param crc32
+ * A preliminary CRC32 checksum.
+ *
+ * @return
+ * The ready to use CRC32 checksum in host order.
+ */
+uint32_t zrtpEndCksum(uint32_t crc32);
+
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/ZrtpPacketBase.h b/src/libzrtpcpp/ZrtpPacketBase.h
new file mode 100644
index 0000000..f0d2944
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketBase.h
@@ -0,0 +1,147 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPPACKETBASE_H_
+#define _ZRTPPACKETBASE_H_
+
+/**
+ * @file ZrtpPacketBase.h
+ * @brief The ZRTP message header class
+ *
+ * This class defines the ZRTP message header and provides access and
+ * check methods.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+#include <libzrtpcpp/zrtpPacket.h>
+#include <libzrtpcpp/ZrtpTextData.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+#include <libzrtpcpp/ZrtpCrc32.h>
+
+// #define DEBUGOUT(deb) deb
+#define DEBUGOUT(deb)
+
+/*
+ * This is the unique ZRTP ID in network order (PZ)
+ */
+const uint16_t zrtpId = 0x505a;
+
+/**
+ * This is the base class for all ZRTP packets
+ *
+ * All other ZRTP packet classes inherit from this class. It does not have
+ * an implementation of its own.
+ *
+ * The standard constructors of the subclasses usually initialize the @c allocate
+ * field with their fixed data array which is large enough to hold all message
+ * data. If an implementation needs to change this to use dynamic memory
+ * allocation only that line in the subclasses must be changed and the destructors
+ * should take care of memory management.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketBase {
+
+ private:
+
+ protected:
+ void* allocated; ///< Pointer to ZRTP message data
+ zrtpPacketHeader_t* zrtpHeader; ///< points to the fixed ZRTP header structure
+
+ public:
+ /**
+ * Destructor is empty
+ */
+ virtual ~ZrtpPacketBase() {};
+
+ /**
+ * Get pointer to ZRTP header
+ *
+ * @return
+ * Pointer to ZRTP header structure.
+ */
+ const uint8_t* getHeaderBase() { return (const uint8_t*)zrtpHeader; };
+
+ /**
+ * Check is this is a ZRTP message
+ *
+ * @return
+ * @c true if check was ok
+ */
+ bool isZrtpPacket() { return (ntohs(zrtpHeader->zrtpId) == zrtpId); };
+
+ /**
+ * Get the length in words of the ZRTP message
+ *
+ * @return
+ * The length in words
+ */
+ uint16_t getLength() { return ntohs(zrtpHeader->length); };
+
+ /**
+ * Return pointer to fixed length message type ASCII data
+ *
+ * @return
+ * Pointer to ASCII character array
+ */
+ uint8_t* getMessageType() { return zrtpHeader->messageType; };
+
+ /**
+ * Set the lenght field in the ZRTP header
+ *
+ * @param len
+ * The length of the ZRTP message in words, host order
+ */
+ void setLength(uint16_t len) { zrtpHeader->length = htons(len); };
+
+ /**
+ * Copy the message type ASCII data to ZRTP message type field
+ *
+ * @param msg
+ * Pointer to message type ASCII character array
+ */
+ void setMessageType(uint8_t *msg)
+ { memcpy(zrtpHeader->messageType, msg, sizeof(zrtpHeader->messageType)); };
+
+ /**
+ * Initializes the ZRTP Id field
+ */
+ void setZrtpId() { zrtpHeader->zrtpId = htons(zrtpId); }
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETBASE
diff --git a/src/libzrtpcpp/ZrtpPacketClearAck.h b/src/libzrtpcpp/ZrtpPacketClearAck.h
new file mode 100644
index 0000000..992f6d8
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketClearAck.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETCLEARACK_H_
+#define _ZRTPPACKETCLEARACK_H_
+
+/**
+ * @file ZrtpPacketClearAck.h
+ * @brief The ZRTP ClearAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the ClearAck packet - Currently not used
+ *
+ * The ZRTP simple message ClearAck. The implementation sends this
+ * after switching to clear mode (non-SRTP mode).
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketClearAck : public ZrtpPacketBase {
+
+ public:
+ ZrtpPacketClearAck(); /// Creates a ClearAck packet with default data
+ ZrtpPacketClearAck(uint8_t* data); /// Creates a ClearAck packet from received data
+ virtual ~ZrtpPacketClearAck();
+
+ private:
+ ClearAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCLEARACK
+
diff --git a/src/libzrtpcpp/ZrtpPacketCommit.h b/src/libzrtpcpp/ZrtpPacketCommit.h
new file mode 100644
index 0000000..b23b23d
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketCommit.h
@@ -0,0 +1,134 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+#ifndef _ZRTPPACKETCOMMIT_H_
+#define _ZRTPPACKETCOMMIT_H_
+
+/**
+ * @file ZrtpPacketCommit.h
+ * @brief The ZRTP Commit message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Commit packet.
+ *
+ * The ZRTP message Commit. The ZRTP implementation sends or receives
+ * this message to commit the crypto parameters offered during a Hello
+ * message.
+ *
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketCommit : public ZrtpPacketBase {
+
+ protected:
+ Commit_t* commitHeader; ///< Points to Commit message part
+
+ public:
+ /// Creates a Commit packet with default data
+ ZrtpPacketCommit();
+
+ /// Creates a Commit packet from received data
+ ZrtpPacketCommit(uint8_t* data);
+
+ /// Normal destructor
+ virtual ~ZrtpPacketCommit();
+
+ /// Get pointer to hash algorithm type field, a fixed length character array
+ uint8_t* getHashType() { return commitHeader->hash; };
+
+ /// Get pointer to cipher algorithm type field, a fixed length character array
+ uint8_t* getCipherType() { return commitHeader->cipher; };
+
+ /// Get pointer to SRTP authentication algorithm type field, a fixed length character array
+ uint8_t* getAuthLen() { return commitHeader->authlengths; };
+
+ /// Get pointer to key agreement algorithm type field, a fixed length character array
+ uint8_t* getPubKeysType() { return commitHeader->pubkey; };
+
+ /// Get pointer to SAS algorithm type field, a fixed length character array
+ uint8_t* getSasType() { return commitHeader->sas; };
+
+ /// Get pointer to ZID field, a fixed length byte array
+ uint8_t* getZid() { return commitHeader->zid; };
+
+ /// Get pointer to HVI field, a fixed length byte array
+ uint8_t* getHvi() { return commitHeader->hvi; };
+
+ /// Get pointer to NONCE field, a fixed length byte array, overlaps HVI field
+ uint8_t* getNonce() { return commitHeader->hvi; };
+
+ /// Get pointer to hashH2 field, a fixed length byte array
+ uint8_t* getH2() { return commitHeader->hashH2; };
+
+ /// Get pointer to MAC field, a fixed length byte array
+ uint8_t* getHMAC() { return commitHeader->hmac; };
+
+ /// Get pointer to MAC field during multi-stream mode, a fixed length byte array
+ uint8_t* getHMACMulti() { return commitHeader->hmac-4*ZRTP_WORD_SIZE; };
+
+ /// Set hash algorithm type field, fixed length character field
+ void setHashType(uint8_t* text) { memcpy(commitHeader->hash, text, ZRTP_WORD_SIZE); };
+
+ /// Set cipher algorithm type field, fixed length character field
+ void setCipherType(uint8_t* text) { memcpy(commitHeader->cipher, text, ZRTP_WORD_SIZE); };
+
+ /// Set SRTP authentication algorithm algorithm type field, fixed length character field
+ void setAuthLen(uint8_t* text) { memcpy(commitHeader->authlengths, text, ZRTP_WORD_SIZE); };
+
+ /// Set key agreement algorithm type field, fixed length character field
+ void setPubKeyType(uint8_t* text) { memcpy(commitHeader->pubkey, text, ZRTP_WORD_SIZE); };
+
+ /// Set SAS algorithm type field, fixed length character field
+ void setSasType(uint8_t* text) { memcpy(commitHeader->sas, text, ZRTP_WORD_SIZE); };
+
+ /// Set ZID field, a fixed length byte array
+ void setZid(uint8_t* text) { memcpy(commitHeader->zid, text, sizeof(commitHeader->zid)); };
+
+ /// Set HVI field, a fixed length byte array
+ void setHvi(uint8_t* text) { memcpy(commitHeader->hvi, text, sizeof(commitHeader->hvi)); };
+
+ /// Set conce field, a fixed length byte array, overlapping HVI field
+ void setNonce(uint8_t* text);
+
+ /// Set hashH2 field, a fixed length byte array
+ void setH2(uint8_t* hash) { memcpy(commitHeader->hashH2, hash, sizeof(commitHeader->hashH2)); };
+
+ /// Set MAC field, a fixed length byte array
+ void setHMAC(uint8_t* hash) { memcpy(commitHeader->hmac, hash, sizeof(commitHeader->hmac)); };
+
+ /// Set MAC field during multi-stream mode, a fixed length byte array
+ void setHMACMulti(uint8_t* hash) { memcpy(commitHeader->hmac-4*ZRTP_WORD_SIZE, hash, sizeof(commitHeader->hmac)); };
+
+ private:
+ CommitPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCOMMIT
+
diff --git a/src/libzrtpcpp/ZrtpPacketConf2Ack.h b/src/libzrtpcpp/ZrtpPacketConf2Ack.h
new file mode 100644
index 0000000..a7c2567
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketConf2Ack.h
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETCON2FACK_H_
+#define _ZRTPPACKETCON2FACK_H_
+
+/**
+ * @file ZrtpPacketConf2Ack.h
+ * @brief The ZRTP Conf2Ack message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Conf2Ack packet.
+ *
+ * The ZRTP simple message Conf2Ack. The implementation sends this
+ * after receiving and checking the Confirm2 message.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketConf2Ack : public ZrtpPacketBase {
+
+ public:
+ /// Creates a Conf2Ack packet with default data
+ ZrtpPacketConf2Ack();
+
+ ///Creates a Conf2Ack packet from received data
+ ZrtpPacketConf2Ack(char* data);
+
+ /// Normal destructor
+ virtual ~ZrtpPacketConf2Ack();
+
+ private:
+ Conf2AckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCONF2ACK
+
diff --git a/src/libzrtpcpp/ZrtpPacketConfirm.h b/src/libzrtpcpp/ZrtpPacketConfirm.h
new file mode 100644
index 0000000..b2dfbf4
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketConfirm.h
@@ -0,0 +1,125 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETCONFIRM_H_
+#define _ZRTPPACKETCONFIRM_H_
+
+/**
+ * @file ZrtpPacketConfirm.h
+ * @brief The ZRTP Confirm message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Confirm packet.
+ *
+ * The ZRTP message Confirm. The implementation sends this
+ * to confirm the switch to SRTP (encrypted) mode. The contents of
+ * the Confirm message are encrypted, thus the implementation
+ * can check if the secret keys work.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketConfirm : public ZrtpPacketBase {
+
+ private:
+ Confirm_t* confirmHeader; ///< Point to the Confirm message part
+
+ public:
+ /// Creates a Confirm packet with default data
+ ZrtpPacketConfirm();
+
+ /// Creates a Confirm packet with default data and a given signature length
+ ZrtpPacketConfirm(uint32_t sl);
+
+ /// Creates a Confirm packet from received data
+ ZrtpPacketConfirm(uint8_t* d);
+
+ /// Normal destructor
+ virtual ~ZrtpPacketConfirm();
+
+ /// Check if SAS verify flag is set
+ const bool isSASFlag() { return confirmHeader->flags & 0x4; }
+
+ /// Check if PBXEnrollment flag is set
+ const bool isPBXEnrollment() { return confirmHeader->flags & 0x8; }
+
+ /// Get pointer to filler bytes (contains one bit of signature length)
+ const uint8_t* getFiller() { return confirmHeader->filler; }
+
+ /// Get pointer to IV data, fixed byte array
+ const uint8_t* getIv() { return confirmHeader->iv; }
+
+ /// Get pointer to MAC data, fixed byte array
+ const uint8_t* getHmac() { return confirmHeader->hmac; }
+
+ /// Get Expiration time data
+ const uint32_t getExpTime() { return ntohl(confirmHeader->expTime); }
+
+ /// Get pointer to initial hash chain (H0) data, fixed byte array
+ uint8_t* getHashH0() { return confirmHeader->hashH0; }
+
+ /// Get pointer to signature data, variable length, refer to getSignatureLength()
+ const uint8_t* getSignatureData() { return ((uint8_t*)&confirmHeader->expTime) + 4; }
+
+ /// get the signature length in words
+ int32_t getSignatureLength();
+
+ /// set SAS verified flag
+ void setSASFlag() { confirmHeader->flags |= 0x4; }
+
+ /// set setPBXEnrollment flag
+ void setPBXEnrollment() { confirmHeader->flags |= 0x8; }
+
+ /// Set MAC data, fixed length byte array
+ void setHmac(uint8_t* text) { memcpy(confirmHeader->hmac, text, sizeof(confirmHeader->hmac)); }
+
+ /// Set IV data, fixed length byte array
+ void setIv(uint8_t* text) { memcpy(confirmHeader->iv, text, sizeof(confirmHeader->iv)); }
+
+ /// Set expiration time data
+ void setExpTime(uint32_t t) { confirmHeader->expTime = htonl(t); }
+
+ /// Set initial hash chain (H0) data, fixed length byte array
+ void setHashH0(uint8_t* t) { memcpy(confirmHeader->hashH0, t, sizeof(confirmHeader->hashH0)); }
+
+ /// Set signature data, length of the signature data in bytes and must be a multiple of 4.
+ bool setSignatureData(uint8_t* data, int32_t length);
+
+ /// Set signature length in words
+ bool setSignatureLength(uint32_t sl);
+
+ private:
+ void initialize();
+ // Confirm packet is of variable length. It maximum size is 524 words:
+ // - 11 words fixed size
+ // - up to 513 words variable part, depending if signature is present and its length.
+ // This leads to a maximum of 4*524=2096 bytes.
+ uint8_t data[2100]; // large enough to hold a full blown Confirm packet
+
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCONFIRM
+
diff --git a/src/libzrtpcpp/ZrtpPacketDHPart.h b/src/libzrtpcpp/ZrtpPacketDHPart.h
new file mode 100644
index 0000000..d0ea4ba
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketDHPart.h
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETDHPART_H_
+#define _ZRTPPACKETDHPART_H_
+
+/**
+ * @file ZrtpPacketDHPart.h
+ * @brief The ZRTP DHPart message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the DHPart packet.
+ *
+ * The ZRTP message DHPart. The implementation sends this
+ * to exchange the Diffie-Helman public keys and the shared
+ * secrets between the two parties.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketDHPart : public ZrtpPacketBase {
+
+ protected:
+ uint8_t *pv; ///< points to public key value inside DH message
+ DHPart_t* DHPartHeader; ///< points to DH message structure
+ int32_t dhLength; ///< length of DH message, DH message has variable length
+
+ public:
+ /// Creates a DHPart packet no data, must use setPubKeyType(...)
+ ZrtpPacketDHPart();
+
+ /// Creates a DHPart packet with default data and a give public key type
+ ZrtpPacketDHPart(const char* pkt);
+
+ /// Creates a DHPart packet from received data
+ ZrtpPacketDHPart(uint8_t* data);
+
+ /// Standard destructor
+ virtual ~ZrtpPacketDHPart();
+
+ /// Get pointer to public key value, variable length byte array
+ uint8_t* getPv() { return pv; }
+
+ /// Get pointer to first retained secretd id, fixed length byte array
+ uint8_t* getRs1Id() { return DHPartHeader->rs1Id; };
+
+ /// Get pointer to second retained secretd id, fixed length byte array
+ uint8_t* getRs2Id() { return DHPartHeader->rs2Id; };
+
+ /// Get pointer to additional retained secretd id, fixed length byte array
+ uint8_t* getAuxSecretId() { return DHPartHeader->auxSecretId; };
+
+ /// Get pointer to PBX retained secretd id, fixed length byte array
+ uint8_t* getPbxSecretId() { return DHPartHeader->pbxSecretId; };
+
+ /// Get pointer to first hash (H1) for hash chain, fixed length byte array
+ uint8_t* getH1() { return DHPartHeader->hashH1; };
+
+ /// Get pointer to HMAC, fixed length byte array
+ uint8_t* getHMAC() { return pv+dhLength; };
+
+ /// Setpublic key value, variable length byte array
+ void setPv(uint8_t* text) { memcpy(pv, text, dhLength); };
+
+ /// Set first retained secretd id, fixed length byte array
+ void setRs1Id(uint8_t* text) { memcpy(DHPartHeader->rs1Id, text, sizeof(DHPartHeader->rs1Id)); };
+
+ /// Set second retained secretd id, fixed length byte array
+ void setRs2Id(uint8_t* text) { memcpy(DHPartHeader->rs2Id, text, sizeof(DHPartHeader->rs2Id)); };
+
+ /// Set additional retained secretd id, fixed length byte array
+ void setAuxSecretId(uint8_t* t) { memcpy(DHPartHeader->auxSecretId, t, sizeof(DHPartHeader->auxSecretId)); };
+
+ /// Set PBX retained secretd id, fixed length byte array
+ void setPbxSecretId(uint8_t* t) { memcpy(DHPartHeader->pbxSecretId,t, sizeof(DHPartHeader->pbxSecretId)); };
+
+ /// Set first hash (H1) of hash chain, fixed length byte array
+ void setH1(uint8_t* t) { memcpy(DHPartHeader->hashH1, t, sizeof(DHPartHeader->hashH1)); };
+
+ /// Set key agreement type, fixed size character array
+ void setPubKeyType(const char* pkt);
+
+ /// Set first MAC, fixed length byte array
+ void setHMAC(uint8_t* t) { memcpy(pv+dhLength, t, 2*ZRTP_WORD_SIZE); };
+
+ private:
+ void initialize();
+ // SupportedPubKeys pktype;
+ // DHPart packet is of variable length. It maximum size is 141 words:
+ // - 13 words fixed sizze
+ // - up to 128 words variable part, depending on DH algorithm
+ // leads to a maximum of 4*141=564 bytes.
+ uint8_t data[768]; // large enough to hold a full blown DHPart packet
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETDHPART
+
diff --git a/src/libzrtpcpp/ZrtpPacketError.h b/src/libzrtpcpp/ZrtpPacketError.h
new file mode 100644
index 0000000..d775801
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketError.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETERROR_H_
+#define _ZRTPPACKETERROR_H_
+
+/**
+ * @file ZrtpPacketError.h
+ * @brief The ZRTP Error message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Error packet.
+ *
+ * The ZRTP simple message Error. The implementation sends this
+ * after detecting an error.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketError : public ZrtpPacketBase {
+
+ protected:
+ Error_t* errorHeader; ///< Points to Error message
+
+ public:
+ /// Creates a Error packet with default data
+ ZrtpPacketError();
+
+ /// Creates a Error packet from received data
+ ZrtpPacketError(uint8_t* data);
+
+ virtual ~ZrtpPacketError();
+
+ /// Get the error code from Error message
+ uint32_t getErrorCode() { return ntohl(errorHeader->errorCode); };
+
+ /// Set error code in Error message
+ void setErrorCode(uint32_t code) {errorHeader->errorCode = htonl(code); };
+
+ private:
+ ErrorPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETERROR
+
diff --git a/src/libzrtpcpp/ZrtpPacketErrorAck.h b/src/libzrtpcpp/ZrtpPacketErrorAck.h
new file mode 100644
index 0000000..e64c8a6
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketErrorAck.h
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2007 - 2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETERRORACK_H_
+#define _ZRTPPACKETERRORACK_H_
+
+/**
+ * @file ZrtpPacketErrorAck.h
+ * @brief The ZRTP ErrorAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the ErrorAck packet.
+ *
+ * The ZRTP simple message ErrorAck. The implementation sends this
+ * after receiving and checking the Error message.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketErrorAck : public ZrtpPacketBase {
+
+ public:
+ /// Creates a ErrorAck packet with default data
+ ZrtpPacketErrorAck();
+
+ /// Creates a ErrorAck packet from received data
+ ZrtpPacketErrorAck(uint8_t* data);
+ virtual ~ZrtpPacketErrorAck();
+
+ private:
+ ErrorAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // _ZRTPPACKETERRORACK_H_
diff --git a/src/libzrtpcpp/ZrtpPacketGoClear.h b/src/libzrtpcpp/ZrtpPacketGoClear.h
new file mode 100644
index 0000000..10c3be6
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketGoClear.h
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETGOCLEAR_H_
+#define _ZRTPPACKETGOCLEAR_H_
+
+/**
+ * @file ZrtpPacketGoClear.h
+ * @brief The ZRTP GoClear message
+ *
+ * GNU ZRTP does not implement GoClear feature
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the GoClear packet.
+ *
+ * The ZRTP message GoClear. The implementation sends this
+ * to order the peer to switch to clear mode (non-SRTP mode).
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketGoClear : public ZrtpPacketBase {
+
+ protected:
+ GoClear_t* clearHeader;
+
+ public:
+ /// Creates a GoCLear packet with default data
+ ZrtpPacketGoClear();
+
+ /// Creates a GoClear packet from received data
+ ZrtpPacketGoClear(uint8_t* data);
+
+ virtual ~ZrtpPacketGoClear();
+
+ /// Not used
+ const uint8_t* getClearHmac() { return clearHeader->clearHmac; };
+
+ /// Not used
+ void setClearHmac(uint8_t *text) { memcpy(clearHeader->clearHmac, text, 32); };
+
+ /// Not used
+ void clrClearHmac() { memset(clearHeader->clearHmac, 0, 32); };
+
+ private:
+ GoClearPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETGOCLEAR
+
diff --git a/src/libzrtpcpp/ZrtpPacketHello.h b/src/libzrtpcpp/ZrtpPacketHello.h
new file mode 100644
index 0000000..0cc7403
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketHello.h
@@ -0,0 +1,191 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETHELLO_H_
+#define _ZRTPPACKETHELLO_H_
+
+/**
+ * @file ZrtpPacketHello.h
+ * @brief The ZRTP Hello message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Hello packet.
+ *
+ * The ZRTP Hello message. The implementation sends this
+ * to start the ZRTP negotiation sequence. The Hello message
+ * offers crypto methods and parameters to the other party. The
+ * other party selects methods and parameters it can support
+ * and uses the Commit message to commit these.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketHello : public ZrtpPacketBase {
+
+ protected:
+ Hello_t* helloHeader; ///< Point to the Hello message part
+
+ int32_t nHash, ///< number of hash algorithms offered
+ nCipher, ///< number of cipher algorithms offered
+ nPubkey, ///< number of key agreement algorithms offered
+ nSas, ///< number of SAS algorithms offered
+ nAuth; ///< number of SRTP authentication algorithms offered
+
+ int32_t oHash, ///< offsets in bytes to hash algorithm names
+ oCipher, ///< offsets in bytes to cipher algorithm names
+ oPubkey, ///< offsets in bytes to key agreement algorithm names
+ oSas, ///< offsets in bytes to SAS algorithm names
+ oAuth, ///< offsets in bytes to SRTP authentication algorithm names
+ oHmac; ///< offsets in bytes to MAC of Hello message
+
+ public:
+ /// Creates a Hello packet with default data
+ ZrtpPacketHello();
+
+ /// Creates a Hello packet from received data
+ ZrtpPacketHello(uint8_t *data);
+
+ virtual ~ZrtpPacketHello();
+
+ /**
+ * Set configure data and populate Hello message data.
+ *
+ * Fill in the offered Algorithm names and compute all offset to
+ * names and MAC. An application must call this method on Hello message
+ * objects created with the standard constructor (with default data)
+ * before the application can use most of the getter and setter methods.
+ *
+ * @param config
+ * Pointer to ZrtpConfigure data.
+ */
+ void configureHello(ZrtpConfigure* config);
+
+ /// Get version number from Hello message, fixed ASCII character array
+ uint8_t* getVersion() { return helloHeader->version; };
+
+ /// Get client id from Hello message, fixed ASCII character array
+ uint8_t* getClientId() { return helloHeader->clientId; };
+
+ /// Get H3 hash from Hello message, fixed byte array
+ uint8_t* getH3() { return helloHeader->hashH3; };
+
+ /// Get client ZID from Hello message, fixed bytes array
+ uint8_t* getZid() { return helloHeader->zid; };
+
+ /// Set version sting in Hello message, fixed ASCII character array
+ void setVersion(uint8_t *text) { memcpy(helloHeader->version, text,ZRTP_WORD_SIZE ); }
+
+ /// Set client id in Hello message, fixed ASCII character array
+ void setClientId(const uint8_t *t) { memcpy(helloHeader->clientId, t, sizeof(helloHeader->clientId)); }
+
+ /// Set H3 hash in Hello message, fixed byte array
+ void setH3(uint8_t *hash) { memcpy(helloHeader->hashH3, hash, sizeof(helloHeader->hashH3)); }
+
+ /// Set client ZID in Hello message, fixed bytes array
+ void setZid(uint8_t *text) { memcpy(helloHeader->zid, text, sizeof(helloHeader->zid)); }
+
+ /// Check passive mode (mode not implemented)
+ bool isPassive() { return helloHeader->flags & 0x10; };
+
+ /// Check if MitM flag is set
+ bool isMitmMode() { return helloHeader->flags & 0x20; };
+
+ /// Check if SAS sign flag is set
+ bool isSasSign() { return helloHeader->flags & 0x40; };
+
+ /// Get hash algorithm name at position n, fixed ASCII character array
+ uint8_t* getHashType(int32_t n) { return ((uint8_t*)helloHeader)+oHash+(n*ZRTP_WORD_SIZE); }
+
+ /// Get ciper algorithm name at position n, fixed ASCII character array
+ uint8_t* getCipherType(int32_t n) { return ((uint8_t*)helloHeader)+oCipher+(n*ZRTP_WORD_SIZE); }
+
+ /// Get SRTP authentication algorithm name at position n, fixed ASCII character array
+ uint8_t* getAuthLen(int32_t n) { return ((uint8_t*)helloHeader)+oAuth+(n*ZRTP_WORD_SIZE); }
+
+ /// Get key agreement algorithm name at position n, fixed ASCII character array
+ uint8_t* getPubKeyType(int32_t n) { return ((uint8_t*)helloHeader)+oPubkey+(n*ZRTP_WORD_SIZE); }
+
+ /// Get SAS algorithm name at position n, fixed ASCII character array
+ uint8_t* getSasType(int32_t n) { return ((uint8_t*)helloHeader)+oSas+(n*ZRTP_WORD_SIZE); }
+
+ /// Get Hello MAC, fixed byte array
+ uint8_t* getHMAC() { return ((uint8_t*)helloHeader)+oHmac; }
+
+ /// Set hash algorithm name at position n, fixed ASCII character array
+ void setHashType(int32_t n, int8_t* t)
+ { memcpy(((uint8_t*)helloHeader)+oHash+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+ /// Set ciper algorithm name at position n, fixed ASCII character array
+ void setCipherType(int32_t n, int8_t* t)
+ { memcpy(((uint8_t*)helloHeader)+oCipher+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+ /// Set SRTP authentication algorithm name at position n, fixed ASCII character array
+ void setAuthLen(int32_t n, int8_t* t)
+ { memcpy(((uint8_t*)helloHeader)+oAuth+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+ /// Set key agreement algorithm name at position n, fixed ASCII character array
+ void setPubKeyType(int32_t n, int8_t* t)
+ { memcpy(((uint8_t*)helloHeader)+oPubkey+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+ /// Set SAS algorithm name at position n, fixed ASCII character array
+ void setSasType(int32_t n, int8_t* t)
+ { memcpy(((uint8_t*)helloHeader)+oSas+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }
+
+ /// Set Hello MAC, fixed byte array
+ void setHMAC(uint8_t* t)
+ { memcpy(((uint8_t*)helloHeader)+oHmac, t, 2*ZRTP_WORD_SIZE); }
+
+ /// Get number of offered hash algorithms
+ int32_t getNumHashes() {return nHash; }
+
+ /// Get number of offered cipher algorithms
+ int32_t getNumCiphers() {return nCipher; }
+
+ /// Get number of offered key agreement algorithms
+ int32_t getNumPubKeys() {return nPubkey; }
+
+ /// Get number of offered SAS algorithms
+ int32_t getNumSas() {return nSas; }
+
+ /// Get number of offered SRTP authentication algorithms
+ int32_t getNumAuth() {return nAuth; }
+
+ /// set MitM flag
+ void setMitmMode() { helloHeader->flags |= 0x20; }
+
+ /// set SAS sign flag
+ void setSasSign() { helloHeader->flags |= 0x40; }
+
+ private:
+ // Hello packet is of variable length. It maximum size is 46 words:
+ // - 11 words fixed sizze
+ // - up to 35 words variable part, depending on number of algorithms
+ // leads to a maximum of 4*46=184 bytes.
+ uint8_t data[256]; // large enough to hold a full blown Hello packet
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETHELLO
+
diff --git a/src/libzrtpcpp/ZrtpPacketHelloAck.h b/src/libzrtpcpp/ZrtpPacketHelloAck.h
new file mode 100644
index 0000000..345a071
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketHelloAck.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETHELLOACK_H_
+#define _ZRTPPACKETHELLOACK_H_
+
+/**
+ * @file ZrtpPacketHelloAck.h
+ * @brief The ZRTP HelloAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the HelloAck packet.
+ *
+ * The ZRTP simple message HelloAck. The implementation sends this
+ * after receiving a Hello packet.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketHelloAck : public ZrtpPacketBase {
+
+ public:
+ /// Creates a HelloAck packet with default data
+ ZrtpPacketHelloAck();
+
+ /// Creates a HelloAck packet from received data
+ ZrtpPacketHelloAck(uint8_t* data);
+
+ virtual ~ZrtpPacketHelloAck();
+
+ private:
+ HelloAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETHELLOACK
+
diff --git a/src/libzrtpcpp/ZrtpPacketPing.h b/src/libzrtpcpp/ZrtpPacketPing.h
new file mode 100644
index 0000000..840df62
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketPing.h
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2006-2009 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETPING_H_
+#define _ZRTPPACKETPING_H_
+
+/**
+ * @file ZrtpPacketPing.h
+ * @brief The ZRTP Ping message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the PingAck packet.
+ *
+ * The ZRTP simple message PingAck.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketPing : public ZrtpPacketBase {
+
+ protected:
+ Ping_t* pingHeader; ///< Point the the Ping message
+
+ public:
+ /// Creates a Ping message with default data
+ ZrtpPacketPing();
+
+ /// Creates a Ping message from received data
+ ZrtpPacketPing(uint8_t* data);
+
+ virtual ~ZrtpPacketPing();
+
+ /// Set ZRTP protocol version field, fixed ASCII character array
+ void setVersion(uint8_t *text) { memcpy(pingHeader->version, text,ZRTP_WORD_SIZE ); }
+
+ /// Get the endpoit hash, fixed byte array
+ uint8_t* getEpHash() { return pingHeader->epHash; }
+
+ private:
+ PingPacket_t data;
+};
+
+/**
+ * @}
+ */
+
+#endif // ZRTPPACKETCLEARACK
+
diff --git a/src/libzrtpcpp/ZrtpPacketPingAck.h b/src/libzrtpcpp/ZrtpPacketPingAck.h
new file mode 100644
index 0000000..51ad8c8
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketPingAck.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2006-2009 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETPINGACK_H_
+#define _ZRTPPACKETPINGACK_H_
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+/**
+ * @file ZrtpPacketPingAck.h
+ * @brief The ZRTP PingAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+/**
+ * Implement the PingAck packet.
+ *
+ * The ZRTP simple message PingAck.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketPingAck : public ZrtpPacketBase {
+
+ protected:
+ PingAck_t* pingAckHeader; ///< Points to PingAck message
+
+ public:
+ /// Creates a PingAck message with default data
+ ZrtpPacketPingAck();
+
+ /// Creates a PingAck message from received data
+ ZrtpPacketPingAck(uint8_t* data);
+
+ virtual ~ZrtpPacketPingAck();
+
+ /// Get SSRC from PingAck message
+ uint32_t getSSRC() { return ntohl(pingAckHeader->ssrc); };
+
+ /// Set ZRTP protocol version field, fixed ASCII character array
+ void setVersion(uint8_t *text) { memcpy(pingAckHeader->version, text, ZRTP_WORD_SIZE ); }
+
+ /// Set SSRC in PingAck message
+ void setSSRC(uint32_t data) {pingAckHeader->ssrc = htonl(data); };
+
+ /// Set remote endpoint hash, fixed byte array
+ void setRemoteEpHash(uint8_t *hash) { memcpy(pingAckHeader->remoteEpHash, hash, sizeof(pingAckHeader->remoteEpHash)); }
+
+ /// Set local endpoint hash, fixed byte array
+ void setLocalEpHash(uint8_t *hash) { memcpy(pingAckHeader->localEpHash, hash, sizeof(pingAckHeader->localEpHash)); }
+
+ private:
+ PingAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETCLEARACK
+
diff --git a/src/libzrtpcpp/ZrtpPacketRelayAck.h b/src/libzrtpcpp/ZrtpPacketRelayAck.h
new file mode 100644
index 0000000..93437e6
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketRelayAck.h
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2007 - 2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETRELAYACK_H_
+#define _ZRTPPACKETRELAYACK_H_
+
+/**
+ * @file ZrtpPacketRelayAck.h
+ * @brief The ZRTP RelayAck message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the RelayAck packet.
+ *
+ * The ZRTP simple message RelayAck. The implementation sends this
+ * after receiving and checking the SASrelay message.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+class __EXPORT ZrtpPacketRelayAck : public ZrtpPacketBase {
+
+ public:
+ /// Creates a RelayAck packet with default data
+ ZrtpPacketRelayAck();
+
+ /// Creates a RelayAck packet from received data
+ ZrtpPacketRelayAck(uint8_t* data);
+ virtual ~ZrtpPacketRelayAck();
+
+ private:
+ RelayAckPacket_t data;
+};
+
+/**
+ * @}
+ */
+#endif // _ZRTPPACKETRELAYACK_H_
diff --git a/src/libzrtpcpp/ZrtpPacketSASrelay.h b/src/libzrtpcpp/ZrtpPacketSASrelay.h
new file mode 100644
index 0000000..427ac28
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpPacketSASrelay.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2006-2011 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPPACKETSASRELAY_H_
+#define _ZRTPPACKETSASRELAY_H_
+
+/**
+ * @file ZrtpPacketSASrelay.h
+ * @brief The ZRTP SAS Relay message
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * Implement the Confirm packet.
+ *
+ * The ZRTP message Confirm. The implementation sends this
+ * to confirm the switch to SRTP (encrypted) mode. The contents of
+ * the Confirm message are encrypted, thus the implementation
+ * can check if the secret keys work.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpPacketSASrelay : public ZrtpPacketBase {
+
+ private:
+ SASrelay_t* sasRelayHeader; ///< Point to the Confirm message part
+
+ public:
+ /// Creates a Confirm packet with default data
+ ZrtpPacketSASrelay();
+
+ /// Creates a Confirm packet with default data and a given signature length
+ ZrtpPacketSASrelay(uint32_t sl);
+
+ /// Creates a Confirm packet from received data
+ ZrtpPacketSASrelay(uint8_t* d);
+
+ /// Normal destructor
+ virtual ~ZrtpPacketSASrelay();
+
+ /// Check is SAS verify flag is set
+ const bool isSASFlag() { return sasRelayHeader->flags & 0x4; }
+
+ /// Get pointer to filler bytes (contains one bit of signature length)
+ const uint8_t* getFiller() { return sasRelayHeader->filler; }
+
+ /// Get pointer to IV data, fixed byte array
+ const uint8_t* getIv() { return sasRelayHeader->iv; }
+
+ /// Get pointer to MAC data, fixed byte array
+ const uint8_t* getHmac() { return sasRelayHeader->hmac; }
+
+ /// Get pointer to new SAS rendering algorithm, fixed byte array
+ const uint8_t* getSas() {return sasRelayHeader->sas; }
+
+ /// Get pointer to new SAS hash data, fixed byte array
+ const uint8_t* getTrustedSas() { return sasRelayHeader->trustedSasHash; }
+
+ /// get the signature length in words
+ uint32_t getSignatureLength();
+
+ /// set SAS verified flag
+ void setSASFlag() { sasRelayHeader->flags |= 0x4; }
+
+ /// Set MAC data, fixed length byte array
+ void setHmac(uint8_t* text) { memcpy(sasRelayHeader->hmac, text, sizeof(sasRelayHeader->hmac)); }
+
+ /// Set IV data, fixed length byte array
+ void setIv(uint8_t* text) { memcpy(sasRelayHeader->iv, text, sizeof(sasRelayHeader->iv)); }
+
+ /// Set SAS rendering algorithm, fixed length byte array
+ void setSas(uint8_t* text) { memcpy(sasRelayHeader->sas, text, sizeof(sasRelayHeader->sas)); }
+
+ /// Set SAS hash data, fixed length byte array
+ void setTrustedSas(uint8_t* text) { memcpy(sasRelayHeader->trustedSasHash, text, sizeof(sasRelayHeader->trustedSasHash)); }
+
+ /// Set signature length in words
+ void setSignatureLength(uint32_t sl);
+
+ private:
+ void initialize();
+ // Confirm packet is of variable length. It maximum size is 524 words:
+ // - 11 words fixed size
+ // - up to 513 words variable part, depending if signature is present and its length.
+ // This leads to a maximum of 4*524=2096 bytes.
+ uint8_t data[2100]; // large enough to hold a full blown Confirm packet
+
+};
+
+/**
+ * @}
+ */
+#endif // ZRTPPACKETSASRELAY
+
diff --git a/src/libzrtpcpp/ZrtpQueue.h b/src/libzrtpcpp/ZrtpQueue.h
new file mode 100644
index 0000000..0454771
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpQueue.h
@@ -0,0 +1,917 @@
+/*
+ Copyright (C) 2006-2009 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPQUEUE_H_
+#define _ZRTPQUEUE_H_
+
+#include <ccrtp/cqueue.h>
+#include <ccrtp/rtppkt.h>
+#include <libzrtpcpp/ZrtpCallback.h>
+#include <libzrtpcpp/TimeoutProvider.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+
+class __EXPORT ZrtpUserCallback;
+class __EXPORT ZRtp;
+
+NAMESPACE_COMMONCPP
+
+/**
+ * GNU ccRTP extension to support GNU ZRTP.
+ *
+ * ZRTP was developed by Phil Zimmermann and provides functions to
+ * negotiate keys and other necessary data (crypto data) to set-up
+ * the Secure RTP (SRTP) crypto context. Refer to Phil's ZRTP
+ * specification at his <a href="http://zfoneproject.com/">Zfone
+ * project</a> site to get more detailed imformation about the
+ * capabilities of ZRTP.
+ *
+ * <b>Short overview of the ZRTP implementation</b>
+ *
+ * ZRTP is a specific protocol to negotiate encryption algorithms
+ * and the required key material. ZRTP uses a RTP session to
+ * exchange its protocol messages.
+ *
+ * A complete GNU ZRTP implementation consists of two parts, the
+ * GNU ZRTP core and specific code that binds the GNU ZRTP core to
+ * the underlying RTP/SRTP stack and the operating system:
+ * <ul>
+ * <li>
+ * The GNU ZRTP core is independent of a specific RTP/SRTP
+ * stack and the operationg system and consists of the ZRTP
+ * protocol state engine, the ZRTP protocol messages, and the
+ * GNU ZRTP engine. The GNU ZRTP engine provides methods to
+ * setup ZRTP message and to analyze received ZRTP messages,
+ * to compute the crypto data required for SRTP, and to
+ * maintain the required hashes and HMAC.
+ * </li>
+ * <li>
+ * The second part of an implementation is specific
+ * <em>glue</em> code the binds the GNU ZRTP core to the
+ * actual RTP/SRTP implementation and other operating system
+ * specific services such as timers.
+ * </li>
+ * </ul>
+ *
+ * The GNU ZRTP core uses a callback interface class (refer to
+ * ZrtpCallback) to access RTP/SRTP or operating specific methods,
+ * for example to send data via the RTP/SRTP stack, to access
+ * timers, provide mutex handling, and to report events to the
+ * application.
+ *
+ * <b>The ZrtpQueue</b>
+ *
+ * ZrtpQueue implements code that is specific to the GNU ccRTP
+ * implementation. ZrtpQueue also implements the specific code to
+ * provide the mutex and timeout handling to the GNU ZRTP
+ * core. Both, the mutex and the timeout handling, use the GNU
+ * Common C++ library to stay independent of the operating
+ * seystem. For more information refer to the <a
+ * href="http://www.gnutelephony.org/index.php/GNU_Common_C%2B%2B">GNU
+ * Common C++</a> web site.
+ *
+ * To perform its tasks ZrtpQueue
+ * <ul>
+ * <li> extends GNU ccRTP classes to use the underlying
+ * ccRTP methods and the RTP/SRTP send and receive queues
+ * </li>
+ * <li> implements the ZrtpCallback interface to provide ccRTP
+ * access and other specific services (timer, mutex) to GNU
+ * ZRTP
+ * </li>
+ * <li> provides ZRTP specific methods that applications may use
+ * to control and setup GNU ZRTP
+ * </li>
+ * <li> can register and use an application specific callback
+ * class (refer to ZrtpUserCallback)
+ * </li>
+ * </ul>
+ *
+ * After instantiating a GNU ZRTP session (see below for a short
+ * example) applications may use the ZRTP specific methods of
+ * ZrtpQueue to control and setup GNU ZRTP, for example enable or
+ * disable ZRTP processing or getting ZRTP status information.
+ *
+ * GNU ZRTP provides a ZrtpUserCallback class that an application
+ * may extend and register with ZrtpQueue. GNU ZRTP and ZrtpQueue
+ * use the ZrtpUserCallback methods to report ZRTP events to the
+ * application. The application may display this information to
+ * the user or act otherwise.
+ *
+ * The following figure depicts the relationships between
+ * ZrtpQueue, ccRTP RTP/SRTP implementation, the GNU ZRTP core,
+ * and an application that provides an ZrtpUserCallback class.
+ *
+@verbatim
+
+ +----------+
+ | ccRTP |
+ | RTP/SRTP |
+ | |
+ +----------+
+ ^
+ | extends
+ |
++----------------+ +-----+------+
+| Application | | | +-----------------+
+| instantiates | uses | ZrtpQueue | uses | |
+| a ZRTP Session +------+ implements +------+ GNU ZRTP |
+| and provides | |ZrtpCallback| | core |
+|ZrtpUserCallback| | | | implementation |
++----------------+ +------------+ | (ZRtp et al) |
+ | |
+ +-----------------+
+@endverbatim
+ *
+ * Because ZrtpQueue extends the ccRTP RTP/SRTP implementation
+ * (AVPQueue) all public methods defined by ccRTP are also
+ * available for a ZRTP session. ZrtpQueue overwrites some of the
+ * public methods of ccRTP (AVPQueue) to implement ZRTP specific
+ * code.
+ *
+ * GNU ZRTP provides a <em>SymmetricZRTPSession</em> type to
+ * simplify its use. An application uses this type in the same way
+ * as it would use the normal ccRTP <em>SymmetricRTPSession</em>
+ * type. The following short code snippets show how an application
+ * could instantiate ccRTP and GNU ZRTP sessions. The first
+ * snippet shows how to instantiate a ccRTP session:
+ *
+ * @code
+ * ...
+ * #include <ccrtp/rtp.h>
+ * ...
+ * SymmetricRTPSession tx(pattern.getSsrc(),
+ * InetHostAddress("localhost"));
+ * ...
+ *
+ * @endcode
+ *
+ * The same code as above but using a GNU ZRTP session this time:
+ * @code
+ * ...
+ * #include <libzrtpcpp/zrtpccrtp.h>
+ * ...
+ * SymmetricZRTPSession tx(pattern.getSsrc(),
+ * InetHostAddress("localhost"));
+ * ...
+ *
+ * @endcode
+ *
+ * The only differences are the different include statements and
+ * the different session types.
+ *
+ * The <em>demo</em> folder contains a small example that shows
+ * how to use GNU ZRTP.
+ *
+ * Please refer to the GNU ccRTP documentation for a description
+ * of ccRTP methods and functions. This ZrtpQueue documentation
+ * shows the ZRTP specific extensions and describes overloaded
+ * methods and a possible different behaviour.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpQueue : public AVPQueue, ZrtpCallback {
+
+public:
+
+ /**
+ * Initialize the ZrtpQueue.
+ *
+ * Before an application can use ZRTP it has to initialize the
+ * ZRTP implementation. This method initializes the timeout
+ * thread and opens a file that contains ZRTP specific
+ * information such as the applications ZID (ZRTP id) and its
+ * retained shared secrets.
+ *
+ * If one application requires several ZRTP sessions all
+ * sessions use the same timeout thread and use the same ZID
+ * file. Therefore an application does not need to do any
+ * synchronisation regading ZID files or timeouts. This is
+ * managed by the ZRTP implementation.
+ *
+ * The current implementation of ZrtpQueue does not support
+ * different ZID files for one application instance. This
+ * restriction may be removed in later versions.
+ *
+ * The application may specify its own ZID file name. If no
+ * ZID file name is specified it defaults to
+ * <code>$HOME/.GNUccRTP.zid</code> if the <code>HOME</code>
+ * environment variable is set. If it is not set the current
+ * directory is used.
+ *
+ * If the method could set up the timeout thread and open the ZID
+ * file then it enables ZRTP processing and returns.
+ *
+ * @param zidFilename
+ * The name of the ZID file, can be a relative or absolut
+ * filename.
+ *
+ * @param autoEnable
+ * if set to true the method automatically sets enableZrtp to
+ * true. This enables the ZRTP auto-sense mode. Default is true.
+ *
+ * @param config
+ * this parameter points to ZRTP configuration data. If it is
+ * NULL then ZrtpQueue uses a default setting. Default is NULL.
+ *
+ * @return
+ * 1 on success, ZRTP processing enabled, -1 on failure,
+ * ZRTP processing disabled.
+ *
+ */
+ int32_t initialize(const char *zidFilename, bool autoEnable = true,
+ ZrtpConfigure* config = NULL);
+
+ /*
+ * Applications use the following methods to control ZRTP, for example
+ * to enable ZRTP, set flags etc.
+ */
+
+ /**
+ * Enable or disable ZRTP processing.
+ *
+ * Call this method to enable or disable ZRTP processing after
+ * calling <code>initialize()</code>. This can be done before
+ * using a RTP session or at any time during a RTP session.
+ *
+ * Existing SRTP sessions or currently active ZRTP processing will
+ * not be stopped or disconnected.
+ *
+ * If the application enables ZRTP then:
+ * <ul>
+ * <li>ZrtpQueue starts to send ZRTP Hello packets after at least
+ * one RTP packet was sent and received on the associated RTP
+ * session. Thus if an application enables ZRTP and ZrtpQueue
+ * detects traffic on the RTP session then ZrtpQueue automatically
+ * starts the ZRTP protocol. This automatic start is convenient
+ * for applications that negotiate RTP parameters and set up RTP
+ * sessions but the actual RTP traffic starts some time later.
+ * </li>
+ * <li>ZrtpQueue analyses incoming packets to detect ZRTP
+ * messages. If ZRTP was started, either via automatic start (see
+ * above) or explicitly via startZrtp(), then ZrtpQueue
+ * forwards ZRTP packets to the GNU ZRTP core.
+ * </ul>
+ *
+ * @param onOff
+ * @c true to enable ZRTP, @c false to disable ZRTP
+ */
+ void setEnableZrtp(bool onOff);
+
+ /**
+ * Return the state of ZRTP enable state.
+ *
+ * @return @c true if ZRTP processing is enabled, @c false
+ * otherwise.
+ */
+ bool isEnableZrtp();
+
+ /**
+ * Set SAS as verified.
+ *
+ * The application may call this method if the user confirmed
+ * (verfied) the Short Authentication String (SAS) with the peer.
+ *
+ * ZRTP calls ZrtpUserCallback#showSAS after it computed the SAS
+ * and the application registered a user callback class. The
+ * application should display the SAS and provide a mechanism at
+ * the user interface that enables the user to confirm the SAS.
+ *
+ * ZRTP remembers the SAS confirmation status together with the
+ * retained secrets data. If both parties confirmed the SAS then
+ * ZRTP informs the application about this status on the next ZRTP
+ * session.
+ *
+ * For more detailed information regarding SAS please refer to the
+ * ZRTP specification, chapter 8.
+ */
+ void SASVerified();
+
+ /**
+ * Reset the SAS verfied flag for the current user's retained secrets.
+ *
+ */
+ void resetSASVerified();
+
+ /**
+ * To confirm a go clear request.
+ *
+ * Call this method if the user confirmed a go clear (secure mode off).
+ */
+ void goClearOk();
+
+ /**
+ * Request to switch off secure mode.
+ *
+ * Call this method is the user itself wants to switch off secure
+ * mode (go clear). After sending the "go clear" request to the peer
+ * ZRTP immediatly switch off SRTP processing. Every RTP data is sent
+ * in clear after the go clear request.
+ */
+ void requestGoClear();
+
+ /**
+ * Set the auxilliary secret.
+ *
+ * Use this method to set the srtps secret data. Refer to ZRTP
+ * specification, chapter 5.3 ff
+ *
+ * @param data
+ * Points to the auxilliary secret data.
+ * @param length
+ * Length of the auxilliary secrect in bytes
+ */
+ void setAuxSecret(uint8_t* data, int32_t length);
+
+ /**
+ * Set the application's callback class.
+ *
+ * The destructor of ZrtpQueue also destorys the user callback
+ * class if it was set. The application must not delete the
+ * callback object or use/reference the callback object after
+ * ZrtpQueue was destroyed.
+ *
+ * @param ucb
+ * Implementation of the application's ZrtpUserCallback class
+ */
+ void setUserCallback(ZrtpUserCallback* ucb);
+
+ /**
+ * Set the client ID for ZRTP Hello message.
+ *
+ * The GNU ccRTP client may set its id to identify itself in the
+ * ZRTP Hello message. The maximum length is 16 characters. A
+ * shorter id string is possible, it will be filled with blanks. A
+ * longer id string will be truncated to 16 characters. The
+ * standard client id is <code>'GNU ccRTP ZRTP '</code> (without
+ * the quotes).
+ *
+ * Setting the client's id must be done before calling
+ * ZrtpQueue#initialize() or ZrtpQueue#startZrtp() .
+ *
+ * @param id
+ * The client's id string
+ */
+ void setClientId(std::string id);
+
+ /**
+ * Get the ZRTP Hello Hash data.
+ *
+ * Use this method to get the ZRTP Hello Hash data. The method
+ * returns the data as a string containing hex-digits. Refer
+ * to ZRTP specification, chapter 9.1.
+ *
+ * @return
+ * a std:string containing the Hello hash value as hex-digits. The
+ * hello hash is available immediatly after calling
+ * ZrtpQueue#startZrtp. If ZRTP was not started the method returns
+ * an empty string.
+ */
+ std::string getHelloHash();
+
+ /**
+ * Get the peer's ZRTP Hello Hash data.
+ *
+ * Use this method to get the peer's ZRTP Hello Hash data. The method
+ * returns the data as a string containing the ZRTP protocol version and
+ * hex-digits.
+ *
+ * The peer's hello hash is available only after ZRTP received a hello. If
+ * no data is available the function returns an empty string.
+ *
+ * Refer to ZRTP specification, chapter 8.
+ *
+ * @return
+ * a std:string containing the Hello version and the hello hash as hex digits.
+ */
+ std::string getPeerHelloHash();
+
+ /**
+ * Get Multi-stream parameters.
+ *
+ * Use this method to get the Multi-stream that were computed during
+ * the ZRTP handshake. An application may use these parameters to
+ * enable multi-stream processing for an associated SRTP session.
+ *
+ * Refer to chapter 5.4.2 in the ZRTP specification for further details
+ * and restriction how and when to use multi-stream mode.
+ *
+ * @return
+ * a string that contains the multi-stream parameters. The application
+ * must not modify the contents of this string, it is opaque data. The
+ * application may hand over this string to a new ZrtpQueue instance
+ * to enable multi-stream processing for this ZrtpQueue. If ZRTP was
+ * not started or ZRTP is not yet in secure state the method returns an
+ * empty string.
+ *
+ * @see setMultiStrParams()
+ */
+ std::string getMultiStrParams();
+
+ /**
+ * Set Multi-stream parameters.
+ *
+ * Use this method to set the parameters required to enable Multi-stream
+ * processing of ZRTP. The multi-stream parameters must be set before the
+ * application starts the ZRTP protocol engine.
+ *
+ * Refer to chapter 5.4.2 in the ZRTP specification for further details
+ * of multi-stream mode.
+ *
+ * @param parameters
+ * A string that contains the multi-stream parameters that this
+ * new ZrtpQueue instanace shall use.
+ *
+ * @see getMultiStrParams()
+ */
+ void setMultiStrParams(std::string parameters);
+
+ /**
+ * Check if this ZRTP use Multi-stream.
+ *
+ * Use this method to check if this ZRTP instance uses multi-stream. Even
+ * if the application provided multi-stram parameters it may happen that
+ * full DH mode was used. Refer to chapters 5.2 and 5.4.2 in the ZRTP #
+ * when this may happen.
+ *
+ * @return
+ * True if multi-stream is used, false otherwise.
+ */
+ bool isMultiStream();
+
+ /**
+ * Check if the other ZRTP client supports Multi-stream.
+ *
+ * Use this method to check if the other ZRTP client supports
+ * Multi-stream mode.
+ *
+ * @return
+ * True if multi-stream is available, false otherwise.
+ */
+ bool isMultiStreamAvailable();
+
+ /**
+ * Accept a PBX enrollment request.
+ *
+ * If a PBX service asks to enroll the MiTM key and the user accepts this
+ * requtes, for example by pressing an OK button, the client application
+ * shall call this method and set the parameter <code>accepted</code> to
+ * true. If the user does not accept the request set the parameter to
+ * false.
+ *
+ * @param accepted
+ * True if the enrollment request is accepted, false otherwise.
+ */
+ void acceptEnrollment(bool accepted);
+
+ /**
+ * Get the commited SAS rendering algorithm for this ZRTP session.
+ *
+ * @return the commited SAS rendering algorithm
+ */
+ std::string getSasType();
+
+ /**
+ * Get the computed SAS hash for this ZRTP session.
+ *
+ * A PBX ZRTP back-to-Back function uses this function to get the SAS
+ * hash of an enrolled client to construct the SAS relay packet for
+ * the other client.
+ *
+ * @return a refernce to the byte array that contains the full
+ * SAS hash.
+ */
+ uint8_t* getSasHash();
+
+ /**
+ * Send the SAS relay packet.
+ *
+ * The method creates and sends a SAS relay packet according to the ZRTP
+ * specifications. Usually only a MitM capable user agent (PBX) uses this
+ * function.
+ *
+ * @param sh the full SAS hash value
+ * @param render the SAS rendering algorithm
+ */
+ bool sendSASRelayPacket(uint8_t* sh, std::string render);
+
+ /**
+ * Check the state of the MitM mode flag.
+ *
+ * If true then this ZRTP session acts as MitM, usually enabled by a PBX
+ * client (user agent)
+ *
+ * @return state of mitmMode
+ */
+ bool isMitmMode();
+
+ /**
+ * Set the state of the MitM mode flag.
+ *
+ * If MitM mode is set to true this ZRTP session acts as MitM, usually
+ * enabled by a PBX client (user agent).
+ *
+ * @param mitmMode defines the new state of the mitmMode flag
+ */
+ void setMitmMode(bool mitmMode);
+
+ /**
+ * Enable or disable paranoid mode.
+ *
+ * The Paranoid mode controls the behaviour and handling of the SAS verify flag. If
+ * Panaoid mode is set to flase then ZRtp applies the normal handling. If Paranoid
+ * mode is set to true then the handling is:
+ *
+ * <ul>
+ * <li> always set the SAS verify flag to <code>false</code> at srtpSecretsOn() callback. The
+ * user interface (UI) must show <b>SAS not verified</b>. See implementation note below.</li>
+ * <li> don't set the SAS verify flag in the <code>Confirm</code> packets, thus forcing the other
+ * peer to report <b>SAS not verified</b>.</li>
+ * <li> ignore the <code>SASVerified()</code> function, thus do not set the SAS verified flag
+ * in the ZRTP cache. </li>
+ * <li> Disable the <em>Trusted PBX MitM</em> feature. Just send the <code>SASRelay</code> packet
+ * but do not process the relayed data. This protects the user from a malicious
+ * "trusted PBX".</li>
+ * </ul>
+ * ZRtp performs alls other steps during the ZRTP negotiations as usual, in particular it
+ * computes, compares, uses, and stores the retained secrets. This avoids unnecessary warning
+ * messages. The user may enable or disable the Paranoid mode on a call-by-call basis without
+ * breaking the key continuity data.
+ *
+ * <b>Implementation note:</b><br/>
+ * An application shall <b>always display the SAS if the SAS verify flag is <code>false</code></b>.
+ * The application shall remind the user to compare the SAS code, for example using larger fonts,
+ * different colours and other display features.
+ */
+ void setParanoidMode(bool yesNo);
+
+ /**
+ * Check status of paranoid mode.
+ *
+ * @return
+ * Returns true if paranoid mode is enabled.
+ */
+ bool isParanoidMode();
+
+ /**
+ * Check the state of the enrollment mode.
+ *
+ * If true then we will set the enrollment flag (E) in the confirm
+ * packets and performs the enrollment actions. A MitM (PBX) enrollment service sets this flagstarted this ZRTP
+ * session. Can be set to true only if mitmMode is also true.
+ * @return status of the enrollmentMode flag.
+ */
+ bool isEnrollmentMode();
+
+ /**
+ * Check the state of the enrollment mode.
+ *
+ * If true then we will set the enrollment flag (E) in the confirm
+ * packets and perform the enrollment actions. A MitM (PBX) enrollment
+ * service must sets this mode to true.
+ *
+ * Can be set to true only if mitmMode is also true.
+ *
+ * @param enrollmentMode defines the new state of the enrollmentMode flag
+ */
+ void setEnrollmentMode(bool enrollmentMode);
+
+ /**
+ * Backwards compatible api fix...
+ */
+ inline void setPBXEnrollment(bool enrollmentMode)
+ {setMitmMode(enrollmentMode); setEnrollmentMode(enrollmentMode);}
+
+ /**
+ * Check if a peer's cache entry has a vaild MitM key.
+ *
+ * If true then the other peer ha a valid MtiM key, i.e. the peer has performed
+ * the enrollment procedure. A PBX ZRTP Back-2-Back application can use this function
+ * to check which of the peers is enrolled.
+ *
+ * @return True if the other peer has a valid Mitm key (is enrolled).
+ */
+ bool isPeerEnrolled();
+
+ /**
+ * Set the state of the SAS signature mode flag.
+ *
+ * If SAS signature mode is set to true this ZRTP session support SAS signature
+ * callbacks and signature transfer between clients.
+ *
+ * @param sasSignMode defines the new state of the sasSignMode flag
+ */
+ void setSignSas(bool sasSignMode);
+
+ /**
+ * Set signature data
+ *
+ * This functions stores signature data and transmitts it during ZRTP
+ * processing to the other party as part of the Confirm packets. Refer to
+ * chapters 6.7 and 8.2 in the ZRTP specification.
+ *
+ * @param data
+ * The signature data including the signature type block. The method
+ * copies this data into the Confirm packet at signature type block.
+ * @param length
+ * The length of the signature data in bytes. This length must be
+ * multiple of 4.
+ * @return
+ * True if the method stored the data, false otherwise.
+ */
+ bool setSignatureData(uint8* data, int32 length);
+
+ /**
+ * Get signature data
+ *
+ * This functions returns signature data that was receivied during ZRTP
+ * processing. Refer to chapters 6.7 and 8.2.
+ *
+ * @return
+ * Pointer to signature data. This is a pointer to volatile data that is
+ * only valid during the checkSASSignature() callback. The application
+ * shall copy the data if necessary.
+ */
+ const uint8* getSignatureData();
+
+ /**
+ * Get length of signature data
+ *
+ * This functions returns the length of signature data that was receivied
+ * during ZRTP processing. Refer to chapters 6.7 and 8.2.
+ *
+ * @return
+ * Length in bytes of the received signature data. The method returns
+ * zero if no signature data avilable.
+ */
+ int32 getSignatureLength();
+
+ /**
+ * Put data into the RTP output queue.
+ *
+ * This is used to create a data packet in the send queue.
+ * Sometimes a "NULL" or empty packet will be used instead, and
+ * these are known as "silent" packets. "Silent" packets are
+ * used simply to "push" the scheduler along more accurately
+ * by giving the appearence that a next packet is waiting to
+ * be sent and to provide a valid timestamp for that packet.
+ *
+ * This method overrides the same method in OutgoingDataQueue class.
+ * During ZRTP processing it may be necessary to control the
+ * flow of outgoing RTP payload packets (GoClear processing).
+ *
+ * @param stamp Timestamp for expected send time of packet.
+ * @param data Value or NULL if special "silent" packet.
+ * @param len May be 0 to indicate a default by payload type.
+ **/
+ void
+ putData(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);
+
+ /**
+ * Immediatly send a data packet.
+ *
+ * This is used to create a data packet and send it immediately.
+ * Sometimes a "NULL" or empty packet will be used instead, and
+ * these are known as "silent" packets. "Silent" packets are
+ * used simply to "push" the scheduler along more accurately
+ * by giving the appearence that a next packet is waiting to
+ * be sent and to provide a valid timestamp for that packet.
+ *
+ * This method overrides the same method in OutgoingDataQueue
+ * class. During ZRTP processing it may be necessary to
+ * control the flow of outgoing RTP payload packets (GoClear
+ * processing).
+ *
+ * @param stamp Timestamp immediate send time of packet.
+ * @param data Value or NULL if special "silent" packet.
+ * @param len May be 0 to indicate a default by payload type.
+ **/
+ void
+ sendImmediate(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);
+
+ /**
+ * Starts the ZRTP protocol engine.
+ *
+ * Applications may call this method to immediatly start the ZRTP protocol
+ * engine any time after initializing ZRTP and setting optinal parameters,
+ * for example client id or multi-stream parameters.
+ *
+ * If the application does not call this method but sucessfully initialized
+ * the ZRTP engine using <code>initialize()</code> then ZRTP also starts
+ * after the application sent and received RTP packets. An application can
+ * disable this automatic, delayed start of the ZRTP engine using
+ * <code>setEnableZrtp(false)</code> before sending or receiving RTP
+ * packets.
+ *
+ */
+ void startZrtp();
+
+ /**
+ * Stops the ZRTP protocol engine.
+ *
+ * Applications call this method to stop the ZRTP protocol
+ * engine.
+ *
+ */
+ void stopZrtp();
+
+ /**
+ * Get other party's ZID (ZRTP Identifier) data
+ *
+ * This functions returns the other party's ZID that was receivied
+ * during ZRTP processing.
+ *
+ * The ZID data can be retrieved after ZRTP receive the first Hello
+ * packet from the other party. The application may call this method
+ * for example during SAS processing in showSAS(...) user callback
+ * method.
+ *
+ * @param data
+ * Pointer to a data buffer. This buffer must have a size of
+ * at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
+ * @return
+ * Number of bytes copied into the data buffer - must be equivalent
+ * to 96 bit, usually 12 bytes.
+ */
+ int32 getPeerZid(uint8* data);
+
+protected:
+ friend class TimeoutProvider<std::string, ost::ZrtpQueue*>;
+
+ /**
+ * A hook that gets called if the decoding of an incoming SRTP
+ * was erroneous
+ *
+ * @param pkt
+ * The SRTP packet with error.
+ * @param errorCode
+ * The error code: -1 - SRTP authentication failure, -2 - replay
+ * check failed
+ * @return
+ * True: put the packet in incoming queue for further processing
+ * by the applications; false: dismiss packet. The default
+ * implementation returns false.
+ */
+ virtual bool
+ onSRTPPacketError(IncomingRTPPkt& pkt, int32 errorCode);
+
+ /**
+ * Handle timeout event forwarded by the TimeoutProvider.
+ *
+ * Just call the ZRTP engine for further processing.
+ */
+ void handleTimeout(const std::string &c);
+
+ /**
+ * This function is used by the service thread to process
+ * the next incoming packet and place it in the receive list.
+ *
+ * This class overloads the function of IncomingDataQueue
+ * implementation.
+ *
+ * @return number of payload bytes received, <0 if error.
+ */
+ virtual size_t takeInDataPacket();
+
+ /*
+ * The following methods implement the GNU ZRTP callback interface.
+ * For detailed documentation refer to file ZrtpCallback.h
+ */
+ int32_t sendDataZRTP(const unsigned char* data, int32_t length);
+
+ int32_t activateTimer(int32_t time);
+
+ int32_t cancelTimer();
+
+ void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+ bool srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part);
+
+ void srtpSecretsOff(EnableSecurity part);
+
+ void srtpSecretsOn(std::string c, std::string s, bool verified);
+
+ void handleGoClear();
+
+ void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);
+
+ void zrtpNotSuppOther();
+
+ void synchEnter();
+
+ void synchLeave();
+
+ void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info);
+
+ void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info);
+
+ void signSAS(uint8_t* sasHash);
+
+ bool checkSASSignature(uint8_t* sasHash);
+
+ /*
+ * End of ZrtpCallback functions.
+ */
+
+ ZrtpQueue(uint32 size = RTPDataQueue::defaultMembersHashSize,
+ RTPApplication& app = defaultApplication());
+
+ /**
+ * Local SSRC is given instead of computed by the queue.
+ */
+ ZrtpQueue(uint32 ssrc, uint32 size =
+ RTPDataQueue::defaultMembersHashSize,
+ RTPApplication& app = defaultApplication());
+
+ virtual ~ZrtpQueue();
+
+private:
+ void init();
+ size_t rtpDataPacket(unsigned char* packet, int32 rtn,
+ InetHostAddress network_address,
+ tpport_t transport_port);
+
+ ZRtp *zrtpEngine;
+ ZrtpUserCallback* zrtpUserCallback;
+
+ std::string clientIdString;
+
+ bool enableZrtp;
+
+ int32 secureParts;
+
+ int16 senderZrtpSeqNo;
+ ost::Mutex synchLock; // Mutex for ZRTP (used by ZrtpStateClass)
+ uint32 peerSSRC;
+ bool started;
+ bool mitmMode;
+ bool signSas;
+ bool enableParanoidMode;
+};
+
+class IncomingZRTPPkt : public IncomingRTPPkt {
+
+public:
+ /**
+ * Build a ZRTP packet object from a data buffer.
+ *
+ * @param block pointer to the buffer the whole packet is stored in.
+ * @param len length of the whole packet, expressed in octets.
+ *
+ **/
+
+ IncomingZRTPPkt(const unsigned char* block, size_t len);
+
+ ~IncomingZRTPPkt()
+ { }
+
+ uint32
+ getZrtpMagic() const;
+
+ uint32
+ getSSRC() const;
+};
+
+class OutgoingZRTPPkt : public OutgoingRTPPkt {
+
+public:
+ /**
+ * Construct a new ZRTP packet to be sent.
+ *
+ * A new copy in memory (holding all this components
+ * along with the fixed header) is created.
+ *
+ * @param hdrext whole header extension.
+ * @param hdrextlen size of whole header extension, in octets.
+ **/
+ OutgoingZRTPPkt(const unsigned char* const hdrext, uint32 hdrextlen);
+ ~OutgoingZRTPPkt()
+ { }
+};
+
+END_NAMESPACE
+
+#endif
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
+
diff --git a/src/libzrtpcpp/ZrtpStateClass.h b/src/libzrtpcpp/ZrtpStateClass.h
new file mode 100644
index 0000000..fba061d
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpStateClass.h
@@ -0,0 +1,324 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPSTATECLASS_H_
+#define _ZRTPSTATECLASS_H_
+
+/**
+ * @file ZrtpStateClass.h
+ * @brief The ZRTP state handling class
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpStates.h>
+#include <libzrtpcpp/ZrtpPacketBase.h>
+
+/**
+ * The ZRTP states
+ *
+ * Depending on the role of this state engine and the actual protocl flow
+ * not all states are processed during a ZRTP handshake.
+ */
+enum zrtpStates {
+ Initial, ///< Initial state after starting the state engine
+ Detect, ///< State sending Hello, try to detect answer message
+ AckDetected, ///< HelloAck received
+ AckSent, ///< HelloAck sent after Hello received
+ WaitCommit, ///< Wait for a Commit message
+ CommitSent, ///< Commit message sent
+ WaitDHPart2, ///< Wait for a DHPart2 message
+ WaitConfirm1, ///< Wait for a Confirm1 message
+ WaitConfirm2, ///< Wait for a confirm2 message
+ WaitConfAck, ///< Wait for Conf2Ack
+ WaitClearAck, ///< Wait for clearAck - not used
+ SecureState, ///< This is the secure state - SRTP active
+ WaitErrorAck, ///< Wait for ErrorAck message
+ numberOfStates ///< Gives total number of protocol states
+};
+
+enum EventReturnCodes {
+ Fail = 0, ///< ZRTP event processing failed.
+ Done = 1 ///< Event processing ok.
+};
+
+enum EventDataType {
+ ZrtpInitial = 1, ///< Initial event, enter Initial state
+ ZrtpClose, ///< Close event, shut down state engine
+ ZrtpPacket, ///< Normal ZRTP message event, process according to state
+ Timer, ///< Timer event
+ ErrorPkt ///< Error packet event
+};
+
+enum SecureSubStates {
+ Normal,
+ WaitSasRelayAck,
+ numberofSecureSubStates
+};
+
+/// A ZRTP state event
+typedef struct Event {
+ EventDataType type; ///< Type of event
+ uint8_t* packet; ///< Event data if availabe, usually a ZRTP message
+} Event_t;
+
+
+/**
+ * The ZRTP timer structure.
+ *
+ * This structure holds all necessary data to compute the timer for
+ * the protocol timers. The state engine allocate one structure for
+ * each timer. ZRTP uses two timers, T1 and T2, to monitor protocol
+ * timeouts. As a slight misuse but to make overall handling a bit
+ * simpler this structure also contains the resend counter. This is
+ * possible in ZRTP because it uses a simple timeout strategy.
+ */
+typedef struct zrtpTimer {
+ int32_t time, ///< Current timeout value
+ start, ///< Start value for timeout
+ increment, ///< increment timeout after each timeout event (not used anymore)
+ capping, ///< Maximum timeout value
+ counter, ///< Current number of timeouts
+ maxResend; ///< Maximum number of timeout resends
+} zrtpTimer_t;
+
+
+class ZRtp;
+
+/**
+ * This class is the ZRTP protocol state engine.
+ *
+ * This class is responsible to handle the ZRTP protocol. It does not
+ * handle the ZRTP HMAC, DH, and other data management. This is done in
+ * class ZRtp, which is the parent of this class.
+ *
+ * The methods of this class implement the ZRTP state actions.
+ *
+ */
+
+
+class __EXPORT ZrtpStateClass {
+
+private:
+ ZRtp* parent; ///< The ZRTP implmentation
+ ZrtpStates* engine; ///< The state switching engine
+ Event_t* event; ///< Current event to process
+
+ /**
+ * The last packet that was sent.
+ *
+ * If we are <code>Initiator</code> then resend this packet in case of
+ * timeout.
+ */
+ ZrtpPacketBase* sentPacket;
+
+ /**
+ * Points to prepared Commit packet after receiving a Hello packet
+ */
+ ZrtpPacketCommit* commitPkt;
+
+ zrtpTimer_t T1; ///< The Hello message timeout timer
+ zrtpTimer_t T2; ///< Timeout timer for other messages
+
+ /*
+ * If this is set to true the protocol engine handle the multi-stream
+ * variant of ZRTP. Refer to chapter 5.4.2 in the ZRTP specification.
+ */
+ bool multiStream;
+
+ // Secure substate to handle SAS relay packets
+ SecureSubStates secSubstate;
+
+ /**
+ * Secure Sub state WaitSasRelayAck.
+ *
+ * This state belongs to the secure substates and handles
+ * SAS Relay Ack.
+ *
+ * When entering this transition function
+ * - sentPacket contains Error packet, Error timer active
+ *
+ * Possible events in this state are:
+ * - timeout for sent SAS Relay packet: causes a resend check and repeat sending
+ * of packet
+ * - SASRelayAck: Stop timer and switch to secure substate Normal.
+ */
+ bool subEvWaitRelayAck();
+
+public:
+ /// Create a ZrtpStateClass
+ ZrtpStateClass(ZRtp *p);
+ ~ZrtpStateClass();
+
+ /// Check if in a specified state
+ bool inState(const int32_t state) { return engine->inState(state); };
+
+ /// Switch to the specified state
+ void nextState(int32_t state) { engine->nextState(state); };
+
+ /// Process an event, the main entry point into the state engine
+ void processEvent(Event_t *ev);
+
+ /**
+ * The state event handling methods.
+ *
+ * Refer to the protocol state diagram for further documentation.
+ */
+ /// Initial event state
+ void evInitial();
+
+ /// Detect state
+ void evDetect();
+
+ /// HelloAck detected state
+ void evAckDetected();
+
+ /// HelloAck sent state
+ void evAckSent();
+
+ /// Wait for Commit message
+ void evWaitCommit();
+
+ /// Commit sent state
+ void evCommitSent();
+
+ /// Wait for DHPart2 message
+ void evWaitDHPart2();
+
+ /// Wait for Confirm2 message
+ void evWaitConfirm1();
+
+ /// Wait for Confirm2 message
+ void evWaitConfirm2();
+
+ /// Wait for ConfAck message
+ void evWaitConfAck();
+
+ /// Wait for ClearAck message (not used)
+ void evWaitClearAck();
+
+ /// Secure reached state
+ void evSecureState();
+
+ /// Wait for ErrorAck message
+ void evWaitErrorAck();
+
+ /**
+ * Initialize and activate a timer.
+ *
+ * @param t
+ * The ZRTP timer structure to use for the timer.
+ * @return
+ * 1 timer was activated
+ * 0 activation failed
+ */
+ int32_t startTimer(zrtpTimer_t *t);
+
+ /**
+ * Compute and set the next timeout value.
+ *
+ * @param t
+ * The ZRTP timer structure to use for the timer.
+ * @return
+ * 1 timer was activated
+ * 0 activation failed
+ * -1 resend counter exceeded
+ */
+ int32_t nextTimer(zrtpTimer_t *t);
+
+ /**
+ * Cancel the active timer.
+ *
+ * @return
+ * 1 timer was canceled
+ * 0 cancelation failed
+ */
+ int32_t cancelTimer() {return parent->cancelTimer(); };
+
+ /**
+ * Prepare and send an Error packet.
+ *
+ * Preparse an Error packet and sends it. It stores the Error
+ * packet in the sentPacket variable to enable resending. The
+ * method switches to protocol state Initial.
+ */
+ void sendErrorPacket(uint32_t errorCode);
+
+ /**
+ * Set status if an error occured while sending a ZRTP packet.
+ *
+ * This functions clears data and set the state to Initial after the engine
+ * detected a problem while sending a ZRTP packet.
+ *
+ * @return
+ * Fail code
+ */
+ void sendFailed();
+
+ /**
+ * Set status if a timer problems occure.
+ *
+ * This functions clears data and set state to Initial after a timer
+ * error occured. Either no timer available or resend counter exceedeed.
+ *
+ * @return
+ * Fail code
+ */
+ void timerFailed(int32_t subCode);
+
+ /**
+ * Set multi-stream mode flag.
+ *
+ * This functions set the multi-stream mode. The protocol
+ * engine will run the multi-stream mode variant of the ZRTP
+ * protocol if this flag is set to true.
+ *
+ * @param multi
+ * Set the multi-stream mode flag to true or false.
+ */
+ void setMultiStream(bool multi);
+
+ /**
+ * Status of multi-stream mode flag.
+ *
+ * This functions returns the value of the multi-stream mode flag.
+ *
+ * @return
+ * Value of the multi-stream mode flag.
+ */
+ bool isMultiStream();
+
+ /**
+ * Send a SAS relay packet.
+ *
+ * the functions stores sends the SAS relay packet and stores the pointer in
+ * the sentPacket variable to enable resending.
+ *
+ * The method switches to secure substate WaitSasRelayAck.
+ *
+ * @param relay
+ * Pointer to the SAS relay packet.
+ */
+ void sendSASRelay(ZrtpPacketSASrelay* relay);
+};
+
+/**
+ * @}
+ */
+#endif // _ZRTPSTATECLASS_H_
+
diff --git a/src/libzrtpcpp/ZrtpStates.h b/src/libzrtpcpp/ZrtpStates.h
new file mode 100644
index 0000000..44662a0
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpStates.h
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPSTATES_H_
+#define _ZRTPSTATES_H_
+
+/**
+ * @file ZrtpStates.h
+ * @brief The ZRTP state switching class
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdint.h>
+
+class __EXPORT ZrtpStateClass;
+/**
+ * This structure hold the state name as enum (int) number and the pointer to
+ * the functions that handles the various triggers that can occur in a state.
+ */
+typedef struct {
+ int32_t stateName; ///< The state number
+ void (ZrtpStateClass::* handler)(void); ///< The state handler
+} state_t;
+
+/**
+ * Implement a simple state switching.
+ *
+ * This class provides functions that manage the states and the event handler
+ * functions. Its a very simple implementation.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpStates {
+ public:
+
+ /// Create an initialize state switching
+ ZrtpStates(state_t* const zstates,
+ const int32_t numStates,
+ const int32_t initialState):
+ numStates(numStates), states(zstates), state(initialState) {}
+
+ /// Call a state handler
+ int32_t processEvent(ZrtpStateClass& zsc) {
+ (zsc.*states[state].handler)();
+ return 0;
+ }
+
+ /// Check if in specified state
+ bool inState(const int32_t s) { return ((s == state)); }
+
+ /// Set the next state
+ void nextState(int32_t s) { state = s; }
+
+ private:
+ const int32_t numStates;
+ const state_t* states;
+ int32_t state;
+
+ ZrtpStates();
+};
+
+/**
+ * @}
+ */
+#endif //ZRTPSTATES
+
diff --git a/src/libzrtpcpp/ZrtpTextData.h b/src/libzrtpcpp/ZrtpTextData.h
new file mode 100644
index 0000000..e79cb98
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpTextData.h
@@ -0,0 +1,124 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPTEXTDATA_H_
+#define _ZRTPTEXTDATA_H_
+
+/**
+ * @file ZrtpTextData.h
+ * @brief The ZRTP ASCII texts - extern references
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <libzrtpcpp/ZrtpConfigure.h>
+
+/**
+ * The extern references to the global data.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+extern char clientId[];
+extern char zrtpVersion[];
+
+/**
+ *
+ */
+extern char HelloMsg[];
+extern char HelloAckMsg[];
+extern char CommitMsg[];
+extern char DHPart1Msg[];
+extern char DHPart2Msg[];
+extern char Confirm1Msg[];
+extern char Confirm2Msg[];
+extern char Conf2AckMsg[];
+extern char ErrorMsg[];
+extern char ErrorAckMsg[];
+extern char GoClearMsg[];
+extern char ClearAckMsg[];
+extern char PingMsg[];
+extern char PingAckMsg[];
+extern char SasRelayMsg[];
+extern char RelayAckMsg[];
+
+/**
+ *
+ */
+extern char responder[];
+extern char initiator[];
+extern char iniMasterKey[];
+extern char iniMasterSalt[];
+extern char respMasterKey[];
+extern char respMasterSalt[];
+
+extern char iniHmacKey[];
+extern char respHmacKey[];
+extern char retainedSec[];
+
+extern char iniZrtpKey[];
+extern char respZrtpKey[];
+
+extern char sasString[];
+
+extern char KDFString[];
+extern char zrtpSessionKey[];
+extern char zrtpMsk[];
+extern char zrtpTrustedMitm[];
+
+
+extern char s256[];
+extern char s384[];
+extern const char* mandatoryHash;
+
+extern char aes3[];
+extern char aes2[];
+extern char aes1[];
+extern char two3[];
+extern char two2[];
+extern char two1[];
+
+extern const char* mandatoryCipher;
+
+extern char dh2k[];
+extern char dh3k[];
+extern char ec25[];
+extern char ec38[];
+
+extern char mult[];
+
+extern const char* mandatoryPubKey;
+
+extern char b32[];
+extern const char* mandatorySasType;
+
+extern char hs32[];
+extern char hs80[];
+extern char sk32[];
+extern char sk64[];
+extern const char* mandatoryAuthLen_1;
+extern const char* mandatoryAuthLen_2;
+
+/**
+ * @}
+ */
+#endif // _ZRTPTEXTDATA_H_
+
diff --git a/src/libzrtpcpp/ZrtpUserCallback.h b/src/libzrtpcpp/ZrtpUserCallback.h
new file mode 100644
index 0000000..3e4871c
--- /dev/null
+++ b/src/libzrtpcpp/ZrtpUserCallback.h
@@ -0,0 +1,234 @@
+/*
+ Copyright (C) 2006-2008 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPUSERCALLBACK_H_
+#define _ZRTPUSERCALLBACK_H_
+
+/**
+ * @file ZrtpUserCallback.h
+ * @brief The ZRTP UserCallback class
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+#include <string>
+
+#include <libzrtpcpp/ZrtpCodes.h>
+
+/**
+ * Application callback methods.
+ *
+ * The ccRTP specific part of GNU ZRTP uses these callback methods
+ * to report ZRTP events to the application. This class implements a
+ * default behaviour for each callback method, usually just a return.
+ *
+ * An application may extend this class and overload methods
+ * to implement its own behaviour. The application must register its
+ * callback class using ZrtpQueue#setUserCallback().
+ *
+ * <b>CAVEAT</b><br/>
+ * All methods of the user callback class and classes that
+ * extend this class run in the context of the RTP thread. Thus it is
+ * of paramount importance to keep the execution time of the methods
+ * as short as possible.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class __EXPORT ZrtpUserCallback {
+
+ public:
+
+ /// Create the stadard user callback class.
+ ZrtpUserCallback() {}
+
+ virtual ~ZrtpUserCallback() {};
+
+ /**
+ * Inform user interface that security is active now.
+ *
+ * ZRTP calls this method if the sender and the receiver are
+ * in secure mode now.
+ *
+ * @param cipher
+ * Name and mode of cipher used to encrypt the SRTP stream
+ */
+ virtual void secureOn(std::string cipher) {
+ return;
+ }
+ /**
+ * Inform user interface that security is not active any more.
+ *
+ * ZRTP calls this method if either the sender or the receiver
+ * left secure mode.
+ *
+ */
+ virtual void secureOff() {
+ return;
+ }
+
+ /**
+ * Show the Short Authentication String (SAS) on user interface.
+ *
+ * ZRTP calls this method to display the SAS and inform about the SAS
+ * verification status. The user interface shall enable a SAS verfication
+ * button (or similar UI element). The user shall click on this UI
+ * element after he/she confirmed the SAS code with the partner.
+ *
+ * @param sas
+ * The string containing the SAS.
+ * @param verified
+ * If <code>verified</code> is true then SAS was verified by both
+ * parties during a previous call, otherwise it is set to false.
+ */
+ virtual void showSAS(std::string sas, bool verified) {
+ return;
+ }
+
+ /**
+ * Inform the user that ZRTP received "go clear" message from its peer.
+ *
+ * On receipt of a go clear message the user is requested to confirm
+ * a switch to unsecure (clear) modus. Until the user confirms ZRTP
+ * (and the underlying RTP) does not send any data.
+ */
+ virtual void confirmGoClear() {
+ return;
+ }
+
+ /**
+ * Show some information to user.
+ *
+ * ZRTP calls this method to display some information to the user.
+ * Along with the message ZRTP provides a severity indicator that
+ * defines: Info, Warning, Error, and Alert. Refer to the <code>
+ * MessageSeverity</code> enum in <code>ZrtpCodes.h</code>. The
+ * UI may use this indicator to highlight messages or alike.
+ *
+ * @param sev
+ * Severity of the message.
+ * @param subCode
+ * The subcode identifying the reason.
+ */
+ virtual void showMessage(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) {
+ return;
+ }
+
+ /**
+ * ZRTPQueue calls this if the negotiation failed.
+ *
+ * ZRTPQueue calls this method in case ZRTP negotiation failed. The
+ * parameters show the severity as well as some explanatory text.
+ * Refer to the <code>MessageSeverity</code> enum above.
+ *
+ * @param severity
+ * This defines the message's severity
+ * @param subCode
+ * The subcode identifying the reason.
+ */
+ virtual void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity,
+ int32_t subCode) {
+ return;
+ }
+
+ /**
+ * ZRTPQueue calls this method if the other side does not support ZRTP.
+ *
+ * If the other side does not answer the ZRTP <em>Hello</em> packets then
+ * ZRTP calls this method.
+ *
+ */
+ virtual void zrtpNotSuppOther() {
+ return;
+ }
+
+ /**
+ * ZRTPQueue calls this method to inform about a PBX enrollment request.
+ *
+ * Please refer to chapter 8.3 ff to get more details about PBX enrollment
+ * and SAS relay.
+ *
+ * @param info
+ * Give some information to the user about the PBX requesting an
+ * enrollment.
+ *
+ */
+ virtual void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info) {
+ return;
+ }
+
+ /**
+ * ZRTPQueue calls this method to inform about PBX enrollment result.
+ *
+ * Informs the use about the acceptance or denial of an PBX enrollment
+ * request
+ *
+ * @param info
+ * Give some information to the user about the result of an
+ * enrollment.
+ *
+ */
+ virtual void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info) {
+ return;
+ }
+
+ /**
+ * ZRTPQueue calls this method to request a SAS signature.
+ *
+ * After ZRTP core was able to compute the Short Authentication String
+ * (SAS) it calls this method. The client may now use an approriate
+ * method to sign the SAS. The client may use
+ * setSignatureData() of ZrtpQueue to store the signature
+ * data an enable signature transmission to the other peer. Refer
+ * to chapter 8.2 of ZRTP specification.
+ *
+ * @param sasHash
+ * Pointer to the 32 byte SAS hash to be signed.
+ * @see ZrtpQueue#setSignatureData
+ *
+ */
+ virtual void signSAS(uint8_t* sasHash) {
+ return;
+ }
+
+ /**
+ * ZRTPQueue calls this method to request a SAS signature check.
+ *
+ * After ZRTP received a SAS signature in one of the Confirm packets it
+ * call this method. The client may use <code>getSignatureLength()</code>
+ * and <code>getSignatureData()</code>of ZrtpQueue to get the signature
+ * data and perform the signature check. Refer to chapter 8.2 of ZRTP
+ * specification.
+ *
+ * If the signature check fails the client may return false to ZRTP. In
+ * this case ZRTP signals an error to the other peer and terminates
+ * the ZRTP handshake.
+ *
+ * @param sasHash
+ * Pointer to the 32 byte SAS hash that was signed by the other peer.
+ * @return
+ * true if the signature was ok, false otherwise.
+ *
+ */
+ virtual bool checkSASSignature(uint8_t* sasHash) {
+ return true;
+ }
+};
+
+#endif
diff --git a/src/libzrtpcpp/crypto/TwoCFB.cpp b/src/libzrtpcpp/crypto/TwoCFB.cpp
new file mode 100755
index 0000000..be3dda4
--- /dev/null
+++ b/src/libzrtpcpp/crypto/TwoCFB.cpp
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) 2011 by Werner Dittmann
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/** Copyright (C) 2011
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <string.h>
+
+#include <libzrtpcpp/crypto/twoCFB.h>
+#include <libzrtpcpp/crypto/twofish.h>
+
+static int initialized = 0;
+
+void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+ int32_t dataLength)
+{
+ Twofish_key keyCtx;
+ int usedBytes = 0;
+
+ if (!initialized) {
+ Twofish_initialise();
+ initialized = 1;
+ }
+
+ memset(&keyCtx, 0, sizeof(Twofish_key));
+ Twofish_prepare_key(key, keyLength, &keyCtx);
+
+ Twofish_cfb128_encrypt(&keyCtx, (Twofish_Byte*)data, (Twofish_Byte*)data,
+ (size_t)dataLength, (Twofish_Byte*)IV, &usedBytes);
+}
+
+
+void twoCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+ int32_t dataLength)
+{
+ Twofish_key keyCtx;
+ int usedBytes = 0;
+
+ if (!initialized) {
+ Twofish_initialise();
+ initialized = 1;
+ }
+
+ memset(&keyCtx, 0, sizeof(Twofish_key));
+ Twofish_prepare_key(key, keyLength, &keyCtx);
+
+ Twofish_cfb128_decrypt(&keyCtx, (Twofish_Byte*)data, (Twofish_Byte*)data,
+ (size_t)dataLength, (Twofish_Byte*)IV, &usedBytes);
+}
diff --git a/src/libzrtpcpp/crypto/ZrtpDH.h b/src/libzrtpcpp/crypto/ZrtpDH.h
new file mode 100644
index 0000000..bd32f7f
--- /dev/null
+++ b/src/libzrtpcpp/crypto/ZrtpDH.h
@@ -0,0 +1,168 @@
+/*
+ Copyright (C) 2006-2009 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _ZRTPDH_H__
+#define _ZRTPDH_H__
+
+#include <stdint.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+
+/**
+ * @file ZrtpDH.h
+ * @brief Class that implemets Diffie-Helman key agreement for ZRTP
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+/**
+ * Generates a number of random bytes.
+ *
+ * @param buf
+ * Pointer to a buffer that receives the random data. Must have a size
+ * of at least <code>length</code> bytes.
+ *
+ * @param length
+ * Number of random bytes to produce.
+ */
+void randomZRTP(uint8_t *buf, int32_t length);
+
+const int32_t DH2K = 0;
+const int32_t DH3K = 1;
+const int32_t EC25 = 2;
+const int32_t EC38 = 3;
+
+
+/**
+ * Implementation of Diffie-Helman for ZRTP
+ *
+ * This class defines functions to generate and compute the
+ * Diffie-Helman public and secret data and the shared secret. According to
+ * the ZRTP specification we use the MODP groups as defined by RFC 3526 for
+ * length 3072 and 4096.
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+class ZrtpDH {
+
+private:
+ void* ctx; ///< Context the DH
+ int pkType; ///< Which type of DH to use
+
+public:
+ /**
+ * Create a Diffie-Helman key agreement algorithm
+ *
+ * @param type
+ * Name of the DH algorithm to use
+ */
+ ZrtpDH(const char* type);
+
+ ~ZrtpDH();
+
+ /**
+ * Generates a public key based on the DH parameters and a random
+ * private key.
+ *
+ * @return 1 on success, 0 on failure
+ */
+ int32_t generatePublicKey();
+
+ /**
+ * Returns the size in bytes of the DH parameter p.
+ *
+ * @return Size in bytes.
+ */
+ int32_t getDhSize() const;
+
+ /**
+ * Returns the size in bytes of computed public key.
+ *
+ * @return Size in bytes.
+ */
+ int32_t getPubKeySize() const;
+
+ /**
+ * Returns the bytes of computed secret key.
+ *
+ * Returns the bytes of the public key in network (big endian) order.#
+ *
+ * @param buf
+ * Pointer to a buffer of at least <code>getPubKeySize()</code> bytes.
+ *
+ * @return Size in bytes.
+ */
+ int32_t getPubKeyBytes(uint8_t *buf) const;
+
+ /**
+ * Compute the secret key and returns it to caller.
+ *
+ * This method computes the secret key based on the DH parameters, the
+ * private key and the peer's public key.
+ *
+ * @param pubKeyBytes
+ * Pointer to the peer's public key bytes. Must be in big endian order.
+ *
+ * @param secret
+ * Pointer to a buffer that receives the secret key. This buffer must
+ * have a length of at least <code>getSecretSize()</code> bytes.
+ *
+ * @return the size of the shared secret on success, -1 on error.
+ */
+ int32_t computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret);
+
+ /**
+ * Check and validate the public key received from peer.
+ *
+ * Check if this is a correct Diffie-Helman public key. If the public
+ * key value is either one or (P-1) then this is a wrong public key
+ * value.
+ *
+ * @param pubKeyBytes
+ * Pointer to the peer's public key bytes. Must be in big endian order.
+ *
+ * @return 0 if check faild, 1 if public key value is ok.
+ */
+ int32_t checkPubKey(uint8_t* pubKeyBytes) const;
+
+ /**
+ * Get type of DH algorithm.
+ *
+ * @return
+ * Pointer to DH algorithm name
+ */
+ const char* getDHtype();
+};
+
+#endif // ZRTPDH_H
+
+/**
+ * @}
+ */
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/crypto/aesCFB.h b/src/libzrtpcpp/crypto/aesCFB.h
new file mode 100644
index 0000000..6b4ab6e
--- /dev/null
+++ b/src/libzrtpcpp/crypto/aesCFB.h
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _AESCFB_H__
+#define _AESCFB_H__
+
+#include <stdint.h>
+
+/**
+ * @file aesCFB.h
+ * @brief Function that provide AES CFB mode support
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#ifndef AES_BLOCK_SIZE
+#define AES_BLOCK_SIZE 16
+#endif
+
+/**
+ * Encrypt data with AES CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and encrypts it with
+ * AES CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of AES blocksize.
+ *
+ * @param key
+ * Points to the key bytes.
+ * @param keyLength
+ * Length of the key in bytes
+ * @param IV
+ * The initialization vector which must be AES_BLOCKSIZE (16) bytes.
+ * @param data
+ * Points to a buffer that contains and receives the computed
+ * the data (in-place encryption).
+ * @param dataLength
+ * Length of the data in bytes
+ */
+
+void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+ int32_t dataLength);
+
+/**
+ * Decrypt data with AES CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and decrypts it with
+ * AES CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of AES blocksize.
+ *
+ * @param key
+ * Points to the key bytes.
+ * @param keyLength
+ * Length of the key in bytes
+ * @param IV
+ * The initialization vector which must be AES_BLOCKSIZE (16) bytes.
+ * @param data
+ * Points to a buffer that contains and receives the computed
+ * the data (in-place decryption).
+ * @param dataLength
+ * Length of the data in bytes
+ */
+
+void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+ int32_t dataLength);
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp b/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp
new file mode 100644
index 0000000..1372578
--- /dev/null
+++ b/src/libzrtpcpp/crypto/gcrypt/InitializeGcrypt.cpp
@@ -0,0 +1,130 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+
+#include <malloc.h>
+#include <errno.h>
+#include <gcrypt.h>
+
+#include <libzrtpcpp-config.h>
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#else
+#include <winbase.h>
+#endif
+
+static int initialized = 0;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_PTHREAD_H
+static int gcry_thread_mutex_init (void **priv)
+{
+ int err = 0;
+ pthread_mutex_t *lock = (pthread_mutex_t *)malloc (sizeof (pthread_mutex_t));
+ if (!lock)
+ err = ENOMEM;
+ if (!err) {
+ err = pthread_mutex_init (lock, NULL);
+ if (err)
+ free (lock);
+ else
+ *priv = lock;
+ }
+ return err;
+}
+
+static int gcry_thread_mutex_destroy (void **lock)
+{
+ int err = pthread_mutex_destroy ((pthread_mutex_t *)*lock);
+ free (*lock); return err;
+}
+
+static int gcry_thread_mutex_lock (void **lock)
+{
+ return pthread_mutex_lock ((pthread_mutex_t *)*lock);
+}
+
+static int gcry_thread_mutex_unlock (void **lock)
+{
+ return pthread_mutex_unlock ((pthread_mutex_t *)*lock);
+}
+
+static struct gcry_thread_cbs gcry_threads = {
+ GCRY_THREAD_OPTION_PTHREAD, NULL,
+ gcry_thread_mutex_init, gcry_thread_mutex_destroy,
+ gcry_thread_mutex_lock, gcry_thread_mutex_unlock
+};
+
+#else
+static int gcry_thread_mutex_init (void **priv)
+{
+ int err = 0;
+ CRITICAL_SECTION *lock = (CRITICAL_SECTION *)malloc(sizeof(CRITICAL_SECTION));
+ if (!lock)
+ err = ENOMEM;
+ if (!err) {
+ InitializeCriticalSection(lock);
+ *priv = lock;
+ }
+ return err;
+}
+
+static int gcry_thread_mutex_destroy (void **lock)
+{
+ free(*lock);
+ return 0;
+}
+
+static int gcry_thread_mutex_lock (void **lock)
+{
+ EnterCriticalSection((CRITICAL_SECTION *)*lock);
+ return 0;
+}
+
+static int gcry_thread_mutex_unlock (void **lock)
+{
+ LeaveCriticalSection((CRITICAL_SECTION *)*lock);
+ return 0;
+}
+
+static struct gcry_thread_cbs gcry_threads = {
+ GCRY_THREAD_OPTION_PTHREAD, NULL,
+ gcry_thread_mutex_init, gcry_thread_mutex_destroy,
+ gcry_thread_mutex_lock, gcry_thread_mutex_unlock
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+int initializeGcrypt ()
+{
+
+ if (initialized) {
+ return 1;
+ }
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads);
+ gcry_check_version(NULL);
+ gcry_control(GCRYCTL_DISABLE_SECMEM);
+ initialized = 1;
+ return 1;
+}
diff --git a/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp b/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp
new file mode 100644
index 0000000..3673619
--- /dev/null
+++ b/src/libzrtpcpp/crypto/gcrypt/gcryptAesCFB.cpp
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/** Copyright (C) 2006, 2007
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/aesCFB.h>
+
+
+extern void initializeGcrypt();
+
+void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+ int32_t dataLength)
+{
+ gcry_error_t err = 0;
+ int algo;
+
+ initializeGcrypt();
+
+ if (keyLength == 16) {
+ algo = GCRY_CIPHER_AES;
+ }
+ else if (keyLength == 32) {
+ algo = GCRY_CIPHER_AES256;
+ }
+ else {
+ return;
+ }
+ gcry_cipher_hd_t tmp;
+ err = gcry_cipher_open(&tmp, algo, GCRY_CIPHER_MODE_CFB, 0);
+ err = gcry_cipher_setkey(tmp, key, keyLength);
+ err = gcry_cipher_setiv (tmp, IV, AES_BLOCK_SIZE);
+ err = gcry_cipher_encrypt (tmp, data, dataLength, data, dataLength);
+ gcry_cipher_close(tmp);
+}
+
+void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+ int32_t dataLength)
+{
+ gcry_error_t err = 0;
+ int algo;
+
+ initializeGcrypt();
+
+ if (keyLength == 16) {
+ algo = GCRY_CIPHER_AES;
+ }
+ else if (keyLength == 32) {
+ algo = GCRY_CIPHER_AES256;
+ }
+ else {
+ return;
+ }
+ gcry_cipher_hd_t tmp;
+ err = gcry_cipher_open(&tmp, algo, GCRY_CIPHER_MODE_CFB, 0);
+ err = gcry_cipher_setkey(tmp, key, keyLength);
+ err = gcry_cipher_setiv (tmp, IV, AES_BLOCK_SIZE);
+ err = gcry_cipher_decrypt (tmp, data, dataLength, data, dataLength);
+ gcry_cipher_close(tmp);
+}
diff --git a/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp b/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp
new file mode 100644
index 0000000..1aba680
--- /dev/null
+++ b/src/libzrtpcpp/crypto/gcrypt/gcryptZrtpDH.cpp
@@ -0,0 +1,349 @@
+/*
+ Copyright (C) 2006, 2009 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/** Copyright (C) 2006, 2009
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/ZrtpDH.h>
+#include <libzrtpcpp/ZrtpTextData.h>
+#include <sstream>
+
+struct gcryptCtx {
+ gcry_mpi_t privKey;
+ gcry_mpi_t pubKey;
+// int32_t pLength;
+};
+
+extern void initializeGcrypt();
+
+static gcry_mpi_t bnP2048 = NULL;
+static gcry_mpi_t bnP3072 = NULL;
+// static gcry_mpi_t bnP4096 = NULL;
+static gcry_mpi_t two = NULL;
+static gcry_mpi_t bnP2048MinusOne = NULL;
+static gcry_mpi_t bnP3072MinusOne = NULL;
+// static gcry_mpi_t bnP4096MinusOne = NULL;
+
+static uint8_t dhinit = 0;
+
+void randomZRTP(uint8_t *buf, int32_t length) {
+ initializeGcrypt();
+ gcry_randomize(buf, length, GCRY_STRONG_RANDOM);
+}
+
+static const uint8_t P2048[] =
+{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t P3072[] =
+ {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+ 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+ 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+ 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+ 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+ 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+ 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+
+ /* *************
+static const uint8_t P4096[] =
+{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+ 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+ 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+ 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+ 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+ 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+ 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
+ 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
+ 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
+ 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
+ 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
+ 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+ *************** */
+#define DH3K 1
+#define DH2K 0
+ZrtpDH::ZrtpDH(const char* type){
+
+ // Well - the algo type is only 4 char thus cast to int32 and compare
+ if (*(int32_t*)type == *(int32_t*)dh2k) {
+ pkType = DH2K;
+ }
+ else if (*(int32_t*)type == *(int32_t*)dh3k) {
+ pkType = DH3K;
+ }
+ else {
+ fprintf(stderr, "Unknown pubkey algo: %d\n", pkType);
+ }
+ ctx = static_cast<void*>(new gcryptCtx);
+ gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+ tmpCtx->privKey = NULL;
+ tmpCtx->pubKey = NULL;
+
+ initializeGcrypt();
+
+ if (!dhinit) {
+ gcry_mpi_scan(&bnP2048, GCRYMPI_FMT_USG, P2048, sizeof(P2048), NULL);
+ gcry_mpi_scan(&bnP3072, GCRYMPI_FMT_USG, P3072, sizeof(P3072), NULL);
+// gcry_mpi_scan(&bnP4096, GCRYMPI_FMT_USG, P4096, sizeof(P4096), NULL);
+ two = gcry_mpi_set_ui(NULL, 2);
+
+ bnP2048MinusOne = gcry_mpi_new(sizeof(P2048)*8);
+ gcry_mpi_sub_ui(bnP2048MinusOne, bnP2048, 1);
+
+ bnP3072MinusOne = gcry_mpi_new(sizeof(P3072)*8);
+ gcry_mpi_sub_ui(bnP3072MinusOne, bnP3072, 1);
+
+// bnP4096MinusOne = gcry_mpi_new(sizeof(P4096)*8);
+// gcry_mpi_sub_ui(bnP4096MinusOne, bnP4096, 1);
+ dhinit = 1;
+ }
+
+ if (pkType == DH3K) {
+ tmpCtx->privKey = gcry_mpi_new(256);
+ gcry_mpi_randomize(tmpCtx->privKey, 256, GCRY_STRONG_RANDOM);
+ }
+ else if (pkType == DH2K) {
+ tmpCtx->privKey = gcry_mpi_new(512);
+ gcry_mpi_randomize(tmpCtx->privKey, 512, GCRY_STRONG_RANDOM);
+ }
+// else {
+// tmpCtx->privKey = gcry_mpi_new(512);
+// gcry_mpi_randomize(tmpCtx->privKey, 512, GCRY_STRONG_RANDOM);
+// }
+}
+
+ZrtpDH::~ZrtpDH() {
+ gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+
+ if (tmpCtx != NULL) {
+ gcry_mpi_release(tmpCtx->privKey);
+ tmpCtx->privKey = NULL;
+ gcry_mpi_release(tmpCtx->pubKey);
+ tmpCtx->pubKey = NULL;
+ delete tmpCtx;
+ ctx = NULL;
+ }
+}
+
+int32_t ZrtpDH::computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret) {
+
+ int32_t length = getDhSize();
+ gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+
+ gcry_mpi_t pubKeyOther;
+ gcry_mpi_t sec = gcry_mpi_new(0);
+ gcry_mpi_scan(&pubKeyOther, GCRYMPI_FMT_USG, pubKeyBytes, length, NULL);
+
+ if (pkType == DH2K) {
+ gcry_mpi_powm(sec, pubKeyOther, tmpCtx->privKey, bnP2048);
+ }
+ else if (pkType == DH3K) {
+ gcry_mpi_powm(sec, pubKeyOther, tmpCtx->privKey, bnP3072);
+ }
+ else {
+// gcry_mpi_powm(sec, pubKeyOther, tmpCtx->privKey, bnP4096);
+ return 0;
+ }
+ gcry_mpi_release(pubKeyOther);
+
+ size_t result;
+ gcry_mpi_print(GCRYMPI_FMT_USG, secret, length, &result, sec);
+ gcry_mpi_release(sec);
+
+ return result;
+}
+
+int32_t ZrtpDH::generatePublicKey()
+{
+ gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+
+ tmpCtx->pubKey = gcry_mpi_new(0);
+ if (pkType == DH2K) {
+ gcry_mpi_powm(tmpCtx->pubKey, two, tmpCtx->privKey, bnP2048);
+ }
+ else if (pkType == DH3K) {
+ gcry_mpi_powm(tmpCtx->pubKey, two, tmpCtx->privKey, bnP3072);
+ }
+ else {
+// gcry_mpi_powm(tmpCtx->pubKey, two, tmpCtx->privKey, bnP4096);
+ return 0;
+ }
+ return 1;
+}
+
+int32_t ZrtpDH::getPubKeyBytes(uint8_t *buf) const
+{
+ gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx);
+ int32_t len = getPubKeySize();
+
+ // get length of Dh in bytes, prepend buffer with zeros if necessary
+ int32_t prepend = getDhSize() - getPubKeySize();
+ if (prepend > 0) {
+ memset(buf, 0, prepend);
+ }
+ size_t i = 0;
+ gcry_mpi_print(GCRYMPI_FMT_USG, buf + prepend, len, &i, tmpCtx->pubKey);
+ return i;
+}
+
+int32_t ZrtpDH::getDhSize() const
+{
+ switch (pkType) {
+ case DH2K:
+ return 2048/8;
+ break;
+ case DH3K:
+ return 3072/8;
+ break;
+ }
+ return 0;
+}
+
+int32_t ZrtpDH::getPubKeySize() const
+{
+ return ((gcry_mpi_get_nbits(static_cast<gcryptCtx*>(ctx)->pubKey) + 7) / 8);
+}
+
+int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes) const
+{
+ gcry_mpi_t pubKeyOther = NULL;
+ gcry_mpi_scan(&pubKeyOther, GCRYMPI_FMT_USG, pubKeyBytes, getDhSize(), NULL);
+
+ if (pkType == DH2K) {
+ if (gcry_mpi_cmp(bnP2048MinusOne, pubKeyOther) == 0)
+ return 0;
+ }
+ else if (pkType == DH3K) {
+ if (gcry_mpi_cmp(bnP3072MinusOne, pubKeyOther) == 0)
+ return 0;
+ }
+ else {
+// if (gcry_mpi_cmp(bnP4096MinusOne, pubKeyOther) == 0)
+ return 0;
+ }
+ if (gcry_mpi_cmp_ui(pubKeyOther, 1) == 0) {
+ return 0;
+ }
+
+ gcry_mpi_release(pubKeyOther);
+ return 1;
+}
+
+const char* ZrtpDH::getDHtype()
+{
+ switch (pkType) {
+ case DH2K:
+ return dh2k;
+ break;
+ case DH3K:
+ return dh3k;
+ break;
+ }
+ return NULL;
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp b/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp
new file mode 100644
index 0000000..3a44504
--- /dev/null
+++ b/src/libzrtpcpp/crypto/gcrypt/gcrypthmac256.cpp
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/hmac256.h>
+
+void hmac_sha256(uint8_t* key, uint32_t keyLength,
+ uint8_t* data, int32_t dataLength,
+ uint8_t* mac, uint32_t* macLength)
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(hd, key, keyLength);
+
+ gcry_md_write (hd, data, dataLength);
+
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+ memcpy(mac, p, SHA256_DIGEST_LENGTH);
+ if (macLength != NULL) {
+ *macLength = SHA256_DIGEST_LENGTH;
+ }
+ gcry_md_close (hd);
+}
+
+void hmac_sha256( uint8_t* key, uint32_t keyLength,
+ uint8_t* dataChunks[],
+ uint32_t dataChunkLength[],
+ uint8_t* mac, uint32_t* macLength )
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(hd, key, keyLength);
+
+ while (*dataChunks) {
+ gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+ dataChunks++;
+ dataChunkLength++;
+ }
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+ memcpy(mac, p, SHA256_DIGEST_LENGTH);
+ if (macLength != NULL) {
+ *macLength = SHA256_DIGEST_LENGTH;
+ }
+ gcry_md_close (hd);
+}
diff --git a/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp b/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp
new file mode 100644
index 0000000..c48813c
--- /dev/null
+++ b/src/libzrtpcpp/crypto/gcrypt/gcrypthmac384.cpp
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2006-2009 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/hmac384.h>
+
+void hmac_sha384(uint8_t* key, uint32_t keyLength,
+ uint8_t* data, int32_t dataLength,
+ uint8_t* mac, uint32_t* macLength)
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(hd, key, keyLength);
+
+ gcry_md_write (hd, data, dataLength);
+
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+ memcpy(mac, p, SHA384_DIGEST_LENGTH);
+ if (macLength != NULL) {
+ *macLength = SHA384_DIGEST_LENGTH;
+ }
+ gcry_md_close (hd);
+}
+
+void hmac_sha384( uint8_t* key, uint32_t keyLength,
+ uint8_t* dataChunks[],
+ uint32_t dataChunkLength[],
+ uint8_t* mac, uint32_t* macLength )
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC);
+ gcry_md_setkey(hd, key, keyLength);
+
+ while (*dataChunks) {
+ gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+ dataChunks++;
+ dataChunkLength++;
+ }
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+ memcpy(mac, p, SHA384_DIGEST_LENGTH);
+ if (macLength != NULL) {
+ *macLength = SHA384_DIGEST_LENGTH;
+ }
+ gcry_md_close (hd);
+}
diff --git a/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp b/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp
new file mode 100644
index 0000000..0c32bd8
--- /dev/null
+++ b/src/libzrtpcpp/crypto/gcrypt/gcryptsha256.cpp
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ * Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/sha256.h>
+
+void sha256(unsigned char* data, unsigned int dataLength,
+ unsigned char* mac)
+{
+ gcry_md_hash_buffer(GCRY_MD_SHA256, mac, data, dataLength);
+}
+
+void sha256(unsigned char* dataChunks[],
+ unsigned int dataChunkLength[],
+ unsigned char* mac)
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA256, 0);
+ while (*dataChunks) {
+ gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+ dataChunks++;
+ dataChunkLength++;
+ }
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+ memcpy(mac, p, SHA256_DIGEST_LENGTH);
+ gcry_md_close (hd);
+}
+
+void* createSha256Context()
+{
+ gcry_error_t err = 0;
+ gcry_md_hd_t hd;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA256, 0);
+ return (void*)hd;
+}
+
+void closeSha256Context(void* ctx, unsigned char* digest)
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+ if (digest != NULL) {
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA256);
+ memcpy(digest, p, SHA256_DIGEST_LENGTH);
+ }
+ gcry_md_close (hd);
+}
+
+void sha256Ctx(void* ctx, unsigned char* data,
+ unsigned int dataLength)
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+ gcry_md_write (hd, data, dataLength);
+}
+
+void sha256Ctx(void* ctx, unsigned char* dataChunks[],
+ unsigned int dataChunkLength[])
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+ while (*dataChunks) {
+ gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+ dataChunks++;
+ dataChunkLength++;
+ }
+}
diff --git a/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp b/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp
new file mode 100644
index 0000000..19c8c5b
--- /dev/null
+++ b/src/libzrtpcpp/crypto/gcrypt/gcryptsha384.cpp
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ * Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <gcrypt.h>
+#include <libzrtpcpp/crypto/sha384.h>
+
+void sha384(unsigned char* data, unsigned int dataLength,
+ unsigned char* mac)
+{
+ gcry_md_hash_buffer(GCRY_MD_SHA384, mac, data, dataLength);
+}
+
+void sha384(unsigned char* dataChunks[],
+ unsigned int dataChunkLength[],
+ unsigned char* mac)
+{
+ gcry_md_hd_t hd;
+ gcry_error_t err = 0;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA384, 0);
+ while (*dataChunks) {
+ gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+ dataChunks++;
+ dataChunkLength++;
+ }
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+ memcpy(mac, p, SHA384_DIGEST_LENGTH);
+ gcry_md_close (hd);
+}
+
+void* createSha384Context()
+{
+ gcry_error_t err = 0;
+ gcry_md_hd_t hd;
+
+ err = gcry_md_open(&hd, GCRY_MD_SHA384, 0);
+ return (void*)hd;
+}
+
+void closeSha384Context(void* ctx, unsigned char* digest)
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+ if (digest != NULL) {
+ uint8_t* p = gcry_md_read (hd, GCRY_MD_SHA384);
+ memcpy(digest, p, SHA384_DIGEST_LENGTH);
+ }
+ gcry_md_close (hd);
+}
+
+void sha384Ctx(void* ctx, unsigned char* data,
+ unsigned int dataLength)
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+ gcry_md_write (hd, data, dataLength);
+}
+
+void sha384Ctx(void* ctx, unsigned char* dataChunks[],
+ unsigned int dataChunkLength[])
+{
+ gcry_md_hd_t hd = (gcry_md_hd_t)ctx;
+
+ while (*dataChunks) {
+ gcry_md_write (hd, *dataChunks, (uint32_t)(*dataChunkLength));
+ dataChunks++;
+ dataChunkLength++;
+ }
+}
diff --git a/src/libzrtpcpp/crypto/hmac256.h b/src/libzrtpcpp/crypto/hmac256.h
new file mode 100644
index 0000000..f9110a6
--- /dev/null
+++ b/src/libzrtpcpp/crypto/hmac256.h
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2006, 2005, 2004 Erik Eliasson, Johan Bilien, Werner Dittmann
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+/**
+ * Methods to compute a SHA256 HMAC.
+ *
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * @author Johan Bilien <jobi@via.ecp.fr>
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef HMAC_SHA256_H
+#define HMAC_SHA256_H
+
+/**
+ * @file hmac256.h
+ * @brief Function that provide SHA256 HMAC support
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
+/**
+ * Compute SHA256 HMAC.
+ *
+ * This functions takes one data chunk and computes its SHA256 HMAC.
+ *
+ * @param key
+ * The MAC key.
+ * @param key_length
+ * Lneght of the MAC key in bytes
+ * @param data
+ * Points to the data chunk.
+ * @param data_length
+ * Length of the data in bytes
+ * @param mac
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ * @param mac_length
+ * Point to an integer that receives the length of the computed HMAC.
+ */
+void hmac_sha256( uint8_t* key, uint32_t key_length,
+ uint8_t* data, int32_t data_length,
+ uint8_t* mac, uint32_t* mac_length );
+
+/**
+ * Compute SHA256 HMAC over several data cunks.
+ *
+ * This functions takes several data chunk and computes the SHA256 HAMAC. It
+ * uses the openSSL HAMAC SHA256 implementation.
+ *
+ * @param key
+ * The MAC key.
+ * @param key_length
+ * Lneght of the MAC key in bytes
+ * @param data
+ * Points to an array of pointers that point to the data chunks. A NULL
+ * pointer in an array element terminates the data chunks.
+ * @param data_length
+ * Points to an array of integers that hold the length of each data chunk.
+ * @param mac
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ * @param mac_length
+ * Point to an integer that receives the length of the computed HMAC.
+ */
+
+void hmac_sha256( uint8_t* key, uint32_t key_length,
+ uint8_t* data[], uint32_t data_length[],
+ uint8_t* mac, uint32_t* mac_length );
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/crypto/hmac384.h b/src/libzrtpcpp/crypto/hmac384.h
new file mode 100644
index 0000000..223444a
--- /dev/null
+++ b/src/libzrtpcpp/crypto/hmac384.h
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2009, 2006, 2005, 2004 Erik Eliasson, Johan Bilien, Werner Dittmann
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+/**
+ * Methods to compute a SHA384 HMAC.
+ *
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * @author Johan Bilien <jobi@via.ecp.fr>
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef HMAC_SHA384_H
+#define HMAC_SHA384_H
+
+/**
+ * @file hmac384.h
+ * @brief Function that provide SHA384 HMAC support
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA384_DIGEST_LENGTH
+#define SHA384_DIGEST_LENGTH 48
+#endif
+
+/**
+ * Compute SHA384 HMAC.
+ *
+ * This functions takes one data chunk and computes its SHA384 HMAC.
+ *
+ * @param key
+ * The MAC key.
+ * @param key_length
+ * Lneght of the MAC key in bytes
+ * @param data
+ * Points to the data chunk.
+ * @param data_length
+ * Length of the data in bytes
+ * @param mac
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ * @param mac_length
+ * Point to an integer that receives the length of the computed HMAC.
+ */
+void hmac_sha384( uint8_t* key, uint32_t key_length,
+ uint8_t* data, int32_t data_length,
+ uint8_t* mac, uint32_t* mac_length );
+
+/**
+ * Compute SHA384 HMAC over several data cunks.
+ *
+ * This functions takes several data chunk and computes the SHA384 HAMAC. It
+ * uses the openSSL HAMAC SHA384 implementation.
+ *
+ * @param key
+ * The MAC key.
+ * @param key_length
+ * Lneght of the MAC key in bytes
+ * @param data
+ * Points to an array of pointers that point to the data chunks. A NULL
+ * pointer in an array element terminates the data chunks.
+ * @param data_length
+ * Points to an array of integers that hold the length of each data chunk.
+ * @param mac
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ * @param mac_length
+ * Point to an integer that receives the length of the computed HMAC.
+ */
+
+void hmac_sha384( uint8_t* key, uint32_t key_length,
+ uint8_t* data[], uint32_t data_length[],
+ uint8_t* mac, uint32_t* mac_length );
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/crypto/openssl/AesCFB.cpp b/src/libzrtpcpp/crypto/openssl/AesCFB.cpp
new file mode 100644
index 0000000..595d1ff
--- /dev/null
+++ b/src/libzrtpcpp/crypto/openssl/AesCFB.cpp
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2006, 2007 by Werner Dittmann
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/** Copyright (C) 2006, 2007
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/aes.h>
+#include <string.h>
+
+#include <libzrtpcpp/crypto/aesCFB.h>
+
+// extern void initializeOpenSSL();
+
+
+void aesCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+ int32_t dataLength)
+{
+ AES_KEY aesKey;
+ int usedBytes = 0;
+
+// initializeOpenSSL();
+
+ memset(&aesKey, 0, sizeof( AES_KEY ) );
+ if (keyLength == 16) {
+ AES_set_encrypt_key(key, 128, &aesKey);
+ }
+ else if (keyLength == 32) {
+ AES_set_encrypt_key(key, 256, &aesKey);
+ }
+ else {
+ return;
+ }
+ AES_cfb128_encrypt(data, data, dataLength, &aesKey,
+ IV, &usedBytes, AES_ENCRYPT);
+}
+
+
+void aesCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+ int32_t dataLength)
+{
+ AES_KEY aesKey;
+ int usedBytes = 0;
+
+// initializeOpenSSL();
+
+ memset(&aesKey, 0, sizeof( AES_KEY ) );
+ if (keyLength == 16) {
+ AES_set_encrypt_key(key, 128, &aesKey);
+ }
+ else if (keyLength == 32) {
+ AES_set_encrypt_key(key, 256, &aesKey);
+ }
+ else {
+ return;
+ }
+ AES_cfb128_encrypt(data, data, dataLength, &aesKey,
+ (unsigned char*)IV, &usedBytes, AES_DECRYPT);
+}
diff --git a/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp b/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp
new file mode 100755
index 0000000..17961c3
--- /dev/null
+++ b/src/libzrtpcpp/crypto/openssl/InitializeOpenSSL.cpp
@@ -0,0 +1,242 @@
+/*
+ Copyright (C) 2006 Werner Dittmann
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Boston, MA 02111.
+*/
+
+#include <stdio.h>
+#include <openssl/evp.h>
+#include <libzrtpcpp-config.h>
+
+#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
+#undef _MSWINDOWS_
+#define _MSWINDOWS_
+#include <windows.h>
+#endif
+
+#if defined SOLARIS && !defined HAVE_PTHREAD_H
+#include <synch.h>
+#include <thread.h>
+#endif
+#if !defined(_MSWINDOWS_) && !defined SOLARIS
+#include <pthread.h>
+#endif
+
+#ifdef const
+#undef const
+#endif
+
+static void threadLockSetup(void);
+static void threadLockCleanup(void);
+static void myLockingCallback(int, int, const char *, int);
+
+/**
+ * Implement the locking callback functions for openSSL.
+ *
+ * Unfortunatly we can't use the Commonc++ Mutex here because the
+ * Mutex may use (for some cases) the Commonc++ Thread class. OpenSSL
+ * does not use this Thread class.
+ */
+
+static int initialized = 0;
+
+int initializeOpenSSL ()
+{
+
+ if (initialized) {
+ return 1;
+ }
+ initialized = 1;
+ threadLockSetup();
+ return 1;
+}
+
+int finalizeOpenSSL ()
+{
+ if(!initialized)
+ return 1;
+
+ initialized = 0;
+ threadLockCleanup();
+ return 1;
+}
+
+#ifdef _MSWINDOWS_
+#define __LOCKING
+
+static HANDLE *lock_cs;
+
+static void threadLockSetup(void) {
+ int i;
+
+ lock_cs=(HANDLE*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ lock_cs[i] = CreateMutex(NULL,FALSE,NULL);
+ }
+
+ CRYPTO_set_locking_callback((void (*)(int,int,const char *,int))myLockingCallback);
+ /* id callback defined */
+}
+
+static void threadLockCleanup(void) {
+ int i;
+
+ CRYPTO_set_locking_callback(NULL);
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ CloseHandle(lock_cs[i]);
+ }
+ OPENSSL_free(lock_cs);
+}
+
+static void myLockingCallback(int mode, int type, const char *file, int line) {
+ if (mode & CRYPTO_LOCK) {
+ WaitForSingleObject(lock_cs[type], INFINITE);
+ }
+ else {
+ ReleaseMutex(lock_cs[type]);
+ }
+}
+
+#endif /* OPENSSL_SYS_WIN32 */
+
+
+#if defined SOLARIS && !defined HAVE_PTHREAD_H && !defined(_MSWINDOWS)
+#define __LOCKING
+
+static mutex_t *lock_cs;
+static long *lock_count;
+
+static void threadLockSetup(void) {
+ int i;
+
+ lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t));
+ lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ lock_count[i] = 0;
+ /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
+ mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL);
+ }
+ CRYPTO_set_locking_callback((void (*)(int, int ,const char *, int))myLockingCallback);
+}
+
+static void threadLockCleanup(void) {
+ int i;
+
+ CRYPTO_set_locking_callback(NULL);
+
+ fprintf(stderr,"cleanup\n");
+
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ /* rwlock_destroy(&(lock_cs[i])); */
+ mutex_destroy(&(lock_cs[i]));
+ fprintf(stderr,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
+ }
+ OPENSSL_free(lock_cs);
+ OPENSSL_free(lock_count);
+}
+
+static void myLockingCallback(int mode, int type, const char *file, int line)
+{
+#ifdef undef
+ fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
+ CRYPTO_thread_id(),
+ (mode&CRYPTO_LOCK)?"l":"u",
+ (type&CRYPTO_READ)?"r":"w",file,line);
+#endif
+
+ /*
+ if (CRYPTO_LOCK_SSL_CERT == type)
+ fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
+ CRYPTO_thread_id(),
+ mode,file,line);
+ */
+ if (mode & CRYPTO_LOCK) {
+ mutex_lock(&(lock_cs[type]));
+ lock_count[type]++;
+ }
+ else {
+ mutex_unlock(&(lock_cs[type]));
+ }
+}
+
+static unsigned long solaris_thread_id(void) {
+ unsigned long ret;
+
+ ret=(unsigned long)thr_self();
+ return(ret);
+}
+#endif /* SOLARIS */
+
+
+#ifndef __LOCKING
+static pthread_mutex_t* lock_cs;
+static long* lock_count;
+
+static void threadLockSetup(void) {
+ int i;
+
+ lock_cs = (pthread_mutex_t*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+ lock_count = (long*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ lock_count[i] = 0;
+ pthread_mutex_init(&(lock_cs[i]),NULL);
+ }
+
+ // CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
+ CRYPTO_set_locking_callback((void (*)(int,int,const char *, int))myLockingCallback);
+}
+
+static void threadLockCleanup(void)
+{
+ int i;
+
+ CRYPTO_set_locking_callback(NULL);
+ fprintf(stderr,"cleanup\n");
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ pthread_mutex_destroy(&(lock_cs[i]));
+ fprintf(stderr,"%8ld:%s\n",lock_count[i],
+ CRYPTO_get_lock_name(i));
+ }
+ OPENSSL_free(lock_cs);
+ OPENSSL_free(lock_count);
+}
+
+static void myLockingCallback(int mode, int type, const char *file,
+ int line) {
+#ifdef undef
+ fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
+ CRYPTO_thread_id(),
+ (mode&CRYPTO_LOCK)?"l":"u",
+ (type&CRYPTO_READ)?"r":"w",file,line);
+#endif
+ if (mode & CRYPTO_LOCK) {
+ pthread_mutex_lock(&(lock_cs[type]));
+ lock_count[type]++;
+ }
+ else {
+ pthread_mutex_unlock(&(lock_cs[type]));
+ }
+}
+
+/*
+static unsigned long pthreads_thread_id(void)
+{
+ unsigned long ret;
+
+ ret = (unsigned long)pthread_self();
+ return(ret);
+}
+*/
+#endif
diff --git a/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp b/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp
new file mode 100644
index 0000000..fbd623c
--- /dev/null
+++ b/src/libzrtpcpp/crypto/openssl/ZrtpDH.cpp
@@ -0,0 +1,426 @@
+/*
+ Copyright (C) 2006, 2009 by Werner Dittmann
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/** Copyright (C) 2006, 2009
+ *
+ * @author Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+
+#include <libzrtpcpp/crypto/ZrtpDH.h>
+#include <libzrtpcpp/ZrtpTextData.h>
+
+// extern void initializeOpenSSL();
+
+static BIGNUM* bnP2048 = NULL;
+static BIGNUM* bnP3072 = NULL;
+// static BIGNUM* bnP4096 = NULL;
+
+static BIGNUM* bnP2048MinusOne = NULL;
+static BIGNUM* bnP3072MinusOne = NULL;
+// static BIGNUM* bnP4096MinusOne = NULL;
+
+static uint8_t dhinit = 0;
+
+void randomZRTP(uint8_t *buf, int32_t length)
+{
+// initializeOpenSSL();
+ RAND_bytes(buf, length);
+}
+
+static const uint8_t P2048[] =
+{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t P3072[] =
+{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+ 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+ 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+ 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+ 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+ 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+ 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* **************
+static const uint8_t P4096[] =
+{
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
+0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
+0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
+0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
+0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
+0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+*************** */
+
+ZrtpDH::ZrtpDH(const char* type) {
+
+ uint8_t random[64];
+
+ // Well - the algo type is only 4 char thus cast to int32 and compare
+ if (*(int32_t*)type == *(int32_t*)dh2k) {
+ pkType = DH2K;
+ }
+ else if (*(int32_t*)type == *(int32_t*)dh3k) {
+ pkType = DH3K;
+ }
+ else if (*(int32_t*)type == *(int32_t*)ec25) {
+ pkType = EC25;
+ }
+ else if (*(int32_t*)type == *(int32_t*)ec38) {
+ pkType = EC38;
+ }
+ else {
+ return;
+ }
+
+// initializeOpenSSL();
+
+ if (!dhinit) {
+ bnP2048 = BN_bin2bn(P2048,sizeof(P2048),NULL);
+ bnP3072 = BN_bin2bn(P3072,sizeof(P3072),NULL);
+// bnP4096 = BN_bin2bn(P4096,sizeof(P4096),NULL);
+
+ bnP2048MinusOne = BN_dup(bnP2048);
+ BN_sub_word(bnP2048MinusOne, 1);
+
+ bnP3072MinusOne = BN_dup(bnP3072);
+ BN_sub_word(bnP3072MinusOne, 1);
+
+// bnP4096MinusOne = BN_dup(bnP4096);
+// BN_sub_word(bnP4096MinusOne, 1);
+ dhinit = 1;
+ }
+
+ DH* tmpCtx = NULL;
+ switch (pkType) {
+ case DH2K:
+ case DH3K:
+ ctx = static_cast<void*>(DH_new());
+ tmpCtx = static_cast<DH*>(ctx);
+ tmpCtx->g = BN_new();
+ BN_set_word(tmpCtx->g, DH_GENERATOR_2);
+
+ if (pkType == DH2K) {
+ tmpCtx->p = BN_dup(bnP2048);
+ RAND_bytes(random, 32);
+ tmpCtx->priv_key = BN_bin2bn(random, 32, NULL);
+ }
+ else if (pkType == DH3K) {
+ tmpCtx->p = BN_dup(bnP3072);
+ RAND_bytes(random, 64);
+ tmpCtx->priv_key = BN_bin2bn(random, 32, NULL);
+ }
+ break;
+
+ case EC25:
+ ctx = static_cast<void*>(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ break;
+ case EC38:
+ ctx = static_cast<void*>(EC_KEY_new_by_curve_name(NID_secp384r1));
+ break;
+ }
+}
+
+ZrtpDH::~ZrtpDH() {
+ if (ctx == NULL)
+ return;
+
+ switch (pkType) {
+ case DH2K:
+ case DH3K:
+ DH_free(static_cast<DH*>(ctx));
+ break;
+
+ case EC25:
+ case EC38:
+ EC_KEY_free(static_cast<EC_KEY*>(ctx));
+ break;
+ }
+}
+
+int32_t ZrtpDH::computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret) {
+
+ if (pkType == DH2K || pkType == DH3K) {
+ DH* tmpCtx = static_cast<DH*>(ctx);
+
+ if (tmpCtx->pub_key != NULL) {
+ BN_free(tmpCtx->pub_key);
+ }
+ tmpCtx->pub_key = BN_bin2bn(pubKeyBytes, getDhSize(), NULL);
+ return DH_compute_key(secret, tmpCtx->pub_key, tmpCtx);
+ }
+ if (pkType == EC25 || pkType == EC38) {
+ uint8_t buffer[100];
+ int32_t ret;
+ int32_t len = getPubKeySize();
+
+ buffer[0] = POINT_CONVERSION_UNCOMPRESSED;
+ memcpy(buffer+1, pubKeyBytes, len);
+
+ EC_POINT* point = EC_POINT_new(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)));
+ EC_POINT_oct2point(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+ point, buffer, len+1, NULL);
+ ret = ECDH_compute_key(secret, getDhSize(), point, static_cast<EC_KEY*>(ctx), NULL);
+ EC_POINT_free(point);
+ return ret;
+ }
+ return -1;
+}
+
+int32_t ZrtpDH::generatePublicKey()
+{
+ if (pkType == DH2K || pkType == DH3K)
+ return DH_generate_key(static_cast<DH*>(ctx));
+
+ if (pkType == EC25 || pkType == EC38)
+ return EC_KEY_generate_key(static_cast<EC_KEY*>(ctx));
+ return 0;
+}
+
+int32_t ZrtpDH::getDhSize() const
+{
+ if (pkType == DH2K || pkType == DH3K)
+ return DH_size(static_cast<DH*>(ctx));
+
+ if (pkType == EC25)
+ return 32;
+ if (pkType == EC38)
+ return 48;
+
+ return 0;
+}
+
+int32_t ZrtpDH::getPubKeySize() const
+{
+ if (pkType == DH2K || pkType == DH3K)
+ return BN_num_bytes(static_cast<DH*>(ctx)->pub_key);
+
+ if (pkType == EC25 || pkType == EC38)
+ return EC_POINT_point2oct(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+ EC_KEY_get0_public_key(static_cast<EC_KEY*>(ctx)),
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL) - 1;
+ return 0;
+
+}
+
+int32_t ZrtpDH::getPubKeyBytes(uint8_t *buf) const
+{
+
+ if (pkType == DH2K || pkType == DH3K) {
+ // get len of pub_key, prepend with zeros to DH size
+ int32_t prepend = getDhSize() - getPubKeySize();
+ if (prepend > 0) {
+ memset(buf, 0, prepend);
+ }
+ return BN_bn2bin(static_cast<DH*>(ctx)->pub_key, buf + prepend);
+ }
+ if (pkType == EC25 || pkType == EC38) {
+ uint8_t buffer[100];
+
+ int len = EC_POINT_point2oct(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+ EC_KEY_get0_public_key(static_cast<EC_KEY*>(ctx)),
+ POINT_CONVERSION_UNCOMPRESSED, buffer, 100, NULL);
+ memcpy(buf, buffer+1, len-1);
+ return len-1;
+ }
+ return 0;
+}
+
+int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes) const
+{
+ if (pkType == EC25 || pkType == EC38) {
+ uint8_t buffer[100];
+ int32_t ret;
+ int32_t len = getPubKeySize();
+
+ buffer[0] = POINT_CONVERSION_UNCOMPRESSED;
+ memcpy(buffer+1, pubKeyBytes, len);
+
+ EC_POINT* point = EC_POINT_new(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)));
+ EC_POINT_oct2point(EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)),
+ point, buffer, len+1, NULL);
+ EC_KEY* chkKey = EC_KEY_new();
+ EC_KEY_set_group(chkKey, EC_KEY_get0_group(static_cast<EC_KEY*>(ctx)));
+ EC_KEY_set_public_key(chkKey, point);
+ ret = EC_KEY_check_key(chkKey);
+
+ EC_POINT_free(point);
+ EC_KEY_free(chkKey);
+
+ return ret;
+ }
+
+ BIGNUM* pubKeyOther = BN_bin2bn(pubKeyBytes, getDhSize(), NULL);
+
+ if (pkType == DH2K) {
+ if (BN_cmp(bnP2048MinusOne, pubKeyOther) == 0)
+ return 0;
+ }
+ else if (pkType == DH3K) {
+ if (BN_cmp(bnP3072MinusOne, pubKeyOther) == 0)
+ return 0;
+ }
+ else {
+// if (BN_cmp(bnP4096MinusOne, pubKeyOther) == 0)
+ return 0;
+ }
+ int one = BN_is_one(pubKeyOther);
+ if (one == 1)
+ return 0;
+
+ BN_free(pubKeyOther);
+ return 1;
+}
+
+const char* ZrtpDH::getDHtype()
+{
+ switch (pkType) {
+ case DH2K:
+ return dh2k;
+ break;
+ case DH3K:
+ return dh3k;
+ break;
+ case EC25:
+ return ec25;
+ break;
+ case EC38:
+ return ec38;
+ break;
+ }
+ return NULL;
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/crypto/openssl/hmac256.cpp b/src/libzrtpcpp/crypto/openssl/hmac256.cpp
new file mode 100644
index 0000000..a054c02
--- /dev/null
+++ b/src/libzrtpcpp/crypto/openssl/hmac256.cpp
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <openssl/hmac.h>
+#include <libzrtpcpp/crypto/hmac256.h>
+
+void hmac_sha256(uint8_t* key, uint32_t key_length,
+ uint8_t* data, int32_t data_length,
+ uint8_t* mac, uint32_t* mac_length)
+{
+ unsigned int tmp;
+ HMAC( EVP_sha256(), key, key_length, data, data_length, mac, &tmp );
+ *mac_length = tmp;
+}
+
+void hmac_sha256(uint8_t* key, uint32_t key_length,
+ uint8_t* data_chunks[],
+ uint32_t data_chunck_length[],
+ uint8_t* mac, uint32_t* mac_length )
+{
+ unsigned int tmp;
+ HMAC_CTX ctx;
+ HMAC_CTX_init( &ctx );
+ HMAC_Init_ex( &ctx, key, key_length, EVP_sha256(), NULL );
+ while( *data_chunks ){
+ HMAC_Update( &ctx, *data_chunks, *data_chunck_length );
+ data_chunks ++;
+ data_chunck_length ++;
+ }
+ HMAC_Final( &ctx, mac, &tmp);
+ *mac_length = tmp;
+ HMAC_CTX_cleanup( &ctx );
+}
diff --git a/src/libzrtpcpp/crypto/openssl/hmac384.cpp b/src/libzrtpcpp/crypto/openssl/hmac384.cpp
new file mode 100644
index 0000000..10d6fbc
--- /dev/null
+++ b/src/libzrtpcpp/crypto/openssl/hmac384.cpp
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+
+*/
+
+/*
+ * Authors: Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ */
+
+#include <openssl/hmac.h>
+#include <libzrtpcpp/crypto/hmac256.h>
+
+void hmac_sha384(uint8_t* key, uint32_t key_length,
+ uint8_t* data, int32_t data_length,
+ uint8_t* mac, uint32_t* mac_length)
+{
+ unsigned int tmp;
+ HMAC( EVP_sha384(), key, key_length, data, data_length, mac, &tmp );
+ *mac_length = tmp;
+}
+
+void hmac_sha384(uint8_t* key, uint32_t key_length,
+ uint8_t* data_chunks[],
+ uint32_t data_chunck_length[],
+ uint8_t* mac, uint32_t* mac_length )
+{
+ unsigned int tmp;
+ HMAC_CTX ctx;
+ HMAC_CTX_init( &ctx );
+ HMAC_Init_ex( &ctx, key, key_length, EVP_sha384(), NULL );
+ while( *data_chunks ){
+ HMAC_Update( &ctx, *data_chunks, *data_chunck_length );
+ data_chunks ++;
+ data_chunck_length ++;
+ }
+ HMAC_Final( &ctx, mac, &tmp);
+ *mac_length = tmp;
+ HMAC_CTX_cleanup( &ctx );
+}
diff --git a/src/libzrtpcpp/crypto/openssl/sha256.cpp b/src/libzrtpcpp/crypto/openssl/sha256.cpp
new file mode 100644
index 0000000..2163a6d
--- /dev/null
+++ b/src/libzrtpcpp/crypto/openssl/sha256.cpp
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ * Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/sha.h>
+
+#include <libzrtpcpp/crypto/sha256.h>
+
+void sha256(unsigned char *data, unsigned int data_length,
+ unsigned char *digest )
+{
+ SHA256(data, data_length, digest);
+}
+
+void sha256(unsigned char * data_chunks[],
+ unsigned int data_chunck_length[],
+ unsigned char *digest)
+{
+ SHA256_CTX ctx;
+ SHA256_Init( &ctx);
+ while(*data_chunks) {
+ SHA256_Update(&ctx, *data_chunks, *data_chunck_length);
+ data_chunks++;
+ data_chunck_length++;
+ }
+ SHA256_Final(digest, &ctx);
+}
+
+void* createSha256Context()
+{
+ SHA256_CTX* ctx = (SHA256_CTX*)malloc(sizeof (SHA256_CTX));
+ SHA256_Init(ctx);
+ return (void*)ctx;
+}
+
+void closeSha256Context(void* ctx, unsigned char* digest)
+{
+ SHA256_CTX* hd = (SHA256_CTX*)ctx;
+
+ if (digest != NULL) {
+ SHA256_Final(digest, hd);
+ }
+ free(hd);
+}
+
+void sha256Ctx(void* ctx, unsigned char* data,
+ unsigned int dataLength)
+{
+ SHA256_CTX* hd = (SHA256_CTX*)ctx;
+ SHA256_Update(hd, data, dataLength);
+}
+
+void sha256Ctx(void* ctx, unsigned char* dataChunks[],
+ unsigned int dataChunkLength[])
+{
+ SHA256_CTX* hd = (SHA256_CTX*)ctx;
+
+ while (*dataChunks) {
+ SHA256_Update (hd, *dataChunks, *dataChunkLength);
+ dataChunks++;
+ dataChunkLength++;
+ }
+}
diff --git a/src/libzrtpcpp/crypto/openssl/sha384.cpp b/src/libzrtpcpp/crypto/openssl/sha384.cpp
new file mode 100644
index 0000000..9d166e7
--- /dev/null
+++ b/src/libzrtpcpp/crypto/openssl/sha384.cpp
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+/**
+ * @author Erik Eliasson <eliasson@it.kth.se>
+ * Johan Bilien <jobi@via.ecp.fr>
+ * Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/sha.h>
+
+#include <libzrtpcpp/crypto/sha384.h>
+
+void sha384(unsigned char *data, unsigned int data_length,
+ unsigned char *digest )
+{
+ SHA384(data, data_length, digest);
+}
+
+void sha384(unsigned char * data_chunks[],
+ unsigned int data_chunck_length[],
+ unsigned char *digest)
+{
+ SHA512_CTX ctx;
+ SHA384_Init( &ctx);
+ while(*data_chunks) {
+ SHA384_Update(&ctx, *data_chunks, *data_chunck_length);
+ data_chunks++;
+ data_chunck_length++;
+ }
+ SHA384_Final(digest, &ctx);
+}
+
+void* createSha384Context()
+{
+ SHA512_CTX* ctx = (SHA512_CTX*)malloc(sizeof (SHA512_CTX));
+ SHA384_Init(ctx);
+ return (void*)ctx;
+}
+
+void closeSha384Context(void* ctx, unsigned char* digest)
+{
+ SHA512_CTX* hd = (SHA512_CTX*)ctx;
+
+ if (digest != NULL) {
+ SHA384_Final(digest, hd);
+ }
+ free(hd);
+}
+
+void sha384Ctx(void* ctx, unsigned char* data,
+ unsigned int dataLength)
+{
+ SHA512_CTX* hd = (SHA512_CTX*)ctx;
+ SHA384_Update(hd, data, dataLength);
+}
+
+void sha384Ctx(void* ctx, unsigned char* dataChunks[],
+ unsigned int dataChunkLength[])
+{
+ SHA512_CTX* hd = (SHA512_CTX*)ctx;
+
+ while (*dataChunks) {
+ SHA384_Update (hd, *dataChunks, *dataChunkLength);
+ dataChunks++;
+ dataChunkLength++;
+ }
+}
diff --git a/src/libzrtpcpp/crypto/sha256.h b/src/libzrtpcpp/crypto/sha256.h
new file mode 100644
index 0000000..959a620
--- /dev/null
+++ b/src/libzrtpcpp/crypto/sha256.h
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Functions to compute SHA256 digest.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _SHA256_H
+#define _SHA256_H
+
+/**
+ * @file sha256.h
+ * @brief Function that provide SHA256 support
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
+/**
+ * Compute SHA256 digest.
+ *
+ * This functions takes one data chunk and computes its SHA256 digest. This
+ * function creates and deletes an own SHA256 context to perform the SHA256
+ * operations.
+ *
+ * @param data
+ * Points to the data chunk.
+ * @param data_length
+ * Length of the data in bytes
+ * @param digest
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ */
+void sha256(unsigned char *data,
+ unsigned int data_length,
+ unsigned char *digest);
+
+/**
+ * Compute SHA256 digest over several data cunks.
+ *
+ * This functions takes several data chunks and computes the SHA256 digest.
+ * This function creates and deletes an own SHA256 context to perform the
+ * SHA256 operations.
+ *
+ * @param data
+ * Points to an array of pointers that point to the data chunks. A NULL
+ * pointer in an array element terminates the data chunks.
+ * @param data_length
+ * Points to an array of integers that hold the length of each data chunk.
+ * @param digest
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 32 bytes (SHA256_DIGEST_LENGTH).
+ */
+void sha256(unsigned char *data[],
+ unsigned int data_length[],
+ unsigned char *digest);
+/**
+ * Create and initialize a SHA256 context.
+ *
+ * An application uses this context to hash several data into one SHA256
+ * digest. See also sha256Ctx(...) and closeSha256Context(...).
+ *
+ * @return Returns a pointer to the initialized SHA256 context
+ */
+void* createSha256Context();
+
+/**
+ * Compute a digest and close the SHa256 digest.
+ *
+ * An application uses this function to compute the SHA256 digest and to
+ * close the SHA256 context.
+ *
+ * @param ctx
+ * Points to the SHA256 context.
+ * @param digest
+ * If this pointer is not NULL then it must point to a byte array that
+ * is big enough to hold the SHA256 digest (256 bit = 32 Bytes). If this
+ * pointer is NULL then the functions does not compute the digest but
+ * closes the context only. The context cannot be used anymore.
+ */
+void closeSha256Context(void* ctx,
+ unsigned char* digest);
+
+/**
+ * Update the SHA256 context with data.
+ *
+ * This functions updates the SHA256 context with some data.
+ * See also CloseSha256Context(...) how to get the digest.
+ *
+ * @param ctx
+ * Points to the SHA256 context.
+ * @param data
+ * Points to the data to update the context.
+ * @param dataLength
+ * The length of the data in bytes.
+ */
+void sha256Ctx(void* ctx, unsigned char* data,
+ unsigned int dataLength);
+
+/**
+ * Update the SHA256 context with several data chunks.
+ *
+ * This functions updates the SHA256 context with some data.
+ * See also CloseSha256Context(...) how to get the digest.
+ *
+ * @param ctx
+ * Points to the SHA256 context.
+ * @param dataChunks
+ * Points to an array of pointers that point to the data chunks. A NULL
+ * pointer in an array element terminates the data chunks.
+ * @param dataChunkLength
+ * Points to an array of integers that hold the length of each data chunk.
+ *
+ */
+void sha256Ctx(void* ctx, unsigned char* dataChunks[],
+ unsigned int dataChunkLength[]);
+
+/**
+ * @}
+ */
+#endif
+
diff --git a/src/libzrtpcpp/crypto/sha384.h b/src/libzrtpcpp/crypto/sha384.h
new file mode 100644
index 0000000..6cb7a70
--- /dev/null
+++ b/src/libzrtpcpp/crypto/sha384.h
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Functions to compute SHA384 digest.
+ *
+ * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _SHA384_H
+#define _SHA384_H
+
+/**
+ * @file sha384.h
+ * @brief Function that provide SHA384 support
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdint.h>
+
+#ifndef SHA384_DIGEST_LENGTH
+#define SHA384_DIGEST_LENGTH 48
+#endif
+
+/**
+ * Compute SHA384 digest.
+ *
+ * This functions takes one data chunk and computes its SHA384 digest. This
+ * function creates and deletes an own SHA384 context to perform the SHA384
+ * operations.
+ *
+ * @param data
+ * Points to the data chunk.
+ * @param data_length
+ * Length of the data in bytes
+ * @param digest
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ */
+void sha384(unsigned char *data,
+ unsigned int data_length,
+ unsigned char *digest);
+
+/**
+ * Compute SHA384 digest over several data cunks.
+ *
+ * This functions takes several data chunks and computes the SHA384 digest.
+ * This function creates and deletes an own SHA384 context to perform the
+ * SHA384 operations.
+ *
+ * @param data
+ * Points to an array of pointers that point to the data chunks. A NULL
+ * pointer in an array element terminates the data chunks.
+ * @param data_length
+ * Points to an array of integers that hold the length of each data chunk.
+ * @param digest
+ * Points to a buffer that receives the computed digest. This
+ * buffer must have a size of at least 48 bytes (SHA384_DIGEST_LENGTH).
+ */
+void sha384(unsigned char *data[],
+ unsigned int data_length[],
+ unsigned char *digest);
+/**
+ * Create and initialize a SHA384 context.
+ *
+ * An application uses this context to hash several data into one SHA384
+ * digest. See also sha384Ctx(...) and closeSha384Context(...).
+ *
+ * @return Returns a pointer to the initialized SHA384 context
+ */
+void* createSha384Context();
+
+/**
+ * Compute a digest and close the SHA384 digest.
+ *
+ * An application uses this function to compute the SHA384 digest and to
+ * close the SHA384 context.
+ *
+ * @param ctx
+ * Points to the SHA384 context.
+ * @param digest
+ * If this pointer is not NULL then it must point to a byte array that
+ * is big enough to hold the SHA384 digest (384 bit = 48 Bytes). If this
+ * pointer is NULL then the functions does not compute the digest but
+ * closes the context only. The context cannot be used anymore.
+ */
+void closeSha384Context(void* ctx,
+ unsigned char* digest);
+
+/**
+ * Update the SHA384 context with data.
+ *
+ * This functions updates the SHA384 context with some data.
+ * See also CloseSha384Context(...) how to get the digest.
+ *
+ * @param ctx
+ * Points to the SHA384 context.
+ * @param data
+ * Points to the data to update the context.
+ * @param dataLength
+ * The length of the data in bytes.
+ */
+void sha384Ctx(void* ctx, unsigned char* data,
+ unsigned int dataLength);
+
+/**
+ * Update the SHA384 context with several data chunks.
+ *
+ * This functions updates the SHA384 context with some data.
+ * See also CloseSha384Context(...) how to get the digest.
+ *
+ * @param ctx
+ * Points to the SHA384 context.
+ * @param dataChunks
+ * Points to an array of pointers that point to the data chunks. A NULL
+ * pointer in an array element terminates the data chunks.
+ * @param dataChunkLength
+ * Points to an array of integers that hold the length of each data chunk.
+ *
+ */
+void sha384Ctx(void* ctx, unsigned char* dataChunks[],
+ unsigned int dataChunkLength[]);
+
+/**
+ * @}
+ */
+#endif
+
diff --git a/src/libzrtpcpp/crypto/twoCFB.h b/src/libzrtpcpp/crypto/twoCFB.h
new file mode 100755
index 0000000..593a59c
--- /dev/null
+++ b/src/libzrtpcpp/crypto/twoCFB.h
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef _TWOCFB_H__
+#define _TWOCFB_H__
+
+#include <stdint.h>
+
+/**
+ * @file aesCFB.h
+ * @brief Function that provide AES CFB mode support
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#ifndef TWO_BLOCK_SIZE
+#define TWO_BLOCK_SIZE 16
+#endif
+
+/**
+ * Encrypt data with Twofish CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and encrypts it with
+ * Twofish CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of Twofish blocksize.
+ *
+ * @param key
+ * Points to the key bytes.
+ * @param keyLength
+ * Length of the key in bytes
+ * @param IV
+ * The initialization vector which must be TWO_BLOCKSIZE (16) bytes.
+ * @param data
+ * Points to a buffer that contains and receives the computed
+ * the data (in-place encryption).
+ * @param dataLength
+ * Length of the data in bytes
+ */
+
+void twoCfbEncrypt(uint8_t* key, int32_t keyLength, uint8_t* IV, uint8_t *data,
+ int32_t dataLength);
+
+/**
+ * Decrypt data with Twofish CFB mode, full block feedback size.
+ *
+ * This functions takes one data chunk and decrypts it with
+ * Twofish CFB mode. The lenght of the data may be arbitrary and
+ * it is not needed to be a multiple of Twofish blocksize.
+ *
+ * @param key
+ * Points to the key bytes.
+ * @param keyLength
+ * Length of the key in bytes
+ * @param IV
+ * The initialization vector which must be TWO_BLOCKSIZE (16) bytes.
+ * @param data
+ * Points to a buffer that contains and receives the computed
+ * the data (in-place decryption).
+ * @param dataLength
+ * Length of the data in bytes
+ */
+
+void twoCfbDecrypt(uint8_t* key, int32_t keyLength, const uint8_t* IV, uint8_t *data,
+ int32_t dataLength);
+/**
+ * @}
+ */
+#endif
diff --git a/src/libzrtpcpp/crypto/twofish.c b/src/libzrtpcpp/crypto/twofish.c
new file mode 100644
index 0000000..3d390ea
--- /dev/null
+++ b/src/libzrtpcpp/crypto/twofish.c
@@ -0,0 +1,1733 @@
+/*
+ * Fast, portable, and easy-to-use Twofish implementation,
+ * Version 0.3.
+ * Copyright (c) 2002 by Niels Ferguson.
+ * (See further down for the almost-unrestricted licensing terms.)
+ *
+ * --------------------------------------------------------------------------
+ * There are two files for this implementation:
+ * - twofish.h, the header file.
+ * - twofish.c, the code file.
+ *
+ * To incorporate this code into your program you should:
+ * - Check the licensing terms further down in this comment.
+ * - Fix the two type definitions in twofish.h to suit your platform.
+ * - Fix a few definitions in twofish.c in the section marked
+ * PLATFORM FIXES. There is one important ones that affects
+ * functionality, and then a few definitions that you can optimise
+ * for efficiency but those have no effect on the functionality.
+ * Don't change anything else.
+ * - Put the code in your project and compile it.
+ *
+ * To use this library you should:
+ * - Call Twofish_initialise() in your program before any other function in
+ * this library.
+ * - Use Twofish_prepare_key(...) to convert a key to internal form.
+ * - Use Twofish_encrypt(...) and Twofish_decrypt(...) to encrypt and decrypt
+ * data.
+ * See the comments in the header file for details on these functions.
+ * --------------------------------------------------------------------------
+ *
+ * There are many Twofish implementation available for free on the web.
+ * Most of them are hard to integrate into your own program.
+ * As we like people to use our cipher, I thought I would make it easier.
+ * Here is a free and easy-to-integrate Twofish implementation in C.
+ * The latest version is always available from my personal home page at
+ * http://niels.ferguson.net/
+ *
+ * Integrating library code into a project is difficult because the library
+ * header files interfere with the project's header files and code.
+ * And of course the project's header files interfere with the library code.
+ * I've tried to resolve these problems here.
+ * The header file of this implementation is very light-weight.
+ * It contains two typedefs, a structure, and a few function declarations.
+ * All names it defines start with "Twofish_".
+ * The header file is therefore unlikely to cause problems in your project.
+ * The code file of this implementation doesn't need to include the header
+ * files of the project. There is thus no danger of the project interfering
+ * with all the definitions and macros of the Twofish code.
+ * In most situations, all you need to do is fill in a few platform-specific
+ * definitions in the header file and code file,
+ * and you should be able to run the Twofish code in your project.
+ * I estimate it should take you less than an hour to integrate this code
+ * into your project, most of it spent reading the comments telling you what
+ * to do.
+ *
+ * For people using C++: it is very easy to wrap this library into a
+ * TwofishKey class. One of the big advantages is that you can automate the
+ * wiping of the key material in the destructor. I have not provided a C++
+ * class because the interface depends too much on the abstract base class
+ * you use for block ciphers in your program, which I don't know about.
+ *
+ * This implementation is designed for use on PC-class machines. It uses the
+ * Twofish 'full' keying option which uses large tables. Total table size is
+ * around 5-6 kB for static tables plus 4.5 kB for each pre-processed key.
+ * If you need an implementation that uses less memory,
+ * take a look at Brian Gladman's code on his web site:
+ * http://fp.gladman.plus.com/cryptography_technology/aes/
+ * He has code for all AES candidates.
+ * His Twofish code has lots of options trading off table size vs. speed.
+ * You can also take a look at the optimised code by Doug Whiting on the
+ * Twofish web site
+ * http://www.counterpane.com/twofish.html
+ * which has loads of options.
+ * I believe these existing implementations are harder to re-use because they
+ * are not clean libraries and they impose requirements on the environment.
+ * This implementation is very careful to minimise those,
+ * and should be easier to integrate into any larger program.
+ *
+ * The default mode of this implementation is fully portable as it uses no
+ * behaviour not defined in the C standard. (This is harder than you think.)
+ * If you have any problems porting the default mode, please let me know
+ * so that I can fix the problem. (But only if this code is at fault, I
+ * don't fix compilers.)
+ * Most of the platform fixes are related to non-portable but faster ways
+ * of implementing certain functions.
+ *
+ * In general I've tried to make the code as fast as possible, at the expense
+ * of memory and code size. However, C does impose limits, and this
+ * implementation will be slower than an optimised assembler implementation.
+ * But beware of assembler implementations: a good Pentium implementation
+ * uses completely different code than a good Pentium II implementation.
+ * You basically have to re-write the assembly code for every generation of
+ * processor. Unless you are severely pressed for speed, stick with C.
+ *
+ * The initialisation routine of this implementation contains a self-test.
+ * If initialisation succeeds without calling the fatal routine, then
+ * the implementation works. I don't think you can break the implementation
+ * in such a way that it still passes the tests, unless you are malicious.
+ * In other words: if the initialisation routine returns,
+ * you have successfully ported the implementation.
+ * (Or not implemented the fatal routine properly, but that is your problem.)
+ *
+ * I'm indebted to many people who helped me in one way or another to write
+ * this code. During the design of Twofish and the AES process I had very
+ * extensive discussions of all implementation issues with various people.
+ * Doug Whiting in particular provided a wealth of information. The Twofish
+ * team spent untold hours discussion various cipher features, and their
+ * implementation. Brian Gladman implemented all AES candidates in C,
+ * and we had some fruitful discussions on how to implement Twofish in C.
+ * Jan Nieuwenhuizen tested this code on Linux using GCC.
+ *
+ * Now for the license:
+ * The author hereby grants a perpetual license to everybody to
+ * use this code for any purpose as long as the copyright message is included
+ * in the source code of this or any derived work.
+ *
+ * Yes, this means that you, your company, your club, and anyone else
+ * can use this code anywhere you want. You can change it and distribute it
+ * under the GPL, include it in your commercial product without releasing
+ * the source code, put it on the web, etc.
+ * The only thing you cannot do is remove my copyright message,
+ * or distribute any source code based on this implementation that does not
+ * include my copyright message.
+ *
+ * I appreciate a mention in the documentation or credits,
+ * but I understand if that is difficult to do.
+ * I also appreciate it if you tell me where and why you used my code.
+ *
+ * Please send any questions or comments to niels@ferguson.net
+ *
+ * Have Fun!
+ *
+ * Niels
+ */
+
+/*
+ * DISCLAIMER: As I'm giving away my work for free, I'm of course not going
+ * to accept any liability of any form. This code, or the Twofish cipher,
+ * might very well be flawed; you have been warned.
+ * This software is provided as-is, without any kind of warrenty or
+ * guarantee. And that is really all you can expect when you download
+ * code for free from the Internet.
+ *
+ * I think it is really sad that disclaimers like this seem to be necessary.
+ * If people only had a little bit more common sense, and didn't come
+ * whining like little children every time something happens....
+ */
+
+/*
+ * Version history:
+ * Version 0.0, 2002-08-30
+ * First written.
+ * Version 0.1, 2002-09-03
+ * Added disclaimer. Improved self-tests.
+ * Version 0.2, 2002-09-09
+ * Removed last non-portabilities. Default now works completely within
+ * the C standard. UInt32 can be larger than 32 bits without problems.
+ * Version 0.3, 2002-09-28
+ * Bugfix: use instead of to adhere to ANSI/ISO.
+ * Rename BIG_ENDIAN macro to CPU_IS_BIG_ENDIAN. The gcc library
+ * header already defines BIG_ENDIAN, even though it is not
+ * supposed to.
+ */
+
+
+/*
+ * Minimum set of include files.
+ * You should not need any application-specific include files for this code.
+ * In fact, adding you own header files could break one of the many macros or
+ * functions in this file. Be very careful.
+ * Standard include files will probably be ok.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+/* #include * for memset(), memcpy(), and memcmp() */
+#include "twofish.h"
+
+
+/*
+ * PLATFORM FIXES
+ * ==============
+ *
+ * Fix the type definitions in twofish.h first!
+ *
+ * The following definitions have to be fixed for each particular platform
+ * you work on. If you have a multi-platform program, you no doubt have
+ * portable definitions that you can substitute here without changing the
+ * rest of the code.
+ */
+
+
+/*
+ * Function called if something is fatally wrong with the implementation.
+ * This fatal function is called when a coding error is detected in the
+ * Twofish implementation, or when somebody passes an obviously erroneous
+ * parameter to this implementation. There is not much you can do when
+ * the code contains bugs, so we just stop.
+ *
+ * The argument is a string. Ideally the fatal function prints this string
+ * as an error message. Whatever else this function does, it should never
+ * return. A typical implementation would stop the program completely after
+ * printing the error message.
+ *
+ * This default implementation is not very useful,
+ * but does not assume anything about your environment.
+ * It will at least let you know something is wrong....
+ * I didn't want to include any libraries to print and error or so,
+ * as this makes the code much harder to integrate in a project.
+ *
+ * Note that the Twofish_fatal function may not return to the caller.
+ * Unfortunately this is not something the self-test can test for,
+ * so you have to make sure of this yourself.
+ *
+ * If you want to call an external function, be careful about including
+ * your own header files here. This code uses a lot of macros, and your
+ * header file could easily break it. Maybe the best solution is to use
+ * a separate extern statement for your fatal function.
+ */
+/* #define Twofish_fatal(pmsgx) { fprintf(stderr, pmsgx); exit(1); } */
+#define Twofish_fatal(pmsgx, code) { return(code); }
+
+
+/*
+ * The rest of the settings are not important for the functionality
+ * of this Twofish implementation. That is, their default settings
+ * work on all platforms. You can change them to improve the
+ * speed of the implementation on your platform. Erroneous settings
+ * will result in erroneous implementations, but the self-test should
+ * catch those.
+ */
+
+
+/*
+ * Macros to rotate a Twofish_UInt32 value left or right by the
+ * specified number of bits. This should be a 32-bit rotation,
+ * and not rotation of, say, 64-bit values.
+ *
+ * Every encryption or decryption operation uses 32 of these rotations,
+ * so it is a good idea to make these macros efficient.
+ *
+ * This fully portable definition has one piece of tricky stuff.
+ * The UInt32 might be larger than 32 bits, so we have to mask
+ * any higher bits off. The simplest way to do this is to 'and' the
+ * value first with 0xffffffff and then shift it right. An optimising
+ * compiler that has a 32-bit type can optimise this 'and' away.
+ *
+ * Unfortunately there is no portable way of writing the constant
+ * 0xffffffff. You don't know which suffix to use (U, or UL?)
+ * The UINT32_MASK definition uses a bit of trickery. Shift-left
+ * is only defined if the shift amount is strictly less than the size
+ * of the UInt32, so we can't use (1<<32). The answer it to take the value
+ * 2, cast it to a UInt32, shift it left 31 positions, and subtract one.
+ * Another example of how to make something very simple extremely difficult.
+ * I hate C.
+ *
+ * The rotation macros are straightforward.
+ * They are only applied to UInt32 values, which are _unsigned_
+ * so the >> operator must do a logical shift that brings in zeroes.
+ * On most platforms you will only need to optimise the ROL32 macro; the
+ * ROR32 macro is not inefficient on an optimising compiler as all rotation
+ * amounts in this code are known at compile time.
+ *
+ * On many platforms there is a faster solution.
+ * For example, MS compilers have the __rotl and __rotr functions
+ * that generate x86 rotation instructions.
+ */
+#define UINT32_MASK ( (((Twofish_UInt32)2)<<31) - 1 )
+
+#ifndef _MSC_VER
+#define ROL32(x,n) ( (x)<<(n) | ((x) & UINT32_MASK) >> (32-(n)) )
+#define ROR32(x,n) ( (x)>>(n) | ((x) & UINT32_MASK) << (32-(n)) )
+#else
+#define ROL32(x,n) (_lrotl((x), (n)))
+#define ROR32(x,n) (_lrotr((x), (n)))
+#endif
+
+/*
+ * Select data type for q-table entries.
+ *
+ * Larger entry types cost more memory (1.5 kB), and might be faster
+ * or slower depending on the CPU and compiler details.
+ *
+ * This choice only affects the static data size and the key setup speed.
+ * Functionality, expanded key size, or encryption speed are not affected.
+ * Define to 1 to get large q-table entries.
+ */
+#define LARGE_Q_TABLE 0 /* default = 0 */
+
+
+/*
+ * Method to select a single byte from a UInt32.
+ * WARNING: non-portable code if set; might not work on all platforms.
+ *
+ * Inside the inner loop of Twofish it is necessary to access the 4
+ * individual bytes of a UInt32. This can be done using either shifts
+ * and masks, or memory accesses.
+ *
+ * Set to 0 to use shift and mask operations for the byte selection.
+ * This is more ALU intensive. It is also fully portable.
+ *
+ * Set to 1 to use memory accesses. The UInt32 is stored in memory and
+ * the individual bytes are read from memory one at a time.
+ * This solution is more memory-intensive, and not fully portable.
+ * It might be faster on your platform, or not. If you use this option,
+ * make sure you set the CPU_IS_BIG_ENDIAN flag appropriately.
+ *
+ * This macro does not affect the conversion of the inputs and outputs
+ * of the cipher. See the CONVERT_USING_CASTS macro for that.
+ */
+#define SELECT_BYTE_FROM_UINT32_IN_MEMORY 0 /* default = 0 */
+
+
+/*
+ * Method used to read the input and write the output.
+ * WARNING: non-portable code if set; might not work on all platforms.
+ *
+ * Twofish operates on 32-bit words. The input to the cipher is
+ * a byte array, as is the output. The portable method of doing the
+ * conversion is a bunch of rotate and mask operations, but on many
+ * platforms it can be done faster using a cast.
+ * This only works if your CPU allows UInt32 accesses to arbitrary Byte
+ * addresses.
+ *
+ * Set to 0 to use the shift and mask operations. This is fully
+ * portable. .
+ *
+ * Set to 1 to use a cast. The Byte * is cast to a UInt32 *, and a
+ * UInt32 is read. If necessary (as indicated by the CPU_IS_BIG_ENDIAN
+ * macro) the byte order in the UInt32 is swapped. The reverse is done
+ * to write the output of the encryption/decryption. Make sure you set
+ * the CPU_IS_BIG_ENDIAN flag appropriately.
+ * This option does not work unless a UInt32 is exactly 32 bits.
+ *
+ * This macro only changes the reading/writing of the plaintext/ciphertext.
+ * See the SELECT_BYTE_FROM_UINT32_IN_MEMORY to affect the way in which
+ * a UInt32 is split into 4 bytes for the S-box selection.
+ */
+#define CONVERT_USING_CASTS 0 /* default = 0 */
+
+
+/*
+ * Endianness switch.
+ * Only relevant if SELECT_BYTE_FROM_UINT32_IN_MEMORY or
+ * CONVERT_USING_CASTS is set.
+ *
+ * Set to 1 on a big-endian machine, and to 0 on a little-endian machine.
+ * Twofish uses the little-endian convention (least significant byte first)
+ * and big-endian machines (using most significant byte first)
+ * have to do a few conversions.
+ *
+ * CAUTION: This code has never been tested on a big-endian machine,
+ * because I don't have access to one. Feedback appreciated.
+ */
+#define CPU_IS_BIG_ENDIAN 0
+
+
+/*
+ * Macro to reverse the order of the bytes in a UInt32.
+ * Used to convert to little-endian on big-endian machines.
+ * This macro is always tested, but only used in the encryption and
+ * decryption if CONVERT_USING_CASTS, and CPU_IS_BIG_ENDIAN
+ * are both set. In other words: this macro is only speed-critical if
+ * both these flags have been set.
+ *
+ * This default definition of SWAP works, but on many platforms there is a
+ * more efficient implementation.
+ */
+#define BSWAP(x) ((ROL32((x),8)&0x00ff00ff) | (ROR32((x),8) & 0xff00ff00))
+
+
+/*
+ * END OF PLATFORM FIXES
+ * =====================
+ *
+ * You should not have to touch the rest of this file.
+ */
+
+
+/*
+ * Convert the external type names to some that are easier to use inside
+ * this file. I didn't want to use the names Byte and UInt32 in the
+ * header file, because many programs already define them and using two
+ * conventions at once can be very difficult.
+ * Don't change these definitions! Change the originals
+ * in twofish.h instead.
+ */
+/* A Byte must be an unsigned integer, 8 bits long. */
+/* typedef Twofish_Byte Byte; */
+/* A UInt32 must be an unsigned integer at least 32 bits long. */
+/* typedef Twofish_UInt32 UInt32; */
+
+
+/*
+ * Define a macro ENDIAN_CONVERT.
+ *
+ * We define a macro ENDIAN_CONVERT that performs a BSWAP on big-endian
+ * machines, and is the identity function on little-endian machines.
+ * The code then uses this macro without considering the endianness.
+ */
+
+#if CPU_IS_BIG_ENDIAN
+#define ENDIAN_CONVERT(x) BSWAP(x)
+#else
+#define ENDIAN_CONVERT(x) (x)
+#endif
+
+
+/*
+ * Compute byte offset within a UInt32 stored in memory.
+ *
+ * This is only used when SELECT_BYTE_FROM_UINT32_IN_MEMORY is set.
+ *
+ * The input is the byte number 0..3, 0 for least significant.
+ * Note the use of sizeof() to support UInt32 types that are larger
+ * than 4 bytes.
+ */
+#if CPU_IS_BIG_ENDIAN
+#define BYTE_OFFSET( n ) (sizeof(Twofish_UInt32) - 1 - (n) )
+#else
+#define BYTE_OFFSET( n ) (n)
+#endif
+
+
+/*
+ * Macro to get Byte no. b from UInt32 value X.
+ * We use two different definition, depending on the settings.
+ */
+#if SELECT_BYTE_FROM_UINT32_IN_MEMORY
+ /* Pick the byte from the memory in which X is stored. */
+#define SELECT_BYTE( X, b ) (((Twofish_Byte *)(&(X)))[BYTE_OFFSET(b)])
+#else
+ /* Portable solution: Pick the byte directly from the X value. */
+#define SELECT_BYTE( X, b ) (((X) >> (8*(b))) & 0xff)
+#endif
+
+
+/* Some shorthands because we use byte selection in large formulae. */
+#define b0(X) SELECT_BYTE((X),0)
+#define b1(X) SELECT_BYTE((X),1)
+#define b2(X) SELECT_BYTE((X),2)
+#define b3(X) SELECT_BYTE((X),3)
+
+
+/*
+ * We need macros to load and store UInt32 from/to byte arrays
+ * using the least-significant-byte-first convention.
+ *
+ * GET32( p ) gets a UInt32 in lsb-first form from four bytes pointed to
+ * by p.
+ * PUT32( v, p ) writes the UInt32 value v at address p in lsb-first form.
+ */
+#if CONVERT_USING_CASTS
+
+ /* Get UInt32 from four bytes pointed to by p. */
+#define GET32( p ) ENDIAN_CONVERT( *((Twofish_UInt32 *)(p)) )
+ /* Put UInt32 into four bytes pointed to by p */
+#define PUT32( v, p ) *((Twofish_UInt32 *)(p)) = ENDIAN_CONVERT(v)
+
+#else
+
+ /* Get UInt32 from four bytes pointed to by p. */
+#define GET32( p ) \
+ ( \
+ (Twofish_UInt32)((p)[0]) \
+ | (Twofish_UInt32)((p)[1])<< 8 \
+ | (Twofish_UInt32)((p)[2])<<16 \
+ | (Twofish_UInt32)((p)[3])<<24 \
+ )
+ /* Put UInt32 into four bytes pointed to by p */
+#define PUT32( v, p ) \
+ (p)[0] = (Twofish_Byte)(((v) ) & 0xff); \
+ (p)[1] = (Twofish_Byte)(((v) >> 8) & 0xff); \
+ (p)[2] = (Twofish_Byte)(((v) >> 16) & 0xff); \
+ (p)[3] = (Twofish_Byte)(((v) >> 24) & 0xff)
+
+#endif
+
+
+/*
+ * Test the platform-specific macros.
+ * This function tests the macros defined so far to make sure the
+ * definitions are appropriate for this platform.
+ * If you make any mistake in the platform configuration, this should detect
+ * that and inform you what went wrong.
+ * Somewhere, someday, this is going to save somebody a lot of time,
+ * because misbehaving macros are hard to debug.
+ */
+static int test_platform()
+ {
+ /* Buffer with test values. */
+ Twofish_Byte buf[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0};
+ Twofish_UInt32 C;
+ Twofish_UInt32 x,y;
+ int i;
+
+ /*
+ * Some sanity checks on the types that can't be done in compile time.
+ * A smart compiler will just optimise these tests away.
+ * The pre-processor doesn't understand different types, so we cannot
+ * do these checks in compile-time.
+ *
+ * I hate C.
+ *
+ * The first check in each case is to make sure the size is correct.
+ * The second check is to ensure that it is an unsigned type.
+ */
+ if( ((Twofish_UInt32)((Twofish_UInt32)1 << 31) == 0) || ((Twofish_UInt32)-1 < 0 ))
+ {
+ Twofish_fatal( "Twofish code: Twofish_UInt32 type not suitable", ERR_UINT32 );
+ }
+ if( (sizeof( Twofish_Byte ) != 1) || (((Twofish_Byte)-1) < 0) )
+ {
+ Twofish_fatal( "Twofish code: Twofish_Byte type not suitable", ERR_BYTE );
+ }
+
+ /*
+ * Sanity-check the endianness conversions.
+ * This is just an aid to find problems. If you do the endianness
+ * conversion macros wrong you will fail the full cipher test,
+ * but that does not help you find the error.
+ * Always make it easy to find the bugs!
+ *
+ * Detail: There is no fully portable way of writing UInt32 constants,
+ * as you don't know whether to use the U or UL suffix. Using only U you
+ * might only be allowed 16-bit constants. Using UL you might get 64-bit
+ * constants which cannot be stored in a UInt32 without warnings, and
+ * which generally behave subtly different from a true UInt32.
+ * As long as we're just comparing with the constant,
+ * we can always use the UL suffix and at worst lose some efficiency.
+ * I use a separate '32-bit constant' macro in most of my other code.
+ *
+ * I hate C.
+ *
+ * Start with testing GET32. We test it on all positions modulo 4
+ * to make sure we can handly any position of inputs. (Some CPUs
+ * do not allow non-aligned accesses which we would do if you used
+ * the CONVERT_USING_CASTS option.
+ */
+ if( (GET32( buf ) != 0x78563412UL) || (GET32(buf+1) != 0x9a785634UL)
+ || (GET32( buf+2 ) != 0xbc9a7856UL) || (GET32(buf+3) != 0xdebc9a78UL) )
+ {
+ Twofish_fatal( "Twofish code: GET32 not implemented properly", ERR_GET32 );
+ }
+
+ /*
+ * We can now use GET32 to test PUT32.
+ * We don't test the shifted versions. If GET32 can do that then
+ * so should PUT32.
+ */
+ C = GET32( buf );
+ PUT32( 3*C, buf );
+ if( GET32( buf ) != 0x69029c36UL )
+ {
+ Twofish_fatal( "Twofish code: PUT32 not implemented properly", ERR_PUT32 );
+ }
+
+
+ /* Test ROL and ROR */
+ for( i=1; i<32; i++ )
+ {
+ /* Just a simple test. */
+ x = ROR32( C, i );
+ y = ROL32( C, i );
+ x ^= (C>>i) ^ (C<<(32-i));
+ /*y ^= (C<>(32-i)); */
+ y ^= (C<<i) ^ (C>>(32-i));
+ x |= y;
+ /*
+ * Now all we check is that x is zero in the least significant
+ * 32 bits. Using the UL suffix is safe here, as it doesn't matter
+ * if we get a larger type.
+ */
+ if( (x & 0xffffffffUL) != 0 )
+ {
+ Twofish_fatal( "Twofish ROL or ROR not properly defined.", ERR_ROLR );
+ }
+ }
+
+ /* Test the BSWAP macro */
+ if( BSWAP(C) != 0x12345678UL )
+ {
+ /*
+ * The BSWAP macro should always work, even if you are not using it.
+ * A smart optimising compiler will just remove this entire test.
+ */
+ Twofish_fatal( "BSWAP not properly defined.", ERR_BSWAP );
+ }
+
+ /* And we can test the b macros which use SELECT_BYTE. */
+ if( (b0(C)!=0x12) || (b1(C) != 0x34) || (b2(C) != 0x56) || (b3(C) != 0x78) )
+ {
+ /*
+ * There are many reasons why this could fail.
+ * Most likely is that CPU_IS_BIG_ENDIAN has the wrong value.
+ */
+ Twofish_fatal( "Twofish code: SELECT_BYTE not implemented properly", ERR_SELECTB );
+ }
+ return SUCCESS;
+ }
+
+
+/*
+ * Finally, we can start on the Twofish-related code.
+ * You really need the Twofish specifications to understand this code. The
+ * best source is the Twofish book:
+ * "The Twofish Encryption Algorithm", by Bruce Schneier, John Kelsey,
+ * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson.
+ * you can also use the AES submission document of Twofish, which is
+ * available from my list of publications on my personal web site at
+ * http://niels.ferguson.net/.
+ *
+ * The first thing we do is write the testing routines. This is what the
+ * implementation has to satisfy in the end. We only test the external
+ * behaviour of the implementation of course.
+ */
+
+
+/*
+ * Perform a single self test on a (plaintext,ciphertext,key) triple.
+ * Arguments:
+ * key array of key bytes
+ * key_len length of key in bytes
+ * p plaintext
+ * c ciphertext
+ */
+static int test_vector( Twofish_Byte key[], int key_len, Twofish_Byte p[16], Twofish_Byte c[16] )
+ {
+ Twofish_Byte tmp[16]; /* scratch pad. */
+ Twofish_key xkey; /* The expanded key */
+ int i;
+
+
+ /* Prepare the key */
+ if ((i = Twofish_prepare_key( key, key_len, &xkey)) < 0)
+ return i;
+
+ /*
+ * We run the test twice to ensure that the xkey structure
+ * is not damaged by the first encryption.
+ * Those are hideous bugs to find if you get them in an application.
+ */
+ for( i=0; i<2; i++ )
+ {
+ /* Encrypt and test */
+ Twofish_encrypt( &xkey, p, tmp );
+ if( memcmp( c, tmp, 16 ) != 0 )
+ {
+ Twofish_fatal( "Twofish encryption failure", ERR_TEST_ENC );
+ }
+
+ /* Decrypt and test */
+ Twofish_decrypt( &xkey, c, tmp );
+ if( memcmp( p, tmp, 16 ) != 0 )
+ {
+ Twofish_fatal( "Twofish decryption failure", ERR_TEST_DEC );
+ }
+ }
+
+ /* The test keys are not secret, so we don't need to wipe xkey. */
+ return SUCCESS;
+ }
+
+
+/*
+ * Check implementation using three (key,plaintext,ciphertext)
+ * test vectors, one for each major key length.
+ *
+ * This is an absolutely minimal self-test.
+ * This routine does not test odd-sized keys.
+ */
+static int test_vectors()
+ {
+ /*
+ * We run three tests, one for each major key length.
+ * These test vectors come from the Twofish specification.
+ * One encryption and one decryption using randomish data and key
+ * will detect almost any error, especially since we generate the
+ * tables ourselves, so we don't have the problem of a single
+ * damaged table entry in the source.
+ */
+
+ /* 128-bit test is the I=3 case of section B.2 of the Twofish book. */
+ static Twofish_Byte k128[] = {
+ 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
+ 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A,
+ };
+ static Twofish_Byte p128[] = {
+ 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E,
+ 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19
+ };
+ static Twofish_Byte c128[] = {
+ 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85,
+ 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3
+ };
+
+ /* 192-bit test is the I=4 case of section B.2 of the Twofish book. */
+ static Twofish_Byte k192[] = {
+ 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36,
+ 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
+ 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44
+ };
+ static Twofish_Byte p192[] = {
+ 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5,
+ 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2
+ };
+ static Twofish_Byte c192[] = {
+ 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45,
+ 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65
+ };
+
+ /* 256-bit test is the I=4 case of section B.2 of the Twofish book. */
+ static Twofish_Byte k256[] = {
+ 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46,
+ 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
+ 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B,
+ 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F
+ };
+ static Twofish_Byte p256[] = {
+ 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F,
+ 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6
+ };
+ static Twofish_Byte c256[] = {
+ 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97,
+ 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA
+ };
+
+ int ret;
+
+ /* Run the actual tests. */
+ if ((ret = test_vector( k128, 16, p128, c128 )) < 0)
+ return ret;
+ if ((ret = test_vector( k192, 24, p192, c192 )) < 0)
+ return ret;
+ if ((ret = test_vector( k256, 32, p256, c256 )) < 0)
+ return ret;
+ return SUCCESS;
+ }
+
+
+/*
+ * Perform extensive test for a single key size.
+ *
+ * Test a single key size against the test vectors from section
+ * B.2 in the Twofish book. This is a sequence of 49 encryptions
+ * and decryptions. Each plaintext is equal to the ciphertext of
+ * the previous encryption. The key is made up from the ciphertext
+ * two and three encryptions ago. Both plaintext and key start
+ * at the zero value.
+ * We should have designed a cleaner recurrence relation for
+ * these tests, but it is too late for that now. At least we learned
+ * how to do it better next time.
+ * For details see appendix B of the book.
+ *
+ * Arguments:
+ * key_len Number of bytes of key
+ * final_value Final plaintext value after 49 iterations
+ */
+static int test_sequence( int key_len, Twofish_Byte final_value[] )
+ {
+ Twofish_Byte buf[ (50+3)*16 ]; /* Buffer to hold our computation values. */
+ Twofish_Byte tmp[16]; /* Temp for testing the decryption. */
+ Twofish_key xkey; /* The expanded key */
+ int i, ret;
+ Twofish_Byte * p;
+
+ /* Wipe the buffer */
+ memset( buf, 0, sizeof( buf ) );
+
+ /*
+ * Because the recurrence relation is done in an inconvenient manner
+ * we end up looping backwards over the buffer.
+ */
+
+ /* Pointer in buffer points to current plaintext. */
+ p = &buf[50*16];
+ for( i=1; i<50; i++ )
+ {
+ /*
+ * Prepare a key.
+ * This automatically checks that key_len is valid.
+ */
+ if ((ret = Twofish_prepare_key( p+16, key_len, &xkey)) < 0)
+ return ret;
+
+ /* Compute the next 16 bytes in the buffer */
+ Twofish_encrypt( &xkey, p, p-16 );
+
+ /* Check that the decryption is correct. */
+ Twofish_decrypt( &xkey, p-16, tmp );
+ if( memcmp( tmp, p, 16 ) != 0 )
+ {
+ Twofish_fatal( "Twofish decryption failure in sequence", ERR_SEQ_DEC );
+ }
+ /* Move on to next 16 bytes in the buffer. */
+ p -= 16;
+ }
+
+ /* And check the final value. */
+ if( memcmp( p, final_value, 16 ) != 0 )
+ {
+ Twofish_fatal( "Twofish encryption failure in sequence", ERR_SEQ_ENC );
+ }
+
+ /* None of the data was secret, so there is no need to wipe anything. */
+ return SUCCESS;
+ }
+
+
+/*
+ * Run all three sequence tests from the Twofish test vectors.
+ *
+ * This checks the most extensive test vectors currently available
+ * for Twofish. The data is from the Twofish book, appendix B.2.
+ */
+static int test_sequences()
+ {
+ static Twofish_Byte r128[] = {
+ 0x5D, 0x9D, 0x4E, 0xEF, 0xFA, 0x91, 0x51, 0x57,
+ 0x55, 0x24, 0xF1, 0x15, 0x81, 0x5A, 0x12, 0xE0
+ };
+ static Twofish_Byte r192[] = {
+ 0xE7, 0x54, 0x49, 0x21, 0x2B, 0xEE, 0xF9, 0xF4,
+ 0xA3, 0x90, 0xBD, 0x86, 0x0A, 0x64, 0x09, 0x41
+ };
+ static Twofish_Byte r256[] = {
+ 0x37, 0xFE, 0x26, 0xFF, 0x1C, 0xF6, 0x61, 0x75,
+ 0xF5, 0xDD, 0xF4, 0xC3, 0x3B, 0x97, 0xA2, 0x05
+ };
+
+ /* Run the three sequence test vectors */
+ int ret;
+ if ((ret = test_sequence( 16, r128)) < 0)
+ return ret;
+ if ((ret = test_sequence( 24, r192)) < 0)
+ return ret;
+ if ((ret = test_sequence( 32, r256)) < 0)
+ return ret;
+ return SUCCESS;
+ }
+
+
+/*
+ * Test the odd-sized keys.
+ *
+ * Every odd-sized key is equivalent to a one of 128, 192, or 256 bits.
+ * The equivalent key is found by padding at the end with zero bytes
+ * until a regular key size is reached.
+ *
+ * We just test that the key expansion routine behaves properly.
+ * If the expanded keys are identical, then the encryptions and decryptions
+ * will behave the same.
+ */
+static int test_odd_sized_keys()
+ {
+ Twofish_Byte buf[32];
+ Twofish_key xkey;
+ Twofish_key xkey_two;
+ int i, ret;
+
+ /*
+ * We first create an all-zero key to use as PRNG key.
+ * Normally we would not have to fill the buffer with zeroes, as we could
+ * just pass a zero key length to the Twofish_prepare_key function.
+ * However, this relies on using odd-sized keys, and those are just the
+ * ones we are testing here. We can't use an untested function to test
+ * itself.
+ */
+ memset( buf, 0, sizeof( buf ) );
+ if ((ret = Twofish_prepare_key( buf, 16, &xkey)) < 0)
+ return ret;
+
+ /* Fill buffer with pseudo-random data derived from two encryptions */
+ Twofish_encrypt( &xkey, buf, buf );
+ Twofish_encrypt( &xkey, buf, buf+16 );
+
+ /* Create all possible shorter keys that are prefixes of the buffer. */
+ for( i=31; i>=0; i-- )
+ {
+ /* Set a byte to zero. This is the new padding byte */
+ buf[i] = 0;
+
+ /* Expand the key with only i bytes of length */
+ if ((ret = Twofish_prepare_key( buf, i, &xkey)) < 0)
+ return ret;
+
+ /* Expand the corresponding padded key of regular length */
+ if ((ret = Twofish_prepare_key( buf, i<=16 ? 16 : (i<= 24 ? 24 : 32), &xkey_two )) < 0)
+ return ret;
+
+ /* Compare the two */
+ if( memcmp( &xkey, &xkey_two, sizeof( xkey ) ) != 0 )
+ {
+ Twofish_fatal( "Odd sized keys do not expand properly", ERR_ODD_KEY );
+ }
+ }
+
+ /* None of the key values are secret, so we don't need to wipe them. */
+ return SUCCESS;
+ }
+
+
+/*
+ * Test the Twofish implementation.
+ *
+ * This routine runs all the self tests, in order of importance.
+ * It is called by the Twofish_initialise routine.
+ *
+ * In almost all applications the cost of running the self tests during
+ * initialisation is insignificant, especially
+ * compared to the time it takes to load the application from disk.
+ * If you are very pressed for initialisation performance,
+ * you could remove some of the tests. Make sure you did run them
+ * once in the software and hardware configuration you are using.
+ */
+static int self_test()
+ {
+ int ret;
+ /* The three test vectors form an absolute minimal test set. */
+ if ((ret = test_vectors()) < 0)
+ return ret;
+
+ /*
+ * If at all possible you should run these tests too. They take
+ * more time, but provide a more thorough coverage.
+ */
+ if ((ret = test_sequences()) < 0)
+ return ret;
+
+ /* Test the odd-sized keys. */
+ if ((ret = test_odd_sized_keys()) < 0)
+ return ret;
+ return SUCCESS;
+ }
+
+
+/*
+ * And now, the actual Twofish implementation.
+ *
+ * This implementation generates all the tables during initialisation.
+ * I don't like large tables in the code, especially since they are easily
+ * damaged in the source without anyone noticing it. You need code to
+ * generate them anyway, and this way all the code is close together.
+ * Generating them in the application leads to a smaller executable
+ * (the code is smaller than the tables it generates) and a
+ * larger static memory footprint.
+ *
+ * Twofish can be implemented in many ways. I have chosen to
+ * use large tables with a relatively long key setup time.
+ * If you encrypt more than a few blocks of data it pays to pre-compute
+ * as much as possible. This implementation is relatively inefficient for
+ * applications that need to re-key every block or so.
+ */
+
+/*
+ * We start with the t-tables, directly from the Twofish definition.
+ * These are nibble-tables, but merging them and putting them two nibbles
+ * in one byte is more work than it is worth.
+ */
+static Twofish_Byte t_table[2][4][16] = {
+ {
+ {0x8,0x1,0x7,0xD,0x6,0xF,0x3,0x2,0x0,0xB,0x5,0x9,0xE,0xC,0xA,0x4},
+ {0xE,0xC,0xB,0x8,0x1,0x2,0x3,0x5,0xF,0x4,0xA,0x6,0x7,0x0,0x9,0xD},
+ {0xB,0xA,0x5,0xE,0x6,0xD,0x9,0x0,0xC,0x8,0xF,0x3,0x2,0x4,0x7,0x1},
+ {0xD,0x7,0xF,0x4,0x1,0x2,0x6,0xE,0x9,0xB,0x3,0x0,0x8,0x5,0xC,0xA}
+ },
+ {
+ {0x2,0x8,0xB,0xD,0xF,0x7,0x6,0xE,0x3,0x1,0x9,0x4,0x0,0xA,0xC,0x5},
+ {0x1,0xE,0x2,0xB,0x4,0xC,0x3,0x7,0x6,0xD,0xA,0x5,0xF,0x9,0x0,0x8},
+ {0x4,0xC,0x7,0x5,0x1,0x6,0x9,0xA,0x0,0xE,0xD,0x8,0x2,0xB,0x3,0xF},
+ {0xB,0x9,0x5,0x1,0xC,0x3,0xD,0xE,0x6,0x4,0x7,0xF,0x2,0x0,0x8,0xA}
+ }
+};
+
+
+/* A 1-bit rotation of 4-bit values. Input must be in range 0..15 */
+#define ROR4BY1( x ) (((x)>>1) | (((x)<<3) & 0x8) )
+
+/*
+ * The q-boxes are only used during the key schedule computations.
+ * These are 8->8 bit lookup tables. Some CPUs prefer to have 8->32 bit
+ * lookup tables as it is faster to load a 32-bit value than to load an
+ * 8-bit value and zero the rest of the register.
+ * The LARGE_Q_TABLE switch allows you to choose 32-bit entries in
+ * the q-tables. Here we just define the Qtype which is used to store
+ * the entries of the q-tables.
+ */
+#if LARGE_Q_TABLE
+typedef Twofish_UInt32 Qtype;
+#else
+typedef Twofish_Byte Qtype;
+#endif
+
+/*
+ * The actual q-box tables.
+ * There are two q-boxes, each having 256 entries.
+ */
+static Qtype q_table[2][256];
+
+
+/*
+ * Now the function that converts a single t-table into a q-table.
+ *
+ * Arguments:
+ * t[4][16] : four 4->4bit lookup tables that define the q-box
+ * q[256] : output parameter: the resulting q-box as a lookup table.
+ */
+static void make_q_table( Twofish_Byte t[4][16], Qtype q[256] )
+ {
+ int ae,be,ao,bo; /* Some temporaries. */
+ int i;
+ /* Loop over all input values and compute the q-box result. */
+ for( i=0; i<256; i++ ) {
+ /*
+ * This is straight from the Twofish specifications.
+ *
+ * The ae variable is used for the a_i values from the specs
+ * with even i, and ao for the odd i's. Similarly for the b's.
+ */
+ ae = i>>4; be = i&0xf;
+ ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8);
+ ae = t[0][ao]; be = t[1][bo];
+ ao = ae ^ be; bo = ae ^ ROR4BY1(be) ^ ((ae<<3)&8);
+ ae = t[2][ao]; be = t[3][bo];
+
+ /* Store the result in the q-box table, the cast avoids a warning. */
+ q[i] = (Qtype) ((be<<4) | ae);
+ }
+ }
+
+
+/*
+ * Initialise both q-box tables.
+ */
+static void initialise_q_boxes() {
+ /* Initialise each of the q-boxes using the t-tables */
+ make_q_table( t_table[0], q_table[0] );
+ make_q_table( t_table[1], q_table[1] );
+ }
+
+
+/*
+ * Next up is the MDS matrix multiplication.
+ * The MDS matrix multiplication operates in the field
+ * GF(2)[x]/p(x) with p(x)=x^8+x^6+x^5+x^3+1.
+ * If you don't understand this, read a book on finite fields. You cannot
+ * follow the finite-field computations without some background.
+ *
+ * In this field, multiplication by x is easy: shift left one bit
+ * and if bit 8 is set then xor the result with 0x169.
+ *
+ * The MDS coefficients use a multiplication by 1/x,
+ * or rather a division by x. This is easy too: first make the
+ * value 'even' (i.e. bit 0 is zero) by xorring with 0x169 if necessary,
+ * and then shift right one position.
+ * Even easier: shift right and xor with 0xb4 if the lsbit was set.
+ *
+ * The MDS coefficients are 1, EF, and 5B, and we use the fact that
+ * EF = 1 + 1/x + 1/x^2
+ * 5B = 1 + 1/x^2
+ * in this field. This makes multiplication by EF and 5B relatively easy.
+ *
+ * This property is no accident, the MDS matrix was designed to allow
+ * this implementation technique to be used.
+ *
+ * We have four MDS tables, each mapping 8 bits to 32 bits.
+ * Each table performs one column of the matrix multiplication.
+ * As the MDS is always preceded by q-boxes, each of these tables
+ * also implements the q-box just previous to that column.
+ */
+
+/* The actual MDS tables. */
+static Twofish_UInt32 MDS_table[4][256];
+
+/* A small table to get easy conditional access to the 0xb4 constant. */
+static Twofish_UInt32 mds_poly_divx_const[] = {0,0xb4};
+
+/* Function to initialise the MDS tables. */
+static void initialise_mds_tables()
+ {
+ int i;
+ Twofish_UInt32 q,qef,q5b; /* Temporary variables. */
+
+ /* Loop over all 8-bit input values */
+ for( i=0; i<256; i++ )
+ {
+ /*
+ * To save some work during the key expansion we include the last
+ * of the q-box layers from the h() function in these MDS tables.
+ */
+
+ /* We first do the inputs that are mapped through the q0 table. */
+ q = q_table[0][i];
+ /*
+ * Here we divide by x, note the table to get 0xb4 only if the
+ * lsbit is set.
+ * This sets qef = (1/x)*q in the finite field
+ */
+ qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ];
+ /*
+ * Divide by x again, and add q to get (1+1/x^2)*q.
+ * Note that (1+1/x^2) = 5B in the field, and addition in the field
+ * is exclusive or on the bits.
+ */
+ q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q;
+ /*
+ * Add q5b to qef to set qef = (1+1/x+1/x^2)*q.
+ * Again, (1+1/x+1/x^2) = EF in the field.
+ */
+ qef ^= q5b;
+
+ /*
+ * Now that we have q5b = 5B * q and qef = EF * q
+ * we can fill two of the entries in the MDS matrix table.
+ * See the Twofish specifications for the order of the constants.
+ */
+ MDS_table[1][i] = (q <<24) | (q5b<<16) | (qef<<8) | qef;
+ MDS_table[3][i] = (q5b<<24) | (qef<<16) | (q <<8) | q5b;
+
+ /* Now we do it all again for the two columns that have a q1 box. */
+ q = q_table[1][i];
+ qef = (q >> 1) ^ mds_poly_divx_const[ q & 1 ];
+ q5b = (qef >> 1) ^ mds_poly_divx_const[ qef & 1 ] ^ q;
+ qef ^= q5b;
+
+ /* The other two columns use the coefficient in a different order. */
+ MDS_table[0][i] = (qef<<24) | (qef<<16) | (q5b<<8) | q ;
+ MDS_table[2][i] = (qef<<24) | (q <<16) | (qef<<8) | q5b;
+ }
+ }
+
+
+/*
+ * The h() function is the heart of the Twofish cipher.
+ * It is a complicated sequence of q-box lookups, key material xors,
+ * and finally the MDS matrix.
+ * We use lots of macros to make this reasonably fast.
+ */
+
+/* First a shorthand for the two q-tables */
+#define q0 q_table[0]
+#define q1 q_table[1]
+
+/*
+ * Each macro computes one column of the h for either 2, 3, or 4 stages.
+ * As there are 4 columns, we have 12 macros in all.
+ *
+ * The key bytes are stored in the Byte array L at offset
+ * 0,1,2,3, 8,9,10,11, [16,17,18,19, [24,25,26,27]] as this is the
+ * order we get the bytes from the user. If you look at the Twofish
+ * specs, you'll see that h() is applied to the even key words or the
+ * odd key words. The bytes of the even words appear in this spacing,
+ * and those of the odd key words too.
+ *
+ * These macros are the only place where the q-boxes and the MDS table
+ * are used.
+ */
+#define H02( y, L ) MDS_table[0][q0[q0[y]^L[ 8]]^L[0]]
+#define H12( y, L ) MDS_table[1][q0[q1[y]^L[ 9]]^L[1]]
+#define H22( y, L ) MDS_table[2][q1[q0[y]^L[10]]^L[2]]
+#define H32( y, L ) MDS_table[3][q1[q1[y]^L[11]]^L[3]]
+#define H03( y, L ) H02( q1[y]^L[16], L )
+#define H13( y, L ) H12( q1[y]^L[17], L )
+#define H23( y, L ) H22( q0[y]^L[18], L )
+#define H33( y, L ) H32( q0[y]^L[19], L )
+#define H04( y, L ) H03( q1[y]^L[24], L )
+#define H14( y, L ) H13( q0[y]^L[25], L )
+#define H24( y, L ) H23( q0[y]^L[26], L )
+#define H34( y, L ) H33( q1[y]^L[27], L )
+
+/*
+ * Now we can define the h() function given an array of key bytes.
+ * This function is only used in the key schedule, and not to pre-compute
+ * the keyed S-boxes.
+ *
+ * In the key schedule, the input is always of the form k*(1+2^8+2^16+2^24)
+ * so we only provide k as an argument.
+ *
+ * Arguments:
+ * k input to the h() function.
+ * L pointer to array of key bytes at
+ * offsets 0,1,2,3, ... 8,9,10,11, [16,17,18,19, [24,25,26,27]]
+ * kCycles # key cycles, 2, 3, or 4.
+ */
+static Twofish_UInt32 h( int k, Twofish_Byte L[], int kCycles )
+ {
+ switch( kCycles ) {
+ /* We code all 3 cases separately for speed reasons. */
+ case 2:
+ return H02(k,L) ^ H12(k,L) ^ H22(k,L) ^ H32(k,L);
+ case 3:
+ return H03(k,L) ^ H13(k,L) ^ H23(k,L) ^ H33(k,L);
+ case 4:
+ return H04(k,L) ^ H14(k,L) ^ H24(k,L) ^ H34(k,L);
+ default:
+ /* This is always a coding error, which is fatal. */
+ Twofish_fatal( "Twofish h(): Illegal argument", ERR_ILL_ARG );
+ return ERR_ILL_ARG;
+ }
+ }
+
+
+/*
+ * Pre-compute the keyed S-boxes.
+ * Fill the pre-computed S-box array in the expanded key structure.
+ * Each pre-computed S-box maps 8 bits to 32 bits.
+ *
+ * The S argument contains half the number of bytes of the full key, but is
+ * derived from the full key. (See Twofish specifications for details.)
+ * S has the weird byte input order used by the Hxx macros.
+ *
+ * This function takes most of the time of a key expansion.
+ *
+ * Arguments:
+ * S pointer to array of 8*kCycles Bytes containing the S vector.
+ * kCycles number of key words, must be in the set {2,3,4}
+ * xkey pointer to Twofish_key structure that will contain the S-boxes.
+ */
+static int fill_keyed_sboxes( Twofish_Byte S[], int kCycles, Twofish_key * xkey )
+ {
+ int i;
+ switch( kCycles ) {
+ /* We code all 3 cases separately for speed reasons. */
+ case 2:
+ for( i=0; i<256; i++ )
+ {
+ xkey->s[0][i]= H02( i, S );
+ xkey->s[1][i]= H12( i, S );
+ xkey->s[2][i]= H22( i, S );
+ xkey->s[3][i]= H32( i, S );
+ }
+ break;
+ case 3:
+ for( i=0; i<256; i++ )
+ {
+ xkey->s[0][i]= H03( i, S );
+ xkey->s[1][i]= H13( i, S );
+ xkey->s[2][i]= H23( i, S );
+ xkey->s[3][i]= H33( i, S );
+ }
+ break;
+ case 4:
+ for( i=0; i<256; i++ )
+ {
+ xkey->s[0][i]= H04( i, S );
+ xkey->s[1][i]= H14( i, S );
+ xkey->s[2][i]= H24( i, S );
+ xkey->s[3][i]= H34( i, S );
+ }
+ break;
+ default:
+ /* This is always a coding error, which is fatal. */
+ Twofish_fatal( "Twofish fill_keyed_sboxes(): Illegal argument", ERR_ILL_ARG );
+ }
+ return SUCCESS;
+ }
+
+
+/* A flag to keep track of whether we have been initialised or not. */
+static int Twofish_initialised = 0;
+
+/*
+ * Initialise the Twofish implementation.
+ * This function must be called before any other function in the
+ * Twofish implementation is called.
+ * This routine also does some sanity checks, to make sure that
+ * all the macros behave, and it tests the whole cipher.
+ */
+int Twofish_initialise()
+ {
+ int ret;
+ /* First test the various platform-specific definitions. */
+ if ((ret = test_platform()) < 0)
+ return ret;
+
+ /* We can now generate our tables, in the right order of course. */
+ initialise_q_boxes();
+ initialise_mds_tables();
+
+ /* We're finished with the initialisation itself. */
+ Twofish_initialised = 1;
+
+ /*
+ * And run some tests on the whole cipher.
+ * Yes, you need to do this every time you start your program.
+ * It is called assurance; you have to be certain that your program
+ * still works properly.
+ */
+ return self_test();
+ }
+
+
+/*
+ * The Twofish key schedule uses an Reed-Solomon code matrix multiply.
+ * Just like the MDS matrix, the RS-matrix is designed to be easy
+ * to implement. Details are below in the code.
+ *
+ * These constants make it easy to compute in the finite field used
+ * for the RS code.
+ *
+ * We use Bytes for the RS computation, but these are automatically
+ * widened to unsigned integers in the expressions. Having unsigned
+ * ints in these tables therefore provides the fastest access.
+ */
+static unsigned int rs_poly_const[] = {0, 0x14d};
+static unsigned int rs_poly_div_const[] = {0, 0xa6 };
+
+
+/*
+ * Prepare a key for use in encryption and decryption.
+ * Like most block ciphers, Twofish allows the key schedule
+ * to be pre-computed given only the key.
+ * Twofish has a fairly 'heavy' key schedule that takes a lot of time
+ * to compute. The main work is pre-computing the S-boxes used in the
+ * encryption and decryption. We feel that this makes the cipher much
+ * harder to attack. The attacker doesn't even know what the S-boxes
+ * contain without including the entire key schedule in the analysis.
+ *
+ * Unlike most Twofish implementations, this one allows any key size from
+ * 0 to 32 bytes. Odd key sizes are defined for Twofish (see the
+ * specifications); the key is simply padded with zeroes to the next real
+ * key size of 16, 24, or 32 bytes.
+ * Each odd-sized key is thus equivalent to a single normal-sized key.
+ *
+ * Arguments:
+ * key array of key bytes
+ * key_len number of bytes in the key, must be in the range 0,...,32.
+ * xkey Pointer to an Twofish_key structure that will be filled
+ * with the internal form of the cipher key.
+ */
+int Twofish_prepare_key( Twofish_Byte key[], int key_len, Twofish_key * xkey )
+ {
+ /* We use a single array to store all key material in,
+ * to simplify the wiping of the key material at the end.
+ * The first 32 bytes contain the actual (padded) cipher key.
+ * The next 32 bytes contain the S-vector in its weird format,
+ * and we have 4 bytes of overrun necessary for the RS-reduction.
+ */
+ Twofish_Byte K[32+32+4];
+
+ int kCycles; /* # key cycles, 2,3, or 4. */
+
+ int i;
+ Twofish_UInt32 A, B; /* Used to compute the round keys. */
+
+ Twofish_Byte * kptr; /* Three pointers for the RS computation. */
+ Twofish_Byte * sptr;
+ Twofish_Byte * t;
+
+ Twofish_Byte b,bx,bxx; /* Some more temporaries for the RS computation. */
+
+ /* Check that the Twofish implementation was initialised. */
+ if( Twofish_initialised == 0 )
+ {
+ /*
+ * You didn't call Twofish_initialise before calling this routine.
+ * This is a programming error, and therefore we call the fatal
+ * routine.
+ *
+ * I could of course call the initialisation routine here,
+ * but there are a few reasons why I don't. First of all, the
+ * self-tests have to be done at startup. It is no good to inform
+ * the user that the cipher implementation fails when he wants to
+ * write his data to disk in encrypted form. You have to warn him
+ * before he spends time typing his data. Second, the initialisation
+ * and self test are much slower than a single key expansion.
+ * Calling the initialisation here makes the performance of the
+ * cipher unpredictable. This can lead to really weird problems
+ * if you use the cipher for a real-time task. Suddenly it fails
+ * once in a while the first time you try to use it. Things like
+ * that are almost impossible to debug.
+ */
+ /* Twofish_fatal( "Twofish implementation was not initialised.", ERR_INIT ); */
+
+ /*
+ * There is always a danger that the Twofish_fatal routine returns,
+ * in spite of the specifications that it should not.
+ * (A good programming rule: don't trust the rest of the code.)
+ * This would be disasterous. If the q-tables and MDS-tables have
+ * not been initialised, they are probably still filled with zeroes.
+ * Suppose the MDS-tables are all zero. The key expansion would then
+ * generate all-zero round keys, and all-zero s-boxes. The danger
+ * is that nobody would notice as the encry
+ * mangles the input, and the decryption still 'decrypts' it,
+ * but now in a completely key-independent manner.
+ * To stop such security disasters, we use blunt force.
+ * If your program hangs here: fix the fatal routine!
+ */
+ for(;;); /* Infinite loop, which beats being insecure. */
+ }
+
+ /* Check for valid key length. */
+ if( key_len < 0 || key_len > 32 )
+ {
+ /*
+ * This can only happen if a programmer didn't read the limitations
+ * on the key size.
+ */
+ Twofish_fatal( "Twofish_prepare_key: illegal key length", ERR_KEY_LEN );
+ /*
+ * A return statement just in case the fatal macro returns.
+ * The rest of the code assumes that key_len is in range, and would
+ * buffer-overflow if it wasn't.
+ *
+ * Why do we still use a programming language that has problems like
+ * buffer overflows, when these problems were solved in 1960 with
+ * the development of Algol? Have we not leared anything?
+ */
+ return ERR_KEY_LEN;
+ }
+
+ /* Pad the key with zeroes to the next suitable key length. */
+ memcpy( K, key, key_len );
+ memset( K+key_len, 0, sizeof(K)-key_len );
+
+ /*
+ * Compute kCycles: the number of key cycles used in the cipher.
+ * 2 for 128-bit keys, 3 for 192-bit keys, and 4 for 256-bit keys.
+ */
+ kCycles = (key_len + 7) >> 3;
+ /* Handle the special case of very short keys: minimum 2 cycles. */
+ if( kCycles < 2 )
+ {
+ kCycles = 2;
+ }
+
+ /*
+ * From now on we just pretend to have 8*kCycles bytes of
+ * key material in K. This handles all the key size cases.
+ */
+
+ /*
+ * We first compute the 40 expanded key words,
+ * formulas straight from the Twofish specifications.
+ */
+ for( i=0; i<40; i+=2 )
+ {
+ /*
+ * Due to the byte spacing expected by the h() function
+ * we can pick the bytes directly from the key K.
+ * As we use bytes, we never have the little/big endian
+ * problem.
+ *
+ * Note that we apply the rotation function only to simple
+ * variables, as the rotation macro might evaluate its argument
+ * more than once.
+ */
+ A = h( i , K , kCycles );
+ B = h( i+1, K+4, kCycles );
+ B = ROL32( B, 8 );
+
+ /* Compute and store the round keys. */
+ A += B;
+ B += A;
+ xkey->K[i] = A;
+ xkey->K[i+1] = ROL32( B, 9 );
+ }
+
+ /* Wipe variables that contained key material. */
+ A=B=0;
+
+ /*
+ * And now the dreaded RS multiplication that few seem to understand.
+ * The RS matrix is not random, and is specially designed to compute the
+ * RS matrix multiplication in a simple way.
+ *
+ * We work in the field GF(2)[x]/x^8+x^6+x^3+x^2+1. Note that this is a
+ * different field than used for the MDS matrix.
+ * (At least, it is a different representation because all GF(2^8)
+ * representations are equivalent in some form.)
+ *
+ * We take 8 consecutive bytes of the key and interpret them as
+ * a polynomial k_0 + k_1 y + k_2 y^2 + ... + k_7 y^7 where
+ * the k_i bytes are the key bytes and are elements of the finite field.
+ * We multiply this polynomial by y^4 and reduce it modulo
+ * y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1.
+ * using straightforward polynomial modulo reduction.
+ * The coefficients of the result are the result of the RS
+ * matrix multiplication. When we wrote the Twofish specification,
+ * the original RS definition used the polynomials,
+ * but that requires much more mathematical knowledge.
+ * We were already using matrix multiplication in a finite field for
+ * the MDS matrix, so I re-wrote the RS operation as a matrix
+ * multiplication to reduce the difficulty of understanding it.
+ * Some implementors have not picked up on this simpler method of
+ * computing the RS operation, even though it is mentioned in the
+ * specifications.
+ *
+ * It is possible to perform these computations faster by using 32-bit
+ * word operations, but that is not portable and this is not a speed-
+ * critical area.
+ *
+ * We explained the 1/x computation when we did the MDS matrix.
+ *
+ * The S vector is stored in K[32..64].
+ * The S vector has to be reversed, so we loop cross-wise.
+ *
+ * Note the weird byte spacing of the S-vector, to match the even
+ * or odd key words arrays. See the discussion at the Hxx macros for
+ * details.
+ */
+ kptr = K + 8*kCycles; /* Start at end of key */
+ sptr = K + 32; /* Start at start of S */
+
+ /* Loop over all key material */
+ while( kptr > K )
+ {
+ kptr -= 8;
+ /*
+ * Initialise the polynimial in sptr[0..12]
+ * The first four coefficients are 0 as we have to multiply by y^4.
+ * The next 8 coefficients are from the key material.
+ */
+ memset( sptr, 0, 4 );
+ memcpy( sptr+4, kptr, 8 );
+
+ /*
+ * The 12 bytes starting at sptr are now the coefficients of
+ * the polynomial we need to reduce.
+ */
+
+ /* Loop over the polynomial coefficients from high to low */
+ t = sptr+11;
+ /* Keep looping until polynomial is degree 3; */
+ while( t > sptr+3 )
+ {
+ /* Pick up the highest coefficient of the poly. */
+ b = *t;
+
+ /*
+ * Compute x and (x+1/x) times this coefficient.
+ * See the MDS matrix implementation for a discussion of
+ * multiplication by x and 1/x. We just use different
+ * constants here as we are in a
+ * different finite field representation.
+ *
+ * These two statements set
+ * bx = (x) * b
+ * bxx= (x + 1/x) * b
+ */
+ bx = (Twofish_Byte)((b<<1) ^ rs_poly_const[ b>>7 ]);
+ bxx= (Twofish_Byte)((b>>1) ^ rs_poly_div_const[ b&1 ] ^ bx);
+
+ /*
+ * Subtract suitable multiple of
+ * y^4 + (x + 1/x)y^3 + (x)y^2 + (x + 1/x)y + 1
+ * from the polynomial, except that we don't bother
+ * updating t[0] as it will become zero anyway.
+ */
+ t[-1] ^= bxx;
+ t[-2] ^= bx;
+ t[-3] ^= bxx;
+ t[-4] ^= b;
+
+ /* Go to the next coefficient. */
+ t--;
+ }
+
+ /* Go to next S-vector word, obeying the weird spacing rules. */
+ sptr += 8;
+ }
+
+ /* Wipe variables that contained key material. */
+ b = bx = bxx = 0;
+
+ /* And finally, we can compute the key-dependent S-boxes. */
+ fill_keyed_sboxes( &K[32], kCycles, xkey );
+
+ /* Wipe array that contained key material. */
+ memset( K, 0, sizeof( K ) );
+ return SUCCESS;
+ }
+
+
+/*
+ * We can now start on the actual encryption and decryption code.
+ * As these are often speed-critical we will use a lot of macros.
+ */
+
+/*
+ * The g() function is the heart of the round function.
+ * We have two versions of the g() function, one without an input
+ * rotation and one with.
+ * The pre-computed S-boxes make this pretty simple.
+ */
+#define g0(X,xkey) \
+ (xkey->s[0][b0(X)]^xkey->s[1][b1(X)]^xkey->s[2][b2(X)]^xkey->s[3][b3(X)])
+
+#define g1(X,xkey) \
+ (xkey->s[0][b3(X)]^xkey->s[1][b0(X)]^xkey->s[2][b1(X)]^xkey->s[3][b2(X)])
+
+/*
+ * A single round of Twofish. The A,B,C,D are the four state variables,
+ * T0 and T1 are temporaries, xkey is the expanded key, and r the
+ * round number.
+ *
+ * Note that this macro does not implement the swap at the end of the round.
+ */
+#define ENCRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \
+ T0 = g0(A,xkey); T1 = g1(B,xkey);\
+ C ^= T0+T1+xkey->K[8+2*(r)]; C = ROR32(C,1);\
+ D = ROL32(D,1); D ^= T0+2*T1+xkey->K[8+2*(r)+1]
+
+/*
+ * Encrypt a single cycle, consisting of two rounds.
+ * This avoids the swapping of the two halves.
+ * Parameter r is now the cycle number.
+ */
+#define ENCRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \
+ ENCRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r) );\
+ ENCRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r)+1 )
+
+/* Full 16-round encryption */
+#define ENCRYPT( A,B,C,D,T0,T1,xkey ) \
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 );\
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\
+ ENCRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 )
+
+/*
+ * A single round of Twofish for decryption. It differs from
+ * ENCRYTP_RND only because of the 1-bit rotations.
+ */
+#define DECRYPT_RND( A,B,C,D, T0, T1, xkey, r ) \
+ T0 = g0(A,xkey); T1 = g1(B,xkey);\
+ C = ROL32(C,1); C ^= T0+T1+xkey->K[8+2*(r)];\
+ D ^= T0+2*T1+xkey->K[8+2*(r)+1]; D = ROR32(D,1)
+
+/*
+ * Decrypt a single cycle, consisting of two rounds.
+ * This avoids the swapping of the two halves.
+ * Parameter r is now the cycle number.
+ */
+#define DECRYPT_CYCLE( A, B, C, D, T0, T1, xkey, r ) \
+ DECRYPT_RND( A,B,C,D,T0,T1,xkey,2*(r)+1 );\
+ DECRYPT_RND( C,D,A,B,T0,T1,xkey,2*(r) )
+
+/* Full 16-round decryption. */
+#define DECRYPT( A,B,C,D,T0,T1, xkey ) \
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 7 );\
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 6 );\
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 5 );\
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 4 );\
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 3 );\
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 2 );\
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 1 );\
+ DECRYPT_CYCLE( A,B,C,D,T0,T1,xkey, 0 )
+
+/*
+ * A macro to read the state from the plaintext and do the initial key xors.
+ * The koff argument allows us to use the same macro
+ * for the decryption which uses different key words at the start.
+ */
+#define GET_INPUT( src, A,B,C,D, xkey, koff ) \
+ A = GET32(src )^xkey->K[ koff]; B = GET32(src+ 4)^xkey->K[1+koff]; \
+ C = GET32(src+ 8)^xkey->K[2+koff]; D = GET32(src+12)^xkey->K[3+koff]
+
+/*
+ * Similar macro to put the ciphertext in the output buffer.
+ * We xor the keys into the state variables before we use the PUT32
+ * macro as the macro might use its argument multiple times.
+ */
+#define PUT_OUTPUT( A,B,C,D, dst, xkey, koff ) \
+ A ^= xkey->K[ koff]; B ^= xkey->K[1+koff]; \
+ C ^= xkey->K[2+koff]; D ^= xkey->K[3+koff]; \
+ PUT32( A, dst ); PUT32( B, dst+ 4 ); \
+ PUT32( C, dst+8 ); PUT32( D, dst+12 )
+
+
+/*
+ * Twofish block encryption
+ *
+ * Arguments:
+ * xkey expanded key array
+ * p 16 bytes of plaintext
+ * c 16 bytes in which to store the ciphertext
+ */
+void Twofish_encrypt( Twofish_key * xkey, Twofish_Byte p[16], Twofish_Byte c[16])
+ {
+ Twofish_UInt32 A,B,C,D,T0,T1; /* Working variables */
+
+ /* Get the four plaintext words xorred with the key */
+ GET_INPUT( p, A,B,C,D, xkey, 0 );
+
+ /* Do 8 cycles (= 16 rounds) */
+ ENCRYPT( A,B,C,D,T0,T1,xkey );
+
+ /* Store them with the final swap and the output whitening. */
+ PUT_OUTPUT( C,D,A,B, c, xkey, 4 );
+ }
+
+
+/*
+ * Twofish block decryption.
+ *
+ * Arguments:
+ * xkey expanded key array
+ * p 16 bytes of plaintext
+ * c 16 bytes in which to store the ciphertext
+ */
+void Twofish_decrypt( Twofish_key * xkey, Twofish_Byte c[16], Twofish_Byte p[16])
+ {
+ Twofish_UInt32 A,B,C,D,T0,T1; /* Working variables */
+
+ /* Get the four plaintext words xorred with the key */
+ GET_INPUT( c, A,B,C,D, xkey, 4 );
+
+ /* Do 8 cycles (= 16 rounds) */
+ DECRYPT( A,B,C,D,T0,T1,xkey );
+
+ /* Store them with the final swap and the output whitening. */
+ PUT_OUTPUT( C,D,A,B, p, xkey, 0 );
+ }
+
+/*
+ * Using the macros it is easy to make special routines for
+ * CBC mode, CTR mode etc. The only thing you might want to
+ * add is a XOR_PUT_OUTPUT which xors the outputs into the
+ * destinationa instead of overwriting the data. This requires
+ * a XOR_PUT32 macro as well, but that should all be trivial.
+ *
+ * I thought about including routines for the separate cipher
+ * modes here, but it is unclear which modes should be included,
+ * and each encryption or decryption routine takes up a lot of code space.
+ * Also, I don't have any test vectors for any cipher modes
+ * with Twofish.
+ */
+
+
diff --git a/src/libzrtpcpp/crypto/twofish.h b/src/libzrtpcpp/crypto/twofish.h
new file mode 100755
index 0000000..0c8b0d7
--- /dev/null
+++ b/src/libzrtpcpp/crypto/twofish.h
@@ -0,0 +1,265 @@
+/*
+ * Fast, portable, and easy-to-use Twofish implementation,
+ * Version 0.3.
+ * Copyright (c) 2002 by Niels Ferguson.
+ *
+ * See the twofish.c file for the details of the how and why of this code.
+ *
+ * The author hereby grants a perpetual license to everybody to
+ * use this code for any purpose as long as the copyright message is included
+ * in the source code of this or any derived work.
+ */
+
+
+/*
+ * PLATFORM FIXES
+ * ==============
+ *
+ * The following definitions have to be fixed for each particular platform
+ * you work on. If you have a multi-platform program, you no doubt have
+ * portable definitions that you can substitute here without changing
+ * the rest of the code.
+ *
+ * The defaults provided here should work on most PC compilers.
+ */
+
+#ifndef TWOFISH_H
+#define TWOFISH_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file twofish.h
+ * @brief Function that provide basic Twofish crypto support
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+/**
+ * A Twofish_Byte must be an unsigned 8-bit integer.
+ *
+ * It must also be the elementary data size of your C platform,
+ * i.e. sizeof( Twofish_Byte ) == 1.
+ */
+typedef unsigned char Twofish_Byte;
+
+/**
+ * A Twofish_UInt32 must be an unsigned integer of at least 32 bits.
+ *
+ * This type is used only internally in the implementation, so ideally it
+ * would not appear in the header file, but it is used inside the
+ * Twofish_key structure which means it has to be included here.
+ */
+typedef unsigned int Twofish_UInt32;
+
+
+/*
+ * END OF PLATFORM FIXES
+ * =====================
+ *
+ * You should not have to touch the rest of this file, but the code
+ * in twofish.c has a few things you need to fix too.
+ */
+
+/**
+ * Return codes
+ */
+#define SUCCESS 1
+#define ERR_UINT32 -2
+#define ERR_BYTE -3
+#define ERR_GET32 -4
+#define ERR_PUT32 -5
+#define ERR_ROLR -6
+#define ERR_BSWAP -7
+#define ERR_SELECTB -8
+#define ERR_TEST_ENC -9
+#define ERR_TEST_DEC -10
+#define ERR_SEQ_ENC -11
+#define ERR_SEQ_DEC -12
+#define ERR_ODD_KEY -13
+#define ERR_INIT -14
+#define ERR_KEY_LEN -15
+#define ERR_ILL_ARG -16
+
+
+/**
+ * Structure that contains a prepared Twofish key.
+ *
+ * A cipher key is used in two stages. In the first stage it is converted
+ * form the original form to an internal representation.
+ * This internal form is then used to encrypt and decrypt data.
+ * This structure contains the internal form. It is rather large: 4256 bytes
+ * on a platform with 32-bit unsigned values.
+ *
+ * Treat this as an opague structure, and don't try to manipulate the
+ * elements in it. I wish I could hide the inside of the structure,
+ * but C doesn't allow that.
+ */
+typedef
+ struct
+ {
+ Twofish_UInt32 s[4][256]; /* pre-computed S-boxes */
+ Twofish_UInt32 K[40]; /* Round key words */
+ }
+ Twofish_key;
+
+
+/**
+ * Initialise and test the Twofish implementation.
+ *
+ * This function MUST be called before any other function in the
+ * Twofish implementation is called.
+ * It only needs to be called once.
+ *
+ * Apart from initialising the implementation it performs a self test.
+ * If the Twofish_fatal function is not called, the code passed the test.
+ * (See the twofish.c file for details on the Twofish_fatal function.)
+ *
+ * @returns a negative number if an error happend, +1 otherwise
+ */
+extern int Twofish_initialise();
+
+
+/**
+ * Convert a cipher key to the internal form used for
+ * encryption and decryption.
+ *
+ * The cipher key is an array of bytes; the Twofish_Byte type is
+ * defined above to a type suitable on your platform.
+ *
+ * Any key must be converted to an internal form in the Twofisk_key structure
+ * before it can be used.
+ * The encryption and decryption functions only work with the internal form.
+ * The conversion to internal form need only be done once for each key value.
+ *
+ * Be sure to wipe all key storage, including the Twofish_key structure,
+ * once you are done with the key data.
+ * A simple memset( TwofishKey, 0, sizeof( TwofishKey ) ) will do just fine.
+ *
+ * Unlike most implementations, this one allows any key size from 0 bytes
+ * to 32 bytes. According to the Twofish specifications,
+ * irregular key sizes are handled by padding the key with zeroes at the end
+ * until the key size is 16, 24, or 32 bytes, whichever
+ * comes first. Note that each key of irregular size is equivalent to exactly
+ * one key of 16, 24, or 32 bytes.
+ *
+ * WARNING: Short keys have low entropy, and result in low security.
+ * Anything less than 8 bytes is utterly insecure. For good security
+ * use at least 16 bytes. I prefer to use 32-byte keys to prevent
+ * any collision attacks on the key.
+ *
+ * The key length argument key_len must be in the proper range.
+ * If key_len is not in the range 0,...,32 this routine attempts to generate
+ * a fatal error (depending on the code environment),
+ * and at best (or worst) returns without having done anything.
+ *
+ * @param key Array of key bytes
+ * @param key_len Number of key bytes, must be in the range 0,1,...,32.
+ * @param xkey Pointer to an Twofish_key structure that will be filled
+ * with the internal form of the cipher key.
+ * @returns a negative number if an error happend, +1 otherwise
+ */
+extern int Twofish_prepare_key(
+ Twofish_Byte key[],
+ int key_len,
+ Twofish_key * xkey
+ );
+
+
+/**
+ * Encrypt a single block of data.
+ *
+ * This function encrypts a single block of 16 bytes of data.
+ * If you want to encrypt a larger or variable-length message,
+ * you will have to use a cipher mode, such as CBC or CTR.
+ * These are outside the scope of this implementation.
+ *
+ * The xkey structure is not modified by this routine, and can be
+ * used for further encryption and decryption operations.
+ *
+ * @param xkey pointer to Twofish_key, internal form of the key
+ * produces by Twofish_prepare_key()
+ * @param p Plaintext to be encrypted
+ * @param c Place to store the ciphertext
+ */
+extern void Twofish_encrypt(
+ Twofish_key * xkey,
+ Twofish_Byte p[16],
+ Twofish_Byte c[16]
+ );
+
+
+/**
+ * Decrypt a single block of data.
+ *
+ * This function decrypts a single block of 16 bytes of data.
+ * If you want to decrypt a larger or variable-length message,
+ * you will have to use a cipher mode, such as CBC or CTR.
+ * These are outside the scope of this implementation.
+ *
+ * The xkey structure is not modified by this routine, and can be
+ * used for further encryption and decryption operations.
+ *
+ * @param xkey pointer to Twofish_key, internal form of the key
+ * produces by Twofish_prepare_key()
+ * @param c Ciphertext to be decrypted
+ * @param p Place to store the plaintext
+ */
+extern void Twofish_decrypt(
+ Twofish_key * xkey,
+ Twofish_Byte c[16],
+ Twofish_Byte p[16]
+ );
+
+
+/**
+ * Encrypt data in CFB mode.
+ *
+ * This function encrypts data in CFB mode.
+ *
+ * The key structure is not modified by this routine, and can be
+ * used for further encryption and decryption operations.
+ *
+ * @param keyCtx pointer to Twofish_key, internal form of the key
+ * produced by Twofish_prepare_key()
+ * @param in Plaintext to be encrypted
+ * @param out Place to store the ciphertext
+ * @param len number of bytes to encrypt.
+ * @param ivec initialization vector for this CFB mode encryption.
+ * @param num pointer to integer that holds number of available crypto bytes.
+ */
+void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in,
+ Twofish_Byte* out, size_t len,
+ Twofish_Byte* ivec, int *num);
+
+/**
+ * Decrypt data in CFB mode.
+ *
+ * This function decrypts data in CFB.
+ *
+ * The key structure is not modified by this routine, and can be
+ * used for further encryption and decryption operations.
+ *
+ * @param keyCtx pointer to Twofish_key, internal form of the key
+ * produced by Twofish_prepare_key()
+ * @param in Ciphertext to be decrypted
+ * @param out Place to store the plaintext
+ * @param len number of bytes to decrypt.
+ * @param ivec initialization vector for this CFB mode encryption.
+ * @param num pointer to integer that holds number of available crypto bytes.
+ */
+void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in,
+ Twofish_Byte* out, size_t len,
+ Twofish_Byte* ivec, int *num);
+/**
+ * @}
+ */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libzrtpcpp/crypto/twofish_cfb.c b/src/libzrtpcpp/crypto/twofish_cfb.c
new file mode 100755
index 0000000..7540738
--- /dev/null
+++ b/src/libzrtpcpp/crypto/twofish_cfb.c
@@ -0,0 +1,82 @@
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "twofish.h"
+
+void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in,
+ Twofish_Byte* out, size_t len,
+ Twofish_Byte* ivec, int32_t *num)
+{
+ uint32_t n;
+
+ n = *num;
+
+ do {
+ while (n && len) {
+ *(out++) = ivec[n] ^= *(in++);
+ --len;
+ n = (n+1) % 16;
+ }
+ while (len>=16) {
+ Twofish_encrypt(keyCtx, ivec, ivec);
+ for (n=0; n<16; n+=sizeof(size_t)) {
+ *(size_t*)(out+n) =
+ *(size_t*)(ivec+n) ^= *(size_t*)(in+n);
+ }
+ len -= 16;
+ out += 16;
+ in += 16;
+ }
+ n = 0;
+ if (len) {
+ Twofish_encrypt(keyCtx, ivec, ivec);
+ while (len--) {
+ out[n] = ivec[n] ^= in[n];
+ ++n;
+ }
+ }
+ *num = n;
+ return;
+ } while (0);
+}
+
+
+void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in,
+ Twofish_Byte* out, size_t len,
+ Twofish_Byte* ivec, int32_t *num)
+{
+ uint32_t n;
+
+ n = *num;
+
+ do {
+ while (n && len) {
+ unsigned char c;
+ *(out++) = ivec[n] ^ (c = *(in++)); ivec[n] = c;
+ --len;
+ n = (n+1) % 16;
+ }
+ while (len>=16) {
+ Twofish_encrypt(keyCtx, ivec, ivec);
+ for (n=0; n<16; n+=sizeof(size_t)) {
+ size_t t = *(size_t*)(in+n);
+ *(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t;
+ *(size_t*)(ivec+n) = t;
+ }
+ len -= 16;
+ out += 16;
+ in += 16;
+ }
+ n = 0;
+ if (len) {
+ Twofish_encrypt(keyCtx, ivec, ivec);
+ while (len--) {
+ unsigned char c;
+ out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c;
+ ++n;
+ }
+ }
+ *num = n;
+ return;
+ } while (0);
+}
diff --git a/src/libzrtpcpp/zrtpPacket.h b/src/libzrtpcpp/zrtpPacket.h
new file mode 100644
index 0000000..18ba7a1
--- /dev/null
+++ b/src/libzrtpcpp/zrtpPacket.h
@@ -0,0 +1,342 @@
+/*
+ Copyright (C) 2006-2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
+ */
+
+#ifndef ZRTPPACKET_H
+#define ZRTPPACKET_H
+
+/**
+ *
+ * @file zrtpPacket.h
+ * @brief The data structures and definitions for ZRTP messages
+ *
+ * This include file defines the ZRTP message structures. Refer to
+ * chapter 5 of the ZRTP specification which defines the ZRTP messages and
+ * the transport format.
+ *
+ * @ingroup GNU_ZRTP
+ * @{
+ */
+
+#include <stdio.h>
+
+/**
+ * The following defines match the ZRTP specification, chapter 5
+ */
+#define ZRTP_MAGIC 0x5a525450
+
+#define ZRTP_WORD_SIZE 4
+#define CRC_SIZE 4
+
+#define TYPE_SIZE (2*ZRTP_WORD_SIZE)
+#define CLIENT_ID_SIZE (4*ZRTP_WORD_SIZE)
+#define HASH_IMAGE_SIZE (8*ZRTP_WORD_SIZE)
+#define ZID_SIZE (3*ZRTP_WORD_SIZE)
+#define HVI_SIZE (8*ZRTP_WORD_SIZE)
+#define HMAC_SIZE (2*ZRTP_WORD_SIZE)
+#define ID_SIZE (2*ZRTP_WORD_SIZE)
+#define IV_SIZE (4*ZRTP_WORD_SIZE)
+#define PING_HASH_SIZE (2*ZRTP_WORD_SIZE)
+
+
+/**
+ * The ZRTP message header
+ *
+ * A complete ZRTP message always consists of the ZRTP header
+ * and a message specific part. This specific part may have a variable
+ * length. The length field includes the header.
+ */
+typedef struct zrtpPacketHeader {
+ uint16_t zrtpId; ///< Id to identify the message, always 0x505a
+ uint16_t length; ///< Length of the ZRTP message in words
+ uint8_t messageType[TYPE_SIZE]; ///< 2 word (8 octest) message type in ASCII
+} zrtpPacketHeader_t;
+
+/**
+ * Hello message, fixed part.
+ *
+ * The complete Hello message consists of ZRTP message header, Hello fixed
+ * part and a variable part. The Hello class initializes the variable part.
+ */
+typedef struct Hello {
+ uint8_t version[ZRTP_WORD_SIZE]; ///< Announces the ZRTP protocol version
+ uint8_t clientId[CLIENT_ID_SIZE]; ///< A 4 word ASCII identifier of the ZRTP client
+ uint8_t hashH3[HASH_IMAGE_SIZE]; ///< The last hash of the hash chain (chap. 9)
+ uint8_t zid[ZID_SIZE]; ///< ZID - 3 word identifier for the ZRTP endpoint
+ uint8_t flags; ///< flag bits (chap 7.2)
+ uint8_t lengths[3]; ///< number of algorithms present
+} Hello_t;
+
+/**
+ * The complete ZRTP Hello message.
+ */
+typedef struct HelloPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ Hello_t hello; ///< Fixed part of Hello message
+} HelloPacket_t;
+
+/**
+ * HelloAck message.
+ *
+ * The complete HelloAck message consists of ZRTP message header and
+ * the CRC which is the only HelloAck specific data.
+ */
+typedef struct HelloAckPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} HelloAckPacket_t;
+
+/**
+ * Commit message
+ *
+ * There are three subtypes of Commit messages, each of which
+ * has a fixed size. The data structure defines the maximum
+ * Commit message. During the ZRTP protocol the implementation
+ * uses fileds according to the use case (DH handshake,
+ * Multi-stream handshake) and adjusts the length.
+ */
+typedef struct Commit {
+ uint8_t hashH2[HASH_IMAGE_SIZE]; ///< The second hash of the hash chain (chap. 9)
+ uint8_t zid[ZID_SIZE]; ///< ZID - 3 word identifier for the ZRTP endpoint
+ uint8_t hash[ZRTP_WORD_SIZE]; ///< Commited hash algorithm
+ uint8_t cipher[ZRTP_WORD_SIZE]; ///< Commited symmetrical cipher algorithm
+ uint8_t authlengths[ZRTP_WORD_SIZE]; ///< Commited SRTP authentication algorithm
+ uint8_t pubkey[ZRTP_WORD_SIZE]; ///< Commited key agreement algorithm
+ uint8_t sas[ZRTP_WORD_SIZE]; ///< Commited SAS algorithm
+ uint8_t hvi[HVI_SIZE]; ///< Hash value Initiator - chap 4.4.1.1
+ uint8_t hmac[HMAC_SIZE]; ///< MAC of the Commit message
+} Commit_t;
+
+/**
+ * The complete ZRTP Commit message.
+ */
+typedef struct CommitPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ Commit_t commit; ///< Commit message
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} CommitPacket_t;
+
+/**
+ * DHPart1 and DHPart2 messages
+ *
+ * The DHPart messages have a variable length. The following struct
+ * defines the fixed part only. The DHPart class initializes the
+ * variable part.
+ */
+typedef struct DHPart {
+ uint8_t hashH1[HASH_IMAGE_SIZE]; ///< The first hash of the hash chain (chap. 9)
+ uint8_t rs1Id[ID_SIZE]; ///< Id of first retained secret
+ uint8_t rs2Id[ID_SIZE]; ///< Id of second retained secret
+ uint8_t auxSecretId[ID_SIZE]; ///< Id of additional (auxilliary) secret
+ uint8_t pbxSecretId[ID_SIZE]; ///< Id of PBX secret (chap 7.3.1)
+} DHPart_t;
+
+/**
+ * The complete ZRTP DHPart message.
+ */
+typedef struct DHPartPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ DHPart_t dhPart; ///< DHPart message fixed part
+} DHPartPacket_t;
+
+/**
+ * Confirm1 and Confirm2 messages
+ *
+ * The Confirm message have a variable length. The following struct
+ * defines the fixed part only. The Confirm class initializes the
+ * variable part.
+ *
+ * ZRTP encrypts a part of the Confirm messages, starting at @c hashH0
+ * and includes the variable part.
+ */
+typedef struct Confirm {
+ uint8_t hmac[HMAC_SIZE]; ///< MAC over the encrypted part of Commit message
+ uint8_t iv[IV_SIZE]; ///< IV for CFB mode to encrypt part of Commit
+ uint8_t hashH0[HASH_IMAGE_SIZE]; ///< starting hash of hash chain (chap. 9)
+ uint8_t filler[2]; ///< Filler bytes
+ uint8_t sigLength; ///< Length of an optional signature length (chap 7.2)
+ uint8_t flags; ///< various flags to control behaviour
+ uint32_t expTime; ///< Expiration time of retained secrets (chap 4.9)
+} Confirm_t;
+
+/**
+ * The complete ZRTP Confirm message.
+ */
+typedef struct ConfirmPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ Confirm_t confirm; ///< Confirm message fixed part
+} ConfirmPacket_t;
+
+/**
+ * Conf2Ack message.
+ *
+ * The complete Conf2Ack message consists of ZRTP message header and
+ * the CRC which is the only Conf2Ack specific data.
+ */
+typedef struct Conf2AckPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} Conf2AckPacket_t;
+
+/**
+ * The GoClear message is currently not used in
+ * GNU ZRTP C++ - not support for GoClear.
+ */
+typedef struct GoClear {
+ uint8_t clearHmac[HMAC_SIZE]; ///< no used
+} GoClear_t;
+
+/**
+ * The complete ZRTP GoClear message - no used.
+ */
+typedef struct GoClearPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ GoClear_t goClear; ///< not used
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} GoClearPacket_t;
+
+/**
+ * The ClearAck message is currently not used in
+ * GNU ZRTP C++ - not support for GoClear.
+ */
+typedef struct ClearAckPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} ClearAckPacket_t;
+
+/**
+ * The Error message
+ */
+typedef struct Error {
+ uint32_t errorCode; ///< Error code, see chap 5.9
+} Error_t;
+
+/**
+ * The complete ZRTP Error message.
+ */
+typedef struct ErrorPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ Error_t error; ///< Error message part
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} ErrorPacket_t;
+
+/**
+ * ErrorAck message.
+ *
+ * The complete ErrorAck message consists of ZRTP message header and
+ * the CRC which is the only ErrorAck specific data.
+ */
+typedef struct ErrorAckPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} ErrorAckPacket_t;
+
+/**
+ * Ping message.
+ *
+ * The Ping message has a fixed size.
+ */
+typedef struct Ping {
+ uint8_t version[ZRTP_WORD_SIZE]; ///< The ZRTP protocol version
+ uint8_t epHash[PING_HASH_SIZE]; ///< End point hash, see chap 5.16
+} Ping_t;
+
+/**
+ * The complete ZRTP Ping message.
+ */
+typedef struct PingPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ Ping_t ping; ///< Ping message part
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} PingPacket_t;
+
+/**
+ * PingAck message.
+ *
+ * The PingAck message has a fixed size.
+ */
+typedef struct PingAck {
+ uint8_t version[ZRTP_WORD_SIZE]; ///< The ZRTP protocol version
+ uint8_t localEpHash[PING_HASH_SIZE]; ///< Local end point hash, see chap 5.16
+ uint8_t remoteEpHash[PING_HASH_SIZE]; ///< Remote end point hash, see chap 5.16
+ uint32_t ssrc; ///< SSRC copied from the Ping message (RTP packet part)
+} PingAck_t;
+
+/**
+ * The complete ZRTP PingAck message.
+ */
+typedef struct PingAckPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ PingAck_t pingAck; ///< PingAck message part
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} PingAckPacket_t;
+
+/**
+ * SASrelay message
+ *
+ * The SASrelay message has a variable length. The following struct
+ * defines the fixed part only. The SASrelay class initializes the
+ * variable part.
+ *
+ * ZRTP encrypts a part of the SASrelay message, starting at @c hashH0
+ * and includes the variable part.
+ */
+typedef struct SASrelay {
+ uint8_t hmac[HMAC_SIZE]; ///< MAC over the encrypted part of Commit message
+ uint8_t iv[IV_SIZE]; ///< IV for CFB mode to encrypt part of Commit
+ uint8_t filler[2]; ///< Filler bytes
+ uint8_t sigLength; ///< Length of an optional signature length (chap 7.2)
+ uint8_t flags; ///< various flags to control behaviour
+ uint8_t sas[ZRTP_WORD_SIZE]; ///< SAS algorithm to use
+ uint8_t trustedSasHash[HASH_IMAGE_SIZE]; ///< New trusted SAS hash for enrolled client
+} SASrelay_t;
+
+/**
+ * The complete ZRTP SASrelay message.
+ */
+typedef struct SASrelayPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ SASrelay_t sasrelay; ///< SASrelay message fixed part
+} SASrelayPacket_t;
+
+/**
+ * RelayAck message.
+ *
+ * The complete RelayAck message consists of ZRTP message header and
+ * the CRC which is the only RelayAck specific data.
+ */
+typedef struct RelayAckPacket {
+ zrtpPacketHeader_t hdr; ///< ZRTP Header
+ uint8_t crc[ZRTP_WORD_SIZE]; ///< CRC of ZRTP message
+} RelayAckPacket_t;
+
+#endif // ZRTPPACKET_H
+
+/**
+ * @}
+ */
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/src/libzrtpcpp/zrtpccrtp.h b/src/libzrtpcpp/zrtpccrtp.h
new file mode 100644
index 0000000..d94ca5a
--- /dev/null
+++ b/src/libzrtpcpp/zrtpccrtp.h
@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2006-2007 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ZRTPCCRTP_H_
+#define _ZRTPCCRTP_H_
+
+#include <ccrtp/rtp.h>
+#include <libzrtpcpp/ZrtpQueue.h>
+
+NAMESPACE_COMMONCPP
+
+// Define a dummy variable only to overcome a doxygen problem.
+static int dummy __attribute__ ((unused)) = 0;
+
+
+/**
+ * @typedef SymmetricZRTPSession
+ *
+ * Uses one pair of sockets, (1) for RTP data and (2) for RTCP
+ * transmission/reception.
+ *
+ * This session uses the ZrtpQueue instead of the AVPQueue. The ZrtpQueue
+ * inherits from AVPQueue and adds support for ZRTP thus enabling
+ * ad-hoc key negotiation to setup SRTP sessions.
+ *
+ * @short Symmetric UDP/IPv4 RTP session scheduled by one thread of execution.
+ **/
+typedef SingleThreadRTPSession<SymmetricRTPChannel,
+ SymmetricRTPChannel,
+ ZrtpQueue> SymmetricZRTPSession;
+
+
+#ifdef CCXX_IPV6
+/**
+ * @typedef SymmetricZRTPSession
+ *
+ * Uses one pair of sockets, (1) for RTP data and (2) for RTCP
+ * transmission/reception.
+ *
+ * This session uses the ZrtpQueue instead of the AVPQueue. The ZrtpQueue
+ * inherits from AVPQueue and adds support for ZRTP thus enabling
+ * ad-hoc key negotiation to setup SRTP sessions.
+ *
+ * @short Symmetric UDP/IPv6 RTP session scheduled by one thread of execution.
+ **/
+typedef SingleThreadRTPSessionIPV6<SymmetricRTPChannelIPV6,
+ SymmetricRTPChannelIPV6,
+ ZrtpQueue> SymmetricZRTPSessionIPV6;
+#endif // CCXX_IPV6
+
+END_NAMESPACE
+
+#endif // _ZRTPCCRTP_H_
+
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */