blob: 11600a92fd0770624151b1a6064dc460ff9aeb4c [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
18/**
19 * @author Werner Dittmann <Werner.Dittmann@t-online.de>
20 */
21
22#include <iostream>
23#include <cstdlib>
24#include <ctype.h>
25
26#include <libzrtpcpp/ZRtp.h>
27#include <libzrtpcpp/ZrtpStateClass.h>
28
29using namespace std;
30using namespace GnuZrtpCodes;
31
32state_t states[numberOfStates] = {
33 {Initial, &ZrtpStateClass::evInitial },
34 {Detect, &ZrtpStateClass::evDetect },
35 {AckDetected, &ZrtpStateClass::evAckDetected },
36 {AckSent, &ZrtpStateClass::evAckSent },
37 {WaitCommit, &ZrtpStateClass::evWaitCommit },
38 {CommitSent, &ZrtpStateClass::evCommitSent },
39 {WaitDHPart2, &ZrtpStateClass::evWaitDHPart2 },
40 {WaitConfirm1, &ZrtpStateClass::evWaitConfirm1 },
41 {WaitConfirm2, &ZrtpStateClass::evWaitConfirm2 },
42 {WaitConfAck, &ZrtpStateClass::evWaitConfAck },
43 {WaitClearAck, &ZrtpStateClass::evWaitClearAck },
44 {SecureState, &ZrtpStateClass::evSecureState },
45 {WaitErrorAck, &ZrtpStateClass::evWaitErrorAck }
46};
47
48
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050049ZrtpStateClass::ZrtpStateClass(ZRtp *p) : parent(p), commitPkt(NULL), multiStream(false), secSubstate(Normal), sentVersion(0) {
Alexandre Lision51140e12013-12-02 10:54:09 -050050 engine = new ZrtpStates(states, numberOfStates, Initial);
51
Alexandre Lision51140e12013-12-02 10:54:09 -050052 // Set up timers according to ZRTP spec
53 T1.start = 50;
54 T1.maxResend = 20;
55 T1.capping = 200;
56
57 T2.start = 150;
58 T2.maxResend = 10;
59 T2.capping = 600;
60}
61
62ZrtpStateClass::~ZrtpStateClass(void) {
63
64 // If not in Initial state: close the protocol engine
65 // before destroying it. This will free pending packets
66 // if necessary.
67 if (!inState(Initial)) {
68 Event_t ev;
69
70 cancelTimer();
71 ev.type = ZrtpClose;
72 event = &ev;
73 engine->processEvent(*this);
74 }
75 delete engine;
76}
77
78void ZrtpStateClass::processEvent(Event_t *ev) {
79
Alexandre Lision51140e12013-12-02 10:54:09 -050080 char *msg, first, middle, last;
81 uint8_t *pkt;
82
83 parent->synchEnter();
84
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050085 event = ev;
Alexandre Lision51140e12013-12-02 10:54:09 -050086 if (event->type == ZrtpPacket) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050087 pkt = event->packet;
88 msg = (char *)pkt + 4;
89 first = tolower(*msg);
90 middle = tolower(*(msg+4));
Alexandre Lision51140e12013-12-02 10:54:09 -050091 last = tolower(*(msg+7));
92
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050093 // Sanity check of packet size for all states except WaitErrorAck.
94 if (!inState(WaitErrorAck)) {
95 uint16_t totalLength = *(uint16_t*)(pkt+2);
96 totalLength = zrtpNtohs(totalLength) * ZRTP_WORD_SIZE;
97 totalLength += 12 + sizeof(uint32_t); // 12 bytes is fixed header, uint32_t is CRC
98
99 if (totalLength != ev->length) {
100 fprintf(stderr, "Total length does not match received length: %d - %ld\n", totalLength, ev->length);
101 sendErrorPacket(MalformedPacket);
102 parent->synchLeave();
103 return;
104 }
105 }
106
Alexandre Lision51140e12013-12-02 10:54:09 -0500107 // Check if this is an Error packet.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500108 if (first == 'e' && middle =='r' && last == ' ') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500109 /*
110 * Process a received Error packet.
111 *
112 * In any case stop timer to prevent resending packets.
113 * Use callback method to prepare and get an ErrorAck packet.
114 * Modify event type to "ErrorPkt" and hand it over to current
115 * state for further processing.
116 */
117 cancelTimer();
118 ZrtpPacketError epkt(pkt);
119 ZrtpPacketErrorAck* eapkt = parent->prepareErrorAck(&epkt);
120 parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(eapkt));
121 event->type = ErrorPkt;
122 }
123 else if (first == 'p' && middle == ' ' && last == ' ') {
124 ZrtpPacketPing ppkt(pkt);
125 ZrtpPacketPingAck* ppktAck = parent->preparePingAck(&ppkt);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500126 if (ppktAck != NULL) { // ACK only to valid PING packet, otherwise ignore it
Alexandre Lision51140e12013-12-02 10:54:09 -0500127 parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck));
128 }
129 parent->synchLeave();
130 return;
131 }
132 else if (first == 's' && last == 'y') {
133 uint32_t errorCode = 0;
134 ZrtpPacketSASrelay* srly = new ZrtpPacketSASrelay(pkt);
135 ZrtpPacketRelayAck* rapkt = parent->prepareRelayAck(srly, &errorCode);
136 parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(rapkt));
137 parent->synchLeave();
138 return;
139 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500140 }
141 /*
142 * Shut down protocol state engine: cancel outstanding timer, further
143 * processing in current state.
144 */
145 else if (event->type == ZrtpClose) {
146 cancelTimer();
147 }
148 engine->processEvent(*this);
149 parent->synchLeave();
150}
151
152
153void ZrtpStateClass::evInitial(void) {
154 DEBUGOUT((cout << "Checking for match in Initial.\n"));
155
156 if (event->type == ZrtpInitial) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500157 ZrtpPacketHello* hello = parent->prepareHello();
158 sentVersion = hello->getVersionInt();
Alexandre Lision51140e12013-12-02 10:54:09 -0500159
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500160 // remember packet for easy resend in case timer triggers
161 sentPacket = static_cast<ZrtpPacketBase *>(hello);
Alexandre Lision51140e12013-12-02 10:54:09 -0500162
163 if (!parent->sendPacketZRTP(sentPacket)) {
164 sendFailed(); // returns to state Initial
165 return;
166 }
167 if (startTimer(&T1) <= 0) {
168 timerFailed(SevereNoTimer); // returns to state Initial
169 return;
170 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500171 nextState(Detect);
Alexandre Lision51140e12013-12-02 10:54:09 -0500172 }
173}
174
175/*
176 * Detect state.
177 *
178 * When in this state the protocol engine sent an initial Hello packet
179 * to the peer.
180 *
181 * When entering this state transition function then:
182 * - Assume Initiator mode, mode may change later on peer reaction
183 * - Instance variable sentPacket contains the sent Hello packet
184 * - Hello timer T1 may be active. This is the case if the other peer
185 * has prepared its RTP session and answers our Hello packets nearly
186 * immediately, i.e. before the Hello timeout counter expires. If the
187 * other peer does not send a Hello during this time the state engine
188 * reports "other peer does not support ZRTP" but stays
189 * in state Detect with no active timer (passiv mode). Staying in state
190 * Detect allows another peer to start its detect phase any time later.
191 *
192 * This restart capability is the reason why we use "startTimer(&T1)" in
193 * case we received a Hello packet from another peer. This effectively
194 * restarts the Hello timeout counter.
195 *
196 * In this state we also handle ZrtpInitialize event. This forces a
197 * restart of ZRTP discovery if an application calls ZrtpQueue#startZrtp
198 * again. This may happen after a previous discovery phase were not
199 * successful.
200 *
201 * Usually applications use some sort of signaling protocol, for example
202 * SIP, to negotiate the RTP parameters. Thus the RTP sessions setup is
203 * fairly sychronized and thus also the ZRTP detection phase. Applications
204 * that use some other ways to setup the RTP sessions this restart capability
205 * comes in handy because no RTP setup sychronization is necessary.
206 *
207 * Possible events in this state are:
208 * - timeout for sent Hello packet: causes a resend check and
209 * repeat sending of Hello packet
210 * - received a HelloAck: stop active timer, prepare and send Hello packet,
211 * switch to state AckDeteced.
212 * - received a Hello: stop active timer, send HelloAck, prepare Commit
213 * packet, switch to state AckSent.
214 *
215 */
216void ZrtpStateClass::evDetect(void) {
217
218 DEBUGOUT((cout << "Checking for match in Detect.\n"));
219
220 char *msg, first, last;
221 uint8_t *pkt;
222 uint32_t errorCode = 0;
223
224 /*
225 * First check the general event type, then discrimnate
226 * the real event.
227 */
228 if (event->type == ZrtpPacket) {
229 pkt = event->packet;
230 msg = (char *)pkt + 4;
231
232 first = tolower(*msg);
233 last = tolower(*(msg+7));
234 /*
235 * HelloAck:
236 * - our peer acknowledged our Hello packet, we have not seen the peer's Hello yet
237 * - cancel timer T1 to stop resending Hello
238 * - switch to state AckDetected, wait for peer's Hello (F3)
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500239 *
240 * When we receive an HelloAck this also means that out partner accepted our protocol version.
Alexandre Lision51140e12013-12-02 10:54:09 -0500241 */
242 if (first == 'h' && last =='k') {
243 cancelTimer();
244 sentPacket = NULL;
245 nextState(AckDetected);
246 return;
247 }
248 /*
249 * Hello:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500250 * - send HelloAck packet to acknowledge the received Hello packet if versions match.
251 * Otherweise negotiate ZRTP versions.
Alexandre Lision51140e12013-12-02 10:54:09 -0500252 * - use received Hello packet to prepare own Commit packet. We need to
253 * do it at this point because we need the hash value computed from
254 * peer's Hello packet. Follwing states my use the prepared Commit.
255 * - switch to new state AckSent which sends own Hello packet until
256 * peer acknowledges this
257 * - Don't clear sentPacket, points to Hello
258 */
259 if (first == 'h' && last ==' ') {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500260 ZrtpPacketHello hpkt(pkt);
261
Alexandre Lision51140e12013-12-02 10:54:09 -0500262 cancelTimer();
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500263
264 /*
265 * Check and negotiate the ZRTP protocol version first.
266 *
267 * This selection mechanism relies on the fact that we sent the highest supported protocol version in
268 * the initial Hello packet with as stated in RFC6189, section 4.1.1
269 */
270 int32_t recvVersion = hpkt.getVersionInt();
271 if (recvVersion > sentVersion) { // We don't support this version, stay in state with timer active
272 if (startTimer(&T1) <= 0) {
273 timerFailed(SevereNoTimer); // returns to state Initial
274 }
275 return;
276 }
277
278 /*
279 * The versions don't match. Start negotiating versions. This negotiation stays in the Detect state.
280 * Only if the received version matches our own sent version we start to send a HelloAck.
281 */
282 if (recvVersion != sentVersion) {
283 ZRtp::HelloPacketVersion* hpv = parent->helloPackets;
284
285 int32_t index;
286 for (index = 0; hpv->packet && hpv->packet != parent->currentHelloPacket; hpv++, index++) // Find current sent Hello
287 ;
288
289 for(; index >= 0 && hpv->version > recvVersion; hpv--, index--) // find a supported version less-equal to received version
290 ;
291
292 if (index < 0) {
293 sendErrorPacket(UnsuppZRTPVersion);
294 return;
295 }
296 parent->currentHelloPacket = hpv->packet;
297 sentVersion = parent->currentHelloPacket->getVersionInt();
298
299 // remember packet for easy resend in case timer triggers
300 sentPacket = static_cast<ZrtpPacketBase *>(parent->currentHelloPacket);
301
302 if (!parent->sendPacketZRTP(sentPacket)) {
303 sendFailed(); // returns to state Initial
304 return;
305 }
306 if (startTimer(&T1) <= 0) {
307 timerFailed(SevereNoTimer); // returns to state Initial
308 return;
309 }
310 return;
311 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500312 ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck();
313
314 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
315 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
316 return;
317 }
318 // Use peer's Hello packet to create my commit packet, store it
319 // for possible later usage in state AckSent
Alexandre Lision51140e12013-12-02 10:54:09 -0500320 commitPkt = parent->prepareCommit(&hpkt, &errorCode);
321
322 nextState(AckSent);
323 if (commitPkt == NULL) {
324 sendErrorPacket(errorCode); // switches to Error state
325 return;
326 }
327 if (startTimer(&T1) <= 0) { // restart own Hello timer/counter
328 timerFailed(SevereNoTimer); // returns to state Initial
329 }
330 T1.maxResend = 60; // more retries to extend time, see chap. 6
331 }
332 return; // unknown packet for this state - Just ignore it
333 }
334 // Timer event triggered - this is Timer T1 to resend Hello
335 else if (event->type == Timer) {
336 if (!parent->sendPacketZRTP(sentPacket)) {
337 sendFailed(); // returns to state Initial
338 return;
339 }
340 if (nextTimer(&T1) <= 0) {
341 commitPkt = NULL;
342 parent->zrtpNotSuppOther();
343 nextState(Detect);
344 }
345 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500346 // If application calls zrtpStart() to restart discovery
Alexandre Lision51140e12013-12-02 10:54:09 -0500347 else if (event->type == ZrtpInitial) {
348 cancelTimer();
349 if (!parent->sendPacketZRTP(sentPacket)) {
350 sendFailed(); // returns to state Initial
351 return;
352 }
353 if (startTimer(&T1) <= 0) {
354 timerFailed(SevereNoTimer); // returns to state Initial
355 }
356 }
357 else { // unknown Event type for this state (covers Error and ZrtpClose)
358 if (event->type != ZrtpClose) {
359 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
360 }
361 sentPacket = NULL;
362 nextState(Initial);
363 }
364}
365
366/*
367 * AckSent state.
368 *
369 * The protocol engine got a Hello packet from peer and answered with a
370 * HelloAck response. According to the protocol we must also send a
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500371 * Hello after HelloAck (refer to figure 1 in ZRTP RFC 6189, message
Alexandre Lision51140e12013-12-02 10:54:09 -0500372 * HelloACK (F2) must be followed by Hello (F3)). We use the timeout in
373 * this state to send the required Hello (F3).
374 *
375 * Our peer must acknowledge the Hello with HelloAck. In earlier versions
376 * also a Commit was a valid packet thus the code covers this.
377 * Figure 1 in the RFC shows the HelloAck, chapter 7 states that a Commit
378 * may be send to acknowledge Hello. There is one constraint when using a Commit to
379 * acknowledge Hello: refer to chapter 4.1 that requires that both parties
380 * have completed the Hello/HelloAck discovery handshake. This implies that
381 * only message F4 may be replaced by a Commit. This constraint guarantees
382 * that both peers have seen at least one Hello.
383 *
384 * When entering this transition function:
385 * - The instance variabe sentPacket contains own Hello packet
386 * - The instance variabe commitPkt points to prepared Commit packet
387 * - Timer T1 is active
388 *
389 * Possible events in this state are:
390 * - timeout for sent Hello packet: causes a resend check and repeat sending
391 * of Hello packet
392 * - HelloAck: The peer answered with HelloAck to own HelloAck/Hello. Send
393 * prepared Commit packet and try Initiator mode.
394 * - Commit: The peer answered with Commit to HelloAck/Hello, thus switch to
395 * responder mode.
396 * - Hello: If the protcol engine receives another Hello it repeats the
397 * HelloAck/Hello response until Timer T1 exceeds its maximum. This may
398 * happen if the other peer sends Hello only (maybe due to network problems)
399 */
400void ZrtpStateClass::evAckSent(void) {
401
402 DEBUGOUT((cout << "Checking for match in AckSent.\n"));
403
404 char *msg, first, last;
405 uint8_t *pkt;
406 uint32_t errorCode = 0;
407
408 /*
409 * First check the general event type, then discrimnate
410 * the real event.
411 */
412 if (event->type == ZrtpPacket) {
413 pkt = event->packet;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500414 msg = (char *)pkt + 4;
Alexandre Lision51140e12013-12-02 10:54:09 -0500415
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500416 first = tolower(*msg);
417 last = tolower(*(msg+7));
Alexandre Lision51140e12013-12-02 10:54:09 -0500418
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500419 /*
Alexandre Lision51140e12013-12-02 10:54:09 -0500420 * HelloAck:
421 * The peer answers with HelloAck to own HelloAck/Hello. Send Commit
422 * and try Initiator mode. The requirement defined in chapter 4.1 to
423 * have a complete Hello/HelloAck is fulfilled.
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500424 * - stop Hello timer T1
425 * - send own Commit message
426 * - switch state to CommitSent, start Commit timer, assume Initiator
427 */
428 if (first == 'h' && last =='k') {
429 cancelTimer();
Alexandre Lision51140e12013-12-02 10:54:09 -0500430
431 // remember packet for easy resend in case timer triggers
432 // Timer trigger received in new state CommitSend
433 sentPacket = static_cast<ZrtpPacketBase *>(commitPkt);
434 commitPkt = NULL; // now stored in sentPacket
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500435 nextState(CommitSent);
Alexandre Lision51140e12013-12-02 10:54:09 -0500436 if (!parent->sendPacketZRTP(sentPacket)) {
437 sendFailed(); // returns to state Initial
438 return;
439 }
440 if (startTimer(&T2) <= 0) {
441 timerFailed(SevereNoTimer); // returns to state Initial
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500442 }
443 return;
Alexandre Lision51140e12013-12-02 10:54:09 -0500444 }
445 /*
446 * Hello:
447 * - peer didn't receive our HelloAck
448 * - repeat HelloAck/Hello response:
449 * -- get HelloAck packet, send it
450 * -- The timeout trigger of T1 sends our Hello packet
451 * -- stay in state AckSent
452 *
453 * Similar to Detect state: just acknowledge the Hello, the next
454 * timeout sends the following Hello.
455 */
456
457 if (first == 'h' && last ==' ') {
458 ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck();
459
460 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
461 nextState(Detect);
462 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
463 }
464 return;
465 }
466 /*
467 * Commit:
468 * The peer answers with Commit to HelloAck/Hello, thus switch to
469 * responder mode.
470 * - stop timer T1
471 * - prepare and send our DHPart1
472 * - switch to state WaitDHPart2 and wait for peer's DHPart2
473 * - don't start timer, we are responder
474 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500475 if (first == 'c' && last == ' ') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500476 cancelTimer();
477 ZrtpPacketCommit cpkt(pkt);
478
479 if (!multiStream) {
480 ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&cpkt, &errorCode);
481
482 // Something went wrong during processing of the Commit packet
483 if (dhPart1 == NULL) {
484 if (errorCode != IgnorePacket) {
485 sendErrorPacket(errorCode);
486 }
487 return;
488 }
489 commitPkt = NULL;
490 sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
491 nextState(WaitDHPart2);
492 }
493 else {
494 ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&cpkt, &errorCode);
495
496 // Something went wrong during processing of the Commit packet
497 if (confirm == NULL) {
498 if (errorCode != IgnorePacket) {
499 sendErrorPacket(errorCode);
500 }
501 return;
502 }
503 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
504 nextState(WaitConfirm2);
505 }
506 if (!parent->sendPacketZRTP(sentPacket)) {
507 sendFailed(); // returns to state Initial
508 }
509 }
510 }
511 /*
512 * Timer:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500513 * - resend Hello packet, stay in state, restart timer until repeat
Alexandre Lision51140e12013-12-02 10:54:09 -0500514 * counter triggers
515 * - if repeat counter triggers switch to state Detect, con't clear
516 * sentPacket, Detect requires it to point to own Hello message
517 */
518 else if (event->type == Timer) {
519 if (!parent->sendPacketZRTP(sentPacket)) {
520 return sendFailed(); // returns to state Initial
521 }
522 if (nextTimer(&T1) <= 0) {
523 parent->zrtpNotSuppOther();
524 commitPkt = NULL;
525 // Stay in state Detect to be prepared get an hello from
526 // other peer any time later
527 nextState(Detect);
528 }
529 }
530 else { // unknown Event type for this state (covers Error and ZrtpClose)
531 if (event->type != ZrtpClose) {
532 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
533 }
534 commitPkt = NULL;
535 sentPacket = NULL;
536 nextState(Initial);
537 }
538}
539/*
540 * AckDetected state.
541 *
542 * The protocol engine received a HelloAck in state Detect, thus the peer
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500543 * acknowledged our the Hello. According to ZRT RFC 6189 our peer must send
Alexandre Lision51140e12013-12-02 10:54:09 -0500544 * its Hello until our protocol engine sees it (refer also to comment for
545 * state AckSent). This protocol sequence gurantees that both peers got at
546 * least one Hello.
547 *
548 * When entering this transition function
549 * - instance variable sentPacket is NULL, Hello timer stopped
550 *
551 * Possible events in this state are:
552 * Hello: we have to choices
553 * 1) we can acknowledge the peer's Hello with a HelloAck
554 * 2) we can acknowledge the peer's Hello with a Commit
555 * Both choices are implemented and may be enabled by setting a compile
556 * time #if (see code below). Currently we use choice 1) here because
557 * it's more aligned to the ZRTP specification
558 */
559void ZrtpStateClass::evAckDetected(void) {
560
561 DEBUGOUT((cout << "Checking for match in AckDetected.\n"));
562
563 char *msg, first, last;
564 uint8_t *pkt;
565 uint32_t errorCode = 0;
566
567 if (event->type == ZrtpPacket) {
568 pkt = event->packet;
569 msg = (char *)pkt + 4;
570
571 first = tolower(*msg);
572 last = tolower(*(msg+7));
573
574#if 1
575 /*
576 * Implementation for choice 1)
577 * Hello:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500578 * - Acknowledge peer's Hello, sending HelloACK (F4)
Alexandre Lision51140e12013-12-02 10:54:09 -0500579 * - switch to state WaitCommit, wait for peer's Commit
580 * - we are going to be in the Responder role
581 */
582
583 if (first == 'h' && last ==' ') {
584 // Parse Hello packet and build an own Commit packet even if the
585 // Commit is not send to the peer. We need to do this to check the
586 // Hello packet and prepare the shared secret stuff.
587 ZrtpPacketHello hpkt(pkt);
588 ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode);
589
590 // Something went wrong during processing of the Hello packet, for
591 // example wrong version, duplicate ZID.
592 if (commit == NULL) {
593 sendErrorPacket(errorCode);
594 return;
595 }
596 ZrtpPacketHelloAck *helloAck = parent->prepareHelloAck();
597 nextState(WaitCommit);
598
599 // remember packet for easy resend
600 sentPacket = static_cast<ZrtpPacketBase *>(helloAck);
601 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
602 sendFailed();
603 }
604 }
605#else
606 /*
607 * Implementation for choice 2)
608 * Hello:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500609 * - Acknowledge peer's Hello by sending Commit (F5)
Alexandre Lision51140e12013-12-02 10:54:09 -0500610 * instead of HelloAck (F4)
611 * - switch to state CommitSent
612 * - Initiator role, thus start timer T2 to monitor timeout for Commit
613 */
614
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500615 if (first == 'h' && last == ' ') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500616 // Parse peer's packet data into a Hello packet
617 ZrtpPacketHello hpkt(pkt);
618 ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode);
619 // Something went wrong during processing of the Hello packet
620 if (commit == NULL) {
621 sendErrorPacket(errorCode);
622 return;
623 }
624 nextState(CommitSent);
625
626 // remember packet for easy resend in case timer triggers
627 // Timer trigger received in new state CommitSend
628 sentPacket = static_cast<ZrtpPacketBase *>(commit);
629 if (!parent->sendPacketZRTP(sentPacket)) {
630 sendFailed();
631 return;
632 }
633 if (startTimer(&T2) <= 0) {
634 timerFailed(SevereNoTimer);
635 }
636 }
637#endif
638 }
639 else { // unknown Event type for this state (covers Error and ZrtpClose)
640 if (event->type != ZrtpClose) {
641 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
642 }
643 nextState(Initial);
644 }
645}
646
647/*
648 * WaitCommit state.
649 *
650 * This state is only used if we use choice 1) in AckDetected.
651 *
652 * When entering this transition function
653 * - instance variable sentPacket contains a HelloAck packet
654 *
655 * Possible events in this state are:
656 * - Hello: just resend our HelloAck
657 * - Commit: prepare and send our DHPart1 message to start first
658 * half of DH key agreement. Switch to state WaitDHPart2, don't
659 * start any timer, we a Responder.
660 */
661void ZrtpStateClass::evWaitCommit(void) {
662
663 DEBUGOUT((cout << "Checking for match in WaitCommit.\n"));
664
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500665 char *msg, first, last;
Alexandre Lision51140e12013-12-02 10:54:09 -0500666 uint8_t *pkt;
667 uint32_t errorCode = 0;
668
669 if (event->type == ZrtpPacket) {
670 pkt = event->packet;
671 msg = (char *)pkt + 4;
672
673 first = tolower(*msg);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500674 last = tolower(*(msg+7));
Alexandre Lision51140e12013-12-02 10:54:09 -0500675 /*
676 * Hello:
677 * - resend HelloAck
678 * - stay in WaitCommit
679 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500680 if (first == 'h' && last == ' ') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500681 if (!parent->sendPacketZRTP(sentPacket)) {
682 sendFailed(); // returns to state Initial
683 }
684 return;
685 }
686 /*
687 * Commit:
688 * - prepare DH1Part packet or Confirm1 if multi stream mode
689 * - send it to peer
690 * - switch state to WaitDHPart2 or WaitConfirm2 if multi stream mode
691 * - don't start timer, we are responder
692 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500693 if (first == 'c' && last == ' ') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500694 ZrtpPacketCommit cpkt(pkt);
695
696 if (!multiStream) {
697 ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&cpkt, &errorCode);
698
699 // Something went wrong during processing of the Commit packet
700 if (dhPart1 == NULL) {
701 if (errorCode != IgnorePacket) {
702 sendErrorPacket(errorCode);
703 }
704 return;
705 }
706 sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
707 nextState(WaitDHPart2);
708 }
709 else {
710 ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&cpkt, &errorCode);
711
712 // Something went wrong during processing of the Commit packet
713 if (confirm == NULL) {
714 if (errorCode != IgnorePacket) {
715 sendErrorPacket(errorCode);
716 }
717 return;
718 }
719 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
720 nextState(WaitConfirm2);
721 }
722 if (!parent->sendPacketZRTP(sentPacket)) {
723 sendFailed(); // returns to state Initial
724 }
725 }
726 }
727 else { // unknown Event type for this state (covers Error and ZrtpClose)
728 if (event->type != ZrtpClose) {
729 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
730 }
731 sentPacket = NULL;
732 nextState(Initial);
733 }
734}
735
736/*
737 * CommitSent state.
738 *
739 * This state either handles a DH1Part1 message to start the first
740 * half of DH key agreement or it handles a Commit clash. If handling a
741 * Commit clash it may happen that we change our role from Initiator to
742 * Responder.
743 *
744 * When entering this transition function
745 * - assume Initiator mode, may change if we reveice a Commit here
746 * - sentPacket contains Commit packet
747 * - Commit timer (T2) active
748 *
749 * Possible events in this state are:
750 * - timeout for sent Commit packet: causes a resend check and repeat sending
751 * of Commit packet
752 * - Commit: This is a Commit clash. Break the tie accroding to chapter 5.2
753 * - DHPart1: start first half of DH key agreement. Perpare and send own DHPart2
754 * and switch to state WaitConfirm1.
755 */
756
757void ZrtpStateClass::evCommitSent(void) {
758
759 DEBUGOUT((cout << "Checking for match in CommitSend.\n"));
760
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500761 char *msg, first, middle, last, secondLast;
Alexandre Lision51140e12013-12-02 10:54:09 -0500762 uint8_t *pkt;
763 uint32_t errorCode = 0;
764
765 if (event->type == ZrtpPacket) {
766 pkt = event->packet;
767 msg = (char *)pkt + 4;
768
769 first = tolower(*msg);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500770 middle = tolower(*(msg+4));
Alexandre Lision51140e12013-12-02 10:54:09 -0500771 last = tolower(*(msg+7));
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500772 secondLast = tolower(*(msg+6));
Alexandre Lision51140e12013-12-02 10:54:09 -0500773
774 /*
775 * HelloAck or Hello:
776 * - delayed "HelloAck" or "Hello", maybe due to network latency, just
777 * ignore it
778 * - no switch in state, leave timer as it is
779 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500780 if (first == 'h' && middle == 'o' && (last =='k' || last == ' ')) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500781 return;
782 }
783
784 /*
785 * Commit:
786 * We have a "Commit" clash. Resolve it.
787 *
788 * - switch off resending Commit
789 * - compare my hvi with peer's hvi
790 * - if my hvi is greater
791 * - we are Initiator, stay in state, wait for peer's DHPart1 packet
792 * - else
793 * - we are Responder, stop timer
794 * - prepare and send DH1Packt,
795 * - switch to state WaitDHPart2, implies Responder path
796 */
797 if (first == 'c' && last == ' ') {
798 ZrtpPacketCommit zpCo(pkt);
799
800 if (!parent->verifyH2(&zpCo)) {
801 return;
802 }
803 cancelTimer(); // this cancels the Commit timer T2
804
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500805 if (!zpCo.isLengthOk(multiStream ? ZrtpPacketCommit::MultiStream : ZrtpPacketCommit::DhExchange)) {
806 sendErrorPacket(CriticalSWError);
807 return;
808 }
809
Alexandre Lision51140e12013-12-02 10:54:09 -0500810 // if our hvi is less than peer's hvi: switch to Responder mode and
811 // send DHPart1 or Confirm1 packet. Peer (as Initiator) will retrigger if
812 // necessary
813 //
814 if (parent->compareCommit(&zpCo) < 0) {
815 if (!multiStream) {
816 ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&zpCo, &errorCode);
817
818 // Something went wrong during processing of the Commit packet
819 if (dhPart1 == NULL) {
820 if (errorCode != IgnorePacket) {
821 sendErrorPacket(errorCode);
822 }
823 return;
824 }
825 nextState(WaitDHPart2);
826 sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
827 }
828 else {
829 ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&zpCo, &errorCode);
830
831 // Something went wrong during processing of the Commit packet
832 if (confirm == NULL) {
833 if (errorCode != IgnorePacket) {
834 sendErrorPacket(errorCode);
835 }
836 return;
837 }
838 nextState(WaitConfirm2);
839 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
840 }
841 if (!parent->sendPacketZRTP(sentPacket)) {
842 sendFailed(); // returns to state Initial
843 }
844 }
845 // Stay in state, we are Initiator, wait for DHPart1 of Confirm1 packet from peer.
846 // Resend Commit after timeout until we get a DHPart1 or Confirm1
847 else {
848 if (startTimer(&T2) <= 0) { // restart the Commit timer, gives peer more time to react
849 timerFailed(SevereNoTimer); // returns to state Initial
850 }
851 }
852 return;
853 }
854
855 /*
856 * DHPart1:
857 * - switch off resending Commit
858 * - Prepare and send DHPart2
859 * - switch to WaitConfirm1
860 * - start timer to resend DHPart2 if necessary, we are Initiator
861 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500862 if (first == 'd' && secondLast == '1') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500863 cancelTimer();
864 sentPacket = NULL;
865 ZrtpPacketDHPart dpkt(pkt);
866 ZrtpPacketDHPart* dhPart2 = parent->prepareDHPart2(&dpkt, &errorCode);
867
868 // Something went wrong during processing of the DHPart1 packet
869 if (dhPart2 == NULL) {
870 if (errorCode != IgnorePacket) {
871 sendErrorPacket(errorCode);
872 }
873 else {
874 if (startTimer(&T2) <= 0) {
875 timerFailed(SevereNoTimer); // switches to state Initial
876 }
877 }
878
879 return;
880 }
881 sentPacket = static_cast<ZrtpPacketBase *>(dhPart2);
882 nextState(WaitConfirm1);
883
884 if (!parent->sendPacketZRTP(sentPacket)) {
885 sendFailed(); // returns to state Initial
886 return;
887 }
888 if (startTimer(&T2) <= 0) {
889 timerFailed(SevereNoTimer); // switches to state Initial
890 }
891 return;
892 }
893
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500894 /*
895 * Confirm1 and multi-stream mode
896 * - switch off resending commit
897 * - prepare Confirm2
898 */
Alexandre Lision51140e12013-12-02 10:54:09 -0500899 if (multiStream && (first == 'c' && last == '1')) {
900 cancelTimer();
901 ZrtpPacketConfirm cpkt(pkt);
902
903 ZrtpPacketConfirm* confirm = parent->prepareConfirm2MultiStream(&cpkt, &errorCode);
904
905 // Something went wrong during processing of the Confirm1 packet
906 if (confirm == NULL) {
907 sendErrorPacket(errorCode);
908 return;
909 }
910 nextState(WaitConfAck);
911 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
912
913 if (!parent->sendPacketZRTP(sentPacket)) {
914 sendFailed(); // returns to state Initial
915 return;
916 }
917 if (startTimer(&T2) <= 0) {
918 timerFailed(SevereNoTimer); // returns to state Initial
919 return;
920 }
921 // according to chap 5.6: after sending Confirm2 the Initiator must
922 // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck
923 // state.
924 if (!parent->srtpSecretsReady(ForReceiver)) {
925 parent->sendInfo(Severe, CriticalSWError);
926 sendErrorPacket(CriticalSWError);
927 return;
928 }
929 }
930 }
931 // Timer event triggered, resend the Commit packet
932 else if (event->type == Timer) {
933 if (!parent->sendPacketZRTP(sentPacket)) {
934 sendFailed(); // returns to state Initial
935 return;
936 }
937 if (nextTimer(&T2) <= 0) {
938 timerFailed(SevereTooMuchRetries); // returns to state Initial
939 }
940 }
941 else { // unknown Event type for this state (covers Error and ZrtpClose)
942 if (event->type != ZrtpClose) {
943 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
944 }
945 sentPacket = NULL;
946 nextState(Initial);
947 }
948}
949
950/*
951 * WaitDHPart2 state.
952 *
953 * This state handles the second part of SH key agreement. Only the Resonder
954 * can enter this state.
955 *
956 * When entering this transition function
957 * - sentPacket contains DHPart1 packet, no timer active
958 *
959 * Possible events in this state are:
960 * - Commit: Our peer didn't receive out DHPart1 thus the peer sends Commit again.
961 * Just repeat our DHPart1.
962 * - DHPart2: start second half of DH key agreement. Perpare and send own Confirm1
963 * and switch to state WaitConfirm2.
964 */
965void ZrtpStateClass::evWaitDHPart2(void) {
966
967 DEBUGOUT((cout << "Checking for match in DHPart2.\n"));
968
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500969 char *msg, first, secondLast, last;
Alexandre Lision51140e12013-12-02 10:54:09 -0500970 uint8_t *pkt;
971 uint32_t errorCode = 0;
972
973 if (event->type == ZrtpPacket) {
974 pkt = event->packet;
975 msg = (char *)pkt + 4;
976
977 first = tolower(*msg);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500978 last = tolower(*(msg+7));
979 secondLast = tolower(*(msg+6));
Alexandre Lision51140e12013-12-02 10:54:09 -0500980 /*
981 * Commit:
982 * - resend DHPart1
983 * - stay in state
984 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500985 if (first == 'c' && last == ' ') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500986 if (!parent->sendPacketZRTP(sentPacket)) {
987 return sendFailed(); // returns to state Initial
988 }
989 return;
990 }
991 /*
992 * DHPart2:
993 * - prepare Confirm1 packet
994 * - switch to WaitConfirm2
995 * - No timer, we are responder
996 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500997 if (first == 'd' && secondLast == '2') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500998 ZrtpPacketDHPart dpkt(pkt);
999 ZrtpPacketConfirm* confirm = parent->prepareConfirm1(&dpkt, &errorCode);
1000
1001 if (confirm == NULL) {
1002 if (errorCode != IgnorePacket) {
1003 sendErrorPacket(errorCode);
1004 }
1005 return;
1006 }
1007 nextState(WaitConfirm2);
1008 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
1009 if (!parent->sendPacketZRTP(sentPacket)) {
1010 sendFailed(); // returns to state Initial
1011 }
1012 }
1013 }
1014 else { // unknown Event type for this state (covers Error and ZrtpClose)
1015 if (event->type != ZrtpClose) {
1016 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1017 }
1018 sentPacket = NULL;
1019 nextState(Initial);
1020 }
1021}
1022
1023/*
1024 * WaitConirm1 state.
1025 *
1026 * This state handles a received Confirm1 message and only the Initiator
1027 * can enter this state.
1028 *
1029 * When entering this transition function in DH mode:
1030 * - Initiator mode
1031 * - sentPacket contains DHPart2 packet, DHPart2 timer active
1032 *
1033 * When entering this transition function in Multi stream mode via AckSent:
1034 * - Initiator mode
1035 * - sentPacket contains my Commit packet, Commit timer active
1036 *
1037* Possible events in this state are:
1038 * - timeout for sent DHPart2 packet: causes a resend check and repeat sending
1039 * of DHPart2 packet.
1040 * - Confirm1: Check Confirm1 message. If it is ok then prepare and send own
1041 * Confirm2 packet and switch to state WaitConfAck.
1042 */
1043void ZrtpStateClass::evWaitConfirm1(void) {
1044
1045 DEBUGOUT((cout << "Checking for match in WaitConfirm1.\n"));
1046
1047 char *msg, first, last;
1048 uint8_t *pkt;
1049 uint32_t errorCode = 0;
1050
1051 if (event->type == ZrtpPacket) {
1052 pkt = event->packet;
1053 msg = (char *)pkt + 4;
1054
1055 first = tolower(*msg);
1056 last = tolower(*(msg+7));
1057
1058 /*
1059 * Confirm1:
1060 * - Switch off resending DHPart2
1061 * - prepare a Confirm2 packet
1062 * - switch to state WaitConfAck
1063 * - set timer to monitor Confirm2 packet, we are initiator
1064 */
1065 if (first == 'c' && last == '1') {
1066 cancelTimer();
1067 ZrtpPacketConfirm cpkt(pkt);
1068
1069 ZrtpPacketConfirm* confirm = parent->prepareConfirm2(&cpkt, &errorCode);
1070
1071 // Something went wrong during processing of the Confirm1 packet
1072 if (confirm == NULL) {
1073 sendErrorPacket(errorCode);
1074 return;
1075 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001076 // according to chap 5.8: after sending Confirm2 the Initiator must
1077 // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck
1078 // state.
1079 if (!parent->srtpSecretsReady(ForReceiver)) {
1080 parent->sendInfo(Severe, CriticalSWError);
1081 sendErrorPacket(CriticalSWError);
1082 return;
1083 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001084 nextState(WaitConfAck);
1085 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
1086
1087 if (!parent->sendPacketZRTP(sentPacket)) {
1088 sendFailed(); // returns to state Initial
1089 return;
1090 }
1091 if (startTimer(&T2) <= 0) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001092 timerFailed(SevereNoTimer); // returns to state Initial
Alexandre Lision51140e12013-12-02 10:54:09 -05001093 }
1094 }
1095 }
1096 else if (event->type == Timer) {
1097 if (!parent->sendPacketZRTP(sentPacket)) {
1098 sendFailed(); // returns to state Initial
1099 return;
1100 }
1101 if (nextTimer(&T2) <= 0) {
1102 timerFailed(SevereTooMuchRetries); // returns to state Initial
1103 }
1104 }
1105 else { // unknown Event type for this state (covers Error and ZrtpClose)
1106 if (event->type != ZrtpClose) {
1107 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1108 }
1109 sentPacket = NULL;
1110 nextState(Initial);
1111 }
1112}
1113
1114/*
1115 * WaitConfirm2 state.
1116 *
1117 * Handles the Confirm2 message that closes the key agreement handshake. Only
1118 * the Responder can enter this state. If the Confirm2 message is ok send a
1119 * Conf2Ack to our peer. Switch to secure mode after sending Conf2Ack, our
1120 * peer switches to secure mode after receiving Conf2Ack.
1121 *
1122 * TODO - revise documentation comments
1123 *
1124 * When entering this transition function
1125 * - Responder mode
1126 * - sentPacket contains Confirm1 packet, no timer active
1127 *
1128 * Possible events in this state are:
1129 * - DHPart2: Our peer didn't receive our Confirm1 thus sends DHPart2 again.
1130 * Just repeat our Confirm1.
1131 * - Confirm2: close DH key agreement. Perpare and send own Conf2Ack
1132 * and switch to state SecureState.
1133 */
1134void ZrtpStateClass::evWaitConfirm2(void) {
1135
1136 DEBUGOUT((cout << "Checking for match in WaitConfirm2.\n"));
1137
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001138 char *msg, first, secondLast, last;
Alexandre Lision51140e12013-12-02 10:54:09 -05001139 uint8_t *pkt;
1140 uint32_t errorCode = 0;
1141
1142 if (event->type == ZrtpPacket) {
1143 pkt = event->packet;
1144 msg = (char *)pkt + 4;
1145
1146 first = tolower(*msg);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001147 secondLast = tolower(*(msg+6));
Alexandre Lision51140e12013-12-02 10:54:09 -05001148 last = tolower(*(msg+7));
1149
1150 /*
1151 * DHPart2 or Commit in multi stream mode:
1152 * - resend Confirm1 packet
1153 * - stay in state
1154 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001155 if ((first == 'd' && secondLast == '2') || (multiStream && (first == 'c' && last == ' '))) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001156 if (!parent->sendPacketZRTP(sentPacket)) {
1157 sendFailed(); // returns to state Initial
1158 }
1159 return;
1160 }
1161 /*
1162 * Confirm2:
1163 * - prepare ConfAck
1164 * - switch on security (SRTP)
1165 * - switch to SecureState
1166 */
1167 if (first == 'c' && last == '2') {
1168 ZrtpPacketConfirm cpkt(pkt);
1169 ZrtpPacketConf2Ack* confack = parent->prepareConf2Ack(&cpkt, &errorCode);
1170
1171 // Something went wrong during processing of the confirm2 packet
1172 if (confack == NULL) {
1173 sendErrorPacket(errorCode);
1174 return;
1175 }
1176 sentPacket = static_cast<ZrtpPacketBase *>(confack);
1177
1178 if (!parent->sendPacketZRTP(sentPacket)) {
1179 sendFailed(); // returns to state Initial
1180 return;
1181 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001182 if (!parent->srtpSecretsReady(ForReceiver) || !parent->srtpSecretsReady(ForSender)) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001183 parent->sendInfo(Severe, CriticalSWError);
1184 sendErrorPacket(CriticalSWError);
1185 return;
1186 }
1187 nextState(SecureState);
1188 parent->sendInfo(Info, InfoSecureStateOn);
1189 }
1190 }
1191 else { // unknown Event type for this state (covers Error and ZrtpClose)
1192 if (event->type != ZrtpClose) {
1193 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1194 }
1195 sentPacket = NULL;
1196 nextState(Initial);
1197 }
1198}
1199
1200/*
1201 * WaitConf2Ack state.
1202 *
1203 * This state handles the Conf2Ack message that acknowledges the successfull
1204 * processing of Confirm2. Only the Initiator can enter this state. Switch on
1205 * secure mode and switch to state SecureState.
1206 *
1207 * When entering this transition function
1208 * - Initiator mode
1209 * - sentPacket contains Confirm2 packet, Confirm2 timer active
1210 * - receiver security switched on
1211 *
1212 * Possible events in this state are:
1213 * - timeout for sent Confirm2 packet: causes a resend check and repeat sending
1214 * of Confirm2 packet
1215 * - Conf2Ack: Key agreement was successfull, switch to secure mode.
1216 */
1217void ZrtpStateClass::evWaitConfAck(void) {
1218
1219 DEBUGOUT((cout << "Checking for match in WaitConfAck.\n"));
1220
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001221 char *msg, first, last;
Alexandre Lision51140e12013-12-02 10:54:09 -05001222 uint8_t *pkt;
1223
1224 if (event->type == ZrtpPacket) {
1225 pkt = event->packet;
1226 msg = (char *)pkt + 4;
1227
1228 first = tolower(*msg);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001229 last = tolower(*(msg+7));
Alexandre Lision51140e12013-12-02 10:54:09 -05001230 /*
1231 * ConfAck:
1232 * - Switch off resending Confirm2
1233 * - switch to SecureState
1234 */
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001235 if (first == 'c' && last == 'k') {
Alexandre Lision51140e12013-12-02 10:54:09 -05001236 cancelTimer();
1237 sentPacket = NULL;
1238 // Receiver was already enabled after sending Confirm2 packet
1239 // see previous states.
1240 if (!parent->srtpSecretsReady(ForSender)) {
1241 parent->sendInfo(Severe, CriticalSWError);
1242 sendErrorPacket(CriticalSWError);
1243 return;
1244 }
1245 nextState(SecureState);
1246 // TODO: call parent to clear signature data at initiator
1247 parent->sendInfo(Info, InfoSecureStateOn);
1248 }
1249 }
1250 else if (event->type == Timer) {
1251 if (!parent->sendPacketZRTP(sentPacket)) {
1252 sendFailed(); // returns to state Initial
1253 parent->srtpSecretsOff(ForReceiver);
1254 return;
1255 }
1256 if (nextTimer(&T2) <= 0) {
1257 timerFailed(SevereTooMuchRetries); // returns to state Initial
1258 parent->srtpSecretsOff(ForReceiver);
1259 }
1260 }
1261 else { // unknown Event type for this state (covers Error and ZrtpClose)
1262 if (event->type != ZrtpClose) {
1263 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1264 }
1265 sentPacket = NULL;
1266 nextState(Initial);
1267 parent->srtpSecretsOff(ForReceiver);
1268 }
1269}
1270
1271/*
1272 * When entering this transition function
1273 * - sentPacket contains GoClear packet, GoClear timer active
1274 */
1275
1276void ZrtpStateClass::evWaitClearAck(void) {
1277 DEBUGOUT((cout << "Checking for match in ClearAck.\n"));
1278
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001279// char *msg, first, last, middle;
1280// uint8_t *pkt;
1281//
1282// if (event->type == ZrtpPacket) {
1283// pkt = event->packet;
1284// msg = (char *)pkt + 4;
1285//
1286// first = tolower(*msg);
1287// middle = tolower(*(msg+4));
1288// last = tolower(*(msg+7));
1289//
1290// /*
1291// * ClearAck:
1292// * - stop resending GoClear,
1293// * - switch to state AckDetected, wait for peer's Hello
1294// */
1295// if (first == 'c' && middle == 'r' && last =='k') {
1296// cancelTimer();
1297// sentPacket = NULL;
1298// nextState(Initial);
1299// }
1300// }
1301// // Timer event triggered - this is Timer T2 to resend GoClear w/o HMAC
1302// else if (event->type == Timer) {
1303// if (!parent->sendPacketZRTP(sentPacket)) {
1304// sendFailed(); // returns to state Initial
1305// return;
1306// }
1307// if (nextTimer(&T2) <= 0) {
1308// timerFailed(SevereTooMuchRetries); // returns to state Initial
1309// }
1310// }
1311// else { // unknown Event type for this state (covers Error and ZrtpClose)
1312// if (event->type != ZrtpClose) {
1313// parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1314// }
1315// sentPacket = NULL;
1316// nextState(Initial);
1317// }
Alexandre Lision51140e12013-12-02 10:54:09 -05001318}
1319
1320
1321/*
1322 * WaitErrorAck state.
1323 *
1324 * This state belongs to the "error handling state overlay" and handle
1325 * ErrorAck message. Most of the ZRTP states can send Error message for
1326 * example if they detect wrong packets. After sending an Error message
1327 * the protocol engine switches to WaitErrorAck state. Receiving an
1328 * ErrorAck message completes the ZRTP error handling.
1329 *
1330 * When entering this transition function
1331 * - sentPacket contains Error packet, Error timer active
1332 *
1333 * Possible events in this state are:
1334 * - timeout for sent Error packet: causes a resend check and repeat sending
1335 * of Error packet
1336 * - ErrorAck: Stop timer and switch to state Initial.
1337 */
1338
1339void ZrtpStateClass::evWaitErrorAck(void) {
1340 DEBUGOUT((cout << "Checking for match in ErrorAck.\n"));
1341
1342 char *msg, first, last;
1343 uint8_t *pkt;
1344
1345 if (event->type == ZrtpPacket) {
1346 pkt = event->packet;
1347 msg = (char *)pkt + 4;
1348
1349 first = tolower(*msg);
1350 last = tolower(*(msg+7));
1351
1352 /*
1353 * Errorck:
1354 * - stop resending Error,
1355 * - switch to state Initial
1356 */
1357 if (first == 'e' && last =='k') {
1358 cancelTimer();
1359 sentPacket = NULL;
1360 nextState(Initial);
1361 }
1362 }
1363 // Timer event triggered - this is Timer T2 to resend Error.
1364 else if (event->type == Timer) {
1365 if (!parent->sendPacketZRTP(sentPacket)) {
1366 sendFailed(); // returns to state Initial
1367 return;
1368 }
1369 if (nextTimer(&T2) <= 0) {
1370 timerFailed(SevereTooMuchRetries); // returns to state Initial
1371 }
1372 }
1373 else { // unknown Event type for this state (covers Error and ZrtpClose)
1374 if (event->type != ZrtpClose) {
1375 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1376 }
1377 sentPacket = NULL;
1378 nextState(Initial);
1379 }
1380}
1381
1382void ZrtpStateClass::evSecureState(void) {
1383
1384 DEBUGOUT((cout << "Checking for match in SecureState.\n"));
1385
1386 char *msg, first, last;
1387 uint8_t *pkt;
1388
1389 /*
1390 * Handle a possible substate. If substate handling was ok just return.
1391 */
1392 if (secSubstate == WaitSasRelayAck) {
1393 if (subEvWaitRelayAck())
1394 return;
1395 }
1396
1397 if (event->type == ZrtpPacket) {
1398 pkt = event->packet;
1399 msg = (char *)pkt + 4;
1400
1401 first = tolower(*msg);
1402 last = tolower(*(msg+7));
1403
1404 /*
1405 * Confirm2:
1406 * - resend Conf2Ack packet
1407 * - stay in state
1408 */
1409 if (first == 'c' && last == '2') {
1410 if (sentPacket != NULL && !parent->sendPacketZRTP(sentPacket)) {
1411 sentPacket = NULL;
1412 nextState(Initial);
1413 parent->srtpSecretsOff(ForSender);
1414 parent->srtpSecretsOff(ForReceiver);
1415 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
1416 }
1417 return;
1418 }
1419 /*
1420 * GoClear received, handle it. TODO fix go clear handling
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001421 *
Alexandre Lision51140e12013-12-02 10:54:09 -05001422 if (first == 'g' && last == 'r') {
1423 ZrtpPacketGoClear gpkt(pkt);
1424 ZrtpPacketClearAck* clearAck = parent->prepareClearAck(&gpkt);
1425
1426 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(clearAck))) {
1427 return;
1428 }
1429 // TODO Timeout to resend clear ack until user user confirmation
1430 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001431 */
Alexandre Lision51140e12013-12-02 10:54:09 -05001432 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001433 else if (event->type == Timer) {
1434 // Ignore stray timeout in this state
1435 ;
1436 }
1437 // unknown Event type for this state (covers Error and ZrtpClose)
1438 else {
1439 // If in secure state ingnore error events to avoid Error packet injection
1440 // attack - found by Dmitry Monakhov (dmonakhov@openvz.org)
1441 if (event->type == ErrorPkt)
1442 return;
Alexandre Lision51140e12013-12-02 10:54:09 -05001443 sentPacket = NULL;
1444 parent->srtpSecretsOff(ForSender);
1445 parent->srtpSecretsOff(ForReceiver);
1446 nextState(Initial);
1447 if (event->type != ZrtpClose) {
1448 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1449 }
1450 parent->sendInfo(Info, InfoSecureStateOff);
1451 }
1452}
1453
1454bool ZrtpStateClass::subEvWaitRelayAck() {
1455 char *msg, first, last;
1456 uint8_t* pkt;
1457
1458 /*
1459 * First check the general event type, then discrimnate the real event.
1460 */
1461 if (event->type == ZrtpPacket) {
1462 pkt = event->packet;
1463 msg = (char *)pkt + 4;
1464
1465 first = tolower(*msg);
1466 last = tolower(*(msg+7));
1467
1468 /*
1469 * SAS relayAck:
1470 * - stop resending SASRelay,
1471 * - switch to secure substate Normal
1472 */
1473 if (first == 'r' && last =='k') {
1474 cancelTimer();
1475 secSubstate = Normal;
1476 sentPacket = NULL;
1477 }
1478 return true;
1479 }
1480 // Timer event triggered - this is Timer T2 to resend Error.
1481 else if (event->type == Timer) {
1482 if (!parent->sendPacketZRTP(sentPacket)) {
1483 sendFailed(); // returns to state Initial
1484 return false;
1485 }
1486 if (nextTimer(&T2) <= 0) {
1487 // returns to state initial
1488 // timerFailed(ZrtpCodes.SevereCodes.SevereTooMuchRetries);
1489 return false;
1490 }
1491 return true;
1492 }
1493 return false;
1494}
1495
1496int32_t ZrtpStateClass::startTimer(zrtpTimer_t *t) {
1497
1498 t->time = t->start;
1499 t->counter = 0;
1500 return parent->activateTimer(t->time);
1501}
1502
1503int32_t ZrtpStateClass::nextTimer(zrtpTimer_t *t) {
1504
1505 t->time += t->time;
1506 t->time = (t->time > t->capping)? t->capping : t->time;
1507 t->counter++;
1508 if (t->counter > t->maxResend) {
1509 return -1;
1510 }
1511 return parent->activateTimer(t->time);
1512}
1513
1514void ZrtpStateClass::sendErrorPacket(uint32_t errorCode) {
1515 cancelTimer();
1516
1517 ZrtpPacketError* err = parent->prepareError(errorCode);
1518 parent->zrtpNegotiationFailed(ZrtpError, errorCode);
1519
1520 sentPacket = static_cast<ZrtpPacketBase *>(err);
1521 nextState(WaitErrorAck);
1522 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(err)) || (startTimer(&T2) <= 0)) {
1523 sendFailed();
1524 }
1525}
1526
1527void ZrtpStateClass::sendSASRelay(ZrtpPacketSASrelay* relay) {
1528 cancelTimer();
1529 sentPacket = static_cast<ZrtpPacketBase *>(relay);
1530 secSubstate = WaitSasRelayAck;
1531 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(relay)) || (startTimer(&T2) <= 0)) {
1532 sendFailed();
1533 }
1534}
1535
1536void ZrtpStateClass::sendFailed() {
1537 sentPacket = NULL;
1538 nextState(Initial);
1539 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
1540}
1541
1542void ZrtpStateClass::timerFailed(int32_t subCode) {
1543 sentPacket = NULL;
1544 nextState(Initial);
1545 parent->zrtpNegotiationFailed(Severe, subCode);
1546}
1547
1548void ZrtpStateClass::setMultiStream(bool multi) {
1549 multiStream = multi;
1550}
1551
1552bool ZrtpStateClass::isMultiStream() {
1553 return multiStream;
1554}
1555
1556/** EMACS **
1557 * Local variables:
1558 * mode: c++
1559 * c-default-style: ellemtel
1560 * c-basic-offset: 4
1561 * End:
1562 */