r2823 - in trunk: libminisip libminisip/include/libminisip/zrtp libminisip/source/mediahandler libminisip/source/zrtp libzrtpcpp/src libzrtpcpp/src/libzrtpcpp libzrtpcpp/src/libzrtpcpp/crypto libzrtpcpp/src/libzrtpcpp/crypto/openssl

werner at minisip.org werner at minisip.org
Sat Oct 7 14:20:49 CEST 2006


Author: werner
Date: 2006-10-07 14:20:48 +0200 (Sat, 07 Oct 2006)
New Revision: 2823

Modified:
   trunk/libminisip/configure.ac
   trunk/libminisip/include/libminisip/zrtp/ZrtpHostBridgeMinisip.h
   trunk/libminisip/source/mediahandler/MediaStream.cxx
   trunk/libminisip/source/zrtp/ZrtpHostBridgeMinisip.cxx
   trunk/libzrtpcpp/src/ZIDFile.cxx
   trunk/libzrtpcpp/src/ZIDRecord.cxx
   trunk/libzrtpcpp/src/ZRtp.cxx
   trunk/libzrtpcpp/src/ZrtpStateClass.cxx
   trunk/libzrtpcpp/src/ZrtpTextData.cxx
   trunk/libzrtpcpp/src/libzrtpcpp/ZIDRecord.h
   trunk/libzrtpcpp/src/libzrtpcpp/ZRtp.h
   trunk/libzrtpcpp/src/libzrtpcpp/ZrtpCallback.h
   trunk/libzrtpcpp/src/libzrtpcpp/crypto/ZrtpDH.h
   trunk/libzrtpcpp/src/libzrtpcpp/crypto/openssl/ZrtpDH.cxx
Log:
Update ZRTP implementation, fix SAS handling, some smaller problems.

