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