summaryrefslogtreecommitdiff
path: root/demo
diff options
context:
space:
mode:
Diffstat (limited to 'demo')
-rwxr-xr-xdemo/CMakeLists.txt19
-rw-r--r--demo/README27
-rw-r--r--demo/wrappertest.c169
-rw-r--r--demo/zrtptest.cpp665
-rw-r--r--demo/zrtptestMulti.cpp715
5 files changed, 1595 insertions, 0 deletions
diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt
new file mode 100755
index 0000000..015807c
--- /dev/null
+++ b/demo/CMakeLists.txt
@@ -0,0 +1,19 @@
+########### next target ###############
+
+add_executable(zrtptest zrtptest.cpp)
+target_link_libraries(zrtptest zrtpcpp ccrtp commoncpp)
+add_dependencies(zrtptest zrtpcpp)
+
+########### next target ###############
+
+add_executable(zrtptestMulti zrtptestMulti.cpp)
+target_link_libraries(zrtptestMulti zrtpcpp ccrtp commoncpp)
+add_dependencies(zrtptestMulti zrtpcpp)
+
+########### next target ###############
+
+#add_executable(wrappertest wrappertest.c)
+#target_link_libraries(wrappertest zrtpcpp)
+
+########### install files ###############
+# None
diff --git a/demo/README b/demo/README
new file mode 100644
index 0000000..42ecf8b
--- /dev/null
+++ b/demo/README
@@ -0,0 +1,27 @@
+
+This directory includes example programs intended for testing
+and illustrating features of ccRTP and the ZRTP extension.
+
+Before using these programs make sure that ccRTP is up and
+working correctly.
+
+* zrtptest: is similar to ccrtptest in ccRTP demo directory. This
+ program shows how to use the class SymmetricZRTPSession instead
+ of RTPSession.
+
+ The first test shows that SymmetricZRTPSession is compatible to
+ RTPSession if it is used without specific initialization or configuration.
+
+ The second test initializes the ZRTP engine and starts it just before
+ sending or receiving RTP data. The enable ZRTP the test sets RTP in
+ bi-directional mode. This is the main difference to the first test case.
+
+ The third test shows how to use an application supplied callback class
+ to control message printout, switching to secure mode, displaying
+ the Short Authentication String (SAS).
+
+To start the demo application you may open two shell (command) windows
+and start "zrtptest -r" in one window first, then start "zrtptest -s"
+in the second window. The application use the port numbers 10002 thruogh
+10004 on localhost to communicate.
+
diff --git a/demo/wrappertest.c b/demo/wrappertest.c
new file mode 100644
index 0000000..abbb3cf
--- /dev/null
+++ b/demo/wrappertest.c
@@ -0,0 +1,169 @@
+/*
+ This class maps the ZRTP C calls to ZRTP C++ methods.
+ Copyright (C) 2010 Werner Dittmann
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <libzrtpcpp/ZrtpCWrapper.h>
+
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Forward declaration of thethe ZRTP specific callback functions that this
+ adapter must implement */
+static int32_t zrtp_sendDataZRTP (ZrtpContext* ctx, const uint8_t* data, int32_t length ) ;
+static int32_t zrtp_activateTimer (ZrtpContext* ctx, int32_t time ) ;
+static int32_t zrtp_cancelTimer(ZrtpContext* ctx) ;
+static void zrtp_sendInfo (ZrtpContext* ctx, int32_t severity, int32_t subCode ) ;
+static int32_t zrtp_srtpSecretsReady (ZrtpContext* ctx, C_SrtpSecret_t* secrets, int32_t part ) ;
+static void zrtp_srtpSecretsOff (ZrtpContext* ctx, int32_t part ) ;
+static void zrtp_rtpSecretsOn (ZrtpContext* ctx, char* c, char* s, int32_t verified ) ;
+static void zrtp_handleGoClear(ZrtpContext* ctx) ;
+static void zrtp_zrtpNegotiationFailed(ZrtpContext* ctx, int32_t severity, int32_t subCode ) ;
+static void zrtp_zrtpNotSuppOther(ZrtpContext* ctx) ;
+static void zrtp_synchEnter(ZrtpContext* ctx) ;
+static void zrtp_synchLeave(ZrtpContext* ctx) ;
+static void zrtp_zrtpAskEnrollment (ZrtpContext* ctx, char* info ) ;
+static void zrtp_zrtpInformEnrollment(ZrtpContext* ctx, char* info ) ;
+static void zrtp_signSAS(ZrtpContext* ctx, char* sas) ;
+static int32_t zrtp_checkSASSignature (ZrtpContext* ctx, char* sas ) ;
+
+/* The callback function structure for ZRTP */
+static zrtp_Callbacks c_callbacks = {
+ &zrtp_sendDataZRTP,
+ &zrtp_activateTimer,
+ &zrtp_cancelTimer,
+ &zrtp_sendInfo,
+ &zrtp_srtpSecretsReady,
+ &zrtp_srtpSecretsOff,
+ &zrtp_rtpSecretsOn,
+ &zrtp_handleGoClear,
+ &zrtp_zrtpNegotiationFailed,
+ &zrtp_zrtpNotSuppOther,
+ &zrtp_synchEnter,
+ &zrtp_synchLeave,
+ &zrtp_zrtpAskEnrollment,
+ &zrtp_zrtpInformEnrollment,
+ &zrtp_signSAS,
+ &zrtp_checkSASSignature
+};
+
+/*
+ * Here start with callback functions that support the ZRTP core
+ */
+static int32_t zrtp_sendDataZRTP (ZrtpContext* ctx, const uint8_t* data, int32_t length )
+{
+ return 0;
+}
+
+static int32_t zrtp_activateTimer (ZrtpContext* ctx, int32_t time)
+{
+ return 0;
+}
+
+static int32_t zrtp_cancelTimer(ZrtpContext* ctx)
+{
+ return 0;
+}
+
+static void zrtp_sendInfo (ZrtpContext* ctx, int32_t severity, int32_t subCode )
+{
+}
+
+static int32_t zrtp_srtpSecretsReady (ZrtpContext* ctx, C_SrtpSecret_t* secrets, int32_t part )
+{
+ return 0;
+}
+
+static void zrtp_srtpSecretsOff (ZrtpContext* ctx, int32_t part )
+{
+}
+
+static void zrtp_rtpSecretsOn (ZrtpContext* ctx, char* c, char* s, int32_t verified )
+{
+}
+
+static void zrtp_handleGoClear(ZrtpContext* ctx)
+{
+}
+
+static void zrtp_zrtpNegotiationFailed (ZrtpContext* ctx, int32_t severity, int32_t subCode )
+{
+}
+
+static void zrtp_zrtpNotSuppOther(ZrtpContext* ctx)
+{
+}
+
+static void zrtp_synchEnter(ZrtpContext* ctx)
+{
+}
+
+static void zrtp_synchLeave(ZrtpContext* ctx)
+{
+}
+
+static void zrtp_zrtpAskEnrollment(ZrtpContext* ctx, char* info )
+{
+
+}
+static void zrtp_zrtpInformEnrollment(ZrtpContext* ctx, char* info )
+{
+}
+
+static void zrtp_signSAS(ZrtpContext* ctx, char* sas)
+{
+}
+
+static int32_t zrtp_checkSASSignature(ZrtpContext* ctx, char* sas )
+{
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ ZrtpContext* zrtpCtx;
+ char* hh;
+ char** names;
+
+ zrtpCtx = zrtp_CreateWrapper ();
+ zrtp_initializeZrtpEngine(zrtpCtx, &c_callbacks, "test", "test.zid", NULL);
+
+ hh = zrtp_getHelloHash(zrtpCtx);
+ if (hh != 0)
+ {
+ printf("hh: %s\n", hh);
+ }
+ else
+ printf("no hh");
+
+ zrtp_InitializeConfig(zrtpCtx);
+ names = zrtp_getAlgorithmNames(zrtpCtx, zrtp_HashAlgorithm);
+
+ for (; *names; names++) {
+ printf("name: %s\n", *names);
+ }
+
+ return 0;
+}
+#ifdef __cplusplus
+}
+#endif
diff --git a/demo/zrtptest.cpp b/demo/zrtptest.cpp
new file mode 100644
index 0000000..394d31c
--- /dev/null
+++ b/demo/zrtptest.cpp
@@ -0,0 +1,665 @@
+// Test ZRTP extension for ccRTP
+//
+// Copyright (C) 2008 Werner Dittmann <Werner.Dittmann@t-online.de>
+//
+// 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#include <cstdlib>
+#include <map>
+#include <libzrtpcpp/zrtpccrtp.h>
+#include <libzrtpcpp/ZrtpUserCallback.h>
+
+using namespace ost;
+using namespace std;
+using namespace GnuZrtpCodes;
+
+class PacketsPattern
+{
+public:
+ inline const InetHostAddress&
+ getDestinationAddress() const
+ { return destinationAddress; }
+
+ inline const tpport_t
+ getDestinationPort() const
+ { return destinationPort; }
+
+ uint32
+ getPacketsNumber() const
+ { return packetsNumber; }
+
+ uint32
+ getSsrc() const
+ { return 0xdeadbeef; }
+
+ const unsigned char*
+ getPacketData(uint32 i)
+ { return data[i%2]; }
+
+ const size_t
+ getPacketSize(uint32 i)
+ { return strlen((char*)data[i%2]) + 1 ; }
+
+private:
+ static const InetHostAddress destinationAddress;
+ static const uint16 destinationPort = 5002;
+ static const uint32 packetsNumber = 10;
+ static const uint32 packetsSize = 12;
+ static const unsigned char* data[];
+};
+
+const InetHostAddress PacketsPattern::destinationAddress =
+ InetHostAddress("localhost");
+
+const unsigned char* PacketsPattern::data[] = {
+ (unsigned char*)"0123456789\n",
+ (unsigned char*)"987654321\n"
+};
+
+PacketsPattern pattern;
+
+class ExtZrtpSession : public SymmetricZRTPSession {
+// ExtZrtpSession(InetMcastAddress& ima, tpport_t port) :
+// RTPSession(ima,port) {}
+//
+// ExtZrtpSession(InetHostAddress& ia, tpport_t port) :
+// RTPSession(ia,port) {}
+
+public:
+ ExtZrtpSession(uint32 ssrc, const InetHostAddress& ia) :
+ SingleThreadRTPSession(ssrc, ia){
+ cout << "Extended" << endl;
+ }
+
+ ExtZrtpSession(uint32 ssrc, const InetHostAddress& ia, tpport_t dataPort) :
+ SingleThreadRTPSession(ssrc, ia, dataPort) {
+ cout << "Extended" << endl;
+ }
+
+ ExtZrtpSession(const InetHostAddress& ia, tpport_t dataPort) :
+ SingleThreadRTPSession(ia, dataPort) {
+ cout << "Extended" << endl;
+ }
+
+ void onGotGoodbye(const SyncSource& source, const std::string& reason)
+ {
+ cout << "I got a Goodbye packet from "
+ << hex << (int)source.getID() << "@"
+ << dec
+ << source.getNetworkAddress() << ":"
+ << source.getControlTransportPort() << endl;
+ cout << " Goodbye reason: \"" << reason << "\"" << endl;
+ }
+ // redefined from QueueRTCPManager
+ void onGotRR(SyncSource& source, RecvReport& RR, uint8 blocks)
+ {
+ SingleThreadRTPSession::onGotRR(source,RR,blocks);
+ cout << "I got an RR RTCP report from "
+ << hex << (int)source.getID() << "@"
+ << dec
+ << source.getNetworkAddress() << ":"
+ << source.getControlTransportPort() << endl;
+ }
+};
+
+
+/**
+ * SymmetricZRTPSession in non-security mode (RTPSession compatible).
+ *
+ * The next two classes show how to use <code>SymmetricZRTPSession</code>
+ * in the same way as <code>RTPSession</code>. This is straightforward,
+ * just don't do any configuration or initialization.
+ */
+class SendPacketTransmissionTest: public Thread, public TimerPort {
+public:
+ void
+ run() {
+ doTest();
+ }
+
+ int doTest() {
+ // should be valid?
+ //RTPSession tx();
+ ExtZrtpSession tx(pattern.getSsrc(), InetHostAddress("localhost"));
+// SymmetricZRTPSession tx(pattern.getSsrc(), InetHostAddress("localhost"));
+ tx.setSchedulingTimeout(10000);
+ tx.setExpireTimeout(1000000);
+
+ tx.startRunning();
+
+ tx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
+ if (!tx.addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()) ) {
+ return 1;
+ }
+
+ // 2 packets per second (packet duration of 500ms)
+ uint32 period = 500;
+ uint16 inc = tx.getCurrentRTPClockRate()/2;
+ TimerPort::setTimer(period);
+ uint32 i;
+ for (i = 0; i < pattern.getPacketsNumber(); i++ ) {
+ tx.putData(i*inc,
+ pattern.getPacketData(i),
+ pattern.getPacketSize(i));
+ cout << "Sent some data: " << i << endl;
+ Thread::sleep(TimerPort::getTimer());
+ TimerPort::incTimer(period);
+ }
+ tx.putData(i*inc, (unsigned char*)"exit", 5);
+ Thread::sleep(TimerPort::getTimer());
+ return 0;
+ }
+};
+
+
+class RecvPacketTransmissionTest: public Thread {
+public:
+ void
+ run() {
+ doTest();
+ }
+
+ int
+ doTest() {
+ ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(),
+ pattern.getDestinationPort());
+
+// SymmetricZRTPSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(),
+// pattern.getDestinationPort());
+ rx.setSchedulingTimeout(10000);
+ rx.setExpireTimeout(1000000);
+
+ rx.startRunning();
+ rx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
+ // arbitrary number of loops to provide time to start transmitter
+ if (!rx.addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2) ) {
+ return 1;
+ }
+ for ( int i = 0; i < 5000 ; i++ ) {
+ const AppDataUnit* adu;
+ while ( (adu = rx.getData(rx.getFirstTimestamp())) ) {
+ cerr << "got some data: " << adu->getData() << endl;
+ if (*adu->getData() == 'e') {
+ delete adu;
+ return 0;
+ }
+ delete adu;
+ }
+ Thread::sleep(70);
+ }
+ return 0;
+ }
+};
+
+
+/**
+ * SymmetricZRTPSession in security mode.
+ *
+ * The next two classes show how to use <code>SymmetricZRTPSession</code>
+ * using the standard ZRTP handshake an switching to encrypted (SRTP) mode.
+ * The application enables this by calling <code>initialize(...)</code>.
+ * Some embedded logging informs about the ZRTP processing.
+ */
+
+class ZrtpSendPacketTransmissionTest: public Thread, public TimerPort {
+public:
+ void
+ run() {
+ doTest();
+ }
+
+ int doTest() {
+ // should be valid?
+ //RTPSession tx();
+ ExtZrtpSession tx(pattern.getSsrc(), pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2);
+ tx.initialize("test_t.zid");
+
+ tx.setSchedulingTimeout(10000);
+ tx.setExpireTimeout(1000000);
+
+ tx.startRunning();
+
+ tx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
+ if (!tx.addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()) ) {
+ return 1;
+ }
+ tx.startZrtp();
+ // 2 packets per second (packet duration of 500ms)
+ uint32 period = 500;
+ uint16 inc = tx.getCurrentRTPClockRate()/2;
+ TimerPort::setTimer(period);
+ uint32 i;
+ for (i = 0; i < pattern.getPacketsNumber(); i++ ) {
+ tx.putData(i*inc,
+ pattern.getPacketData(i),
+ pattern.getPacketSize(i));
+ cout << "Sent some data: " << i << endl;
+ Thread::sleep(TimerPort::getTimer());
+ TimerPort::incTimer(period);
+ }
+ tx.putData(i*inc, (unsigned char*)"exit", 5);
+ Thread::sleep(200);
+ return 0;
+ }
+};
+
+class ZrtpRecvPacketTransmissionTest: public Thread {
+public:
+ void
+ run() {
+ doTest();
+ }
+
+ int
+ doTest() {
+ ExtZrtpSession rx(pattern.getSsrc()+1, pattern.getDestinationAddress(),
+ pattern.getDestinationPort());
+
+ rx.initialize("test_r.zid");
+
+ rx.setSchedulingTimeout(10000);
+ rx.setExpireTimeout(1000000);
+
+ rx.startRunning();
+ rx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
+ // arbitrary number of loops to provide time to start transmitter
+ if (!rx.addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2) ) {
+ return 1;
+ }
+ rx.startZrtp();
+ for ( int i = 0; i < 5000 ; i++ ) {
+ const AppDataUnit* adu;
+ while ( (adu = rx.getData(rx.getFirstTimestamp())) ) {
+ cerr << "got some data: " << adu->getData() << endl;
+ if (*adu->getData() == 'e') {
+ delete adu;
+ return 0;
+ }
+ delete adu;
+ }
+ Thread::sleep(70);
+ }
+ return 0;
+ }
+};
+
+/**
+ * Simple User Callback class
+ *
+ * This class overwrite some methods from ZrtpUserCallback to get information
+ * about ZRTP processing and information about ZRTP results. The standard
+ * implementation of this class just perform return, thus effectively
+ * supressing any callback or trigger.
+ */
+class MyUserCallback: public ZrtpUserCallback {
+
+ static map<int32, std::string*> infoMap;
+ static map<int32, std::string*> warningMap;
+ static map<int32, std::string*> severeMap;
+ static map<int32, std::string*> zrtpMap;
+
+ static bool initialized;
+
+ SymmetricZRTPSession* session;
+ public:
+ MyUserCallback(SymmetricZRTPSession* s) {
+ session = s;
+ if (initialized) {
+ return;
+ }
+ infoMap.insert(pair<int32, std::string*>(InfoHelloReceived, new string("Hello received, preparing a Commit")));
+ infoMap.insert(pair<int32, std::string*>(InfoCommitDHGenerated, new string("Commit: Generated a public DH key")));
+ infoMap.insert(pair<int32, std::string*>(InfoRespCommitReceived, new string("Responder: Commit received, preparing DHPart1")));
+ infoMap.insert(pair<int32, std::string*>(InfoDH1DHGenerated, new string("DH1Part: Generated a public DH key")));
+ infoMap.insert(pair<int32, std::string*>(InfoInitDH1Received, new string("Initiator: DHPart1 received, preparing DHPart2")));
+ infoMap.insert(pair<int32, std::string*>(InfoRespDH2Received, new string("Responder: DHPart2 received, preparing Confirm1")));
+ infoMap.insert(pair<int32, std::string*>(InfoInitConf1Received, new string("Initiator: Confirm1 received, preparing Confirm2")));
+ infoMap.insert(pair<int32, std::string*>(InfoRespConf2Received, new string("Responder: Confirm2 received, preparing Conf2Ack")));
+ infoMap.insert(pair<int32, std::string*>(InfoRSMatchFound, new string("At least one retained secrets matches - security OK")));
+ infoMap.insert(pair<int32, std::string*>(InfoSecureStateOn, new string("Entered secure state")));
+ infoMap.insert(pair<int32, std::string*>(InfoSecureStateOff, new string("No more security for this session")));
+
+ warningMap.insert(pair<int32, std::string*>(WarningDHAESmismatch,
+ new string("Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096")));
+ warningMap.insert(pair<int32, std::string*>(WarningGoClearReceived, new string("Received a GoClear message")));
+ warningMap.insert(pair<int32, std::string*>(WarningDHShort,
+ new string("Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096")));
+ warningMap.insert(pair<int32, std::string*>(WarningNoRSMatch, new string("No retained secret matches - verify SAS")));
+ warningMap.insert(pair<int32, std::string*>(WarningCRCmismatch, new string("Internal ZRTP packet checksum mismatch - packet dropped")));
+ warningMap.insert(pair<int32, std::string*>(WarningSRTPauthError, new string("Dropping packet because SRTP authentication failed!")));
+ warningMap.insert(pair<int32, std::string*>(WarningSRTPreplayError, new string("Dropping packet because SRTP replay check failed!")));
+
+ severeMap.insert(pair<int32, std::string*>(SevereHelloHMACFailed, new string("Hash HMAC check of Hello failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereCommitHMACFailed, new string("Hash HMAC check of Commit failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereDH1HMACFailed, new string("Hash HMAC check of DHPart1 failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereDH2HMACFailed, new string("Hash HMAC check of DHPart2 failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereCannotSend, new string("Cannot send data - connection or peer down?")));
+ severeMap.insert(pair<int32, std::string*>(SevereProtocolError, new string("Internal protocol error occured!")));
+ severeMap.insert(pair<int32, std::string*>(SevereNoTimer, new string("Cannot start a timer - internal resources exhausted?")));
+ severeMap.insert(pair<int32, std::string*>(SevereTooMuchRetries,
+ new string("Too much retries during ZRTP negotiation - connection or peer down?")));
+
+ zrtpMap.insert(pair<int32, std::string*>(MalformedPacket, new string("Malformed packet (CRC OK, but wrong structure)")));
+ zrtpMap.insert(pair<int32, std::string*>(CriticalSWError, new string("Critical software error")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppZRTPVersion, new string("Unsupported ZRTP version")));
+ zrtpMap.insert(pair<int32, std::string*>(HelloCompMismatch, new string("Hello components mismatch")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppHashType, new string("Hash type not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppCiphertype, new string("Cipher type not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppPKExchange, new string("Public key exchange not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppSRTPAuthTag, new string("SRTP auth. tag not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppSASScheme, new string("SAS scheme not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(NoSharedSecret, new string("No shared secret available, DH mode required")));
+ zrtpMap.insert(pair<int32, std::string*>(DHErrorWrongPV, new string("DH Error: bad pvi or pvr ( == 1, 0, or p-1)")));
+ zrtpMap.insert(pair<int32, std::string*>(DHErrorWrongHVI, new string("DH Error: hvi != hashed data")));
+ zrtpMap.insert(pair<int32, std::string*>(SASuntrustedMiTM, new string("Received relayed SAS from untrusted MiTM")));
+ zrtpMap.insert(pair<int32, std::string*>(ConfirmHMACWrong, new string("Auth. Error: Bad Confirm pkt HMAC")));
+ zrtpMap.insert(pair<int32, std::string*>(NonceReused, new string("Nonce reuse")));
+ zrtpMap.insert(pair<int32, std::string*>(EqualZIDHello, new string("Equal ZIDs in Hello")));
+ zrtpMap.insert(pair<int32, std::string*>(GoCleatNotAllowed, new string("GoClear packet received, but not allowed")));
+
+ initialized = true;
+ }
+
+ void showMessage(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) {
+ string* msg;
+ if (sev == Info) {
+ msg = infoMap[subCode];
+ if (msg != NULL) {
+ cout << *msg << endl;
+ }
+ }
+ if (sev == Warning) {
+ msg = warningMap[subCode];
+ if (msg != NULL) {
+ cout << *msg << endl;
+ }
+ }
+ if (sev == Severe) {
+ msg = severeMap[subCode];
+ if (msg != NULL) {
+ cout << *msg << endl;
+ }
+ }
+ if (sev == ZrtpError) {
+ if (subCode < 0) { // received an error packet from peer
+ subCode *= -1;
+ cout << "Received error packet: ";
+ }
+ else {
+ cout << "Sent error packet: ";
+ }
+ msg = zrtpMap[subCode];
+ if (msg != NULL) {
+ cout << *msg << endl;
+ }
+ }
+ }
+
+ void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) {
+ string* msg;
+ if (sev == ZrtpError) {
+ if (subCode < 0) { // received an error packet from peer
+ subCode *= -1;
+ cout << "Received error packet: ";
+ }
+ else {
+ cout << "Sent error packet: ";
+ }
+ msg = zrtpMap[subCode];
+ if (msg != NULL) {
+ cout << *msg << endl;
+ }
+ }
+ else {
+ msg = severeMap[subCode];
+ cout << *msg << endl;
+ }
+ }
+
+ void secureOn(std::string cipher) {
+ cout << "Using cipher:" << cipher << endl;
+ }
+
+ void showSAS(std::string sas, bool verified) {
+ cout << "SAS is: " << sas << endl;
+
+ }
+};
+
+map<int32, std::string*>MyUserCallback::infoMap;
+map<int32, std::string*>MyUserCallback::warningMap;
+map<int32, std::string*>MyUserCallback::severeMap;
+map<int32, std::string*>MyUserCallback::zrtpMap;
+
+bool MyUserCallback::initialized = false;
+
+/**
+ * SymmetricZRTPSession in security mode and using a callback class.
+ *
+ * The next two classes show how to use <code>SymmetricZRTPSession</code>
+ * using the standard ZRTP handshake an switching to encrypted (SRTP) mode.
+ * The application enables this by calling <code>initialize(...)</code>.
+ * In addition the application sets a callback class (see above). ZRTP calls
+ * the methods of the callback class and the application may implement
+ * appropriate methods to deal with these triggers.
+ */
+
+class
+ZrtpSendPacketTransmissionTestCB : public Thread, public TimerPort
+{
+public:
+ void
+ run()
+ {
+ doTest();
+ }
+
+ int doTest()
+ {
+ // should be valid?
+ //RTPSession tx();
+ ExtZrtpSession tx(/*pattern.getSsrc(),*/ pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2);
+ tx.initialize("test_t.zid");
+ // At this point the Hello hash is available. See ZRTP specification
+ // chapter 9.1 for further information when an how to use the Hello
+ // hash.
+ cout << "TX Hello hash: " << tx.getHelloHash() << endl;
+ cout << "TX Hello hash length: " << tx.getHelloHash().length() << endl;
+
+ tx.setUserCallback(new MyUserCallback(&tx));
+
+ tx.setSchedulingTimeout(10000);
+ tx.setExpireTimeout(1000000);
+
+ tx.startRunning();
+
+ tx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
+ if (!tx.addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()) ) {
+ return 1;
+ }
+ tx.startZrtp();
+
+ // 2 packets per second (packet duration of 500ms)
+ uint32 period = 500;
+ uint16 inc = tx.getCurrentRTPClockRate()/2;
+ TimerPort::setTimer(period);
+ uint32 i;
+ for (i = 0; i < pattern.getPacketsNumber(); i++ ) {
+ tx.putData(i*inc,
+ pattern.getPacketData(i),
+ pattern.getPacketSize(i));
+ cout << "Sent some data: " << i << endl;
+ Thread::sleep(TimerPort::getTimer());
+ TimerPort::incTimer(period);
+ }
+ tx.putData(i*inc, (unsigned char*)"exit", 5);
+ Thread::sleep(TimerPort::getTimer());
+ return 0;
+ }
+};
+
+
+class
+ZrtpRecvPacketTransmissionTestCB: public Thread
+{
+public:
+ void
+ run() {
+ doTest();
+ }
+
+ int
+ doTest() {
+ ExtZrtpSession rx( /*pattern.getSsrc()+1,*/ pattern.getDestinationAddress(),
+ pattern.getDestinationPort());
+
+ rx.initialize("test_r.zid");
+ // At this point the Hello hash is available. See ZRTP specification
+ // chapter 9.1 for further information when an how to use the Hello
+ // hash.
+ cout << "RX Hello hash: " << rx.getHelloHash() << endl;
+ cout << "RX Hello hash length: " << rx.getHelloHash().length() << endl;
+
+ rx.setUserCallback(new MyUserCallback(&rx));
+
+ rx.setSchedulingTimeout(10000);
+ rx.setExpireTimeout(1000000);
+
+ rx.startRunning();
+ rx.setPayloadFormat(StaticPayloadFormat(sptPCMU));
+ // arbitrary number of loops to provide time to start transmitter
+ if (!rx.addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2) ) {
+ return 1;
+ }
+ rx.startZrtp();
+
+ for ( int i = 0; i < 5000 ; i++ ) {
+ const AppDataUnit* adu;
+ while ( (adu = rx.getData(rx.getFirstTimestamp())) ) {
+ cerr << "got some data: " << adu->getData() << endl;
+ if (*adu->getData() == 'e') {
+ delete adu;
+ return 0;
+ }
+ delete adu;
+ }
+ Thread::sleep(500);
+ }
+ return 0;
+ }
+};
+
+
+int main(int argc, char *argv[])
+{
+ int result = 0;
+ bool send = false;
+ bool recv = false;
+
+ char c;
+
+ /* check args */
+ while (1) {
+ c = getopt(argc, argv, "rs");
+ if (c == -1) {
+ break;
+ }
+ switch (c) {
+ case 'r':
+ recv = true;
+ break;
+ case 's':
+ send = true;
+ break;
+ default:
+ cerr << "Wrong Arguments, only -s and -r are accepted" << endl;
+ }
+ }
+
+ if (send || recv) {
+ if (send) {
+ cout << "Running as sender" << endl;
+ }
+ else {
+ cout << "Running as receiver" << endl;
+ }
+ }
+ else {
+ cerr << "No send or receive argument specificied" << endl;
+ exit(1);
+ }
+
+ // accept as parameter if must run as --send or --recv
+
+#if 0
+ RecvPacketTransmissionTest *rx;
+ SendPacketTransmissionTest *tx;
+
+ // run several tests in parallel threads
+ if ( send ) {
+ tx = new SendPacketTransmissionTest();
+ tx->start();
+ tx->join();
+ } else if ( recv ) {
+ rx = new RecvPacketTransmissionTest();
+ rx->start();
+ rx->join();
+ }
+//#endif
+//#if 0
+ ZrtpRecvPacketTransmissionTest *zrx;
+ ZrtpSendPacketTransmissionTest *ztx;
+
+ if ( send ) {
+ ztx = new ZrtpSendPacketTransmissionTest();
+ ztx->start();
+ ztx->join();
+ } else if ( recv ) {
+ zrx = new ZrtpRecvPacketTransmissionTest();
+ zrx->start();
+ zrx->join();
+ }
+#endif
+ ZrtpRecvPacketTransmissionTestCB *zrxcb;
+ ZrtpSendPacketTransmissionTestCB *ztxcb;
+
+ if ( send ) {
+ ztxcb = new ZrtpSendPacketTransmissionTestCB();
+ ztxcb->start();
+ ztxcb->join();
+ } else if ( recv ) {
+ zrxcb = new ZrtpRecvPacketTransmissionTestCB();
+ zrxcb->start();
+ zrxcb->join();
+ }
+
+ exit(result);
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/demo/zrtptestMulti.cpp b/demo/zrtptestMulti.cpp
new file mode 100644
index 0000000..39e20a7
--- /dev/null
+++ b/demo/zrtptestMulti.cpp
@@ -0,0 +1,715 @@
+// Test ZRTP extension for ccRTP
+//
+// Copyright (C) 2008 Werner Dittmann <Werner.Dittmann@t-online.de>
+//
+// 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#include <cstdlib>
+#include <map>
+#include <libzrtpcpp/zrtpccrtp.h>
+#include <libzrtpcpp/ZrtpUserCallback.h>
+#include <libzrtpcpp/ZrtpConfigure.h>
+
+using namespace ost;
+using namespace std;
+using namespace GnuZrtpCodes;
+
+/* maybe should be by special define...
+static void hexdump(const char* title, const unsigned char *s, int l) {
+ int n=0;
+
+ if (s == NULL) return;
+
+ fprintf(stderr, "%s",title);
+ for( ; n < l ; ++n)
+ {
+ if((n%16) == 0)
+ fprintf(stderr, "\n%04x",n);
+ fprintf(stderr, " %02x",s[n]);
+ }
+ fprintf(stderr, "\n");
+}
+*/
+
+class PacketsPattern
+{
+public:
+ inline const InetHostAddress&
+ getDestinationAddress() const
+ {
+ return destinationAddress;
+ }
+
+ inline const tpport_t
+ getDestinationPort() const
+ {
+ return destinationPort;
+ }
+
+ uint32
+ getPacketsNumber() const
+ {
+ return packetsNumber;
+ }
+
+ uint32
+ getSsrc() const
+ {
+ return 0xdeadbeef;
+ }
+
+ const unsigned char*
+ getPacketData(uint32 i)
+ {
+ return data[i%2];
+ }
+
+ const size_t
+ getPacketSize(uint32 i)
+ {
+ return strlen((char*)data[i%2]) + 1 ;
+ }
+
+private:
+ static const InetHostAddress destinationAddress;
+ static const uint16 destinationPort = 5002;
+ static const uint32 packetsNumber = 10;
+ static const uint32 packetsSize = 12;
+ static const unsigned char* data[];
+};
+
+const InetHostAddress PacketsPattern::destinationAddress =
+ InetHostAddress("localhost");
+
+const unsigned char* PacketsPattern::data[] = {
+ (unsigned char*)"0123456789\n",
+ (unsigned char*)"987654321\n"
+};
+
+PacketsPattern pattern;
+
+class ZrtpRecvPacketTransmissionTestCB;
+class ZrtpSendPacketTransmissionTestCB;
+class MyUserCallback;
+class MyUserCallbackMulti;
+
+static ZrtpRecvPacketTransmissionTestCB* zrxcb = NULL;
+static ZrtpSendPacketTransmissionTestCB* ztxcb = NULL;
+
+static ZrtpRecvPacketTransmissionTestCB* zrxcbMulti = NULL;
+static ZrtpSendPacketTransmissionTestCB* ztxcbMulti = NULL;
+
+static bool enroll = false;
+static bool mitm = false;
+static bool untrusted = false;
+static bool sender = false;
+static bool recver = false;
+static bool signsas = false;
+
+
+/**
+ * SymmetricZRTPSession in security mode and using a callback class.
+ *
+ * The next two classes show how to use <code>SymmetricZRTPSession</code>
+ * using the standard ZRTP handshake an switching to encrypted (SRTP) mode.
+ * The application enables this by calling <code>initialize(...)</code>.
+ * In addition the application sets a callback class (see above). ZRTP calls
+ * the methods of the callback class and the application may implement
+ * appropriate methods to deal with these triggers.
+ */
+
+class
+ ZrtpSendPacketTransmissionTestCB : public Thread, public TimerPort {
+
+private:
+ SymmetricZRTPSession* tx;
+ string multiParams;
+ string prefix;
+
+public:
+
+ ZrtpSendPacketTransmissionTestCB(): tx(NULL), multiParams("") {};
+
+ void run() {
+ doTest();
+ }
+
+ int doTest();
+
+ string getMultiStrParams() {
+ return tx->getMultiStrParams();
+ }
+
+ void setMultiStrParams(string params) {
+ multiParams = params;
+ return;
+ }
+};
+
+
+class
+ ZrtpRecvPacketTransmissionTestCB: public Thread {
+
+private:
+ SymmetricZRTPSession* rx;
+ string multiParams;
+ string prefix;
+
+public:
+ ZrtpRecvPacketTransmissionTestCB(): rx(NULL), multiParams("") {};
+
+ void run() {
+ doTest();
+ }
+
+ int doTest();
+
+ string getMultiStrParams() {
+ return rx->getMultiStrParams();
+ }
+
+ void setMultiStrParams(string params) {
+ multiParams = params;
+ return;
+ }
+};
+
+/**
+ * Simple User Callback class
+ *
+ * This class overwrite some methods from ZrtpUserCallback to get information
+ * about ZRTP processing and information about ZRTP results. The standard
+ * implementation of this class just perform return, thus effectively
+ * supressing any callback or trigger.
+ */
+class MyUserCallback: public ZrtpUserCallback {
+
+protected:
+ static map<int32, std::string*> infoMap;
+ static map<int32, std::string*> warningMap;
+ static map<int32, std::string*> severeMap;
+ static map<int32, std::string*> zrtpMap;
+ static map<int32, std::string*> enrollMap;
+
+
+ static bool initialized;
+
+ SymmetricZRTPSession* session;
+
+ std::string prefix;
+
+public:
+ MyUserCallback(SymmetricZRTPSession* s): session(s), prefix("default: ") {
+
+ if (initialized) {
+ return;
+ }
+ infoMap.insert(pair<int32, std::string*>(InfoHelloReceived, new string("Hello received, preparing a Commit")));
+ infoMap.insert(pair<int32, std::string*>(InfoCommitDHGenerated, new string("Commit: Generated a public DH key")));
+ infoMap.insert(pair<int32, std::string*>(InfoRespCommitReceived, new string("Responder: Commit received, preparing DHPart1")));
+ infoMap.insert(pair<int32, std::string*>(InfoDH1DHGenerated, new string("DH1Part: Generated a public DH key")));
+ infoMap.insert(pair<int32, std::string*>(InfoInitDH1Received, new string("Initiator: DHPart1 received, preparing DHPart2")));
+ infoMap.insert(pair<int32, std::string*>(InfoRespDH2Received, new string("Responder: DHPart2 received, preparing Confirm1")));
+ infoMap.insert(pair<int32, std::string*>(InfoInitConf1Received, new string("Initiator: Confirm1 received, preparing Confirm2")));
+ infoMap.insert(pair<int32, std::string*>(InfoRespConf2Received, new string("Responder: Confirm2 received, preparing Conf2Ack")));
+ infoMap.insert(pair<int32, std::string*>(InfoRSMatchFound, new string("At least one retained secrets matches - security OK")));
+ infoMap.insert(pair<int32, std::string*>(InfoSecureStateOn, new string("Entered secure state")));
+ infoMap.insert(pair<int32, std::string*>(InfoSecureStateOff, new string("No more security for this session")));
+
+ warningMap.insert(pair<int32, std::string*>(WarningDHAESmismatch,
+ new string("Commit contains an AES256 cipher but does not offer a Diffie-Helman 4096")));
+ warningMap.insert(pair<int32, std::string*>(WarningGoClearReceived, new string("Received a GoClear message")));
+ warningMap.insert(pair<int32, std::string*>(WarningDHShort,
+ new string("Hello offers an AES256 cipher but does not offer a Diffie-Helman 4096")));
+ warningMap.insert(pair<int32, std::string*>(WarningNoRSMatch, new string("No retained secret matches - verify SAS")));
+ warningMap.insert(pair<int32, std::string*>(WarningCRCmismatch, new string("Internal ZRTP packet checksum mismatch - packet dropped")));
+ warningMap.insert(pair<int32, std::string*>(WarningSRTPauthError, new string("Dropping packet because SRTP authentication failed!")));
+ warningMap.insert(pair<int32, std::string*>(WarningSRTPreplayError, new string("Dropping packet because SRTP replay check failed!")));
+ warningMap.insert(pair<int32, std::string*>(WarningNoExpectedRSMatch,
+ new string("Valid retained shared secrets availabe but no matches found - must verify SAS")));
+
+ severeMap.insert(pair<int32, std::string*>(SevereHelloHMACFailed, new string("Hash HMAC check of Hello failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereCommitHMACFailed, new string("Hash HMAC check of Commit failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereDH1HMACFailed, new string("Hash HMAC check of DHPart1 failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereDH2HMACFailed, new string("Hash HMAC check of DHPart2 failed!")));
+ severeMap.insert(pair<int32, std::string*>(SevereCannotSend, new string("Cannot send data - connection or peer down?")));
+ severeMap.insert(pair<int32, std::string*>(SevereProtocolError, new string("Internal protocol error occured!")));
+ severeMap.insert(pair<int32, std::string*>(SevereNoTimer, new string("Cannot start a timer - internal resources exhausted?")));
+ severeMap.insert(pair<int32, std::string*>(SevereTooMuchRetries,
+ new string("Too much retries during ZRTP negotiation - connection or peer down?")));
+
+ zrtpMap.insert(pair<int32, std::string*>(MalformedPacket, new string("Malformed packet (CRC OK, but wrong structure)")));
+ zrtpMap.insert(pair<int32, std::string*>(CriticalSWError, new string("Critical software error")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppZRTPVersion, new string("Unsupported ZRTP version")));
+ zrtpMap.insert(pair<int32, std::string*>(HelloCompMismatch, new string("Hello components mismatch")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppHashType, new string("Hash type not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppCiphertype, new string("Cipher type not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppPKExchange, new string("Public key exchange not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppSRTPAuthTag, new string("SRTP auth. tag not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(UnsuppSASScheme, new string("SAS scheme not supported")));
+ zrtpMap.insert(pair<int32, std::string*>(NoSharedSecret, new string("No shared secret available, DH mode required")));
+ zrtpMap.insert(pair<int32, std::string*>(DHErrorWrongPV, new string("DH Error: bad pvi or pvr ( == 1, 0, or p-1)")));
+ zrtpMap.insert(pair<int32, std::string*>(DHErrorWrongHVI, new string("DH Error: hvi != hashed data")));
+ zrtpMap.insert(pair<int32, std::string*>(SASuntrustedMiTM, new string("Received relayed SAS from untrusted MiTM")));
+ zrtpMap.insert(pair<int32, std::string*>(ConfirmHMACWrong, new string("Auth. Error: Bad Confirm pkt HMAC")));
+ zrtpMap.insert(pair<int32, std::string*>(NonceReused, new string("Nonce reuse")));
+ zrtpMap.insert(pair<int32, std::string*>(EqualZIDHello, new string("Equal ZIDs in Hello")));
+ zrtpMap.insert(pair<int32, std::string*>(GoCleatNotAllowed, new string("GoClear packet received, but not allowed")));
+
+ enrollMap.insert(pair<int32, std::string*>(EnrollmentRequest, new string("Trusted MitM enrollment requested")));
+ enrollMap.insert(pair<int32, std::string*>(EnrollmentCanceled, new string("Trusted MitM enrollment canceled by user")));
+ enrollMap.insert(pair<int32, std::string*>(EnrollmentFailed, new string("Trusted MitM enrollment failed")));
+ enrollMap.insert(pair<int32, std::string*>(EnrollmentOk, new string("Trusted MitM enrollment OK")));
+
+ initialized = true;
+ }
+
+ void showMessage(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) {
+ string* msg;
+ uint8_t sasHash[32];
+
+ if (sev == Info) {
+ msg = infoMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ // this sets up and starts off the multi-stream test
+ if (subCode == InfoSecureStateOn) {
+ if (zrxcbMulti != NULL) {
+ zrxcbMulti->setMultiStrParams(session->getMultiStrParams());
+ zrxcbMulti->start();
+ }
+ if (ztxcbMulti != NULL) {
+ ztxcbMulti->setMultiStrParams(session->getMultiStrParams());
+ ztxcbMulti->start();
+ }
+ if (sender) {
+ if (mitm && !enroll) { // sender now acts as trusted PBX in normal mode, not in enrollement service
+ std::string render = session->getSasType();
+ for (int i = 0; i < 32; i++) {
+ sasHash[i] = 0;
+ }
+ if (untrusted) { // treat receiver as non-enrolled receiver
+ cout << prefix << "send SAS relay to non-enrolled receiver" << endl;
+ session->sendSASRelayPacket(sasHash, render);
+ }
+ else {
+ sasHash[0] = 0x11;
+ sasHash[1] = 0x22;
+ sasHash[2] = 0x33;
+ sasHash[4] = 0x44;
+ cout << prefix << "send SAS relay to enrolled receiver" << endl;
+ session->sendSASRelayPacket(sasHash, render);
+ }
+ }
+ }
+ }
+ }
+ if (sev == Warning) {
+ msg = warningMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ if (sev == Severe) {
+ msg = severeMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ if (sev == ZrtpError) {
+ if (subCode < 0) { // received an error packet from peer
+ subCode *= -1;
+ cout << prefix << "Received error packet: ";
+ }
+ else {
+ cout << prefix << "Sent error packet: ";
+ }
+ msg = zrtpMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ }
+
+ void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) {
+ string* msg;
+ if (sev == ZrtpError) {
+ if (subCode < 0) { // received an error packet from peer
+ subCode *= -1;
+ cout << prefix << "Received error packet: ";
+ }
+ else {
+ cout << prefix << "Sent error packet: ";
+ }
+ msg = zrtpMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ else {
+ msg = severeMap[subCode];
+ cout << prefix << *msg << endl;
+ }
+ }
+
+ void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info) {
+ string* msg = enrollMap[info];
+ cout << prefix << *msg << endl;
+ session->acceptEnrollment(true);
+ }
+
+ void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info) {
+ string* msg = enrollMap[info];
+ cout << prefix << *msg << endl;
+ }
+
+ void secureOn(std::string cipher) {
+ cout << prefix << "Using cipher:" << cipher << endl;
+ cout << prefix << "peer hello hash: " << session->getPeerHelloHash() << endl;
+ }
+
+ void showSAS(std::string sas, bool verified) {
+ cout << prefix << "SAS is: " << sas << endl;
+
+ }
+
+ void signSAS(uint8_t* sasHash) {
+ cout << prefix << "SAS to sign" << endl;
+ uint8_t sign[12];
+ sign[0] = sasHash[0];
+ sign[1] = sasHash[1];
+ sign[2] = sasHash[2];
+ sign[3] = sasHash[3];
+ if (recver) {
+ sign[4] = 'R';
+ sign[5] = 'E';
+ sign[6] = 'C';
+ sign[7] = 'E';
+ sign[8] = 'I';
+ sign[9] = 'V';
+ sign[10] = 'E';
+ sign[11] = 'R';
+ }
+ else {
+ sign[4] = 'T';
+ sign[5] = 'R';
+ sign[6] = 'A';
+ sign[7] = 'N';
+ sign[8] = 'S';
+ sign[9] = 'M';
+ sign[10] = 'I';
+ sign[11] = 'T';
+ }
+ cout << prefix << "set signature data result: " << session->setSignatureData(sign, 12) << endl;
+ }
+
+ bool checkSASSignature(uint8_t* sasHash) {
+ cout << prefix << "check signature" << endl;
+ const uint8_t* sign = session->getSignatureData();
+ cout << prefix << "signature: " << sign << endl;
+ return true;
+ }
+
+ void setPrefix(std::string p) {
+ prefix = p;
+ }
+};
+
+map<int32, std::string*>MyUserCallback::infoMap;
+map<int32, std::string*>MyUserCallback::warningMap;
+map<int32, std::string*>MyUserCallback::severeMap;
+map<int32, std::string*>MyUserCallback::zrtpMap;
+map<int32, std::string*>MyUserCallback::enrollMap;
+
+bool MyUserCallback::initialized = false;
+
+
+class MyUserCallbackMulti: public MyUserCallback {
+
+public:
+
+ MyUserCallbackMulti(SymmetricZRTPSession* s): MyUserCallback(s) {
+ }
+
+ void showMessage(GnuZrtpCodes::MessageSeverity sev, int32_t subCode) {
+ string* msg;
+ if (sev == Info) {
+ msg = infoMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ if (sev == Warning) {
+ msg = warningMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ if (sev == Severe) {
+ msg = severeMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ if (sev == ZrtpError) {
+ if (subCode < 0) { // received an error packet from peer
+ subCode *= -1;
+ cout << prefix << "Received error packet: ";
+ }
+ else {
+ cout << prefix << "Sent error packet: ";
+ }
+ msg = zrtpMap[subCode];
+ if (msg != NULL) {
+ cout << prefix << *msg << endl;
+ }
+ }
+ }
+};
+
+int ZrtpSendPacketTransmissionTestCB::doTest() {
+
+ ZrtpConfigure config;
+
+ MyUserCallback* mcb;
+ if (!multiParams.empty()) {
+ tx = new SymmetricZRTPSession(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2+10);
+// tx->initialize("test_t.zid", true, &config);
+ tx->initialize("test_t.zid", true);
+ tx->setMultiStrParams(multiParams);
+
+ prefix = "TX Multi: ";
+ mcb = new MyUserCallbackMulti(tx);
+ mcb->setPrefix(prefix);
+ }
+ else {
+ tx = new SymmetricZRTPSession(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2);
+ //config.addHashAlgo(Sha384);
+// tx->initialize("test_t.zid", true, &config);
+ if (mitm) { // Act as trusted MitM - could be enrolled
+ tx->setMitmMode(true);
+ }
+
+ tx->setSignSas(signsas);
+ tx->initialize("test_t.zid", true);
+
+ if (enroll) // act as PBX enrollement service
+ tx->setEnrollmentMode(true);
+
+ prefix = "TX: ";
+ mcb = new MyUserCallback(tx);
+ mcb->setPrefix(prefix);
+ }
+ // At this point the Hello hash is available. See ZRTP specification
+ // chapter 9.1 for further information when an how to use the Hello
+ // hash.
+ cout << prefix << "Hello hash: " << tx->getHelloHash() << endl;
+ cout << prefix << "Hello hash length: " << tx->getHelloHash().length() << endl;
+ tx->setUserCallback(mcb);
+ tx->setSchedulingTimeout(10000);
+ tx->setExpireTimeout(1000000);
+
+ tx->startRunning();
+
+ tx->setPayloadFormat(StaticPayloadFormat(sptPCMU));
+
+ if (!multiParams.empty()) {
+ if (!tx->addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+10) ) {
+ return 1;
+ }
+ }
+ else {
+ if (!tx->addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()) ) {
+ return 1;
+ }
+ }
+ tx->startZrtp();
+
+ // 2 packets per second (packet duration of 500ms)
+ uint32 period = 500;
+ uint16 inc = tx->getCurrentRTPClockRate()/2;
+ TimerPort::setTimer(period);
+ uint32 i;
+ for (i = 0; i < pattern.getPacketsNumber(); i++ ) {
+ tx->putData(i*inc,
+ pattern.getPacketData(i),
+ pattern.getPacketSize(i));
+ cout << prefix << "Sent some data: " << i << endl;
+ Thread::sleep(TimerPort::getTimer());
+ TimerPort::incTimer(period);
+ }
+ tx->putData(i*inc, (unsigned char*)"exit", 5);
+ Thread::sleep(TimerPort::getTimer());
+ delete tx;
+ return 0;
+}
+
+
+int ZrtpRecvPacketTransmissionTestCB::doTest() {
+
+ ZrtpConfigure config;
+
+ MyUserCallback* mcb;
+ if (!multiParams.empty()) {
+ rx = new SymmetricZRTPSession(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+10);
+
+// rx->initialize("test_r.zid", true, &config);
+ rx->initialize("test_r.zid", true);
+ rx->setMultiStrParams(multiParams);
+
+ prefix = "RX Multi: ";
+ mcb = new MyUserCallbackMulti(rx);
+ mcb->setPrefix(prefix);
+ }
+ else {
+ rx = new SymmetricZRTPSession(pattern.getDestinationAddress(),
+ pattern.getDestinationPort());
+ config.setStandardConfig();
+ if (enroll)
+ config.setTrustedMitM(true); // allow a trusted MitM to start enrollment process
+
+ rx->setSignSas(signsas);
+
+ // config.addHashAlgo(Sha384);
+ rx->initialize("test_r.zid", true, &config);
+// rx->initialize("test_r.zid", true);
+
+ prefix = "RX: ";
+ mcb = new MyUserCallback(rx);
+ mcb->setPrefix(prefix);
+ }
+ // At this point the Hello hash is available. See ZRTP specification
+ // chapter 9.1 for further information when an how to use the Hello
+ // hash.
+ cout << prefix << "Hello hash: " << rx->getHelloHash() << endl;
+ cout << prefix << "Hello hash length: " << rx->getHelloHash().length() << endl;
+ rx->setUserCallback(mcb);
+ rx->setSchedulingTimeout(10000);
+ rx->setExpireTimeout(1000000);
+
+ rx->startRunning();
+ rx->setPayloadFormat(StaticPayloadFormat(sptPCMU));
+ // arbitrary number of loops to provide time to start transmitter
+ if (!multiParams.empty()) {
+ if (!rx->addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2+10) ) {
+ return 1;
+ }
+ }
+ else {
+ if (!rx->addDestination(pattern.getDestinationAddress(),
+ pattern.getDestinationPort()+2) ) {
+ return 1;
+ }
+ }
+// rx->startZrtp();
+
+ for ( int i = 0; i < 5000 ; i++ ) {
+ const AppDataUnit* adu;
+ while ( (adu = rx->getData(rx->getFirstTimestamp())) ) {
+ cerr << prefix << "got some data: " << adu->getData() << endl;
+ if (*adu->getData() == 'e') {
+ delete adu;
+ delete rx;
+ return 0;
+ }
+ delete adu;
+ }
+ Thread::sleep(70);
+ }
+ delete rx;
+ return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int result = 0;
+
+ char c;
+
+ /* check args */
+ while (1) {
+ c = getopt(argc, argv, "rsSmeu");
+ if (c == -1) {
+ break;
+ }
+ switch (c) {
+ case 'r':
+ recver = true;
+ break;
+ case 's':
+ sender = true;
+ break;
+ case 'm':
+ mitm = true;
+ break;
+ case 'e':
+ enroll = true;
+ break;
+ case 'u':
+ untrusted = true;
+ break;
+ case 'S':
+ signsas = true;
+ break;
+ default:
+ cerr << "Wrong Arguments, only -s and -r are accepted" << endl;
+ }
+ }
+
+ if (sender || recver) {
+ if (sender) {
+ cout << "Running as sender" << endl;
+ }
+ else {
+ cout << "Running as receiver" << endl;
+ }
+ }
+ else {
+ cerr << "No send or receive argument specificied" << endl;
+ exit(1);
+ }
+
+ if ( sender ) {
+ ztxcb = new ZrtpSendPacketTransmissionTestCB();
+ ztxcbMulti = new ZrtpSendPacketTransmissionTestCB();
+ ztxcb->start();
+ ztxcb->join();
+ ztxcbMulti->join();
+ } else if ( recver ) {
+ zrxcb = new ZrtpRecvPacketTransmissionTestCB();
+ zrxcbMulti = new ZrtpRecvPacketTransmissionTestCB();
+ zrxcb->start();
+ zrxcb->join();
+ zrxcbMulti->join();
+ }
+
+ exit(result);
+}
+
+/** EMACS **
+ * Local variables:
+ * mode: c++
+ * c-default-style: ellemtel
+ * c-basic-offset: 4
+ * End:
+ */