Modified: trunk/libminisip/configure.ac
===================================================================
--- trunk/libminisip/configure.ac	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libminisip/configure.ac	2006-10-07 12:20:48 UTC (rev 2823)
@@ -235,7 +235,7 @@
 
 
 AC_ARG_ENABLE(onlineconf,
-    AS_HELP_STRING([--enable-onlineconf], 
+    AS_HELP_STRING([--enable-onlineconf],
     	[enables support for storing minisip configuration data online (default disabled - under development).])
    )
 

Modified: trunk/libminisip/include/libminisip/zrtp/ZrtpHostBridgeMinisip.h
===================================================================
--- trunk/libminisip/include/libminisip/zrtp/ZrtpHostBridgeMinisip.h	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libminisip/include/libminisip/zrtp/ZrtpHostBridgeMinisip.h	2006-10-07 12:20:48 UTC (rev 2823)
@@ -232,6 +232,17 @@
     void srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part);
 
     /**
+     * This method shall switch on GUI inidicators.
+     *
+     * @param c
+     *    The name of the used cipher algorithm and mode, or NULL
+     * @param s
+     *    The SAS string or NULL
+     */
+    virtual void srtpSecretsOn(const char* c, const char* s);
+
+
+    /**
      * Switch off the security for the defined part.
      *
      * Create an empty CryproContext and register it with the

Modified: trunk/libminisip/source/mediahandler/MediaStream.cxx
===================================================================
--- trunk/libminisip/source/mediahandler/MediaStream.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libminisip/source/mediahandler/MediaStream.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -233,11 +233,11 @@
 }
 
 void MediaStream::setZrtpHostBridge(MRef<ZrtpHostBridgeMinisip *> zsb) {
-	zrtpBridge = zsb; 
+	zrtpBridge = zsb;
 }
 
 MRef<ZrtpHostBridgeMinisip *> MediaStream::getZrtpHostBridge() {
-	return zrtpBridge; 
+	return zrtpBridge;
 }
 
 #endif
@@ -300,11 +300,11 @@
         recvSsrc = packet->getHeader().getSSRC();
 	seq_no = packet->getHeader().getSeqNo();
 
-        if (zrtpBridge->isZrtpPacket(packet)) {
-            packet->checkZrtpChecksum(false);
-        }
+        // if (zrtpBridge->isZrtpPacket(packet)) {
+        //    packet->checkZrtpChecksum(false);
+        // }
         // Look for a CryptoContext for this packet's SSRC
-        MRef<CryptoContext *> pcc = getCryptoContext( recvSsrc, seq_no);
+        MRef<CryptoContext *> pcc = getCryptoContext(recvSsrc, seq_no);
 
 	if( packet->unprotect(pcc)) { // Authentication or replay protection failed
 		return;
@@ -326,9 +326,9 @@
 	seq_no = packet->getHeader().getSeqNo();
 
 #ifdef ZRTP_SUPPORT
-        if (zrtpBridge && packet->getHeader().getExtension() && zrtpBridge->isZrtpPacket(packet)) {
-            packet->checkZrtpChecksum(false);
-        }
+        // if (zrtpBridge && packet->getHeader().getExtension() && zrtpBridge->isZrtpPacket(packet)) {
+        //    packet->checkZrtpChecksum(false);
+        // }
         MRef<CryptoContext *> pcc = getCryptoContext(packetSsrc, seq_no);
 
         // If empty crypto context for this SSRC but we are already in Secure
@@ -477,7 +477,7 @@
 
 	packet->protect(getCryptoContext(ssrc, seqNo));
 
-        packet->enableZrtpChecksum();
+        // packet->enableZrtpChecksum();
 	packet->sendTo( **senderSock, **remoteAddress, remotePort );
 	delete packet;
 	senderLock.unlock();
@@ -533,7 +533,7 @@
 		packet->sendTo( **senderSock, **remoteAddress, remotePort );
 	else if( remoteAddress->getAddressFamily() == AF_INET6 && sender6Sock )
 		packet->sendTo( **sender6Sock, **remoteAddress, remotePort );
-		
+
 	delete packet;
 	senderLock.unlock();
 

Modified: trunk/libminisip/source/zrtp/ZrtpHostBridgeMinisip.cxx
===================================================================
--- trunk/libminisip/source/zrtp/ZrtpHostBridgeMinisip.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libminisip/source/zrtp/ZrtpHostBridgeMinisip.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -94,6 +94,7 @@
 
     if (zrtpEngine == NULL) {
         zrtpEngine = new ZRtp((uint8_t*)ownZid, (ZrtpCallback*)this);
+        zrtpEngine->setClientId(clientId);
         zrtpEngine->startZrtpEngine();
     }
 }
@@ -275,10 +276,6 @@
 
         secureParts++;
     }
-    if (secureParts == 2) {
-        CommandString cmd(callId, "zrtp_security_change", "secure", secrets->sas);
-        messageRouterCallback->handleCommand("gui", cmd);
-    }
 }
 
 MRef<CryptoContext *>
@@ -294,6 +291,18 @@
     return pcc;
 }
 
+void ZrtpHostBridgeMinisip::srtpSecretsOn(const char* c, const char* s)
+{
+
+    if (s != NULL) {
+        CommandString cmd(callId, "zrtp_security_change", "secure", s);
+        messageRouterCallback->handleCommand("gui", cmd);
+    }
+//    if (s != NULL && zrtpUserCallback != NULL) {
+//        zrtpUserCallback->showSAS(s);
+//    }
+}
+
 void ZrtpHostBridgeMinisip::srtpSecretsOff(EnableSecurity part) {
     MRef<CryptoContext *> cryptoContext;
 

Modified: trunk/libzrtpcpp/src/ZIDFile.cxx
===================================================================
--- trunk/libzrtpcpp/src/ZIDFile.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/ZIDFile.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -59,7 +59,7 @@
     }
     if ((zidFile = fopen(name, "rb+")) == NULL) {
 	zidFile = fopen(name, "wb+");
-	// New file, generate an associated randomw ZID and save
+	// New file, generate an associated random ZID and save
         // it as first record
 	if (zidFile != NULL) {
 	    ip = (unsigned int*)associatedZid;
@@ -72,14 +72,19 @@
 	    fseek(zidFile, 0L, SEEK_SET);
 	    rec.ownZid = 1;
 	    fwrite(&rec, sizeof(zidrecord_t), 1, zidFile);
+            fflush(zidFile);
 	}
     }
     else {
 	fseek(zidFile, 0L, SEEK_SET);
 	if (fread(&rec, sizeof(zidrecord_t), 1, zidFile) != 1) {
+            fclose(zidFile);
+            zidFile = NULL;
 	    return -1;
 	}
 	if (rec.ownZid != 1) {
+            fclose(zidFile);
+            zidFile = NULL;
 	    return -1;
 	}
 	memcpy(associatedZid, rec.identifier, IDENTIFIER_LEN);

Modified: trunk/libzrtpcpp/src/ZIDRecord.cxx
===================================================================
--- trunk/libzrtpcpp/src/ZIDRecord.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/ZIDRecord.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -31,6 +31,10 @@
   // set new RS1 data
   memcpy(record.rs1Data, data, RS_LENGTH);
   record.rs1Valid = 1;
+  // copy the SAS verified flag to new record as well
+  if (record.rs2Valid & SASVerified) {
+      record.rs1Valid |= SASVerified;
+  }
 }
 
 /** EMACS **

Modified: trunk/libzrtpcpp/src/ZRtp.cxx
===================================================================
--- trunk/libzrtpcpp/src/ZRtp.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/ZRtp.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -67,6 +67,7 @@
     zrtpConf2Ack = NULL;
     DHss = NULL;
     pubKeyBytes = NULL;
+    Zfone = 0;
 
     memcpy(zid, myZid, 12);
     zrtpHello = new ZrtpPacketHello();
@@ -78,42 +79,49 @@
 }
 
 ZRtp::~ZRtp() {
+    stopZrtp();
+
     if (DHss != NULL) {
 	free(DHss);
+        DHss = NULL;
     }
     if (pubKeyBytes != NULL) {
         free(pubKeyBytes);
+        pubKeyBytes = NULL;
     }
     if (zrtpHello != NULL) {
 	delete zrtpHello;
+        pubKeyBytes = NULL;
     }
     if (zrtpHelloAck != NULL) {
 	delete zrtpHelloAck;
+        zrtpHelloAck = NULL;
     }
     if (zrtpConf2Ack != NULL) {
 	delete zrtpConf2Ack;
+        zrtpConf2Ack = NULL;
     }
     if (stateEngine != NULL) {
 	delete stateEngine;
+        stateEngine = NULL;
     }
     if (dhContext != NULL) {
 	delete dhContext;
+        dhContext = NULL;
     }
-
     memset(hmacSrtp, 0, SHA256_DIGEST_LENGTH);
-
     /*
      * Clear the Initiator's srtp key and salt
      */
     memset(srtpKeyI, 0, SHA256_DIGEST_LENGTH);
     memset(srtpSaltI, 0,  SHA256_DIGEST_LENGTH);
