blob: c7d2a464e33ffe1453031d65ef1e0be2d5f3a245 [file] [log] [blame]
Alexandre Lision51140e12013-12-02 10:54:09 -05001/*
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002 Copyright (C) 2006-2013 Werner Dittmann
Alexandre Lision51140e12013-12-02 10:54:09 -05003
4 This program is free software: you can redistribute it and/or modify
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05005 it under the terms of the GNU Lesser General Public License as published by
Alexandre Lision51140e12013-12-02 10:54:09 -05006 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050018/*
Alexandre Lision51140e12013-12-02 10:54:09 -050019 * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
20 */
21#include <sstream>
22
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050023#include <crypto/zrtpDH.h>
24#include <crypto/hmac256.h>
25#include <crypto/sha256.h>
26#include <crypto/hmac384.h>
27#include <crypto/sha384.h>
28
29#include <crypto/skeinMac256.h>
30#include <crypto/skein256.h>
31#include <crypto/skeinMac384.h>
32#include <crypto/skein384.h>
33
34#include <crypto/aesCFB.h>
35#include <crypto/twoCFB.h>
Alexandre Lision51140e12013-12-02 10:54:09 -050036
37#include <libzrtpcpp/ZRtp.h>
38#include <libzrtpcpp/ZrtpStateClass.h>
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050039#include <libzrtpcpp/ZIDCache.h>
Alexandre Lision51140e12013-12-02 10:54:09 -050040#include <libzrtpcpp/Base32.h>
41
42using namespace GnuZrtpCodes;
43
44/* disabled...but used in testing and debugging, probably should have a
45 controlling #define...
46 *
47static void hexdump(const char* title, const unsigned char *s, int l) {
48 int n=0;
49
50 if (s == NULL) return;
51
52 fprintf(stderr, "%s",title);
53 for( ; n < l ; ++n)
54 {
55 if((n%16) == 0)
56 fprintf(stderr, "\n%04x",n);
57 fprintf(stderr, " %02x",s[n]);
58 }
59 fprintf(stderr, "\n");
60}
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050061 * */
Alexandre Lision51140e12013-12-02 10:54:09 -050062
63/*
64 * This method simplifies detection of libzrtpcpp inside Automake, configure
65 * and friends
66 */
67#ifdef __cplusplus
68extern "C" {
69#endif
70 int ZrtpAvailable()
71 {
72 return 1;
73 }
74#ifdef __cplusplus
75}
76#endif
77
78ZRtp::ZRtp(uint8_t *myZid, ZrtpCallback *cb, std::string id, ZrtpConfigure* config, bool mitmm, bool sasSignSupport):
79 callback(cb), dhContext(NULL), DHss(NULL), auxSecret(NULL), auxSecretLength(0), rs1Valid(false),
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050080 rs2Valid(false), msgShaContext(NULL), hash(NULL), cipher(NULL), pubKey(NULL), sasType(NULL), authLength(NULL),
81 multiStream(false), multiStreamAvailable(false), peerIsEnrolled(false), mitmSeen(false), pbxSecretTmp(NULL),
82 enrollmentMode(false), configureAlgos(*config), zidRec(NULL), saveZidRecord(true) {
Alexandre Lision51140e12013-12-02 10:54:09 -050083
84 enableMitmEnrollment = config->isTrustedMitM();
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050085 signatureData = NULL;
Alexandre Lision51140e12013-12-02 10:54:09 -050086 paranoidMode = config->isParanoidMode();
87
88 // setup the implicit hash function pointers and length
89 hashLengthImpl = SHA256_DIGEST_LENGTH;
90 hashFunctionImpl = sha256;
91 hashListFunctionImpl = sha256;
92
93 hmacFunctionImpl = hmac_sha256;
94 hmacListFunctionImpl = hmac_sha256;
95
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050096 memcpy(ownZid, myZid, ZID_SIZE); // save the ZID
97
Alexandre Lision51140e12013-12-02 10:54:09 -050098 /*
99 * Generate H0 as a random number (256 bits, 32 bytes) and then
100 * the hash chain, refer to chapter 9. Use the implicit hash function.
101 */
102 randomZRTP(H0, HASH_IMAGE_SIZE);
103 sha256(H0, HASH_IMAGE_SIZE, H1); // hash H0 and generate H1
104 sha256(H1, HASH_IMAGE_SIZE, H2); // H2
105 sha256(H2, HASH_IMAGE_SIZE, H3); // H3
106
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500107 // configure all supported Hello packet versions
108 zrtpHello_11.configureHello(&configureAlgos);
109 zrtpHello_11.setH3(H3); // set H3 in Hello, included in helloHash
110 zrtpHello_11.setZid(ownZid);
111 zrtpHello_11.setVersion((uint8_t*)zrtpVersion_11);
Alexandre Lision51140e12013-12-02 10:54:09 -0500112
Alexandre Lision51140e12013-12-02 10:54:09 -0500113
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500114 zrtpHello_12.configureHello(&configureAlgos);
115 zrtpHello_12.setH3(H3); // set H3 in Hello, included in helloHash
116 zrtpHello_12.setZid(ownZid);
117 zrtpHello_12.setVersion((uint8_t*)zrtpVersion_12);
Alexandre Lision51140e12013-12-02 10:54:09 -0500118
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500119 if (mitmm) { // this session acts for a trusted MitM (PBX)
120 zrtpHello_11.setMitmMode();
121 zrtpHello_12.setMitmMode();
122 }
123 if (sasSignSupport) { // the application supports SAS signing
124 zrtpHello_11.setSasSign();
125 zrtpHello_12.setSasSign();
126 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500127
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500128 // Keep array in ascending order (greater index -> greater version)
129 helloPackets[0].packet = &zrtpHello_11;
130 helloPackets[0].version = zrtpHello_11.getVersionInt();
131 setClientId(id, &helloPackets[0]); // set id, compute HMAC and final helloHash
132
133 helloPackets[1].packet = &zrtpHello_12;
134 helloPackets[1].version = zrtpHello_12.getVersionInt();
135 setClientId(id, &helloPackets[1]); // set id, compute HMAC and final helloHash
136
137 currentHelloPacket = helloPackets[SUPPORTED_ZRTP_VERSIONS-1].packet; // start with highest supported version
138 helloPackets[SUPPORTED_ZRTP_VERSIONS].packet = NULL;
139 peerHelloVersion[0] = 0;
Alexandre Lision51140e12013-12-02 10:54:09 -0500140
141 stateEngine = new ZrtpStateClass(this);
142}
143
144ZRtp::~ZRtp() {
145 stopZrtp();
146 if (DHss != NULL) {
147 delete DHss;
148 DHss = NULL;
149 }
150 if (stateEngine != NULL) {
151 delete stateEngine;
152 stateEngine = NULL;
153 }
154 if (dhContext != NULL) {
155 delete dhContext;
156 dhContext = NULL;
157 }
158 if (msgShaContext != NULL) {
159 closeHashCtx(msgShaContext, NULL);
160 msgShaContext = NULL;
161 }
162 if (auxSecret != NULL) {
163 delete auxSecret;
164 auxSecret = NULL;
165 auxSecretLength = 0;
166 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500167 if (zidRec != NULL) {
168 delete zidRec;
169 zidRec = NULL;
170 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500171 memset(hmacKeyI, 0, MAX_DIGEST_LENGTH);
172 memset(hmacKeyR, 0, MAX_DIGEST_LENGTH);
173
174 memset(zrtpKeyI, 0, MAX_DIGEST_LENGTH);
175 memset(zrtpKeyR, 0, MAX_DIGEST_LENGTH);
176 /*
177 * Clear the Initiator's srtp key and salt
178 */
179 memset(srtpKeyI, 0, MAX_DIGEST_LENGTH);
180 memset(srtpSaltI, 0, MAX_DIGEST_LENGTH);
181 /*
182 * Clear he Responder's srtp key and salt
183 */
184 memset(srtpKeyR, 0, MAX_DIGEST_LENGTH);
185 memset(srtpSaltR, 0, MAX_DIGEST_LENGTH);
186
187 memset(zrtpSession, 0, MAX_DIGEST_LENGTH);
188}
189
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500190void ZRtp::processZrtpMessage(uint8_t *message, uint32_t pSSRC, size_t length) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500191 Event_t ev;
192
193 peerSSRC = pSSRC;
194 ev.type = ZrtpPacket;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500195 ev.length = length;
Alexandre Lision51140e12013-12-02 10:54:09 -0500196 ev.packet = message;
197
198 if (stateEngine != NULL) {
199 stateEngine->processEvent(&ev);
200 }
201}
202
203void ZRtp::processTimeout() {
204 Event_t ev;
205
206 ev.type = Timer;
207 if (stateEngine != NULL) {
208 stateEngine->processEvent(&ev);
209 }
210}
211
212#ifdef oldgoclear
213bool ZRtp::handleGoClear(uint8_t *message)
214{
215 char *msg, first, last;
216
217 msg = (char *)message + 4;
218 first = tolower(*msg);
219 last = tolower(*(msg+6));
220
221 if (first == 'g' && last == 'r') {
222 Event_t ev;
223
224 ev.type = ZrtpGoClear;
225 ev.packet = message;
226 if (stateEngine != NULL) {
227 stateEngine->processEvent(&ev);
228 }
229 return true;
230 }
231 else {
232 return false;
233 }
234}
235#endif
236
237void ZRtp::startZrtpEngine() {
238 Event_t ev;
239
240 if (stateEngine != NULL && stateEngine->inState(Initial)) {
241 ev.type = ZrtpInitial;
242 stateEngine->processEvent(&ev);
243 }
244}
245
246void ZRtp::stopZrtp() {
247 Event_t ev;
248
249 if (stateEngine != NULL) {
250 ev.type = ZrtpClose;
251 stateEngine->processEvent(&ev);
252 }
253}
254
255bool ZRtp::inState(int32_t state)
256{
257 if (stateEngine != NULL) {
258 return stateEngine->inState(state);
259 }
260 else {
261 return false;
262 }
263}
264
265ZrtpPacketHello* ZRtp::prepareHello() {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500266 return currentHelloPacket;
Alexandre Lision51140e12013-12-02 10:54:09 -0500267}
268
269ZrtpPacketHelloAck* ZRtp::prepareHelloAck() {
270 return &zrtpHelloAck;
271}
272
273/*
274 * At this point we will assume the role of Initiator. This role may change
275 * in case we have a commit-clash. Refer to chapter 5.2 in the spec how
276 * to break this tie.
277 */
278ZrtpPacketCommit* ZRtp::prepareCommit(ZrtpPacketHello *hello, uint32_t* errMsg) {
279
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500280 myRole = Initiator;
Alexandre Lision51140e12013-12-02 10:54:09 -0500281
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500282 if (!hello->isLengthOk()) {
283 *errMsg = CriticalSWError;
Alexandre Lision51140e12013-12-02 10:54:09 -0500284 return NULL;
285 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500286 // Save data before detailed checks - may aid in analysing problems
287 peerClientId.assign((char*)hello->getClientId(), ZRTP_WORD_SIZE * 4);
288 memcpy(peerHelloVersion, hello->getVersion(), ZRTP_WORD_SIZE);
289 peerHelloVersion[ZRTP_WORD_SIZE] = 0;
290
Alexandre Lision51140e12013-12-02 10:54:09 -0500291 // Save our peer's (presumably the Responder) ZRTP id
292 memcpy(peerZid, hello->getZid(), ZID_SIZE);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500293 if (memcmp(peerZid, ownZid, ZID_SIZE) == 0) { // peers have same ZID????
Alexandre Lision51140e12013-12-02 10:54:09 -0500294 *errMsg = EqualZIDHello;
295 return NULL;
296 }
297 memcpy(peerH3, hello->getH3(), HASH_IMAGE_SIZE);
298
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500299 int32_t helloLen = hello->getLength() * ZRTP_WORD_SIZE;
300
301 // calculate hash over the received Hello packet - is peer's hello hash.
302 // Use implicit hash algorithm
303 hashFunctionImpl((unsigned char*)hello->getHeaderBase(), helloLen, peerHelloHash);
304
305 sendInfo(Info, InfoHelloReceived);
306
Alexandre Lision51140e12013-12-02 10:54:09 -0500307 /*
308 * The Following section extracts the algorithm from the peer's Hello
309 * packet. Always the preferend offered algorithms are
310 * used. If the received Hello does not contain algo specifiers
311 * or offers only unsupported optional algos then replace
312 * these with mandatory algos and put them into the Commit packet.
313 * Refer to the findBest*() functions.
314 * If this is a MultiStream ZRTP object then do not get the cipher,
315 * authentication from hello packet but use the pre-initialized values
316 * as proposed by the standard. If we switch to responder mode the
317 * commit packet may contain other algos - see function
318 * prepareConfirm2MultiStream(...).
319 */
320 sasType = findBestSASType(hello);
321
322 if (!multiStream) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500323 pubKey = findBestPubkey(hello); // Check for public key algorithm first, must set 'hash' as well
324 if (hash == NULL) {
325 *errMsg = UnsuppHashType;
326 return NULL;
327 }
328 if (cipher == NULL) // public key selection may have set the cipher already
329 cipher = findBestCipher(hello, pubKey);
330 if (authLength == NULL) // public key selection may have set the SRTP authLen already
331 authLength = findBestAuthLen(hello);
Alexandre Lision51140e12013-12-02 10:54:09 -0500332 multiStreamAvailable = checkMultiStream(hello);
333 }
334 else {
335 if (checkMultiStream(hello)) {
336 return prepareCommitMultiStream(hello);
337 }
338 else {
339 // we are in multi-stream but peer does not offer multi-stream
340 // return error code to other party - unsupported PK, must be Mult
341 *errMsg = UnsuppPKExchange;
342 return NULL;
343 }
344 }
345 setNegotiatedHash(hash);
346
347 // Modify here when introducing new DH key agreement, for example
348 // elliptic curves.
349 dhContext = new ZrtpDH(pubKey->getName());
350 dhContext->generatePublicKey();
351
352 dhContext->getPubKeyBytes(pubKeyBytes);
353 sendInfo(Info, InfoCommitDHGenerated);
354
355 // Prepare IV data that we will use during confirm packet encryption.
356 randomZRTP(randomIV, sizeof(randomIV));
357
358 /*
359 * Prepare our DHPart2 packet here. Required to compute HVI. If we stay
360 * in Initiator role then we reuse this packet later in prepareDHPart2().
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500361 * To create this DH packet we have to compute the retained secret ids,
362 * thus get our peer's retained secret data first.
Alexandre Lision51140e12013-12-02 10:54:09 -0500363 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500364 zidRec = getZidCacheInstance()->getRecord(peerZid);
Alexandre Lision51140e12013-12-02 10:54:09 -0500365
366 //Compute the Initator's and Responder's retained secret ids.
367 computeSharedSecretSet(zidRec);
368
369 // Check if a PBX application set the MitM flag.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500370 mitmSeen = hello->isMitmMode();
Alexandre Lision51140e12013-12-02 10:54:09 -0500371
372 signSasSeen = hello->isSasSign();
373 // Construct a DHPart2 message (Initiator's DH message). This packet
374 // is required to compute the HVI (Hash Value Initiator), refer to
375 // chapter 5.4.1.1.
376
377 // Fill the values in the DHPart2 packet
378 zrtpDH2.setPubKeyType(pubKey->getName());
379 zrtpDH2.setMessageType((uint8_t*)DHPart2Msg);
380 zrtpDH2.setRs1Id(rs1IDi);
381 zrtpDH2.setRs2Id(rs2IDi);
382 zrtpDH2.setAuxSecretId(auxSecretIDi);
383 zrtpDH2.setPbxSecretId(pbxSecretIDi);
384 zrtpDH2.setPv(pubKeyBytes);
385 zrtpDH2.setH1(H1);
386
387 int32_t len = zrtpDH2.getLength() * ZRTP_WORD_SIZE;
388
389 // Compute HMAC over DH2, excluding the HMAC field (HMAC_SIZE)
390 // and store in DH2. Key to HMAC is H0, use HASH_IMAGE_SIZE bytes only.
391 // Must use implicit HMAC functions.
392 uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
393 uint32_t macLen;
394 hmacFunctionImpl(H0, HASH_IMAGE_SIZE, (uint8_t*)zrtpDH2.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
395 zrtpDH2.setHMAC(hmac);
396
397 // Compute the HVI, refer to chapter 5.4.1.1 of the specification
398 computeHvi(&zrtpDH2, hello);
399
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500400 zrtpCommit.setZid(ownZid);
Alexandre Lision51140e12013-12-02 10:54:09 -0500401 zrtpCommit.setHashType((uint8_t*)hash->getName());
402 zrtpCommit.setCipherType((uint8_t*)cipher->getName());
403 zrtpCommit.setAuthLen((uint8_t*)authLength->getName());
404 zrtpCommit.setPubKeyType((uint8_t*)pubKey->getName());
405 zrtpCommit.setSasType((uint8_t*)sasType->getName());
406 zrtpCommit.setHvi(hvi);
407 zrtpCommit.setH2(H2);
408
409 len = zrtpCommit.getLength() * ZRTP_WORD_SIZE;
410
411 // Compute HMAC over Commit, excluding the HMAC field (HMAC_SIZE)
412 // and store in Hello. Key to HMAC is H1, use HASH_IMAGE_SIZE bytes only.
413 // Must use implicit HMAC functions.
414 hmacFunctionImpl(H1, HASH_IMAGE_SIZE, (uint8_t*)zrtpCommit.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
415 zrtpCommit.setHMAC(hmac);
416
417 // hash first messages to produce overall message hash
418 // First the Responder's Hello message, second the Commit (always Initator's).
419 // Must use negotiated hash.
Alexandre Lision51140e12013-12-02 10:54:09 -0500420 msgShaContext = createHashCtx();
421 hashCtxFunction(msgShaContext, (unsigned char*)hello->getHeaderBase(), helloLen);
422 hashCtxFunction(msgShaContext, (unsigned char*)zrtpCommit.getHeaderBase(), len);
423
424 // store Hello data temporarily until we can check HMAC after receiving Commit as
425 // Responder or DHPart1 as Initiator
426 storeMsgTemp(hello);
427
Alexandre Lision51140e12013-12-02 10:54:09 -0500428 return &zrtpCommit;
429}
430
431ZrtpPacketCommit* ZRtp::prepareCommitMultiStream(ZrtpPacketHello *hello) {
432
433 randomZRTP(hvi, ZRTP_WORD_SIZE*4); // This is the Multi-Stream NONCE size
434
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500435 zrtpCommit.setZid(ownZid);
Alexandre Lision51140e12013-12-02 10:54:09 -0500436 zrtpCommit.setHashType((uint8_t*)hash->getName());
437 zrtpCommit.setCipherType((uint8_t*)cipher->getName());
438 zrtpCommit.setAuthLen((uint8_t*)authLength->getName());
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500439 zrtpCommit.setPubKeyType((uint8_t*)mult); // this is fixed because of Multi Stream mode
Alexandre Lision51140e12013-12-02 10:54:09 -0500440 zrtpCommit.setSasType((uint8_t*)sasType->getName());
441 zrtpCommit.setNonce(hvi);
442 zrtpCommit.setH2(H2);
443
444 int32_t len = zrtpCommit.getLength() * ZRTP_WORD_SIZE;
445
446 // Compute HMAC over Commit, excluding the HMAC field (HMAC_SIZE)
447 // and store in Hello. Key to HMAC is H1, use HASH_IMAGE_SIZE bytes only.
448 // Must use the implicit HMAC function.
449 uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
450 uint32_t macLen;
451 hmacFunctionImpl(H1, HASH_IMAGE_SIZE, (uint8_t*)zrtpCommit.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
452 zrtpCommit.setHMACMulti(hmac);
453
454
455 // hash first messages to produce overall message hash
456 // First the Responder's Hello message, second the Commit
457 // (always Initator's).
458 // Must use the negotiated hash.
459 msgShaContext = createHashCtx();
460
461 int32_t helloLen = hello->getLength() * ZRTP_WORD_SIZE;
462 hashCtxFunction(msgShaContext, (unsigned char*)hello->getHeaderBase(), helloLen);
463 hashCtxFunction(msgShaContext, (unsigned char*)zrtpCommit.getHeaderBase(), len);
464
465 // store Hello data temporarily until we can check HMAC after receiving Commit as
466 // Responder or DHPart1 as Initiator
467 storeMsgTemp(hello);
468
Alexandre Lision51140e12013-12-02 10:54:09 -0500469 return &zrtpCommit;
470}
471
472/*
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500473 * At this point we will take the role of the Responder. We have been in
Alexandre Lision51140e12013-12-02 10:54:09 -0500474 * the role of the Initiator before and already sent a commit packet that
475 * clashed with a commit packet from our peer. If our HVI was lower than our
476 * peer's HVI then we switched to Responder and handle our peer's commit packet
477 * here. This method takes care to delete and refresh data left over from a
478 * possible Initiator preparation. This belongs to prepared DH data, message
479 * hash SHA context
480 */
481ZrtpPacketDHPart* ZRtp::prepareDHPart1(ZrtpPacketCommit *commit, uint32_t* errMsg) {
482
483 sendInfo(Info, InfoRespCommitReceived);
484
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500485 if (!commit->isLengthOk(ZrtpPacketCommit::DhExchange)) {
486 *errMsg = CriticalSWError;
487 return NULL;
488 }
489
490 // Check if ZID in Commit is the same as we got in Hello
491 uint8_t tmpZid[ZID_SIZE];
492 memcpy(tmpZid, commit->getZid(), ZID_SIZE);
493 if (memcmp(peerZid, tmpZid, ZID_SIZE) != 0) { // ZIDs do not match????
494 sendInfo(Severe, SevereProtocolError);
495 *errMsg = CriticalSWError;
496 return NULL;
497 }
498
499 // The following code checks the hash chain according chapter 10 to detect false ZRTP packets.
Alexandre Lision51140e12013-12-02 10:54:09 -0500500 // Must use the implicit hash function.
501 uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH];
502 memcpy(peerH2, commit->getH2(), HASH_IMAGE_SIZE);
503 hashFunctionImpl(peerH2, HASH_IMAGE_SIZE, tmpH3);
504
505 if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) {
506 *errMsg = IgnorePacket;
507 return NULL;
508 }
509
510 // Check HMAC of previous Hello packet stored in temporary buffer. The
511 // HMAC key of peer's Hello packet is peer's H2 that is contained in the
512 // Commit packet. Refer to chapter 9.1.
513 if (!checkMsgHmac(peerH2)) {
514 sendInfo(Severe, SevereHelloHMACFailed);
515 *errMsg = CriticalSWError;
516 return NULL;
517 }
518
519 // check if we support the commited Cipher type
520 AlgorithmEnum* cp = &zrtpSymCiphers.getByName((const char*)commit->getCipherType());
521 if (!cp->isValid()) { // no match - something went wrong
522 *errMsg = UnsuppCiphertype;
523 return NULL;
524 }
525 cipher = cp;
526
527 // check if we support the commited Authentication length
528 cp = &zrtpAuthLengths.getByName((const char*)commit->getAuthLen());
529 if (!cp->isValid()) { // no match - something went wrong
530 *errMsg = UnsuppSRTPAuthTag;
531 return NULL;
532 }
533 authLength = cp;
534
535 // check if we support the commited hash type
536 cp = &zrtpHashes.getByName((const char*)commit->getHashType());
537 if (!cp->isValid()) { // no match - something went wrong
538 *errMsg = UnsuppHashType;
539 return NULL;
540 }
541 // check if the peer's commited hash is the same that we used when
542 // preparing our commit packet. If not do the necessary resets and
543 // recompute some data.
544 if (*(int32_t*)(hash->getName()) != *(int32_t*)(cp->getName())) {
545 hash = cp;
546 setNegotiatedHash(hash);
Alexandre Lision51140e12013-12-02 10:54:09 -0500547 // Compute the Initator's and Responder's retained secret ids
548 // with the committed hash.
549 computeSharedSecretSet(zidRec);
550 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500551 // check if we support the commited pub key type
552 cp = &zrtpPubKeys.getByName((const char*)commit->getPubKeysType());
553 if (!cp->isValid()) { // no match - something went wrong
554 *errMsg = UnsuppPKExchange;
555 return NULL;
556 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500557 if (*(int32_t*)(cp->getName()) == *(int32_t*)ec38 || *(int32_t*)(cp->getName()) == *(int32_t*)e414) {
558 if (!(*(int32_t*)(hash->getName()) == *(int32_t*)s384 || *(int32_t*)(hash->getName()) == *(int32_t*)skn3)) {
559 *errMsg = UnsuppHashType;
560 return NULL;
561 }
562 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500563 pubKey = cp;
564
565 // check if we support the commited SAS type
566 cp = &zrtpSasTypes.getByName((const char*)commit->getSasType());
567 if (!cp->isValid()) { // no match - something went wrong
568 *errMsg = UnsuppSASScheme;
569 return NULL;
570 }
571 sasType = cp;
572
573 // dhContext cannot be NULL - always setup during prepareCommit()
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500574 // check if we can use the dhContext prepared by prepareCommit(),
Alexandre Lision51140e12013-12-02 10:54:09 -0500575 // if not delete old DH context and generate new one
576 // The algorithm names are 4 chars only, thus we can cast to int32_t
577 if (*(int32_t*)(dhContext->getDHtype()) != *(int32_t*)(pubKey->getName())) {
578 delete dhContext;
579 dhContext = new ZrtpDH(pubKey->getName());
580 dhContext->generatePublicKey();
581 }
582 sendInfo(Info, InfoDH1DHGenerated);
583
584 dhContext->getPubKeyBytes(pubKeyBytes);
585
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500586 // Re-compute auxSecretIDr because we changed roles *IDr with my H3, *IDi with peer's H3
Alexandre Lision51140e12013-12-02 10:54:09 -0500587 // Setup a DHPart1 packet.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500588 myRole = Responder;
589 computeAuxSecretIds(); // recompute AUX secret ids because we are now Responder, use different H3
590
Alexandre Lision51140e12013-12-02 10:54:09 -0500591 zrtpDH1.setPubKeyType(pubKey->getName());
592 zrtpDH1.setMessageType((uint8_t*)DHPart1Msg);
593 zrtpDH1.setRs1Id(rs1IDr);
594 zrtpDH1.setRs2Id(rs2IDr);
595 zrtpDH1.setAuxSecretId(auxSecretIDr);
596 zrtpDH1.setPbxSecretId(pbxSecretIDr);
597 zrtpDH1.setPv(pubKeyBytes);
598 zrtpDH1.setH1(H1);
599
600 int32_t len = zrtpDH1.getLength() * ZRTP_WORD_SIZE;
601
602 // Compute HMAC over DHPart1, excluding the HMAC field (HMAC_SIZE)
603 // and store in DHPart1.
604 // Use implicit Hash function
605 uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
606 uint32_t macLen;
607 hmacFunctionImpl(H0, HASH_IMAGE_SIZE, (uint8_t*)zrtpDH1.getHeaderBase(), len-(HMAC_SIZE), hmac, &macLen);
608 zrtpDH1.setHMAC(hmac);
609
610 // We are definitly responder. Save the peer's hvi for later compare.
Alexandre Lision51140e12013-12-02 10:54:09 -0500611 memcpy(peerHvi, commit->getHvi(), HVI_SIZE);
612
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500613 // We are responder. Release the pre-computed SHA context because it was prepared for Initiator.
614 // Setup and compute for Responder.
Alexandre Lision51140e12013-12-02 10:54:09 -0500615 if (msgShaContext != NULL) {
616 closeHashCtx(msgShaContext, NULL);
617 }
618 msgShaContext = createHashCtx();
619
620 // Hash messages to produce overall message hash:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500621 // First the Responder's (my) Hello message, second the Commit (always Initator's),
622 // then the DH1 message (which is always a Responder's message).
623 // Must use negotiated hash.
624 hashCtxFunction(msgShaContext, (unsigned char*)currentHelloPacket->getHeaderBase(), currentHelloPacket->getLength() * ZRTP_WORD_SIZE);
Alexandre Lision51140e12013-12-02 10:54:09 -0500625 hashCtxFunction(msgShaContext, (unsigned char*)commit->getHeaderBase(), commit->getLength() * ZRTP_WORD_SIZE);
626 hashCtxFunction(msgShaContext, (unsigned char*)zrtpDH1.getHeaderBase(), zrtpDH1.getLength() * ZRTP_WORD_SIZE);
627
628 // store Commit data temporarily until we can check HMAC after we got DHPart2
629 storeMsgTemp(commit);
630
631 return &zrtpDH1;
632}
633
634/*
635 * At this point we will take the role of the Initiator.
636 */
637ZrtpPacketDHPart* ZRtp::prepareDHPart2(ZrtpPacketDHPart *dhPart1, uint32_t* errMsg) {
638
639 uint8_t* pvr;
640
641 sendInfo(Info, InfoInitDH1Received);
642
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500643 if (!dhPart1->isLengthOk()) {
644 *errMsg = CriticalSWError;
645 return NULL;
646 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500647 // Because we are initiator the protocol engine didn't receive Commit
648 // thus could not store a peer's H2. A two step SHA256 is required to
649 // re-compute H3. Then compare with peer's H3 from peer's Hello packet.
650 // Must use implicit hash function.
651 uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
652 hashFunctionImpl(dhPart1->getH1(), HASH_IMAGE_SIZE, tmpHash); // Compute peer's H2
653 memcpy(peerH2, tmpHash, HASH_IMAGE_SIZE);
654 hashFunctionImpl(peerH2, HASH_IMAGE_SIZE, tmpHash); // Compute peer's H3 (tmpHash)
655
656 if (memcmp(tmpHash, peerH3, HASH_IMAGE_SIZE) != 0) {
657 *errMsg = IgnorePacket;
658 return NULL;
659 }
660
661 // Check HMAC of previous Hello packet stored in temporary buffer. The
662 // HMAC key of the Hello packet is peer's H2 that was computed above.
663 // Refer to chapter 9.1 and chapter 10.
664 if (!checkMsgHmac(peerH2)) {
665 sendInfo(Severe, SevereHelloHMACFailed);
666 *errMsg = CriticalSWError;
667 return NULL;
668 }
669
670 // get memory to store DH result TODO: make it fixed memory
671 DHss = new uint8_t[dhContext->getDhSize()];
672 if (DHss == NULL) {
673 *errMsg = CriticalSWError;
674 return NULL;
675 }
676
677 // get and check Responder's public value, see chap. 5.4.3 in the spec
678 pvr = dhPart1->getPv();
679 if (!dhContext->checkPubKey(pvr)) {
680 *errMsg = DHErrorWrongPV;
681 return NULL;
682 }
683 dhContext->computeSecretKey(pvr, DHss);
684
Alexandre Lision51140e12013-12-02 10:54:09 -0500685 // We are Initiator: the Responder's Hello and the Initiator's (our) Commit
686 // are already hashed in the context. Now hash the Responder's DH1 and then
687 // the Initiator's (our) DH2 in that order.
688 // Use the negotiated hash function.
689 hashCtxFunction(msgShaContext, (unsigned char*)dhPart1->getHeaderBase(), dhPart1->getLength() * ZRTP_WORD_SIZE);
690 hashCtxFunction(msgShaContext, (unsigned char*)zrtpDH2.getHeaderBase(), zrtpDH2.getLength() * ZRTP_WORD_SIZE);
691
692 // Compute the message Hash
693 closeHashCtx(msgShaContext, messageHash);
694 msgShaContext = NULL;
Alexandre Lision51140e12013-12-02 10:54:09 -0500695 // Now compute the S0, all dependend keys and the new RS1. The function
696 // also performs sign SAS callback if it's active.
697 generateKeysInitiator(dhPart1, zidRec);
Alexandre Lision51140e12013-12-02 10:54:09 -0500698
699 delete dhContext;
700 dhContext = NULL;
701
702 // TODO: at initiator we can call signSAS at this point, don't dealy until confirm1 reveived
703 // store DHPart1 data temporarily until we can check HMAC after receiving Confirm1
704 storeMsgTemp(dhPart1);
705 return &zrtpDH2;
706}
707
708/*
709 * At this point we are Responder.
710 */
711ZrtpPacketConfirm* ZRtp::prepareConfirm1(ZrtpPacketDHPart* dhPart2, uint32_t* errMsg) {
712
713 uint8_t* pvi;
714
715 sendInfo(Info, InfoRespDH2Received);
716
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500717 if (!dhPart2->isLengthOk()) {
718 *errMsg = CriticalSWError;
719 return NULL;
720 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500721 // Because we are responder we received a Commit and stored its H2.
722 // Now re-compute H2 from received H1 and compare with stored peer's H2.
723 // Use implicit hash function
724 uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
725 hashFunctionImpl(dhPart2->getH1(), HASH_IMAGE_SIZE, tmpHash);
726 if (memcmp(tmpHash, peerH2, HASH_IMAGE_SIZE) != 0) {
727 *errMsg = IgnorePacket;
728 return NULL;
729 }
730
731 // Check HMAC of Commit packet stored in temporary buffer. The
732 // HMAC key of the Commit packet is peer's H1 that is contained in
733 // DHPart2. Refer to chapter 9.1 and chapter 10.
734 if (!checkMsgHmac(dhPart2->getH1())) {
735 sendInfo(Severe, SevereCommitHMACFailed);
736 *errMsg = CriticalSWError;
737 return NULL;
738 }
739 // Now we have the peer's pvi. Because we are responder re-compute my hvi
740 // using my Hello packet and the Initiator's DHPart2 and compare with
741 // hvi sent in commit packet. If it doesn't macht then a MitM attack
742 // may have occured.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500743 computeHvi(dhPart2, currentHelloPacket);
Alexandre Lision51140e12013-12-02 10:54:09 -0500744 if (memcmp(hvi, peerHvi, HVI_SIZE) != 0) {
745 *errMsg = DHErrorWrongHVI;
746 return NULL;
747 }
748 DHss = new uint8_t[dhContext->getDhSize()];
749 if (DHss == NULL) {
750 *errMsg = CriticalSWError;
751 return NULL;
752 }
753 // Get and check the Initiator's public value, see chap. 5.4.2 of the spec
754 pvi = dhPart2->getPv();
755 if (!dhContext->checkPubKey(pvi)) {
756 *errMsg = DHErrorWrongPV;
757 return NULL;
758 }
759 dhContext->computeSecretKey(pvi, DHss);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500760
761 // Hash the Initiator's DH2 into the message Hash (other messages already prepared, see method prepareDHPart1().
Alexandre Lision51140e12013-12-02 10:54:09 -0500762 // Use neotiated hash function
763 hashCtxFunction(msgShaContext, (unsigned char*)dhPart2->getHeaderBase(), dhPart2->getLength() * ZRTP_WORD_SIZE);
764
765 closeHashCtx(msgShaContext, messageHash);
766 msgShaContext = NULL;
Alexandre Lision51140e12013-12-02 10:54:09 -0500767 /*
768 * The expected shared secret Ids were already computed when we built the
769 * DHPart1 packet. Generate s0, all depended keys, and the new RS1 value
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500770 * for the ZID record. The functions also performs sign SAS callback if it's
771 * active. May reset the verify flag in ZID record.
Alexandre Lision51140e12013-12-02 10:54:09 -0500772 */
773 generateKeysResponder(dhPart2, zidRec);
Alexandre Lision51140e12013-12-02 10:54:09 -0500774
775 delete dhContext;
776 dhContext = NULL;
777
778 // Fill in Confirm1 packet.
779 zrtpConfirm1.setMessageType((uint8_t*)Confirm1Msg);
780
781 // Check if user verfied the SAS in a previous call and thus verfied
782 // the retained secret. Don't set the verified flag if paranoidMode is true.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500783 if (zidRec->isSasVerified() && !paranoidMode) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500784 zrtpConfirm1.setSASFlag();
785 }
786 zrtpConfirm1.setExpTime(0xFFFFFFFF);
787 zrtpConfirm1.setIv(randomIV);
788 zrtpConfirm1.setHashH0(H0);
789
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500790 // if this runs at PBX user agent enrollment service then set flag in confirm
Alexandre Lision51140e12013-12-02 10:54:09 -0500791 // packet and store the MitM key
792 if (enrollmentMode) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500793 // As clarification to RFC6189: store new PBX secret only if we don't have
794 // a matching PBX secret for the peer's ZID.
795 if (!peerIsEnrolled) {
796 computePBXSecret();
797 zidRec->setMiTMData(pbxSecretTmp);
798 }
799 // Set flag to enable user's client to ask for confirmation or re-confirmation.
Alexandre Lision51140e12013-12-02 10:54:09 -0500800 zrtpConfirm1.setPBXEnrollment();
Alexandre Lision51140e12013-12-02 10:54:09 -0500801 }
802 uint8_t confMac[MAX_DIGEST_LENGTH];
803 uint32_t macLen;
804
805 // Encrypt and HMAC with Responder's key - we are Respondere here
806 int hmlen = (zrtpConfirm1.getLength() - 9) * ZRTP_WORD_SIZE;
807 cipher->getEncrypt()(zrtpKeyR, cipher->getKeylen(), randomIV, zrtpConfirm1.getHashH0(), hmlen);
808 hmacFunction(hmacKeyR, hashLength, (unsigned char*)zrtpConfirm1.getHashH0(), hmlen, confMac, &macLen);
809
810 zrtpConfirm1.setHmac(confMac);
811
812 // store DHPart2 data temporarily until we can check HMAC after receiving Confirm2
813 storeMsgTemp(dhPart2);
814 return &zrtpConfirm1;
815}
816
817/*
818 * At this point we are Responder.
819 */
820ZrtpPacketConfirm* ZRtp::prepareConfirm1MultiStream(ZrtpPacketCommit* commit, uint32_t* errMsg) {
821
822 sendInfo(Info, InfoRespCommitReceived);
823
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500824 if (!commit->isLengthOk(ZrtpPacketCommit::MultiStream)) {
825 *errMsg = CriticalSWError;
826 return NULL;
827 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500828 // The following code checks the hash chain according chapter 10 to detect
829 // false ZRTP packets.
830 // Use implicit hash function
831 uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH];
832 memcpy(peerH2, commit->getH2(), HASH_IMAGE_SIZE);
833 hashFunctionImpl(peerH2, HASH_IMAGE_SIZE, tmpH3);
834
835 if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) {
836 *errMsg = IgnorePacket;
837 return NULL;
838 }
839
840 // Check HMAC of previous Hello packet stored in temporary buffer. The
841 // HMAC key of peer's Hello packet is peer's H2 that is contained in the
842 // Commit packet. Refer to chapter 9.1.
843 if (!checkMsgHmac(peerH2)) {
844 sendInfo(Severe, SevereHelloHMACFailed);
845 *errMsg = CriticalSWError;
846 return NULL;
847 }
848
849 // check if Commit contains "Mult" as pub key type
850 AlgorithmEnum* cp = &zrtpPubKeys.getByName((const char*)commit->getPubKeysType());
851 if (!cp->isValid() || *(int32_t*)(cp->getName()) != *(int32_t*)mult) {
852 *errMsg = UnsuppPKExchange;
853 return NULL;
854 }
855
856 // check if we support the commited cipher
857 cp = &zrtpSymCiphers.getByName((const char*)commit->getCipherType());
858 if (!cp->isValid()) { // no match - something went wrong
859 *errMsg = UnsuppCiphertype;
860 return NULL;
861 }
862 cipher = cp;
863
864 // check if we support the commited Authentication length
865 cp = &zrtpAuthLengths.getByName((const char*)commit->getAuthLen());
866 if (!cp->isValid()) { // no match - something went wrong
867 *errMsg = UnsuppSRTPAuthTag;
868 return NULL;
869 }
870 authLength = cp;
871
872 // check if we support the commited hash type
873 cp = &zrtpHashes.getByName((const char*)commit->getHashType());
874 if (!cp->isValid()) { // no match - something went wrong
875 *errMsg = UnsuppHashType;
876 return NULL;
877 }
878 // check if the peer's commited hash is the same that we used when
879 // preparing our commit packet. If not do the necessary resets and
880 // recompute some data.
881 if (*(int32_t*)(hash->getName()) != *(int32_t*)(cp->getName())) {
882 hash = cp;
883 setNegotiatedHash(hash);
884 }
885 myRole = Responder;
886
887 // We are responder. Release a possibly pre-computed SHA256 context
888 // because this was prepared for Initiator. Then create a new one.
889 if (msgShaContext != NULL) {
890 closeHashCtx(msgShaContext, NULL);
891 }
892 msgShaContext = createHashCtx();
893
894 // Hash messages to produce overall message hash:
895 // First the Responder's (my) Hello message, second the Commit
896 // (always Initator's)
897 // use negotiated hash
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500898 hashCtxFunction(msgShaContext, (unsigned char*)currentHelloPacket->getHeaderBase(), currentHelloPacket->getLength() * ZRTP_WORD_SIZE);
Alexandre Lision51140e12013-12-02 10:54:09 -0500899 hashCtxFunction(msgShaContext, (unsigned char*)commit->getHeaderBase(), commit->getLength() * ZRTP_WORD_SIZE);
900
901 closeHashCtx(msgShaContext, messageHash);
902 msgShaContext = NULL;
903
904 generateKeysMultiStream();
905
906 // Fill in Confirm1 packet.
907 zrtpConfirm1.setMessageType((uint8_t*)Confirm1Msg);
908 zrtpConfirm1.setExpTime(0xFFFFFFFF);
909 zrtpConfirm1.setIv(randomIV);
910 zrtpConfirm1.setHashH0(H0);
911
912 uint8_t confMac[MAX_DIGEST_LENGTH];
913 uint32_t macLen;
914
915 // Encrypt and HMAC with Responder's key - we are Respondere here
916 int32_t hmlen = (zrtpConfirm1.getLength() - 9) * ZRTP_WORD_SIZE;
917 cipher->getEncrypt()(zrtpKeyR, cipher->getKeylen(), randomIV, zrtpConfirm1.getHashH0(), hmlen);
918
919 // Use negotiated HMAC (hash)
920 hmacFunction(hmacKeyR, hashLength, (unsigned char*)zrtpConfirm1.getHashH0(), hmlen, confMac, &macLen);
921
922 zrtpConfirm1.setHmac(confMac);
923
924 // Store Commit data temporarily until we can check HMAC after receiving Confirm2
925 storeMsgTemp(commit);
926 return &zrtpConfirm1;
927}
928
929/*
930 * At this point we are Initiator.
931 */
932ZrtpPacketConfirm* ZRtp::prepareConfirm2(ZrtpPacketConfirm* confirm1, uint32_t* errMsg) {
933
934 sendInfo(Info, InfoInitConf1Received);
935
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500936 if (!confirm1->isLengthOk()) {
937 *errMsg = CriticalSWError;
938 return NULL;
939 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500940 uint8_t confMac[MAX_DIGEST_LENGTH];
941 uint32_t macLen;
942
943 // Use the Responder's keys here because we are Initiator here and
944 // receive packets from Responder
945 int16_t hmlen = (confirm1->getLength() - 9) * ZRTP_WORD_SIZE;
946
947 // Use negotiated HMAC (hash)
948 hmacFunction(hmacKeyR, hashLength, (unsigned char*)confirm1->getHashH0(), hmlen, confMac, &macLen);
949
950 if (memcmp(confMac, confirm1->getHmac(), HMAC_SIZE) != 0) {
951 *errMsg = ConfirmHMACWrong;
952 return NULL;
953 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500954 cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), (uint8_t*)confirm1->getIv(), confirm1->getHashH0(), hmlen);
Alexandre Lision51140e12013-12-02 10:54:09 -0500955
956 // Check HMAC of DHPart1 packet stored in temporary buffer. The
957 // HMAC key of the DHPart1 packet is peer's H0 that is contained in
958 // Confirm1. Refer to chapter 9.
959 if (!checkMsgHmac(confirm1->getHashH0())) {
960 sendInfo(Severe, SevereDH1HMACFailed);
961 *errMsg = CriticalSWError;
962 return NULL;
963 }
964 signatureLength = confirm1->getSignatureLength();
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500965 if (signSasSeen && signatureLength > 0 && confirm1->isSignatureLengthOk()) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500966 signatureData = confirm1->getSignatureData();
967 callback->checkSASSignature(sasHash);
968 // TODO: error handling if checkSASSignature returns false.
969 }
970 /*
971 * The Confirm1 is ok, handle the Retained secret stuff and inform
972 * GUI about state.
973 */
974 bool sasFlag = confirm1->isSASFlag();
975
Alexandre Lision51140e12013-12-02 10:54:09 -0500976 // Our peer did not confirm the SAS in last session, thus reset
977 // our SAS flag too. Reset the flag also if paranoidMode is true.
978 if (!sasFlag || paranoidMode) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500979 zidRec->resetSasVerified();
Alexandre Lision51140e12013-12-02 10:54:09 -0500980 }
981 // get verified flag from current RS1 before set a new RS1. This
982 // may not be set even if peer's flag is set in confirm1 message.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500983 sasFlag = zidRec->isSasVerified();
Alexandre Lision51140e12013-12-02 10:54:09 -0500984
985 // now we are ready to save the new RS1 which inherits the verified
986 // flag from old RS1
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500987 zidRec->setNewRs1((const uint8_t*)newRs1);
Alexandre Lision51140e12013-12-02 10:54:09 -0500988
989 // now generate my Confirm2 message
990 zrtpConfirm2.setMessageType((uint8_t*)Confirm2Msg);
991 zrtpConfirm2.setHashH0(H0);
992
993 if (sasFlag) {
994 zrtpConfirm2.setSASFlag();
995 }
996 zrtpConfirm2.setExpTime(0xFFFFFFFF);
997 zrtpConfirm2.setIv(randomIV);
998
999 // Compute PBX secret if we are in enrollemnt mode (PBX user agent)
1000 // or enrollment was enabled at normal user agent and flag in confirm packet
1001 if (enrollmentMode || (enableMitmEnrollment && confirm1->isPBXEnrollment())) {
1002 computePBXSecret();
1003
1004 // if this runs at PBX user agent enrollment service then set flag in confirm
1005 // packet and store the MitM key. The PBX user agent service always stores
1006 // its MitM key.
1007 if (enrollmentMode) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001008 // As clarification to RFC6189: store new PBX secret only if we don't have
1009 // a matching PBX secret for the peer's ZID.
1010 if (!peerIsEnrolled) {
1011 computePBXSecret();
1012 zidRec->setMiTMData(pbxSecretTmp);
1013 }
1014 // Set flag to enable user's client to ask for confirmation or re-confirmation.
Alexandre Lision51140e12013-12-02 10:54:09 -05001015 zrtpConfirm2.setPBXEnrollment();
Alexandre Lision51140e12013-12-02 10:54:09 -05001016 }
1017 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001018 if (saveZidRecord)
1019 getZidCacheInstance()->saveRecord(zidRec);
1020
Alexandre Lision51140e12013-12-02 10:54:09 -05001021 // Encrypt and HMAC with Initiator's key - we are Initiator here
1022 hmlen = (zrtpConfirm2.getLength() - 9) * ZRTP_WORD_SIZE;
1023 cipher->getEncrypt()(zrtpKeyI, cipher->getKeylen(), randomIV, zrtpConfirm2.getHashH0(), hmlen);
1024
1025 // Use negotiated HMAC (hash)
1026 hmacFunction(hmacKeyI, hashLength, (unsigned char*)zrtpConfirm2.getHashH0(), hmlen, confMac, &macLen);
1027
1028 zrtpConfirm2.setHmac(confMac);
1029
1030 // Ask for enrollment only if enabled via configuration and the
1031 // confirm1 packet contains the enrollment flag. The enrolling user
1032 // agent stores the MitM key only if the user accepts the enrollment
1033 // request.
1034 if (enableMitmEnrollment && confirm1->isPBXEnrollment()) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001035 // As clarification to RFC6189: if already enrolled (having a matching PBX secret)
1036 // ask for reconfirmation.
1037 if (!peerIsEnrolled) {
1038 callback->zrtpAskEnrollment(EnrollmentRequest);
1039 }
1040 else {
1041 callback->zrtpAskEnrollment(EnrollmentReconfirm);
1042 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001043 }
1044 return &zrtpConfirm2;
1045}
1046
Alexandre Lision51140e12013-12-02 10:54:09 -05001047/*
1048 * At this point we are Initiator.
1049 */
1050ZrtpPacketConfirm* ZRtp::prepareConfirm2MultiStream(ZrtpPacketConfirm* confirm1, uint32_t* errMsg) {
1051
1052 // check Confirm1 packet using the keys
1053 // prepare Confirm2 packet
1054 // don't update SAS, RS
1055 sendInfo(Info, InfoInitConf1Received);
1056
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001057 if (!confirm1->isLengthOk()) {
1058 *errMsg = CriticalSWError;
1059 return NULL;
1060 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001061 uint8_t confMac[MAX_DIGEST_LENGTH];
1062 uint32_t macLen;
1063
1064 closeHashCtx(msgShaContext, messageHash);
1065 msgShaContext = NULL;
1066 myRole = Initiator;
1067
1068 generateKeysMultiStream();
1069
1070 // Use the Responder's keys here because we are Initiator here and
1071 // receive packets from Responder
1072 int32_t hmlen = (confirm1->getLength() - 9) * ZRTP_WORD_SIZE;
1073
1074 // Use negotiated HMAC (hash)
1075 hmacFunction(hmacKeyR, hashLength, (unsigned char*)confirm1->getHashH0(), hmlen, confMac, &macLen);
1076
1077 if (memcmp(confMac, confirm1->getHmac(), HMAC_SIZE) != 0) {
1078 *errMsg = ConfirmHMACWrong;
1079 return NULL;
1080 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001081 // Cast away the const for the IV - the standalone AES CFB modifies IV on return
1082 cipher->getDecrypt()(zrtpKeyR, cipher->getKeylen(), (uint8_t*)confirm1->getIv(), confirm1->getHashH0(), hmlen);
Alexandre Lision51140e12013-12-02 10:54:09 -05001083
1084 // Because we are initiator the protocol engine didn't receive Commit and
1085 // because we are using multi-stream mode here we also did not receive a DHPart1 and
1086 // thus could not store a responder's H2 or H1. A two step hash is required to
1087 // re-compute H1, H2.
1088 // USe implicit hash function.
1089 uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
1090 hashFunctionImpl(confirm1->getHashH0(), HASH_IMAGE_SIZE, tmpHash); // Compute peer's H1 in tmpHash
1091 hashFunctionImpl(tmpHash, HASH_IMAGE_SIZE, tmpHash); // Compute peer's H2 in tmpHash
1092 memcpy(peerH2, tmpHash, HASH_IMAGE_SIZE); // copy and truncate to peerH2
1093
1094 // Check HMAC of previous Hello packet stored in temporary buffer. The
1095 // HMAC key of the Hello packet is peer's H2 that was computed above.
1096 // Refer to chapter 9.1 and chapter 10.
1097 if (!checkMsgHmac(peerH2)) {
1098 sendInfo(Severe, SevereHelloHMACFailed);
1099 *errMsg = CriticalSWError;
1100 return NULL;
1101 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001102 // now generate my Confirm2 message
1103 zrtpConfirm2.setMessageType((uint8_t*)Confirm2Msg);
1104 zrtpConfirm2.setHashH0(H0);
1105 zrtpConfirm2.setExpTime(0xFFFFFFFF);
1106 zrtpConfirm2.setIv(randomIV);
1107
1108 // Encrypt and HMAC with Initiator's key - we are Initiator here
1109 hmlen = (zrtpConfirm2.getLength() - 9) * ZRTP_WORD_SIZE;
1110 cipher->getEncrypt()(zrtpKeyI, cipher->getKeylen(), randomIV, zrtpConfirm2.getHashH0(), hmlen);
1111
1112 // Use negotiated HMAC (hash)
1113 hmacFunction(hmacKeyI, hashLength, (unsigned char*)zrtpConfirm2.getHashH0(), hmlen, confMac, &macLen);
1114
1115 zrtpConfirm2.setHmac(confMac);
1116 return &zrtpConfirm2;
1117}
1118
1119/*
1120 * At this point we are Responder.
1121 */
1122ZrtpPacketConf2Ack* ZRtp::prepareConf2Ack(ZrtpPacketConfirm *confirm2, uint32_t* errMsg) {
1123
1124 sendInfo(Info, InfoRespConf2Received);
1125
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001126 if (!confirm2->isLengthOk()) {
1127 *errMsg = CriticalSWError;
1128 return NULL;
1129 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001130 uint8_t confMac[MAX_DIGEST_LENGTH];
1131 uint32_t macLen;
1132
1133 // Use the Initiator's keys here because we are Responder here and
1134 // reveice packets from Initiator
1135 int16_t hmlen = (confirm2->getLength() - 9) * ZRTP_WORD_SIZE;
1136
1137 // Use negotiated HMAC (hash)
1138 hmacFunction(hmacKeyI, hashLength,
1139 (unsigned char*)confirm2->getHashH0(),
1140 hmlen, confMac, &macLen);
1141
1142 if (memcmp(confMac, confirm2->getHmac(), HMAC_SIZE) != 0) {
1143 *errMsg = ConfirmHMACWrong;
1144 return NULL;
1145 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001146 // Cast away the const for the IV - the standalone AES CFB modifies IV on return
1147 cipher->getDecrypt()(zrtpKeyI, cipher->getKeylen(), (uint8_t*)confirm2->getIv(), confirm2->getHashH0(), hmlen);
Alexandre Lision51140e12013-12-02 10:54:09 -05001148
1149 if (!multiStream) {
1150 // Check HMAC of DHPart2 packet stored in temporary buffer. The
1151 // HMAC key of the DHPart2 packet is peer's H0 that is contained in
1152 // Confirm2. Refer to chapter 9.1 and chapter 10.
1153 if (!checkMsgHmac(confirm2->getHashH0())) {
1154 sendInfo(Severe, SevereDH2HMACFailed);
1155 *errMsg = CriticalSWError;
1156 return NULL;
1157 }
1158 signatureLength = confirm2->getSignatureLength();
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001159 if (signSasSeen && signatureLength > 0 && confirm2->isSignatureLengthOk() ) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001160 signatureData = confirm2->getSignatureData();
1161 callback->checkSASSignature(sasHash);
1162 // TODO: error handling if checkSASSignature returns false.
1163 }
1164 /*
1165 * The Confirm2 is ok, handle the Retained secret stuff and inform
1166 * GUI about state.
1167 */
1168 bool sasFlag = confirm2->isSASFlag();
Alexandre Lision51140e12013-12-02 10:54:09 -05001169 // Our peer did not confirm the SAS in last session, thus reset
1170 // our SAS flag too. Reset the flag also if paranoidMode is true.
1171 if (!sasFlag || paranoidMode) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001172 zidRec->resetSasVerified();
Alexandre Lision51140e12013-12-02 10:54:09 -05001173 }
1174
Alexandre Lision51140e12013-12-02 10:54:09 -05001175 // save new RS1, this inherits the verified flag from old RS1
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001176 zidRec->setNewRs1((const uint8_t*)newRs1);
1177 if (saveZidRecord)
1178 getZidCacheInstance()->saveRecord(zidRec);
Alexandre Lision51140e12013-12-02 10:54:09 -05001179
1180 // Ask for enrollment only if enabled via configuration and the
1181 // confirm packet contains the enrollment flag. The enrolling user
1182 // agent stores the MitM key only if the user accepts the enrollment
1183 // request.
1184 if (enableMitmEnrollment && confirm2->isPBXEnrollment()) {
1185 computePBXSecret();
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001186 // As clarification to RFC6189: if already enrolled (having a matching PBX secret)
1187 // ask for reconfirmation.
1188 if (!peerIsEnrolled) {
1189 callback->zrtpAskEnrollment(EnrollmentRequest);
1190 }
1191 else {
1192 callback->zrtpAskEnrollment(EnrollmentReconfirm);
1193 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001194 }
1195 }
1196 else {
1197 // Check HMAC of Commit packet stored in temporary buffer. The
1198 // HMAC key of the Commit packet is initiator's H1
1199 // use implicit hash function.
1200 uint8_t tmpHash[IMPL_MAX_DIGEST_LENGTH];
1201 hashFunctionImpl(confirm2->getHashH0(), HASH_IMAGE_SIZE, tmpHash); // Compute initiator's H1 in tmpHash
1202
1203 if (!checkMsgHmac(tmpHash)) {
1204 sendInfo(Severe, SevereCommitHMACFailed);
1205 *errMsg = CriticalSWError;
1206 return NULL;
1207 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001208 }
1209 return &zrtpConf2Ack;
1210}
1211
1212ZrtpPacketErrorAck* ZRtp::prepareErrorAck(ZrtpPacketError* epkt) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001213 if (epkt->getLength() < 4)
1214 sendInfo(ZrtpError, CriticalSWError * -1);
1215 else
1216 sendInfo(ZrtpError, epkt->getErrorCode() * -1);
Alexandre Lision51140e12013-12-02 10:54:09 -05001217 return &zrtpErrorAck;
1218}
1219
1220ZrtpPacketError* ZRtp::prepareError(uint32_t errMsg) {
1221 zrtpError.setErrorCode(errMsg);
1222 return &zrtpError;
1223}
1224
1225ZrtpPacketPingAck* ZRtp::preparePingAck(ZrtpPacketPing* ppkt) {
1226 if (ppkt->getLength() != 6) // A PING packet must have a length of 6 words
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001227 return NULL;
Alexandre Lision51140e12013-12-02 10:54:09 -05001228 // Because we do not support ZRTP proxy mode use the truncated ZID.
1229 // If this code shall be used in ZRTP proxy implementation the computation
1230 // of the endpoint hash must be enhanced (see chaps 5.15ff and 5.16)
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001231 zrtpPingAck.setLocalEpHash(ownZid);
Alexandre Lision51140e12013-12-02 10:54:09 -05001232 zrtpPingAck.setRemoteEpHash(ppkt->getEpHash());
1233 zrtpPingAck.setSSRC(peerSSRC);
1234 return &zrtpPingAck;
1235}
1236
1237ZrtpPacketRelayAck* ZRtp::prepareRelayAck(ZrtpPacketSASrelay* srly, uint32_t* errMsg) {
1238 // handle and render SAS relay data only if the peer announced that it is a trusted
1239 // PBX. Don't handle SAS relay in paranoidMode.
1240 if (!mitmSeen || paranoidMode)
1241 return &zrtpRelayAck;
1242
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001243 if (!srly->isLengthOk()) {
1244 *errMsg = CriticalSWError;
1245 return NULL;
1246 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001247 uint8_t* hkey, *ekey;
1248 // If we are responder then the PBX used it's Initiator keys
1249 if (myRole == Responder) {
1250 hkey = hmacKeyI;
1251 ekey = zrtpKeyI;
1252 }
1253 else {
1254 hkey = hmacKeyR;
1255 ekey = zrtpKeyR;
1256 }
1257
1258 uint8_t confMac[MAX_DIGEST_LENGTH];
1259 uint32_t macLen;
1260
Alexandre Lision51140e12013-12-02 10:54:09 -05001261 int16_t hmlen = (srly->getLength() - 9) * ZRTP_WORD_SIZE;
1262
1263 // Use negotiated HMAC (hash)
1264 hmacFunction(hkey, hashLength, (unsigned char*)srly->getFiller(), hmlen, confMac, &macLen);
1265
1266 if (memcmp(confMac, srly->getHmac(), HMAC_SIZE) != 0) {
1267 *errMsg = ConfirmHMACWrong;
1268 return NULL; // TODO - check error handling
1269 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001270 // Cast away the const for the IV - the standalone AES CFB modifies IV on return
1271 cipher->getDecrypt()(ekey, cipher->getKeylen(), (uint8_t*)srly->getIv(), (uint8_t*)srly->getFiller(), hmlen);
Alexandre Lision51140e12013-12-02 10:54:09 -05001272
Alexandre Lision51140e12013-12-02 10:54:09 -05001273 const uint8_t* newSasHash = srly->getTrustedSas();
Alexandre Lision51140e12013-12-02 10:54:09 -05001274 bool sasHashNull = true;
1275 for (int i = 0; i < HASH_IMAGE_SIZE; i++) {
1276 if (newSasHash[i] != 0) {
1277 sasHashNull = false;
1278 break;
1279 }
1280 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001281 std::string cs(cipher->getReadable());
1282 cs.append("/").append(pubKey->getName());
1283
Alexandre Lision51140e12013-12-02 10:54:09 -05001284 // Check if new SAS is null or a trusted MitM relationship doesn't exist.
1285 // If this is the case then don't render and don't show the new SAS - use
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001286 // our computed SAS hash but we may use a different SAS rendering algorithm to
Alexandre Lision51140e12013-12-02 10:54:09 -05001287 // render the computed SAS.
1288 if (sasHashNull || !peerIsEnrolled) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001289 cs.append("/MitM");
Alexandre Lision51140e12013-12-02 10:54:09 -05001290 newSasHash = sasHash;
1291 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001292 else {
1293 cs.append("/SASviaMitM");
1294 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001295 // If other SAS schemes required - check here and use others
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001296 const uint8_t* render = srly->getSasAlgo();
Alexandre Lision51140e12013-12-02 10:54:09 -05001297 AlgorithmEnum* renderAlgo = &zrtpSasTypes.getByName((const char*)render);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001298 uint8_t sasBytes[4];
Alexandre Lision51140e12013-12-02 10:54:09 -05001299 if (renderAlgo->isValid()) {
1300 sasBytes[0] = newSasHash[0];
1301 sasBytes[1] = newSasHash[1];
1302 sasBytes[2] = newSasHash[2] & 0xf0;
1303 sasBytes[3] = 0;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001304 if (*(int32_t*)b32 == *(int32_t*)(renderAlgo->getName())) {
1305 SAS = Base32(sasBytes, 20).getEncoded();
1306 }
1307 else {
1308 SAS.assign(sas256WordsEven[sasBytes[0]]).append(":").append(sas256WordsOdd[sasBytes[1]]);
1309 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001310 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001311 bool verify = zidRec->isSasVerified() && srly->isSASFlag();
1312 callback->srtpSecretsOn(cs, SAS, verify);
Alexandre Lision51140e12013-12-02 10:54:09 -05001313 return &zrtpRelayAck;
1314}
1315
1316// TODO Implement GoClear handling
1317ZrtpPacketClearAck* ZRtp::prepareClearAck(ZrtpPacketGoClear* gpkt) {
1318 sendInfo(Warning, WarningGoClearReceived);
1319 return &zrtpClearAck;
1320}
1321
1322ZrtpPacketGoClear* ZRtp::prepareGoClear(uint32_t errMsg) {
1323 ZrtpPacketGoClear* gclr = &zrtpGoClear;
1324 gclr->clrClearHmac();
1325 return gclr;
1326}
1327
1328/*
1329 * The next functions look up and return a prefered algorithm. These
1330 * functions work as follows:
1331 * - If the Hello packet does not contain an algorithm (number of algorithms
1332* is zero) then return the mandatory algorithm.
1333 * - Build a list of algorithm names and ids from configuration data. If
1334 * the configuration data does not contain a mandatory algorithm append
1335 * the mandatory algorithm to the list and ids.
1336 * - Build a list of algorithm names from the Hello message. If
1337 * the Hello message does not contain a mandatory algorithm append
1338 * the mandatory algorithm to the list.
1339 * - Lookup a matching algorithm. The list built from Hello takes
1340 * precedence in the lookup (indexed by the outermost loop).
1341 *
1342 * This guarantees that we always return a supported alogrithm respecting
1343 * the order of algorithms in the Hello message
1344 *
1345 * The mandatory algorithms are: (internal enums are our prefered algoritms)
1346 * Hash: S256 (SHA 256) (internal enum Sha256)
1347 * Symmetric Cipher: AES1 (AES 128) (internal enum Aes128)
1348 * SRTP Authentication: HS32 and HS80 (32/80 bits) (internal enum AuthLen32)
1349 * Key Agreement: DH3k (3072 Diffie-Helman) (internal enum Dh3072)
1350 *
1351 */
1352AlgorithmEnum* ZRtp::findBestHash(ZrtpPacketHello *hello) {
1353
1354 int i;
1355 int ii;
1356 int numAlgosOffered;
1357 AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1];
1358
1359 int numAlgosConf;
1360 AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
1361
Alexandre Lision51140e12013-12-02 10:54:09 -05001362 // If Hello does not contain any hash names return Sha256, its mandatory
1363 int num = hello->getNumHashes();
1364 if (num == 0) {
1365 return &zrtpHashes.getByName(mandatoryHash);
1366 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001367 // Build list of configured hash algorithm names.
Alexandre Lision51140e12013-12-02 10:54:09 -05001368 numAlgosConf = configureAlgos.getNumConfiguredAlgos(HashAlgorithm);
1369 for (i = 0; i < numAlgosConf; i++) {
1370 algosConf[i] = &configureAlgos.getAlgoAt(HashAlgorithm, i);
Alexandre Lision51140e12013-12-02 10:54:09 -05001371 }
1372
1373 // Build list of offered known algos in Hello, append mandatory algos if necessary
Alexandre Lision51140e12013-12-02 10:54:09 -05001374 for (numAlgosOffered = 0, i = 0; i < num; i++) {
1375 algosOffered[numAlgosOffered] = &zrtpHashes.getByName((const char*)hello->getHashType(i));
1376 if (!algosOffered[numAlgosOffered]->isValid())
1377 continue;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001378 numAlgosOffered++;
Alexandre Lision51140e12013-12-02 10:54:09 -05001379 }
1380
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001381 // Lookup offered algos in configured algos.
Alexandre Lision51140e12013-12-02 10:54:09 -05001382 for (i = 0; i < numAlgosOffered; i++) {
1383 for (ii = 0; ii < numAlgosConf; ii++) {
1384 if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
1385 return algosConf[ii];
1386 }
1387 }
1388 }
1389 return &zrtpHashes.getByName(mandatoryHash);
1390}
1391
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001392
Alexandre Lision51140e12013-12-02 10:54:09 -05001393AlgorithmEnum* ZRtp::findBestCipher(ZrtpPacketHello *hello, AlgorithmEnum* pk) {
1394
1395 int i;
1396 int ii;
1397 int numAlgosOffered;
1398 AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1];
1399
1400 int numAlgosConf;
1401 AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
1402
Alexandre Lision51140e12013-12-02 10:54:09 -05001403 int num = hello->getNumCiphers();
1404 if (num == 0 || (*(int32_t*)(pk->getName()) == *(int32_t*)dh2k)) {
1405 return &zrtpSymCiphers.getByName(aes1);
1406 }
1407
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001408 // Build list of configured cipher algorithm names.
Alexandre Lision51140e12013-12-02 10:54:09 -05001409 numAlgosConf = configureAlgos.getNumConfiguredAlgos(CipherAlgorithm);
1410 for (i = 0; i < numAlgosConf; i++) {
1411 algosConf[i] = &configureAlgos.getAlgoAt(CipherAlgorithm, i);
Alexandre Lision51140e12013-12-02 10:54:09 -05001412 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001413 // Build list of offered known algos names in Hello.
Alexandre Lision51140e12013-12-02 10:54:09 -05001414 for (numAlgosOffered = 0, i = 0; i < num; i++) {
1415 algosOffered[numAlgosOffered] = &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
1416 if (!algosOffered[numAlgosOffered]->isValid())
1417 continue;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001418 numAlgosOffered++;
Alexandre Lision51140e12013-12-02 10:54:09 -05001419 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001420 // Lookup offered algos in configured algos. Prefer algorithms that appear first in Hello packet (offered).
Alexandre Lision51140e12013-12-02 10:54:09 -05001421 for (i = 0; i < numAlgosOffered; i++) {
1422 for (ii = 0; ii < numAlgosConf; ii++) {
1423 if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
1424 return algosConf[ii];
1425 }
1426 }
1427 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001428 // If we don't have a match - use the mandatory algorithm
Alexandre Lision51140e12013-12-02 10:54:09 -05001429 return &zrtpSymCiphers.getByName(mandatoryCipher);
1430}
1431
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001432// We can have the non-NIST in the list of orderedAlgos even if they are not available
1433// in the code (refer to ZrtpConfigure.cpp). If they are not build in they cannot appear
1434// in'configureAlgos' and thus not in the intersection lists. Thus a ZRTP build that
1435// does not include the non-NIST curves also works without problems.
1436//
Alexandre Lision51140e12013-12-02 10:54:09 -05001437AlgorithmEnum* ZRtp::findBestPubkey(ZrtpPacketHello *hello) {
1438
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001439 AlgorithmEnum* peerIntersect[ZrtpConfigure::maxNoOfAlgos+1];
1440 AlgorithmEnum* ownIntersect[ZrtpConfigure::maxNoOfAlgos+1];
Alexandre Lision51140e12013-12-02 10:54:09 -05001441
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001442 // Build list of own pubkey algorithm names, must follow the order
1443 // defined in RFC 6189, chapter 4.1.2.
1444 const char *orderedAlgos[] = {dh2k, e255, ec25, dh3k, e414, ec38};
1445 int numOrderedAlgos = sizeof(orderedAlgos) / sizeof(const char*);
Alexandre Lision51140e12013-12-02 10:54:09 -05001446
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001447 int numAlgosPeer = hello->getNumPubKeys();
1448 if (numAlgosPeer == 0) {
1449 hash = findBestHash(hello); // find a hash algorithm
Alexandre Lision51140e12013-12-02 10:54:09 -05001450 return &zrtpPubKeys.getByName(mandatoryPubKey);
1451 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001452 // Build own list of intersecting algos, keep own order or algorithms
1453 // The list must include real public key algorithms only, so skip mult-stream mode,
1454 // preshared and alike.
1455 int numAlgosOwn = configureAlgos.getNumConfiguredAlgos(PubKeyAlgorithm);
1456 int numOwnIntersect = 0;
1457 for (int i = 0; i < numAlgosOwn; i++) {
1458 ownIntersect[numOwnIntersect] = &configureAlgos.getAlgoAt(PubKeyAlgorithm, i);
1459 if (*(int32_t*)(ownIntersect[numOwnIntersect]->getName()) == *(int32_t*)mult) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001460 continue; // skip multi-stream mode
1461 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001462 for (int ii = 0; ii < numAlgosPeer; ii++) {
1463 if (*(int32_t*)(ownIntersect[numOwnIntersect]->getName()) == *(int32_t*)(zrtpPubKeys.getByName((const char*)hello->getPubKeyType(ii)).getName())) {
1464 numOwnIntersect++;
1465 break;
Alexandre Lision51140e12013-12-02 10:54:09 -05001466 }
1467 }
1468 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001469 // Build list of peer's intersecting algos: take own list as input and build a
1470 // list of algorithms that we have in common. The order of the list is according
1471 // to peer's Hello packet (peer's preferences).
1472 int numPeerIntersect = 0;
1473 for (int i = 0; i < numAlgosPeer; i++) {
1474 peerIntersect[numPeerIntersect] = &zrtpPubKeys.getByName((const char*)hello->getPubKeyType(i));
1475 for (int ii = 0; ii < numOwnIntersect; ii++) {
1476 if (*(int32_t*)(ownIntersect[ii]->getName()) == *(int32_t*)(peerIntersect[numPeerIntersect]->getName())) {
1477 numPeerIntersect++;
1478 break;
1479 }
1480 }
1481 }
1482 if (numPeerIntersect == 0) { // If we don't have a common algorithm - use mandatory algorithms
1483 hash = findBestHash(hello);
1484 return &zrtpPubKeys.getByName(mandatoryPubKey);
1485 }
1486
1487 // If we have only one algorithm in common or if the first entry matches - take it.
1488 // Otherwise determine which algorithm from the intersection lists is first in the
1489 // list of ordered algorithms and select it (RFC6189, section 4.1.2).
1490 AlgorithmEnum* useAlgo;
1491 if (numPeerIntersect > 1 && *(int32_t*)(ownIntersect[0]->getName()) != *(int32_t*)(peerIntersect[0]->getName())) {
1492 int own, peer;
1493
1494 const int32_t *name = (int32_t*)ownIntersect[0]->getName();
1495 for (own = 0; own < numOrderedAlgos; own++) {
1496 if (*name == *(int32_t*)orderedAlgos[own])
1497 break;
1498 }
1499 name = (int32_t*)peerIntersect[0]->getName();
1500 for (peer = 0; peer < numOrderedAlgos; peer++) {
1501 if (*name == *(int32_t*)orderedAlgos[peer])
1502 break;
1503 }
1504 if (own < peer) {
1505 useAlgo = ownIntersect[0];
1506 }
1507 else {
1508 useAlgo = peerIntersect[0];
1509 }
1510 // find fastest of conf vs intersecting
1511 }
1512 else {
1513 useAlgo = peerIntersect[0];
1514 }
1515 int32_t algoName = *(int32_t*)(useAlgo->getName());
1516
1517 // select a corresponding strong hash if necessary.
1518 if (algoName == *(int32_t*)ec38 || algoName == *(int32_t*)e414) {
1519 hash = getStrongHashOffered(hello, algoName);
1520 cipher = getStrongCipherOffered(hello, algoName);
1521 }
1522 else {
1523 hash = getHashOffered(hello, algoName);;
1524 cipher = getCipherOffered(hello, algoName);
1525 }
1526 authLength = getAuthLenOffered(hello, algoName);
1527 return useAlgo;
Alexandre Lision51140e12013-12-02 10:54:09 -05001528}
1529
1530AlgorithmEnum* ZRtp::findBestSASType(ZrtpPacketHello *hello) {
1531
1532 int i;
1533 int ii;
1534 int numAlgosOffered;
1535 AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+1];
1536
1537 int numAlgosConf;
1538 AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+1];
1539
Alexandre Lision51140e12013-12-02 10:54:09 -05001540 int num = hello->getNumSas();
1541 if (num == 0) {
1542 return &zrtpSasTypes.getByName(mandatorySasType);
1543 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001544 // Build list of configured SAS algorithm names
Alexandre Lision51140e12013-12-02 10:54:09 -05001545 numAlgosConf = configureAlgos.getNumConfiguredAlgos(SasType);
1546 for (i = 0; i < numAlgosConf; i++) {
1547 algosConf[i] = &configureAlgos.getAlgoAt(SasType, i);
Alexandre Lision51140e12013-12-02 10:54:09 -05001548 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001549 // Build list of offered known algos in Hello,
Alexandre Lision51140e12013-12-02 10:54:09 -05001550 for (numAlgosOffered = 0, i = 0; i < num; i++) {
1551 algosOffered[numAlgosOffered] = &zrtpSasTypes.getByName((const char*)hello->getSasType(i));
1552 if (!algosOffered[numAlgosOffered]->isValid())
1553 continue;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001554 numAlgosOffered++;
Alexandre Lision51140e12013-12-02 10:54:09 -05001555 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001556 // Lookup offered algos in configured algos. Prefer algorithms that appear first in Hello packet (offered).
Alexandre Lision51140e12013-12-02 10:54:09 -05001557 for (i = 0; i < numAlgosOffered; i++) {
1558 for (ii = 0; ii < numAlgosConf; ii++) {
1559 if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
1560 return algosConf[ii];
1561 }
1562 }
1563 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001564 // If we don't have a match - use the mandatory algorithm
Alexandre Lision51140e12013-12-02 10:54:09 -05001565 return &zrtpSasTypes.getByName(mandatorySasType);
1566}
1567
1568AlgorithmEnum* ZRtp::findBestAuthLen(ZrtpPacketHello *hello) {
1569
1570 int i;
1571 int ii;
1572 int numAlgosOffered;
1573 AlgorithmEnum* algosOffered[ZrtpConfigure::maxNoOfAlgos+2];
1574
1575 int numAlgosConf;
1576 AlgorithmEnum* algosConf[ZrtpConfigure::maxNoOfAlgos+2];
1577
Alexandre Lision51140e12013-12-02 10:54:09 -05001578 int num = hello->getNumAuth();
1579 if (num == 0) {
1580 return &zrtpAuthLengths.getByName(mandatoryAuthLen_1);
1581 }
1582
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001583 // Build list of configured Authentication tag length algorithm names.
Alexandre Lision51140e12013-12-02 10:54:09 -05001584 numAlgosConf = configureAlgos.getNumConfiguredAlgos(AuthLength);
1585 for (i = 0; i < numAlgosConf; i++) {
1586 algosConf[i] = &configureAlgos.getAlgoAt(AuthLength, i);
Alexandre Lision51140e12013-12-02 10:54:09 -05001587 }
1588
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001589 // Build list of offered known algos in Hello.
Alexandre Lision51140e12013-12-02 10:54:09 -05001590 for (numAlgosOffered = 0, i = 0; i < num; i++) {
1591 algosOffered[numAlgosOffered] = &zrtpAuthLengths.getByName((const char*)hello->getAuthLen(i));
1592 if (!algosOffered[numAlgosOffered]->isValid())
1593 continue;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001594 numAlgosOffered++;
Alexandre Lision51140e12013-12-02 10:54:09 -05001595 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001596
1597 // Lookup offered algos in configured algos. Prefer algorithms that appear first in Hello packet (offered).
Alexandre Lision51140e12013-12-02 10:54:09 -05001598 for (i = 0; i < numAlgosOffered; i++) {
1599 for (ii = 0; ii < numAlgosConf; ii++) {
1600 if (*(int32_t*)(algosOffered[i]->getName()) == *(int32_t*)(algosConf[ii]->getName())) {
1601 return algosConf[ii];
1602 }
1603 }
1604 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001605 // If we don't have a match - use the mandatory algorithm
Alexandre Lision51140e12013-12-02 10:54:09 -05001606 return &zrtpAuthLengths.getByName(mandatoryAuthLen_1);
1607}
1608
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001609// The following set of functions implement a 'non-NIST first policy' if nonNist computes
1610// to true. They prefer nonNist algorithms if these are available. Otherwise they use the NIST
1611// counterpart or simply call the according findBest*(...) function.
1612//
1613// Only the findBestPubkey(...) function calls them after it selected the public key algorithm.
1614// If the public key algorithm is non-NIST and if the policy is set to PreferNonNist then
1615// nonNist becomes true.
1616//
1617// The functions work according to the RFC6189 spec: the initiator can select every algorithm
1618// that both parties support. Thus the Initiator can even select an algorithm the wasn't offered
1619// in its own Hello packet but that the Initiator found in the peer's Hello and that is available
1620// for it.
1621//
1622AlgorithmEnum* ZRtp::getStrongHashOffered(ZrtpPacketHello *hello, int32_t algoName) {
1623
1624 int numHash = hello->getNumHashes();
1625 bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
1626
1627 if (nonNist) {
1628 for (int i = 0; i < numHash; i++) {
1629 int32_t nm = *(int32_t*)(hello->getHashType(i));
1630 if (nm == *(int32_t*)skn3) {
1631 return &zrtpHashes.getByName((const char*)hello->getHashType(i));
1632 }
1633 }
1634 }
1635 for (int i = 0; i < numHash; i++) {
1636 int32_t nm = *(int32_t*)(hello->getHashType(i));
1637 if (nm == *(int32_t*)s384 || nm == *(int32_t*)skn3) {
1638 return &zrtpHashes.getByName((const char*)hello->getHashType(i));
1639 }
1640 }
1641 return NULL; // returning NULL -> prepareCommit(...) terminates ZRTP, missing strong hash is an error
1642}
1643
1644AlgorithmEnum* ZRtp::getStrongCipherOffered(ZrtpPacketHello *hello, int32_t algoName) {
1645
1646 int num = hello->getNumCiphers();
1647 bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
1648
1649 if (nonNist) {
1650 for (int i = 0; i < num; i++) {
1651 int32_t nm = *(int32_t*)(hello->getCipherType(i));
1652 if (nm == *(int32_t*)two3) {
1653 return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
1654 }
1655 }
1656 }
1657 for (int i = 0; i < num; i++) {
1658 int32_t nm = *(int32_t*)(hello->getCipherType(i));
1659 if (nm == *(int32_t*)aes3 || nm == *(int32_t*)two3) {
1660 return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
1661 }
1662 }
1663 return NULL; // returning NULL -> prepareCommit(...) finds the best cipher
1664}
1665
1666AlgorithmEnum* ZRtp::getHashOffered(ZrtpPacketHello *hello, int32_t algoName) {
1667
1668 int num = hello->getNumHashes();
1669 bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
1670
1671 if (nonNist) {
1672 for (int i = 0; i < num; i++) {
1673 int32_t nm = *(int32_t*)(hello->getHashType(i));
1674 if (nm == *(int32_t*)skn2 || nm == *(int32_t*)skn3) {
1675 return &zrtpHashes.getByName((const char*)hello->getHashType(i));
1676 }
1677 }
1678 }
1679 return findBestHash(hello);
1680}
1681
1682AlgorithmEnum* ZRtp::getCipherOffered(ZrtpPacketHello *hello, int32_t algoName) {
1683
1684 int num = hello->getNumCiphers();
1685 bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
1686
1687 if (nonNist) {
1688 for (int i = 0; i < num; i++) {
1689 int32_t nm = *(int32_t*)(hello->getCipherType(i));
1690 if (nm == *(int32_t*)two2 || nm == *(int32_t*)two3) {
1691 return &zrtpSymCiphers.getByName((const char*)hello->getCipherType(i));
1692 }
1693 }
1694 }
1695 return NULL; // returning NULL -> prepareCommit(...) finds the best cipher
1696}
1697
1698AlgorithmEnum* ZRtp::getAuthLenOffered(ZrtpPacketHello *hello, int32_t algoName) {
1699
1700 int num = hello->getNumAuth();
1701 bool nonNist = (algoName == *(int32_t*)e414 || algoName == *(int32_t*)e255) && configureAlgos.getSelectionPolicy() == ZrtpConfigure::PreferNonNist;
1702
1703 if (nonNist) {
1704 for (int i = 0; i < num; i++) {
1705 int32_t nm = *(int32_t*)(hello->getAuthLen(i));
1706 if (nm == *(int32_t*)sk32 || nm == *(int32_t*)sk64) {
1707 return &zrtpAuthLengths.getByName((const char*)hello->getAuthLen(i));
1708 }
1709 }
1710 }
1711 return findBestAuthLen(hello);
1712}
1713
Alexandre Lision51140e12013-12-02 10:54:09 -05001714bool ZRtp::checkMultiStream(ZrtpPacketHello *hello) {
1715
1716 int i;
1717 int num = hello->getNumPubKeys();
1718
1719 // Multi Stream mode is mandatory, thus if nothing is offered then it is supported :-)
1720 if (num == 0) {
1721 return true;
1722 }
1723 for (i = 0; i < num; i++) {
1724 if (*(int32_t*)(hello->getPubKeyType(i)) == *(int32_t*)mult) {
1725 return true;
1726 }
1727 }
1728 return false;
1729}
1730
1731bool ZRtp::verifyH2(ZrtpPacketCommit *commit) {
1732 uint8_t tmpH3[IMPL_MAX_DIGEST_LENGTH];
1733
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001734 // packet does not have the correct size, treat H2 verfication as failed.
1735 if (!commit->isLengthOk(multiStream ? ZrtpPacketCommit::MultiStream : ZrtpPacketCommit::DhExchange))
1736 return false;
1737
Alexandre Lision51140e12013-12-02 10:54:09 -05001738 sha256(commit->getH2(), HASH_IMAGE_SIZE, tmpH3);
1739 if (memcmp(tmpH3, peerH3, HASH_IMAGE_SIZE) != 0) {
1740 return false;
1741 }
1742 return true;
1743}
1744
1745void ZRtp::computeHvi(ZrtpPacketDHPart* dh, ZrtpPacketHello *hello) {
1746
1747 unsigned char* data[3];
1748 unsigned int length[3];
1749 /*
1750 * populate the vector to compute the HVI hash according to the
1751 * ZRTP specification.
1752 */
1753 data[0] = (uint8_t*)dh->getHeaderBase();
1754 length[0] = dh->getLength() * ZRTP_WORD_SIZE;
1755
1756 data[1] = (uint8_t*)hello->getHeaderBase();
1757 length[1] = hello->getLength() * ZRTP_WORD_SIZE;
1758
1759 data[2] = NULL; // terminate data chunks
1760 hashListFunction(data, length, hvi);
1761 return;
1762}
1763
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001764void ZRtp:: computeSharedSecretSet(ZIDRecord *zidRec) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001765
1766 /*
1767 * Compute the Initiator's and Reponder's retained shared secret Ids.
1768 * Use negotiated HMAC.
1769 */
1770 uint8_t randBuf[RS_LENGTH];
1771 uint32_t macLen;
1772
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001773 fprintf(stderr, "Compute shared secrets\n");
1774 detailInfo.secretsCached = 0;
1775 if (!zidRec->isRs1Valid()) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001776 randomZRTP(randBuf, RS_LENGTH);
1777 hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs1IDi, &macLen);
1778 hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), rs1IDr, &macLen);
1779 }
1780 else {
1781 rs1Valid = true;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001782 hmacFunction((unsigned char*)zidRec->getRs1(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs1IDi, &macLen);
1783 hmacFunction((unsigned char*)zidRec->getRs1(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs1IDr, &macLen);
1784 detailInfo.secretsCached = Rs1;
Alexandre Lision51140e12013-12-02 10:54:09 -05001785 }
1786
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001787 if (!zidRec->isRs2Valid()) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001788 randomZRTP(randBuf, RS_LENGTH);
1789 hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs2IDi, &macLen);
1790 hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), rs2IDr, &macLen);
1791 }
1792 else {
1793 rs2Valid = true;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001794 hmacFunction((unsigned char*)zidRec->getRs2(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), rs2IDi, &macLen);
1795 hmacFunction((unsigned char*)zidRec->getRs2(), RS_LENGTH, (unsigned char*)responder, strlen(responder), rs2IDr, &macLen);
1796 detailInfo.secretsCached |= Rs2;
Alexandre Lision51140e12013-12-02 10:54:09 -05001797 }
1798
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001799 if (!zidRec->isMITMKeyAvailable()) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001800 randomZRTP(randBuf, RS_LENGTH);
1801 hmacFunction(randBuf, RS_LENGTH, (unsigned char*)initiator, strlen(initiator), pbxSecretIDi, &macLen);
1802 hmacFunction(randBuf, RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001803
Alexandre Lision51140e12013-12-02 10:54:09 -05001804 }
1805 else {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001806 hmacFunction((unsigned char*)zidRec->getMiTMData(), RS_LENGTH, (unsigned char*)initiator, strlen(initiator), pbxSecretIDi, &macLen);
1807 hmacFunction((unsigned char*)zidRec->getMiTMData(), RS_LENGTH, (unsigned char*)responder, strlen(responder), pbxSecretIDr, &macLen);
1808 detailInfo.secretsCached |= Pbx;
1809 }
1810 computeAuxSecretIds();
1811}
1812
1813void ZRtp::computeAuxSecretIds() {
1814 uint8_t randBuf[RS_LENGTH];
1815 uint32_t macLen;
1816
1817 if (auxSecret == NULL) {
1818 randomZRTP(randBuf, RS_LENGTH);
1819 hmacFunction(randBuf, RS_LENGTH, H3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen);
1820 hmacFunction(randBuf, RS_LENGTH, H3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen);
1821 }
1822 else {
1823 if (myRole == Initiator) { // I'm initiator thus use my H3 for initiator's IDi, peerH3 for respnder's IDr
1824 hmacFunction(auxSecret, auxSecretLength, H3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen);
1825 hmacFunction(auxSecret, auxSecretLength, peerH3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen);
1826 }
1827 else {
1828 hmacFunction(auxSecret, auxSecretLength, peerH3, HASH_IMAGE_SIZE, auxSecretIDi, &macLen);
1829 hmacFunction(auxSecret, auxSecretLength, H3, HASH_IMAGE_SIZE, auxSecretIDr, &macLen);
1830 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001831 }
1832}
1833
1834/*
1835 * The DH packet for this function is DHPart1 and contains the Responder's
1836 * retained secret ids. Compare them with the expected secret ids (refer
1837 * to chapter 5.3 in the specification).
1838 * When using this method then we are in Initiator role.
1839 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001840void ZRtp::generateKeysInitiator(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001841 const uint8_t* setD[3];
1842 int32_t rsFound = 0;
1843
1844 setD[0] = setD[1] = setD[2] = NULL;
1845
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001846 detailInfo.secretsMatchedDH = 0;
1847 if (memcmp(rs1IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs1IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0)
1848 detailInfo.secretsMatchedDH |= Rs1;
1849 if (memcmp(rs2IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs2IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0)
1850 detailInfo.secretsMatchedDH |= Rs2;
Alexandre Lision51140e12013-12-02 10:54:09 -05001851 /*
1852 * Select the real secrets into setD. The dhPart is DHpart1 message
1853 * received from responder. rs1IDr and rs2IDr are the expected ids using
1854 * the initator's cached retained secrets.
1855 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001856 // Check which RS we shall use for first place (s1)
1857 detailInfo.secretsMatched = 0;
Alexandre Lision51140e12013-12-02 10:54:09 -05001858 if (memcmp(rs1IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001859 setD[0] = zidRec->getRs1();
Alexandre Lision51140e12013-12-02 10:54:09 -05001860 rsFound = 0x1;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001861 detailInfo.secretsMatched = Rs1;
Alexandre Lision51140e12013-12-02 10:54:09 -05001862 }
1863 else if (memcmp(rs1IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001864 setD[0] = zidRec->getRs1();
Alexandre Lision51140e12013-12-02 10:54:09 -05001865 rsFound = 0x2;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001866 detailInfo.secretsMatched = Rs1;
Alexandre Lision51140e12013-12-02 10:54:09 -05001867 }
1868 else if (memcmp(rs2IDr, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001869 setD[0] = zidRec->getRs2();
Alexandre Lision51140e12013-12-02 10:54:09 -05001870 rsFound = 0x4;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001871 detailInfo.secretsMatched = Rs2;
Alexandre Lision51140e12013-12-02 10:54:09 -05001872 }
1873 else if (memcmp(rs2IDr, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001874 setD[0] = zidRec->getRs2();
Alexandre Lision51140e12013-12-02 10:54:09 -05001875 rsFound = 0x8;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001876 detailInfo.secretsMatched = Rs2;
Alexandre Lision51140e12013-12-02 10:54:09 -05001877 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001878
Alexandre Lision51140e12013-12-02 10:54:09 -05001879 if (memcmp(auxSecretIDr, dhPart->getAuxSecretId(), 8) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001880 DEBUGOUT((fprintf(stdout, "Initiator: Match for aux secret found\n")));
1881 setD[1] = auxSecret;
1882 detailInfo.secretsMatched |= Aux;
1883 detailInfo.secretsMatchedDH |= Aux;
Alexandre Lision51140e12013-12-02 10:54:09 -05001884 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001885 if (auxSecret != NULL && (detailInfo.secretsMatched & Aux) == 0) {
1886 sendInfo(Warning, WarningNoExpectedAuxMatch);
1887 }
1888
1889 // check if we have a matching PBX secret and place it third (s3)
1890 if (memcmp(pbxSecretIDr, dhPart->getPbxSecretId(), HMAC_SIZE) == 0) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001891 DEBUGOUT((fprintf(stdout, "%c: Match for Other_secret found\n", zid[0])));
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001892 setD[2] = zidRec->getMiTMData();
1893 detailInfo.secretsMatched |= Pbx;
1894 detailInfo.secretsMatchedDH |= Pbx;
1895 // Flag to record that fact that we have a MitM key of the other peer.
1896 peerIsEnrolled = true;
Alexandre Lision51140e12013-12-02 10:54:09 -05001897 }
1898 // Check if some retained secrets found
1899 if (rsFound == 0) { // no RS matches found
1900 if (rs1Valid || rs2Valid) { // but valid RS records in cache
1901 sendInfo(Warning, WarningNoExpectedRSMatch);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001902 zidRec->resetSasVerified();
1903 saveZidRecord = false; // Don't save RS until user verfied/confirmed SAS
Alexandre Lision51140e12013-12-02 10:54:09 -05001904 }
1905 else { // No valid RS record in cache
1906 sendInfo(Warning, WarningNoRSMatch);
1907 }
1908 }
1909 else { // at least one RS matches
1910 sendInfo(Info, InfoRSMatchFound);
1911 }
1912 /*
1913 * Ready to generate s0 here.
1914 * The formular to compute S0 (Refer to ZRTP specification 5.4.4):
1915 *
1916 s0 = hash( counter | DHResult | "ZRTP-HMAC-KDF" | ZIDi | ZIDr | \
1917 total_hash | len(s1) | s1 | len(s2) | s2 | len(s3) | s3)
1918 *
1919 * Note: in this function we are Initiator, thus ZIDi is our zid
1920 * (zid), ZIDr is the peer's zid (peerZid).
1921 */
1922
1923 /*
1924 * These arrays hold the pointers and lengths of the data that must be
1925 * hashed to create S0. According to the formula the max number of
1926 * elements to hash is 12, add one for the terminating "NULL"
1927 */
1928 unsigned char* data[13];
1929 unsigned int length[13];
1930 uint32_t pos = 0; // index into the array
1931
1932 // we need a number of length data items, so define them here
1933 uint32_t counter, sLen[3];
1934
1935 //Very first element is a fixed counter, big endian
1936 counter = 1;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001937 counter = zrtpHtonl(counter);
Alexandre Lision51140e12013-12-02 10:54:09 -05001938 data[pos] = (unsigned char*)&counter;
1939 length[pos++] = sizeof(uint32_t);
1940
1941 // Next is the DH result itself
1942 data[pos] = DHss;
1943 length[pos++] = dhContext->getDhSize();
1944
1945 // Next the fixed string "ZRTP-HMAC-KDF"
1946 data[pos] = (unsigned char*)KDFString;
1947 length[pos++] = strlen(KDFString);
1948
1949 // Next is Initiator's id (ZIDi), in this case as Initiator
1950 // it is zid
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001951 data[pos] = ownZid;
Alexandre Lision51140e12013-12-02 10:54:09 -05001952 length[pos++] = ZID_SIZE;
1953
1954 // Next is Responder's id (ZIDr), in this case our peer's id
1955 data[pos] = peerZid;
1956 length[pos++] = ZID_SIZE;
1957
1958 // Next ist total hash (messageHash) itself
1959 data[pos] = messageHash;
1960 length[pos++] = hashLength;
1961
1962 /*
1963 * For each matching shared secret hash the length of
1964 * the shared secret as 32 bit big-endian number followd by the
1965 * shared secret itself. The length of a shared seceret is
1966 * currently fixed to RS_LENGTH. If a shared
1967 * secret is not used _only_ its length is hased as zero
1968 * length. NOTE: if implementing auxSecret and/or pbxSecret -> check
1969 * this length stuff again.
1970 */
1971 int secretHashLen = RS_LENGTH;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001972 secretHashLen = zrtpHtonl(secretHashLen); // prepare 32 bit big-endian number
Alexandre Lision51140e12013-12-02 10:54:09 -05001973
1974 for (int32_t i = 0; i < 3; i++) {
1975 if (setD[i] != NULL) { // a matching secret, set length, then secret
1976 sLen[i] = secretHashLen;
1977 data[pos] = (unsigned char*)&sLen[i];
1978 length[pos++] = sizeof(uint32_t);
1979 data[pos] = (unsigned char*)setD[i];
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001980 length[pos++] = (i != 1) ? RS_LENGTH : auxSecretLength;
Alexandre Lision51140e12013-12-02 10:54:09 -05001981 }
1982 else { // no machting secret, set length 0, skip secret
1983 sLen[i] = 0;
1984 data[pos] = (unsigned char*)&sLen[i];
1985 length[pos++] = sizeof(uint32_t);
1986 }
1987 }
1988
1989 data[pos] = NULL;
1990 hashListFunction(data, length, s0);
1991// hexdump("S0 I", s0, hashLength);
1992
1993 memset(DHss, 0, dhContext->getDhSize());
1994 delete[] DHss;
1995 DHss = NULL;
1996
1997 computeSRTPKeys();
1998 memset(s0, 0, MAX_DIGEST_LENGTH);
1999}
2000/*
2001 * The DH packet for this function is DHPart2 and contains the Initiator's
2002 * retained secret ids. Compare them with the expected secret ids (refer
2003 * to chapter 5.3.1 in the specification).
2004 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002005void ZRtp::generateKeysResponder(ZrtpPacketDHPart *dhPart, ZIDRecord *zidRec) {
Alexandre Lision51140e12013-12-02 10:54:09 -05002006 const uint8_t* setD[3];
2007 int32_t rsFound = 0;
2008
2009 setD[0] = setD[1] = setD[2] = NULL;
2010
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002011 detailInfo.secretsMatchedDH = 0;
2012 if (memcmp(rs1IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs1IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0)
2013 detailInfo.secretsMatchedDH |= Rs1;
2014 if (memcmp(rs2IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0 || memcmp(rs2IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0)
2015 detailInfo.secretsMatchedDH |= Rs2;
2016
Alexandre Lision51140e12013-12-02 10:54:09 -05002017 /*
2018 * Select the real secrets into setD
2019 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002020 // Check which RS we shall use for first place (s1)
2021 detailInfo.secretsMatched = 0;
Alexandre Lision51140e12013-12-02 10:54:09 -05002022 if (memcmp(rs1IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002023 setD[0] = zidRec->getRs1();
Alexandre Lision51140e12013-12-02 10:54:09 -05002024 rsFound = 0x1;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002025 detailInfo.secretsMatched = Rs1;
Alexandre Lision51140e12013-12-02 10:54:09 -05002026 }
2027 else if (memcmp(rs1IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002028 setD[0] = zidRec->getRs1();
Alexandre Lision51140e12013-12-02 10:54:09 -05002029 rsFound = 0x2;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002030 detailInfo.secretsMatched = Rs1;
Alexandre Lision51140e12013-12-02 10:54:09 -05002031 }
2032 else if (memcmp(rs2IDi, dhPart->getRs1Id(), HMAC_SIZE) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002033 setD[0] = zidRec->getRs2();
2034 rsFound |= 0x4;
2035 detailInfo.secretsMatched = Rs2;
2036 }
2037 else if (memcmp(rs2IDi, dhPart->getRs2Id(), HMAC_SIZE) == 0) {
2038 setD[0] = zidRec->getRs2();
Alexandre Lision51140e12013-12-02 10:54:09 -05002039 rsFound |= 0x8;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002040 detailInfo.secretsMatched = Rs2;
Alexandre Lision51140e12013-12-02 10:54:09 -05002041 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002042
2043 if (memcmp(auxSecretIDi, dhPart->getAuxSecretId(), 8) == 0) {
2044 DEBUGOUT((fprintf(stdout, "Responder: Match for aux secret found\n")));
2045 setD[1] = auxSecret;
2046 detailInfo.secretsMatched |= Aux;
2047 detailInfo.secretsMatchedDH |= Aux;
Alexandre Lision51140e12013-12-02 10:54:09 -05002048 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002049 // If we have an auxSecret but no match from peer - report this.
2050 if (auxSecret != NULL && (detailInfo.secretsMatched & Aux) == 0) {
2051 sendInfo(Warning, WarningNoExpectedAuxMatch);
2052 }
2053
Alexandre Lision51140e12013-12-02 10:54:09 -05002054 if (memcmp(pbxSecretIDi, dhPart->getPbxSecretId(), 8) == 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002055 DEBUGOUT((fprintf(stdout, "%c: Match for PBX secret found\n", ownZid[0])));
2056 setD[2] = zidRec->getMiTMData();
2057 detailInfo.secretsMatched |= Pbx;
2058 detailInfo.secretsMatchedDH |= Pbx;
2059 peerIsEnrolled = true;
Alexandre Lision51140e12013-12-02 10:54:09 -05002060 }
2061 // Check if some retained secrets found
2062 if (rsFound == 0) { // no RS matches found
2063 if (rs1Valid || rs2Valid) { // but valid RS records in cache
2064 sendInfo(Warning, WarningNoExpectedRSMatch);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002065 zidRec->resetSasVerified();
2066 saveZidRecord = false; // Don't save RS until user verfied/confirmed SAS
Alexandre Lision51140e12013-12-02 10:54:09 -05002067 }
2068 else { // No valid RS record in cache
2069 sendInfo(Warning, WarningNoRSMatch);
2070 }
2071 }
2072 else { // at least one RS matches
2073 sendInfo(Info, InfoRSMatchFound);
2074 }
2075
2076 /*
2077 * ready to generate s0 here.
2078 * The formular to compute S0 (Refer to ZRTP specification 5.4.4):
2079 *
2080 s0 = hash( counter | DHResult | "ZRTP-HMAC-KDF" | ZIDi | ZIDr | \
2081 total_hash | len(s1) | s1 | len(s2) | s2 | len(s3) | s3)
2082 *
2083 * Note: in this function we are Responder, thus ZIDi is the peer's zid
2084 * (peerZid), ZIDr is our zid.
2085 */
2086
2087 /*
2088 * These arrays hold the pointers and lengths of the data that must be
2089 * hashed to create S0. According to the formula the max number of
2090 * elements to hash is 12, add one for the terminating "NULL"
2091 */
2092 unsigned char* data[13];
2093 unsigned int length[13];
2094 uint32_t pos = 0; // index into the array
2095
2096
2097 // we need a number of length data items, so define them here
2098 uint32_t counter, sLen[3];
2099
2100 //Very first element is a fixed counter, big endian
2101 counter = 1;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002102 counter = zrtpHtonl(counter);
Alexandre Lision51140e12013-12-02 10:54:09 -05002103 data[pos] = (unsigned char*)&counter;
2104 length[pos++] = sizeof(uint32_t);
2105
2106 // Next is the DH result itself
2107 data[pos] = DHss;
2108 length[pos++] = dhContext->getDhSize();
2109
2110 // Next the fixed string "ZRTP-HMAC-KDF"
2111 data[pos] = (unsigned char*)KDFString;
2112 length[pos++] = strlen(KDFString);
2113
2114 // Next is Initiator's id (ZIDi), in this case as Responder
2115 // it is peerZid
2116 data[pos] = peerZid;
2117 length[pos++] = ZID_SIZE;
2118
2119 // Next is Responder's id (ZIDr), in this case our own zid
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002120 data[pos] = ownZid;
Alexandre Lision51140e12013-12-02 10:54:09 -05002121 length[pos++] = ZID_SIZE;
2122
2123 // Next ist total hash (messageHash) itself
2124 data[pos] = messageHash;
2125 length[pos++] = hashLength;
2126
2127 /*
2128 * For each matching shared secret hash the length of
2129 * the shared secret as 32 bit big-endian number followd by the
2130 * shared secret itself. The length of a shared seceret is
2131 * currently fixed to SHA256_DIGEST_LENGTH. If a shared
2132 * secret is not used _only_ its length is hased as zero
2133 * length. NOTE: if implementing auxSecret and/or pbxSecret -> check
2134 * this length stuff again.
2135 */
2136 int secretHashLen = RS_LENGTH;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002137 secretHashLen = zrtpHtonl(secretHashLen); // prepare 32 bit big-endian number
Alexandre Lision51140e12013-12-02 10:54:09 -05002138
2139 for (int32_t i = 0; i < 3; i++) {
2140 if (setD[i] != NULL) { // a matching secret, set length, then secret
2141 sLen[i] = secretHashLen;
2142 data[pos] = (unsigned char*)&sLen[i];
2143 length[pos++] = sizeof(uint32_t);
2144 data[pos] = (unsigned char*)setD[i];
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002145 length[pos++] = (i != 1) ? RS_LENGTH : auxSecretLength;
Alexandre Lision51140e12013-12-02 10:54:09 -05002146 }
2147 else { // no machting secret, set length 0, skip secret
2148 sLen[i] = 0;
2149 data[pos] = (unsigned char*)&sLen[i];
2150 length[pos++] = sizeof(uint32_t);
2151 }
2152 }
2153
2154 data[pos] = NULL;
2155 hashListFunction(data, length, s0);
2156// hexdump("S0 R", s0, hashLength);
2157
2158 memset(DHss, 0, dhContext->getDhSize());
2159 delete[] DHss;
2160 DHss = NULL;
2161
2162 computeSRTPKeys();
2163 memset(s0, 0, MAX_DIGEST_LENGTH);
2164}
2165
2166
2167void ZRtp::KDF(uint8_t* key, uint32_t keyLength, uint8_t* label, int32_t labelLength,
2168 uint8_t* context, int32_t contextLength, int32_t L, uint8_t* output) {
2169
2170 unsigned char* data[6];
2171 uint32_t length[6];
2172 uint32_t pos = 0; // index into the array
2173 uint32_t maclen = 0;
2174
2175 // Very first element is a fixed counter, big endian
2176 uint32_t counter = 1;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002177 counter = zrtpHtonl(counter);
Alexandre Lision51140e12013-12-02 10:54:09 -05002178 data[pos] = (unsigned char*)&counter;
2179 length[pos++] = sizeof(uint32_t);
2180
2181 // Next element is the label, null terminated, labelLength includes null byte.
2182 data[pos] = label;
2183 length[pos++] = labelLength;
2184
2185 // Next is the KDF context
2186 data[pos] = context;
2187 length[pos++] = contextLength;
2188
2189 // last element is HMAC length in bits, big endian
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002190 uint32_t len = zrtpHtonl(L);
Alexandre Lision51140e12013-12-02 10:54:09 -05002191 data[pos] = (unsigned char*)&len;
2192 length[pos++] = sizeof(uint32_t);
2193
2194 data[pos] = NULL;
2195
2196 // Use negotiated hash.
2197 hmacListFunction(key, keyLength, data, length, output, &maclen);
2198}
2199
2200// Compute the Multi Stream mode s0
2201void ZRtp::generateKeysMultiStream() {
2202
2203 // allocate the maximum size, compute real size to use
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002204 uint8_t KDFcontext[sizeof(peerZid)+sizeof(ownZid)+sizeof(messageHash)];
2205 int32_t kdfSize = sizeof(peerZid)+sizeof(ownZid)+hashLength;
Alexandre Lision51140e12013-12-02 10:54:09 -05002206
2207 if (myRole == Responder) {
2208 memcpy(KDFcontext, peerZid, sizeof(peerZid));
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002209 memcpy(KDFcontext+sizeof(peerZid), ownZid, sizeof(ownZid));
Alexandre Lision51140e12013-12-02 10:54:09 -05002210 }
2211 else {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002212 memcpy(KDFcontext, ownZid, sizeof(ownZid));
2213 memcpy(KDFcontext+sizeof(ownZid), peerZid, sizeof(peerZid));
Alexandre Lision51140e12013-12-02 10:54:09 -05002214 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002215 memcpy(KDFcontext+sizeof(ownZid)+sizeof(peerZid), messageHash, hashLength);
Alexandre Lision51140e12013-12-02 10:54:09 -05002216
2217 KDF(zrtpSession, hashLength, (unsigned char*)zrtpMsk, strlen(zrtpMsk)+1, KDFcontext, kdfSize, hashLength*8, s0);
2218
2219 memset(KDFcontext, 0, sizeof(KDFcontext));
2220
2221 computeSRTPKeys();
2222}
2223
2224void ZRtp::computePBXSecret() {
2225 // Construct the KDF context as per ZRTP specification chap 7.3.1:
2226 // ZIDi || ZIDr
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002227 uint8_t KDFcontext[sizeof(peerZid)+sizeof(ownZid)];
2228 int32_t kdfSize = sizeof(peerZid)+sizeof(ownZid);
Alexandre Lision51140e12013-12-02 10:54:09 -05002229
2230 if (myRole == Responder) {
2231 memcpy(KDFcontext, peerZid, sizeof(peerZid));
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002232 memcpy(KDFcontext+sizeof(peerZid), ownZid, sizeof(ownZid));
Alexandre Lision51140e12013-12-02 10:54:09 -05002233 }
2234 else {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002235 memcpy(KDFcontext, ownZid, sizeof(ownZid));
2236 memcpy(KDFcontext+sizeof(ownZid), peerZid, sizeof(peerZid));
Alexandre Lision51140e12013-12-02 10:54:09 -05002237 }
2238
2239 KDF(zrtpSession, hashLength, (unsigned char*)zrtpTrustedMitm, strlen(zrtpTrustedMitm)+1, KDFcontext,
2240 kdfSize, SHA256_DIGEST_LENGTH * 8, pbxSecretTmpBuffer);
2241
2242 pbxSecretTmp = pbxSecretTmpBuffer; // set pointer to buffer, signal PBX secret was computed
2243}
2244
2245
2246void ZRtp::computeSRTPKeys() {
2247
2248 // allocate the maximum size, compute real size to use
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002249 uint8_t KDFcontext[sizeof(peerZid)+sizeof(ownZid)+sizeof(messageHash)];
2250 int32_t kdfSize = sizeof(peerZid)+sizeof(ownZid)+hashLength;
Alexandre Lision51140e12013-12-02 10:54:09 -05002251
2252 int32_t keyLen = cipher->getKeylen() * 8;
2253
2254 if (myRole == Responder) {
2255 memcpy(KDFcontext, peerZid, sizeof(peerZid));
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002256 memcpy(KDFcontext+sizeof(peerZid), ownZid, sizeof(ownZid));
Alexandre Lision51140e12013-12-02 10:54:09 -05002257 }
2258 else {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002259 memcpy(KDFcontext, ownZid, sizeof(ownZid));
2260 memcpy(KDFcontext+sizeof(ownZid), peerZid, sizeof(peerZid));
Alexandre Lision51140e12013-12-02 10:54:09 -05002261 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002262 memcpy(KDFcontext+sizeof(ownZid)+sizeof(peerZid), messageHash, hashLength);
Alexandre Lision51140e12013-12-02 10:54:09 -05002263
2264 // Inititiator key and salt
2265 KDF(s0, hashLength, (unsigned char*)iniMasterKey, strlen(iniMasterKey)+1, KDFcontext, kdfSize, keyLen, srtpKeyI);
2266 KDF(s0, hashLength, (unsigned char*)iniMasterSalt, strlen(iniMasterSalt)+1, KDFcontext, kdfSize, 112, srtpSaltI);
2267
2268 // Responder key and salt
2269 KDF(s0, hashLength, (unsigned char*)respMasterKey, strlen(respMasterKey)+1, KDFcontext, kdfSize, keyLen, srtpKeyR);
2270 KDF(s0, hashLength, (unsigned char*)respMasterSalt, strlen(respMasterSalt)+1, KDFcontext, kdfSize, 112, srtpSaltR);
2271
2272 // The HMAC keys for GoClear
2273 KDF(s0, hashLength, (unsigned char*)iniHmacKey, strlen(iniHmacKey)+1, KDFcontext, kdfSize, hashLength*8, hmacKeyI);
Alexandre Lision51140e12013-12-02 10:54:09 -05002274 KDF(s0, hashLength, (unsigned char*)respHmacKey, strlen(respHmacKey)+1, KDFcontext, kdfSize, hashLength*8, hmacKeyR);
2275
2276 // The keys for Confirm messages
2277 KDF(s0, hashLength, (unsigned char*)iniZrtpKey, strlen(iniZrtpKey)+1, KDFcontext, kdfSize, keyLen, zrtpKeyI);
2278 KDF(s0, hashLength, (unsigned char*)respZrtpKey, strlen(respZrtpKey)+1, KDFcontext, kdfSize, keyLen, zrtpKeyR);
2279
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002280 detailInfo.pubKey = detailInfo.sasType = NULL;
Alexandre Lision51140e12013-12-02 10:54:09 -05002281 if (!multiStream) {
2282 // Compute the new Retained Secret
2283 KDF(s0, hashLength, (unsigned char*)retainedSec, strlen(retainedSec)+1, KDFcontext, kdfSize, SHA256_DIGEST_LENGTH*8, newRs1);
2284
2285 // Compute the ZRTP Session Key
2286 KDF(s0, hashLength, (unsigned char*)zrtpSessionKey, strlen(zrtpSessionKey)+1, KDFcontext, kdfSize, hashLength*8, zrtpSession);
2287
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002288 // perform generation according to chapter 5.5 and 8.
Alexandre Lision51140e12013-12-02 10:54:09 -05002289 // we don't need a speciai sasValue filed. sasValue are the first
2290 // (leftmost) 32 bits (4 bytes) of sasHash
2291 uint8_t sasBytes[4];
2292 KDF(s0, hashLength, (unsigned char*)sasString, strlen(sasString)+1, KDFcontext, kdfSize, SHA256_DIGEST_LENGTH*8, sasHash);
2293
2294 // according to chapter 8 only the leftmost 20 bits of sasValue (aka
2295 // sasHash) are used to create the character SAS string of type SAS
2296 // base 32 (5 bits per character)
2297 sasBytes[0] = sasHash[0];
2298 sasBytes[1] = sasHash[1];
2299 sasBytes[2] = sasHash[2] & 0xf0;
2300 sasBytes[3] = 0;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002301 if (*(int32_t*)b32 == *(int32_t*)(sasType->getName())) {
2302 SAS = Base32(sasBytes, 20).getEncoded();
2303 }
2304 else {
2305 SAS.assign(sas256WordsEven[sasBytes[0]]).append(":").append(sas256WordsOdd[sasBytes[1]]);
2306 }
2307
Alexandre Lision51140e12013-12-02 10:54:09 -05002308 if (signSasSeen)
2309 callback->signSAS(sasHash);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002310
2311 detailInfo.pubKey = pubKey->getReadable();
2312 detailInfo.sasType = sasType->getReadable();
Alexandre Lision51140e12013-12-02 10:54:09 -05002313 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002314 // set algorithm names into detailInfo structure
2315 detailInfo.authLength = authLength->getReadable();
2316 detailInfo.cipher = cipher->getReadable();
2317 detailInfo.hash = hash->getReadable();
2318
Alexandre Lision51140e12013-12-02 10:54:09 -05002319 memset(KDFcontext, 0, sizeof(KDFcontext));
2320}
2321
2322bool ZRtp::srtpSecretsReady(EnableSecurity part) {
2323
2324 SrtpSecret_t sec;
2325
2326 sec.symEncAlgorithm = cipher->getAlgoId();
2327
2328 sec.keyInitiator = srtpKeyI;
2329 sec.initKeyLen = cipher->getKeylen() * 8;
2330 sec.saltInitiator = srtpSaltI;
2331 sec.initSaltLen = 112;
2332
2333 sec.keyResponder = srtpKeyR;
2334 sec.respKeyLen = cipher->getKeylen() * 8;
2335 sec.saltResponder = srtpSaltR;
2336 sec.respSaltLen = 112;
2337
2338 sec.authAlgorithm = authLength->getAlgoId();
2339 sec.srtpAuthTagLen = authLength->getKeylen();
2340
2341 sec.sas = SAS;
2342 sec.role = myRole;
2343
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002344 bool rc = callback->srtpSecretsReady(&sec, part);
2345
2346 // The call state engine calls ForSender always after ForReceiver.
2347 if (part == ForSender) {
2348 std::string cs(cipher->getReadable());
2349 if (!multiStream) {
2350 cs.append("/").append(pubKey->getName());
2351 if (mitmSeen)
2352 cs.append("/EndAtMitM");
2353 callback->srtpSecretsOn(cs, SAS, zidRec->isSasVerified());
2354 }
2355 else {
2356 std::string cs1("");
2357 if (mitmSeen)
2358 cs.append("/EndAtMitM");
2359 callback->srtpSecretsOn(cs, cs1, true);
2360 }
2361 }
2362 return rc;
Alexandre Lision51140e12013-12-02 10:54:09 -05002363}
2364
2365
2366void ZRtp::setNegotiatedHash(AlgorithmEnum* hash) {
2367 switch (zrtpHashes.getOrdinal(*hash)) {
2368 case 0:
2369 hashLength = SHA256_DIGEST_LENGTH;
2370 hashFunction = sha256;
2371 hashListFunction = sha256;
2372
2373 hmacFunction = hmac_sha256;
2374 hmacListFunction = hmac_sha256;
2375
2376 createHashCtx = createSha256Context;
2377 closeHashCtx = closeSha256Context;
2378 hashCtxFunction = sha256Ctx;
2379 hashCtxListFunction = sha256Ctx;
2380 break;
2381
2382 case 1:
2383 hashLength = SHA384_DIGEST_LENGTH;
2384 hashFunction = sha384;
2385 hashListFunction = sha384;
2386
2387 hmacFunction = hmac_sha384;
2388 hmacListFunction = hmac_sha384;
2389
2390 createHashCtx = createSha384Context;
2391 closeHashCtx = closeSha384Context;
2392 hashCtxFunction = sha384Ctx;
2393 hashCtxListFunction = sha384Ctx;
2394 break;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002395
2396 case 2:
2397 hashLength = SKEIN256_DIGEST_LENGTH;
2398 hashFunction = skein256;
2399 hashListFunction = skein256;
2400
2401 hmacFunction = macSkein256;
2402 hmacListFunction = macSkein256;
2403
2404 createHashCtx = createSkein256Context;
2405 closeHashCtx = closeSkein256Context;
2406 hashCtxFunction = skein256Ctx;
2407 hashCtxListFunction = skein256Ctx;
2408 break;
2409
2410 case 3:
2411 hashLength = SKEIN384_DIGEST_LENGTH;
2412 hashFunction = skein384;
2413 hashListFunction = skein384;
2414
2415 hmacFunction = macSkein384;
2416 hmacListFunction = macSkein384;
2417
2418 createHashCtx = createSkein384Context;
2419 closeHashCtx = closeSkein384Context;
2420 hashCtxFunction = skein384Ctx;
2421 hashCtxListFunction = skein384Ctx;
2422 break;
Alexandre Lision51140e12013-12-02 10:54:09 -05002423 }
2424}
2425
2426
2427void ZRtp::srtpSecretsOff(EnableSecurity part) {
2428 callback->srtpSecretsOff(part);
2429}
2430
2431void ZRtp::SASVerified() {
2432 if (paranoidMode)
2433 return;
2434
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002435 zidRec->setSasVerified();
2436 saveZidRecord = true;
2437 getZidCacheInstance()->saveRecord(zidRec);
Alexandre Lision51140e12013-12-02 10:54:09 -05002438}
2439
2440void ZRtp::resetSASVerified() {
Alexandre Lision51140e12013-12-02 10:54:09 -05002441
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002442 zidRec->resetSasVerified();
2443 getZidCacheInstance()->saveRecord(zidRec);
Alexandre Lision51140e12013-12-02 10:54:09 -05002444}
2445
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002446void ZRtp::setRs2Valid() {
2447
2448 if (zidRec != NULL) {
2449 zidRec->setRs2Valid();
2450 if (saveZidRecord)
2451 getZidCacheInstance()->saveRecord(zidRec);
2452 }
2453}
Alexandre Lision51140e12013-12-02 10:54:09 -05002454
2455void ZRtp::sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) {
2456
2457 // We've reached secure state: overwrite the SRTP master key and master salt.
2458 if (severity == Info && subCode == InfoSecureStateOn) {
2459 memset(srtpKeyI, 0, cipher->getKeylen());
2460 memset(srtpSaltI, 0, 112/8);
2461 memset(srtpKeyR, 0, cipher->getKeylen());
2462 memset(srtpSaltR, 0, 112/8);
2463 }
2464 callback->sendInfo(severity, subCode);
2465}
2466
2467
2468void ZRtp::zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) {
2469 callback->zrtpNegotiationFailed(severity, subCode);
2470}
2471
2472void ZRtp::zrtpNotSuppOther() {
2473 callback->zrtpNotSuppOther();
2474}
2475
2476void ZRtp::synchEnter() {
2477 callback->synchEnter();
2478}
2479
2480void ZRtp::synchLeave() {
2481 callback->synchLeave();
2482}
2483
2484int32_t ZRtp::sendPacketZRTP(ZrtpPacketBase *packet) {
2485 return ((packet == NULL) ? 0 :
2486 callback->sendDataZRTP(packet->getHeaderBase(), (packet->getLength() * 4) + 4));
2487}
2488
2489int32_t ZRtp::activateTimer(int32_t tm) {
2490 return (callback->activateTimer(tm));
2491}
2492
2493int32_t ZRtp::cancelTimer() {
2494 return (callback->cancelTimer());
2495}
2496
2497void ZRtp::setAuxSecret(uint8_t* data, int32_t length) {
2498 if (length > 0) {
2499 auxSecret = new uint8_t[length];
2500 auxSecretLength = length;
2501 memcpy(auxSecret, data, length);
2502 }
2503}
2504
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002505void ZRtp::setClientId(std::string id, HelloPacketVersion* hpv) {
Alexandre Lision51140e12013-12-02 10:54:09 -05002506
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002507 unsigned char tmp[CLIENT_ID_SIZE +1] = {' '};
2508 memcpy(tmp, id.c_str(), id.size() > CLIENT_ID_SIZE ? CLIENT_ID_SIZE : id.size());
2509 tmp[CLIENT_ID_SIZE] = 0;
Alexandre Lision51140e12013-12-02 10:54:09 -05002510
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002511 hpv->packet->setClientId(tmp);
2512
2513 int32_t len = hpv->packet->getLength() * ZRTP_WORD_SIZE;
2514
2515 // Hello packets are ready now, compute its HMAC
Alexandre Lision51140e12013-12-02 10:54:09 -05002516 // (excluding the HMAC field (2*ZTP_WORD_SIZE)) and store in Hello
2517 // use the implicit hash function
2518 uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
2519 uint32_t macLen;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002520 hmacFunctionImpl(H2, HASH_IMAGE_SIZE, (uint8_t*)hpv->packet->getHeaderBase(), len-(2*ZRTP_WORD_SIZE), hmac, &macLen);
2521 hpv->packet->setHMAC(hmac);
Alexandre Lision51140e12013-12-02 10:54:09 -05002522
2523 // calculate hash over the final Hello packet, refer to chap 9.1 how to
2524 // use this hash in SIP/SDP.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002525 hashFunctionImpl((uint8_t*)hpv->packet->getHeaderBase(), len, hpv->helloHash);
Alexandre Lision51140e12013-12-02 10:54:09 -05002526}
2527
2528void ZRtp::storeMsgTemp(ZrtpPacketBase* pkt) {
2529 uint32_t length = pkt->getLength() * ZRTP_WORD_SIZE;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002530 length = (length > sizeof(tempMsgBuffer)) ? sizeof(tempMsgBuffer) : length;
Alexandre Lision51140e12013-12-02 10:54:09 -05002531 memset(tempMsgBuffer, 0, sizeof(tempMsgBuffer));
2532 memcpy(tempMsgBuffer, (uint8_t*)pkt->getHeaderBase(), length);
2533 lengthOfMsgData = length;
2534}
2535
2536bool ZRtp::checkMsgHmac(uint8_t* key) {
2537 uint8_t hmac[IMPL_MAX_DIGEST_LENGTH];
2538 uint32_t macLen;
2539 int32_t len = lengthOfMsgData-(HMAC_SIZE); // compute HMAC, but exlude the stored HMAC :-)
2540
2541 // Use the implicit hash function
2542 hmacFunctionImpl(key, HASH_IMAGE_SIZE, tempMsgBuffer, len, hmac, &macLen);
2543 return (memcmp(hmac, tempMsgBuffer+len, (HMAC_SIZE)) == 0 ? true : false);
2544}
2545
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002546std::string ZRtp::getHelloHash(int32_t index) {
Alexandre Lision51140e12013-12-02 10:54:09 -05002547 std::ostringstream stm;
2548
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002549 if (index < 0 || index >= MAX_ZRTP_VERSIONS)
2550 return std::string();
Alexandre Lision51140e12013-12-02 10:54:09 -05002551
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002552 uint8_t* hp = helloPackets[index].helloHash;
2553
2554 char version[5] = {'\0'};
2555 strncpy(version, (const char*)helloPackets[index].packet->getVersion(), ZRTP_WORD_SIZE);
2556
2557 stm << version;
Alexandre Lision51140e12013-12-02 10:54:09 -05002558 stm << " ";
2559 stm.fill('0');
2560 stm << hex;
2561 for (int i = 0; i < hashLengthImpl; i++) {
2562 stm.width(2);
2563 stm << static_cast<uint32_t>(*hp++);
2564 }
2565 return stm.str();
2566}
2567
2568std::string ZRtp::getPeerHelloHash() {
2569 std::ostringstream stm;
2570
2571 if (peerHelloVersion[0] == 0)
2572 return std::string();
2573
2574 uint8_t* hp = peerHelloHash;
2575
2576 stm << peerHelloVersion;
2577 stm << " ";
2578 stm.fill('0');
2579 stm << hex;
2580 for (int i = 0; i < hashLengthImpl; i++) {
2581 stm.width(2);
2582 stm << static_cast<uint32_t>(*hp++);
2583 }
2584 return stm.str();
2585}
2586
2587std::string ZRtp::getMultiStrParams() {
2588
2589 // the string will hold binary data - it's opaque to the application
2590 std::string str("");
2591 char tmp[MAX_DIGEST_LENGTH + 1 + 1 + 1]; // hash length + cipher + authLength + hash
2592
2593 if (inState(SecureState) && !multiStream) {
2594 // construct array that holds zrtpSession, cipher type, auth-length, and hash type
2595 tmp[0] = zrtpHashes.getOrdinal(*hash);
2596 tmp[1] = zrtpAuthLengths.getOrdinal(*authLength);
2597 tmp[2] = zrtpSymCiphers.getOrdinal(*cipher);
2598 memcpy(tmp+3, zrtpSession, hashLength);
2599 str.assign(tmp, hashLength + 1 + 1 + 1); // set chars (bytes) to the string
2600 }
2601 return str;
2602}
2603
2604void ZRtp::setMultiStrParams(std::string parameters) {
2605
2606 char tmp[MAX_DIGEST_LENGTH + 1 + 1 + 1]; // max. hash length + cipher + authLength + hash
2607
2608 // First get negotiated hash from parameters, set algorithms and length
2609 int i = parameters.at(0) & 0xff;
2610 hash = &zrtpHashes.getByOrdinal(i);
2611 setNegotiatedHash(hash); // sets hashlength
2612
2613 // use string.copy(buffer, num, start=0) to retrieve chars (bytes) from the string
2614 parameters.copy(tmp, hashLength + 1 + 1 + 1, 0);
2615
2616 i = tmp[1] & 0xff;
2617 authLength = &zrtpAuthLengths.getByOrdinal(i);
2618 i = tmp[2] & 0xff;
2619 cipher = &zrtpSymCiphers.getByOrdinal(i);
2620 memcpy(zrtpSession, tmp+3, hashLength);
2621
2622 // after setting zrtpSession, cipher, and auth-length set multi-stream to true
2623 multiStream = true;
2624 stateEngine->setMultiStream(true);
2625}
2626
2627bool ZRtp::isMultiStream() {
2628 return multiStream;
2629}
2630
2631bool ZRtp::isMultiStreamAvailable() {
2632 return multiStreamAvailable;
2633}
2634
2635void ZRtp::acceptEnrollment(bool accepted) {
2636 if (!accepted) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002637 zidRec->resetMITMKeyAvailable();
Alexandre Lision51140e12013-12-02 10:54:09 -05002638 callback->zrtpInformEnrollment(EnrollmentCanceled);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002639 getZidCacheInstance()->saveRecord(zidRec);
Alexandre Lision51140e12013-12-02 10:54:09 -05002640 return;
2641 }
Alexandre Lision51140e12013-12-02 10:54:09 -05002642 if (pbxSecretTmp != NULL) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002643 zidRec->setMiTMData(pbxSecretTmp);
2644 getZidCacheInstance()->saveRecord(zidRec);
Alexandre Lision51140e12013-12-02 10:54:09 -05002645 callback->zrtpInformEnrollment(EnrollmentOk);
2646 }
2647 else {
2648 callback->zrtpInformEnrollment(EnrollmentFailed);
Alexandre Lision51140e12013-12-02 10:54:09 -05002649 }
Alexandre Lision51140e12013-12-02 10:54:09 -05002650 return;
2651}
2652
2653bool ZRtp::setSignatureData(uint8_t* data, int32_t length) {
2654 if ((length % 4) != 0)
2655 return false;
2656
2657 ZrtpPacketConfirm* cfrm = (myRole == Responder) ? &zrtpConfirm1 : &zrtpConfirm2;
2658 cfrm->setSignatureLength(length / 4);
2659 return cfrm->setSignatureData(data, length);
2660}
2661
2662const uint8_t* ZRtp::getSignatureData() {
2663 return signatureData;
2664}
2665
2666int32_t ZRtp::getSignatureLength() {
2667 return signatureLength * ZRTP_WORD_SIZE;
2668}
2669
2670void ZRtp::conf2AckSecure() {
2671 Event_t ev;
2672
2673 ev.type = ZrtpPacket;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002674 ev.packet = (uint8_t*)zrtpConf2Ack.getHeaderBase();
2675 ev.length = sizeof (Conf2AckPacket_t) + 12; // 12 is fixed ZRTP (RTP) header size
Alexandre Lision51140e12013-12-02 10:54:09 -05002676
2677 if (stateEngine != NULL) {
2678 stateEngine->processEvent(&ev);
2679 }
2680}
2681
2682int32_t ZRtp::compareCommit(ZrtpPacketCommit *commit) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002683 // TODO: enhance to compare according to rules defined in chapter 4.2,
2684 // but we don't support Preshared.
Alexandre Lision51140e12013-12-02 10:54:09 -05002685 int32_t len = 0;
2686 len = !multiStream ? HVI_SIZE : (4 * ZRTP_WORD_SIZE);
2687 return (memcmp(hvi, commit->getHvi(), len));
2688}
2689
2690bool ZRtp::isEnrollmentMode() {
2691 return enrollmentMode;
2692}
2693
2694void ZRtp::setEnrollmentMode(bool enrollmentMode) {
2695 this->enrollmentMode = enrollmentMode;
2696}
2697
2698bool ZRtp::isPeerEnrolled() {
2699 return peerIsEnrolled;
2700}
2701
2702bool ZRtp::sendSASRelayPacket(uint8_t* sh, std::string render) {
2703
2704 uint8_t confMac[MAX_DIGEST_LENGTH];
2705 uint32_t macLen;
2706 uint8_t* hkey, *ekey;
2707
2708 // If we are responder then the PBX used it's Initiator keys
2709 if (myRole == Responder) {
2710 hkey = hmacKeyR;
2711 ekey = zrtpKeyR;
2712 // TODO: check signature length in zrtpConfirm1 and if not zero copy Signature data
2713 }
2714 else {
2715 hkey = hmacKeyI;
2716 ekey = zrtpKeyI;
2717 // TODO: check signature length in zrtpConfirm2 and if not zero copy Signature data
2718 }
2719 // Prepare IV data that we will use during confirm packet encryption.
2720 randomZRTP(randomIV, sizeof(randomIV));
2721 zrtpSasRelay.setIv(randomIV);
2722 zrtpSasRelay.setTrustedSas(sh);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002723 zrtpSasRelay.setSasAlgo((uint8_t*)render.c_str());
Alexandre Lision51140e12013-12-02 10:54:09 -05002724
Alexandre Lision51140e12013-12-02 10:54:09 -05002725 int16_t hmlen = (zrtpSasRelay.getLength() - 9) * ZRTP_WORD_SIZE;
2726 cipher->getEncrypt()(ekey, cipher->getKeylen(), randomIV, (uint8_t*)zrtpSasRelay.getFiller(), hmlen);
2727
2728 // Use negotiated HMAC (hash)
2729 hmacFunction(hkey, hashLength, (unsigned char*)zrtpSasRelay.getFiller(), hmlen, confMac, &macLen);
2730
2731 zrtpSasRelay.setHmac(confMac);
2732
2733 stateEngine->sendSASRelay(&zrtpSasRelay);
2734 return true;
2735}
2736
2737std::string ZRtp::getSasType() {
2738 std::string sasT(sasType->getName());
2739 return sasT;
2740}
2741
2742uint8_t* ZRtp::getSasHash() {
2743 return sasHash;
2744}
2745
2746int32_t ZRtp::getPeerZid(uint8_t* data) {
2747 memcpy(data, peerZid, IDENTIFIER_LEN);
2748 return IDENTIFIER_LEN;
2749}
2750
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05002751const ZRtp::zrtpInfo* ZRtp::getDetailInfo() {
2752 return &detailInfo;
2753}
2754
2755std::string ZRtp::getPeerClientId() {
2756 if (peerClientId.empty())
2757 return std::string();
2758 return peerClientId;
2759}
2760
2761std::string ZRtp::getPeerProtcolVersion() {
2762 if (peerHelloVersion[0] == 0)
2763 return std::string();
2764 return std::string((char*)peerHelloVersion);
2765}
2766
Alexandre Lision51140e12013-12-02 10:54:09 -05002767/** EMACS **
2768 * Local variables:
2769 * mode: c++
2770 * c-default-style: ellemtel
2771 * c-basic-offset: 4
2772 * End:
2773 */
2774