-
     /*
      * Clear he Responder's srtp key and salt
      */
-    memset (srtpKeyR, 0, SHA256_DIGEST_LENGTH);
-    memset (srtpSaltR, 0, SHA256_DIGEST_LENGTH);
+    memset(srtpKeyR, 0, SHA256_DIGEST_LENGTH);
+    memset(srtpSaltR, 0, SHA256_DIGEST_LENGTH);
 
+    memset(s0, 0, SHA256_DIGEST_LENGTH);
 }
 
 int32_t ZRtp::processExtensionHeader(uint8_t *extHeader, uint8_t* content) {
@@ -122,7 +130,12 @@
     ev.type = ZrtpPacket;
     ev.data.packet = extHeader;
     ev.content = content;
-    return stateEngine->processEvent(&ev);
+
+    int32_t ret;
+    if (stateEngine != NULL) {
+        ret = stateEngine->processEvent(&ev);
+    }
+    return ret;
 }
 
 int32_t ZRtp::processTimeout() {
@@ -131,7 +144,12 @@
     ev.type = Timer;
     ev.data.packet = NULL;
     ev.content = NULL;
-    return stateEngine->processEvent(&ev);
+    int32_t ret;
+    if (stateEngine != NULL) {
+        ret = stateEngine->processEvent(&ev);
+    }
+    return ret;
+
 }
 
 bool ZRtp::handleGoClear(uint8_t *extHeader)
@@ -148,7 +166,9 @@
         ev.type = ZrtpGoClear;
         ev.data.packet = extHeader;
         ev.content = NULL;
-        stateEngine->processEvent(&ev);
+        if (stateEngine != NULL) {
+            stateEngine->processEvent(&ev);
+        }
         return true;
     }
     else {
@@ -171,17 +191,24 @@
      * reset to initial state only. This state ignores any event except
      * ZrtpInitial and effectively stops the engine.
      */
-    if (!stateEngine->inState(SecureState)) {
-        stateEngine->nextState(Initial);
-        return;
+    if (stateEngine != NULL) {
+        if (!stateEngine->inState(SecureState)) {
+            stateEngine->nextState(Initial);
+            return;
+        }
+        ev.type = ZrtpClose;
+        stateEngine->processEvent(&ev);
     }
-    ev.type = ZrtpClose;
-    stateEngine->processEvent(&ev);
 }
 
 int32_t ZRtp::checkState(int32_t state)
 {
-    return stateEngine->inState(state);
+    if (stateEngine != NULL) {
+        return stateEngine->inState(state);
+    }
+    else {
+        return -1;
+    }
 }
 
 ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello) {
@@ -190,6 +217,11 @@
 
     sendInfo(Info, "Hello received, preparing a Commit");
 
+    uint8_t* cid = hello->getClientId();
+    if (*cid == 'Z') {  // TODO Zfone hack regarding reused sequence numbers
+        Zfone = 1;
+    }
+
     cipher = findBestCipher(hello);
     if (cipher >= NumSupportedSymCiphers) {
 	sendInfo(Error, "Hello message does not contain a supported Cipher");
@@ -244,10 +276,12 @@
     }
     dhContext->getPubKeyBytes(pubKeyBytes);
 
+    // Here we act as Initiator. Take other peer's Hello packet and my
+    // PVI (public value initiator) and compute the HVI (hash value initiator)
     computeHvi(pubKeyBytes, maxPubKeySize, hello);
 
     char buffer[128];
-    snprintf((char *)buffer, 128, "Generated a public DH key of size: %d", dhContext->getPubKeySize());
+    snprintf((char *)buffer, 128, "Commit: Generated a public DH key of size: %d", dhContext->getPubKeySize());
     sendInfo(Info, buffer);
 
     ZrtpPacketCommit *commit = new ZrtpPacketCommit();
@@ -360,7 +394,7 @@
     pubKeyLen = dhContext->getPubKeySize();
 
     char buffer[128];
-    snprintf(buffer, 128, "Generated a public DH key of size: %d", pubKeyLen);
+    snprintf(buffer, 128, "DH1Part: Generated a public DH key of size: %d", pubKeyLen);
     sendInfo(Info, buffer);
 
     if (pubKeyLen > maxPubKeySize) {
@@ -415,7 +449,8 @@
     uint8_t* pvr;
     uint8_t *data[4];
     unsigned int length[4];
-    uint8_t sas[SHA256_DIGEST_LENGTH];
+    uint8_t sas[SHA256_DIGEST_LENGTH+1];
+    uint32_t sasTemp;
 
     sendInfo(Info, "Initiator: DHPart1 received, preparing DHPart2");
 
@@ -433,20 +468,31 @@
     length[2] = strlen(sasString);
     data[3] = NULL;
 
-    // TODO Check the pvr to avoid MITM
     if (pubKey == Dh3072) {
+        if (!dhContext->checkPubKey(pvr, 384)) {
+            sendInfo(Alert, "Wrong/weak public key value (pvr) received from other party");
+            return NULL;
+        }
 	dhContext->computeKey(pvr, 384, DHss);
         length[1] = 384;
         sha256(data, length, sas);
 
     }
     else {
+        if (!dhContext->checkPubKey(pvr, 512)) {
+            sendInfo(Alert, "Wrong/weak public key value (pvr) received from other party");
+            return NULL;
+        }
         dhContext->computeKey(pvr, 512, DHss);
         length[1] = 512;
         sha256(data, length, sas);
     }
-    SAS = Base32(sas, SHA256_DIGEST_LENGTH*5).getEncoded();
-    SAS = SAS.substr(SAS.length()-4, 4);
+    sas[SHA256_DIGEST_LENGTH] = 0;
+    sasTemp = *(uint32_t*)(sas + SHA256_DIGEST_LENGTH - 3);
+    sasTemp = ntohl(sasTemp);
+    sasTemp <<= 4;
+    *(uint32_t*)sas = htonl(sasTemp);
+    SAS = Base32(sas, 20).getEncoded();
 
     // Initialize a ZID record to get peer's retained secrets
     ZIDRecord zidRec(peerZid);
@@ -493,7 +539,8 @@
     uint8_t* pvi;
     uint8_t *data[4];
     unsigned int length[4];
-    uint8_t sas[SHA256_DIGEST_LENGTH];
+    uint8_t sas[SHA256_DIGEST_LENGTH+1];
+    uint32_t sasTemp;
 
     sendInfo(Info, "Responder: DHPart2 received, preparing Confirm1");
 
@@ -513,19 +560,30 @@
     length[2] = strlen(sasString);
     data[3] = NULL;
 
-    // TODO Check the pvi to avoid MITM
     if (pubKey == Dh3072) {
+        if (!dhContext->checkPubKey(pvi, 384)) {
+            sendInfo(Alert, "Wrong/weak public key value (pvi) received from other party");
+            return NULL;
+        }
 	dhContext->computeKey(pvi, 384, DHss);
         length[0] = 384;
         sha256(data, length, sas);
     }
     else {
+        if (!dhContext->checkPubKey(pvi, 512)) {
+            sendInfo(Alert, "Wrong/weak public key value (pvi) received from other party");
+            return NULL;
+        }
         dhContext->computeKey(pvi, 512, DHss);
         length[0] = 512;
         sha256(data, length, sas);
     }
-    SAS = Base32(sas, SHA256_DIGEST_LENGTH*5).getEncoded();
-    SAS = SAS.substr(SAS.length()-4, 4);
+    sas[SHA256_DIGEST_LENGTH] = 0;
+    sasTemp = *(uint32_t*)(sas + SHA256_DIGEST_LENGTH - 3);
+    sasTemp = ntohl(sasTemp);
+    sasTemp <<= 4;
+    *(uint32_t*)sas = htonl(sasTemp);
+    SAS = Base32(sas, 20).getEncoded();
 
     // Here we have the peers pv. Because we are responder re-compute my hvi
     // using my Hello packet and the Initiator's pv and compare with
@@ -544,8 +602,7 @@
     // thus get the singleton instance to the open file
     ZIDFile *zid = ZIDFile::getInstance();
     zid->getRecord(&zidRec);
-//    int sasFlag = zidRec.isSasVerified() ? 1 : 0;
-    int sasFlag = 0;
+    int sasFlag = zidRec.isSasVerified() ? 1 : 0;
 
     /*
      * The expected shared secret Ids were already computed when we built the
@@ -582,11 +639,8 @@
     sendInfo(Info, "Initiator: Confirm1 received, preparing Confirm2");
 
     uint8_t sasFlag = confirm1->getSASFlag();
-    if (sasFlag & 0x1) {
-    }
 
     if (memcmp(knownPlain, confirm1->getPlainText(), 15) != 0) {
-        fprintf(stderr, "1: %s\n", confirm1->getPlainText());
 	sendInfo(Error, "Cannot read confirm1 message");
 	return NULL;
     }
@@ -598,16 +652,46 @@
     hmac_sha256(hmacSrtp, SHA256_DIGEST_LENGTH, (unsigned char*)confirm1->getPlainText(),
 		20, confMac, &macLen);
 
-    if (memcmp(confMac, confirm1->getHmac(), 32) != 0) {
+    if (memcmp(confMac, confirm1->getHmac(), SHA256_DIGEST_LENGTH) != 0) {
 	sendInfo(Error, "HMAC verification of Confirm1 message failed");
 	return NULL;
     }
+    /*
+     * The Confirm1 is ok, handle the Retained secret stuff and inform
+     * GUI about state.
+     */
 
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+
+    ZIDFile *zid = ZIDFile::getInstance();
+    zid->getRecord(&zidRec);
+
+    // Our peer did not confirm the SAS in last session, thus reset
+    // our SAS flag too.
+    if (!(sasFlag & 0x1)) {
+      zidRec.resetSasVerified();
+    }
+
+    // get verified flag from current RS1 before set a new RS1. This
+    // may not be set even if peer's flag is set in confirm1 message.
+    sasFlag = zidRec.isSasVerified() ? 1 : 0;
+
+    // Inform GUI about security state and SAS state
+    const char* c = (cipher == Aes128) ? "AES-CM-128" : "AES-CM-256";
+    const char* s = (zidRec.isSasVerified()) ? NULL : SAS.c_str();
+    callback->srtpSecretsOn(c, s);
+
+    // now we are ready to save the new RS1 which inherits the verified
+    // flag from old RS1
+    zidRec.setNewRs1((const uint8_t*)newRs1);
+    zid->saveRecord(&zidRec);
+
     // now generate my Confirm2 message
     ZrtpPacketConfirm* zpConf = new ZrtpPacketConfirm();
     zpConf->setMessage((uint8_t*)Confirm2Msg);
     zpConf->setPlainText((uint8_t*)knownPlain);
-    zpConf->setSASFlag(0);
+    zpConf->setSASFlag(sasFlag);
     zpConf->setExpTime(0);
 
     // The HMAC with length 16 includes the SAS flag inside the Confirm packet
@@ -624,12 +708,9 @@
     sendInfo(Info, "Respnder: Confirm2 received, preparing Conf2Ack");
 
     uint8_t sasFlag = confirm2->getSASFlag();
-    if (sasFlag & 0x1) {
-	// prepare the SAS data and display to user
-    }
+
     if (memcmp(knownPlain, confirm2->getPlainText(), 15) != 0) {
-        fprintf(stderr, "2: %s\n", confirm2->getPlainText());
-	sendInfo(Error, "Cannot read confirm2 message");
+     	sendInfo(Error, "Cannot read confirm2 message");
 	return NULL;
     }
     uint8_t confMac[SHA256_DIGEST_LENGTH];
@@ -640,10 +721,37 @@
     hmac_sha256(hmacSrtp, SHA256_DIGEST_LENGTH, (unsigned char*)confirm2->getPlainText(),
 		20, confMac, &macLen);
 
-    if (memcmp(confMac, confirm2->getHmac(), 32) != 0) {
+    if (memcmp(confMac, confirm2->getHmac(), SHA256_DIGEST_LENGTH) != 0) {
 	sendInfo(Error, "HMAC verification of Confirm2 message failed");
 	return NULL;
     }
+
+    /*
+     * The Confirm2 is ok, handle the Retained secret stuff and inform
+     * GUI about state.
+     */
+
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+
+    ZIDFile *zid = ZIDFile::getInstance();
+    zid->getRecord(&zidRec);
+
+    // Our peer did not confirm the SAS in last session, thus reset
+    // our SAS flag too.
+    if (!(sasFlag & 0x1)) {
+      zidRec.resetSasVerified();
+    }
+
+    // Inform GUI about security state and SAS state
+    const char* c = (cipher == Aes128) ? "AES-CM-128" : "AES-CM-256";
+    const char* s = (zidRec.isSasVerified()) ? NULL : SAS.c_str();
+    callback->srtpSecretsOn(c, s);
+
+    // save new RS1, this inherits the verified flag from old RS1
+    zidRec.setNewRs1((const uint8_t*)newRs1);
+    zid->saveRecord(&zidRec);
+
     return zrtpConf2Ack;
 }
 
@@ -839,15 +947,6 @@
     const uint8_t* setE[5];
     int32_t rsFound = 0;
 
-#if 0
-    hexdump("rs1IDr (I)", rs1IDr, 8);
-    hexdump("rs1IDi (I)", rs1IDi, 8);
-    hexdump("rs2IDr (I)", rs2IDr, 8);
-    hexdump("rs2IDi (I)", rs2IDi, 8);
-    hexdump("rs1Id (recv)) (I)", dhPart->getRs1Id(), 8);
-    hexdump("rs2Id (recv)) (I)", dhPart->getRs2Id(), 8);
-#endif
-
     setC[0] = (memcmp(rs1IDr, dhPart->getRs1Id(), 8) == 0) ? rs1IDr : NULL;
     setC[1] = (memcmp(rs2IDr, dhPart->getRs2Id(), 8) == 0) ? rs2IDr : NULL;
     setC[2] = (memcmp(sigsIDr, dhPart->getSigsId(), 8) == 0) ? sigsIDr : NULL;
@@ -872,7 +971,6 @@
 	setE[matchingSecrets++] = rs1IDi;  // rs1IDi will be sent in DHPart2 message
         rsFound = 0x1;
     }
-
     if (setC[1] != NULL) {
 	DEBUGOUT((fprintf(stdout, "%c: Match for Rs2 found\n", zid[0])));
         setD[matchingSecrets] = zidRec.getRs2();
@@ -903,7 +1001,9 @@
         while (notDone) {
 	   notDone = 0;
 	   for (i = 0; i < matchingSecrets - 1; i++) {
-	       if (memcmp(setE[i], setE[i+1], 32) > 0) {
+//               if (memcmp(setE[i], setE[i+1], 8) > 0) { // as defined in specifcation
+               if (memcmp(setD[i], setD[i+1], SHA256_DIGEST_LENGTH) > 0) { // as implemented in Zfone-beta2
+
 	           tmpP = setE[i];
 	           setE[i] = setE[i+1];
 	           setE[i+1] = tmpP;
@@ -915,11 +1015,6 @@
 	   }
         }
     }
-
-#if 0
-    hexdump("setD0 (I)", setD[0], 32);
-    hexdump("setD1 (I)", setD[1], 32);
-#endif
     /*
      * ready to generate s0 here.
      * Hash the DH shared secret and the available shared secrets (max. 5).
@@ -947,7 +1042,7 @@
     free(DHss);
     DHss = NULL;
 
-    computeSRTPKeys(zidRec);
+    computeSRTPKeys();
 }
 
 void ZRtp::generateS0Responder(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec) {
@@ -956,15 +1051,6 @@
     const uint8_t* setE[5];     // Set E is the "compressed" C (no NULLs) for sort
     int32_t rsFound = 0;
 
-#if 0
-    hexdump("rs1IDr (R)", rs1IDr, 8);
-    hexdump("rs1IDi (R)", rs1IDi, 8);
-    hexdump("rs2IDr (R)", rs2IDr, 8);
-    hexdump("rs2IDi (R)", rs2IDi, 8);
-    hexdump("rs1Id (recv)) (R)", dhPart->getRs1Id(), 8);
-    hexdump("rs2Id (recv)) (R)", dhPart->getRs2Id(), 8);
-#endif
-
     setC[0] = (memcmp(rs1IDi, dhPart->getRs1Id(), 8) == 0) ? rs1IDi : NULL;
     setC[1] = (memcmp(rs2IDi, dhPart->getRs2Id(), 8) == 0) ? rs2IDi : NULL;
     setC[2] = (memcmp(sigsIDi, dhPart->getSigsId(), 8) == 0) ? sigsIDi : NULL;
@@ -1019,7 +1105,8 @@
 	while (notDone) {
 	    notDone = 0;
 	    for (i = 0; i < matchingSecrets - 1; i++) {
-		if (memcmp(setE[i], setE[i+1], 32) > 0) {
+//                if (memcmp(setE[i], setE[i+1], 8) > 0) { // orignal spec
+                if (memcmp(setD[i], setD[i+1], SHA256_DIGEST_LENGTH) > 0) { // as implemented in Zfone beta2
 		    tmpP = setE[i];
 		    setE[i] = setE[i+1];
 		    setE[i+1] = tmpP;
@@ -1031,11 +1118,6 @@
 	    }
         }
     }
-#if 0
-    hexdump("setD0 (R)", setD[0], 32);
-    hexdump("setD1 (R)", setD[1], 32);
-#endif
-
     /*
      * ready to generate s0 here.
      * Hash the DH shared secret and the available shared secrets (max. 5).
@@ -1043,11 +1125,14 @@
     unsigned char* data[7];
     uint32_t  length[7];
 
+    // first hash the DH secret
     data[0] = DHss;
     length[0] = dhContext->getSecretSize();
     data[1] = NULL;
     sha256(data, length, DHss);
 
+    // now take the hashed DH secret and the retained secrets and hash
+    // them to get S0
     data[0] = DHss;
     length[0] = SHA256_DIGEST_LENGTH;
 
@@ -1063,33 +1148,32 @@
     free(DHss);
     DHss = NULL;
 
-    computeSRTPKeys(zidRec);
+    computeSRTPKeys();
 }
 
-void ZRtp::computeSRTPKeys(ZIDRecord& zidRec) {
+void ZRtp::computeSRTPKeys() {
 
     unsigned int macLen;
 
-    uint8_t newRs1[RS_LENGTH];
-
+    // Inititiator key and salt
     hmac_sha256(s0, SHA256_DIGEST_LENGTH, (unsigned char*)iniMasterKey, strlen(iniMasterKey),
 		srtpKeyI, &macLen);
     hmac_sha256(s0, SHA256_DIGEST_LENGTH, (unsigned char*)iniMasterSalt, strlen(iniMasterSalt),
 		srtpSaltI, &macLen);
 
+    // Responder key and salt
     hmac_sha256(s0, SHA256_DIGEST_LENGTH, (unsigned char*)respMasterKey, strlen(respMasterKey),
 		srtpKeyR, &macLen);
     hmac_sha256(s0, SHA256_DIGEST_LENGTH, (unsigned char*)respMasterSalt, strlen(respMasterSalt),
 		srtpSaltR, &macLen);
 
+    // The HMAC key for GoClear
     hmac_sha256(s0, SHA256_DIGEST_LENGTH, (unsigned char*)hmacKey, strlen(hmacKey),
 		hmacSrtp, &macLen);
 
+    // Compute the new Retained Secret
     hmac_sha256(s0, SHA256_DIGEST_LENGTH, (unsigned char*)retainedSec, strlen(retainedSec),
 		newRs1, &macLen);
-    zidRec.setNewRs1((const uint8_t*)newRs1);
-
-    memset(s0, 0, SHA256_DIGEST_LENGTH);
 }
 
 void ZRtp::srtpSecretsReady(EnableSecurity part) {
@@ -1126,6 +1210,17 @@
     zid->saveRecord(&zidRec);
 }
 
+void ZRtp::resetSASVerified()
+{
+    // Initialize a ZID record to get peer's retained secrets
+    ZIDRecord zidRec(peerZid);
+    ZIDFile *zid = ZIDFile::getInstance();
+
+    zid->getRecord(&zidRec);
+    zidRec.resetSasVerified();
+    zid->saveRecord(&zidRec);
+}
+
 int32_t ZRtp::sendPacketRTP(ZrtpPacketBase *packet) {
     return ((packet == NULL) ? 0 :
             callback->sendDataRTP(packet->getHeaderBase(), (packet->getLength() * 4) + 4));

Modified: trunk/libzrtpcpp/src/ZrtpStateClass.cxx
===================================================================
--- trunk/libzrtpcpp/src/ZrtpStateClass.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/ZrtpStateClass.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -238,7 +238,9 @@
 	 * - switch to state WaitCommit, wait for peer's Commit
 	 */
 	if (first == 'h') {
-	    ZrtpPacketHelloAck *helloAck = parent->prepareHelloAck();
+            ZrtpPacketHello *hpkt = new ZrtpPacketHello(pkt);
+            ZrtpPacketHelloAck *helloAck = parent->prepareHelloAck(hpkt);
+            delete hpkt;
 
 	    nextState(WaitCommit);
 

Modified: trunk/libzrtpcpp/src/ZrtpTextData.cxx
===================================================================
--- trunk/libzrtpcpp/src/ZrtpTextData.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/ZrtpTextData.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -23,7 +23,7 @@
 /**
  *
  */
-char *clientId = "GNUccRTP      "; // must be 15 chars
+char *clientId = "minisip        "; // must be 15 chars
 char *zrtpVersion = "0.02";	// must be 4 chars
 
 /**

Modified: trunk/libzrtpcpp/src/libzrtpcpp/ZIDRecord.h
===================================================================
--- trunk/libzrtpcpp/src/libzrtpcpp/ZIDRecord.h	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/libzrtpcpp/ZIDRecord.h	2006-10-07 12:20:48 UTC (rev 2823)
@@ -65,8 +65,9 @@
     int isRs1Valid() { return (record.rs1Valid & valid); }
     int isRs2Valid() { return (record.rs2Valid & valid); }
 
-    void setSasVerified() { record.rs1Valid |= SASVerified; }
-    int isSasVerified()   { return (record.rs2Valid & SASVerified); }
+    void setSasVerified()   { record.rs1Valid |= SASVerified; }
+    void resetSasVerified() { record.rs1Valid &= ~SASVerified; }
+    int isSasVerified()     { return (record.rs1Valid & SASVerified); }
 
     const unsigned char *getRs1() { return record.rs1Data; }
     const unsigned char *getRs2() { return record.rs2Data; }

Modified: trunk/libzrtpcpp/src/libzrtpcpp/ZRtp.h
===================================================================
--- trunk/libzrtpcpp/src/libzrtpcpp/ZRtp.h	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/libzrtpcpp/ZRtp.h	2006-10-07 12:20:48 UTC (rev 2823)
@@ -207,6 +207,14 @@
         */
        void SASVerified();
 
+       /**
+        * Reset the SAS verfied flag for the current active user's retained secrets.
+        *
+        */
+       void resetSASVerified();
+
+       int Zfone;
+
  private:
      friend class ZrtpStateClass;
 
@@ -304,6 +312,11 @@
     uint8_t s0[SHA256_DIGEST_LENGTH];
 
     /**
+     * The new Retained Secret
+     */
+    uint8_t newRs1[RS_LENGTH];
+
+    /**
      * The HMAC key
      */
     uint8_t hmacSrtp[SHA256_DIGEST_LENGTH];
@@ -409,7 +422,7 @@
 
     void computeSharedSecretSet(ZIDRecord& zidRec);
 
-    void computeSRTPKeys(ZIDRecord& zidRec);
+    void computeSRTPKeys();
 
     void generateS0Initiator(ZrtpPacketDHPart *dhPart, ZIDRecord& zidRec);
 
@@ -484,7 +497,13 @@
      * @return
      *    A pointer to the initialized HelloAck packet.
      */
-    ZrtpPacketHelloAck *prepareHelloAck() {return zrtpHelloAck; }
+    ZrtpPacketHelloAck *prepareHelloAck(ZrtpPacketHello *hello) {
+        uint8_t* cid = hello->getClientId();
+        if (*cid == 'Z') {
+            Zfone = 1;
+        }
+        return zrtpHelloAck;
+    }
 
     /**
      * Prepare a Commit packet.
@@ -508,8 +527,6 @@
      * a Commit packet received from the peer. Also we a in the role of the
      * Responder.
      *
-     * <p/>
-     *
      * 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
@@ -607,7 +624,7 @@
     }
 
     /**
-     * ZRTP calls this if the negotiation failed.
+     * 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.
@@ -622,7 +639,7 @@
     }
 
     /**
-     * ZRTP calls this method if the other side does not support ZRTP.
+     * 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,

Modified: trunk/libzrtpcpp/src/libzrtpcpp/ZrtpCallback.h
===================================================================
--- trunk/libzrtpcpp/src/libzrtpcpp/ZrtpCallback.h	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/libzrtpcpp/ZrtpCallback.h	2006-10-07 12:20:48 UTC (rev 2823)
@@ -219,7 +219,7 @@
     virtual void srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part) =0;
 
     /**
-     * This method shall clear the ZRTP secrets.
+     * This method shall clear the SRTP Context and switch off GUI inidicators.
      *
      * @param part
      *    Defines for which part (sender or receiver) to switch on security
@@ -227,6 +227,16 @@
     virtual void srtpSecretsOff(EnableSecurity part) =0;
 
     /**
+     * This method shall switch on GUI inidicators.
+     *
+     * @param c
+     *    The name of the used cipher algorithm and mode, or NULL
+     * @param s
+     *    The SAS string or NULL
+     */
+    virtual void srtpSecretsOn(const char* c, const char* s) =0;
+
+    /**
      * This method shall handle GoClear requests.
      *
      * According to the ZRTP specification the user must be informed about
@@ -258,7 +268,6 @@
      *
      */
     virtual void zrtpNotSuppOther() =0;
-
 };
 
 #endif // ZRTPCALLBACK

Modified: trunk/libzrtpcpp/src/libzrtpcpp/crypto/ZrtpDH.h
===================================================================
--- trunk/libzrtpcpp/src/libzrtpcpp/crypto/ZrtpDH.h	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/libzrtpcpp/crypto/ZrtpDH.h	2006-10-07 12:20:48 UTC (rev 2823)
@@ -112,6 +112,23 @@
     int32_t computeKey(uint8_t *pubKeyBytes, int32_t length, 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.
+     *
+     * @param length
+     *    Length in bytes of the peer's public key.
+     *
+     * @return 0 if check faild, 1 if public key value is ok.
+     */
+    int32_t checkPubKey(uint8_t* pubKeyBytes, int32_t length) const;
+
+    /**
      * Generates a number of random bytes.
      *
      * @param buf

Modified: trunk/libzrtpcpp/src/libzrtpcpp/crypto/openssl/ZrtpDH.cxx
===================================================================
--- trunk/libzrtpcpp/src/libzrtpcpp/crypto/openssl/ZrtpDH.cxx	2006-10-06 09:55:41 UTC (rev 2822)
+++ trunk/libzrtpcpp/src/libzrtpcpp/crypto/openssl/ZrtpDH.cxx	2006-10-07 12:20:48 UTC (rev 2823)
@@ -47,9 +47,12 @@
 
 extern void initializeOpenSSL();
 
-static BIGNUM *bnP3072 = NULL;
-static BIGNUM *bnP4096 = NULL;
+static BIGNUM* bnP3072 = NULL;
+static BIGNUM* bnP4096 = NULL;
 
+static BIGNUM* bnP3072MinusOne = NULL;
+static BIGNUM* bnP4096MinusOne = NULL;
+
 static uint8_t dhinit = 0;
 
 // void initializeOpenSSL();
@@ -146,6 +149,10 @@
     if (!dhinit) {
 	bnP3072 = BN_bin2bn(P3072,sizeof(P3072),NULL);
 	bnP4096 = BN_bin2bn(P4096,sizeof(P4096),NULL);
+        bnP3072MinusOne = BN_dup(bnP3072);
+        BN_sub_word(bnP3072MinusOne, 1);
+        bnP4096MinusOne = BN_dup(bnP4096);
+        BN_sub_word(bnP4096MinusOne, 1);
 	dhinit = 1;
     }
 
@@ -188,7 +195,6 @@
     return result;
 }
 
-
 int32_t ZrtpDH::generateKey()
 {
     return DH_generate_key(static_cast<DH*>(ctx));
@@ -214,6 +220,27 @@
     RAND_bytes(buf, length);
 }
 
+int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes,
+                            int32_t length) const
+{
+    BIGNUM* pubKeyOther = BN_bin2bn(pubKeyBytes, length, NULL);
+
+    int one = BN_is_one(pubKeyOther);
+    if (one == 1)
+        return 0;
+
+    if (length == 384) {
+        if (BN_cmp(bnP3072MinusOne, pubKeyOther) == 0)
+            return 0;
+    }
+    else {
+        if (BN_cmp(bnP4096MinusOne, pubKeyOther) == 0)
+            return 0;
+    }
+    BN_free(pubKeyOther);
+    return 1;
+}
+
 /** EMACS **
  * Local variables:
  * mode: c++



More information about the Minisip-devel mailing list