blob: f77f9f925e5c209ebc509dd8b482b352a1a65a53 [file] [log] [blame]
Alexandre Lision51140e12013-12-02 10:54:09 -05001/*
Alexandre Lisione24852d2014-02-04 13:13:02 -05002 Copyright (C) 2006-2008 Werner Dittmann
Alexandre Lision51140e12013-12-02 10:54:09 -05003
4 This program is free software: you can redistribute it and/or modify
Alexandre Lisione24852d2014-02-04 13:13:02 -05005 it under the terms of the GNU 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 Lisione24852d2014-02-04 13:13:02 -050049ZrtpStateClass::ZrtpStateClass(ZRtp *p) {
50 parent = p;
51 secSubstate = Normal;
Alexandre Lision51140e12013-12-02 10:54:09 -050052 engine = new ZrtpStates(states, numberOfStates, Initial);
53
Alexandre Lisione24852d2014-02-04 13:13:02 -050054 commitPkt = NULL;
55 multiStream = false;
56
Alexandre Lision51140e12013-12-02 10:54:09 -050057 // Set up timers according to ZRTP spec
58 T1.start = 50;
59 T1.maxResend = 20;
60 T1.capping = 200;
61
62 T2.start = 150;
63 T2.maxResend = 10;
64 T2.capping = 600;
65}
66
67ZrtpStateClass::~ZrtpStateClass(void) {
68
69 // If not in Initial state: close the protocol engine
70 // before destroying it. This will free pending packets
71 // if necessary.
72 if (!inState(Initial)) {
73 Event_t ev;
74
75 cancelTimer();
76 ev.type = ZrtpClose;
77 event = &ev;
78 engine->processEvent(*this);
79 }
80 delete engine;
81}
82
83void ZrtpStateClass::processEvent(Event_t *ev) {
84
Alexandre Lisione24852d2014-02-04 13:13:02 -050085 event = ev;
Alexandre Lision51140e12013-12-02 10:54:09 -050086 char *msg, first, middle, last;
87 uint8_t *pkt;
88
89 parent->synchEnter();
90
91 if (event->type == ZrtpPacket) {
Alexandre Lisione24852d2014-02-04 13:13:02 -050092 pkt = event->packet;
93 msg = (char *)pkt + 4;
94 first = tolower(*msg);
95 middle = tolower(*(msg+4));
Alexandre Lision51140e12013-12-02 10:54:09 -050096 last = tolower(*(msg+7));
97
98 // Check if this is an Error packet.
Alexandre Lisione24852d2014-02-04 13:13:02 -050099 if (first == 'e' && middle =='r' && last == ' ') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500100 /*
101 * Process a received Error packet.
102 *
103 * In any case stop timer to prevent resending packets.
104 * Use callback method to prepare and get an ErrorAck packet.
105 * Modify event type to "ErrorPkt" and hand it over to current
106 * state for further processing.
107 */
108 cancelTimer();
109 ZrtpPacketError epkt(pkt);
110 ZrtpPacketErrorAck* eapkt = parent->prepareErrorAck(&epkt);
111 parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(eapkt));
112 event->type = ErrorPkt;
113 }
114 else if (first == 'p' && middle == ' ' && last == ' ') {
115 ZrtpPacketPing ppkt(pkt);
116 ZrtpPacketPingAck* ppktAck = parent->preparePingAck(&ppkt);
Alexandre Lisione24852d2014-02-04 13:13:02 -0500117 parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(ppktAck));
Alexandre Lision51140e12013-12-02 10:54:09 -0500118 parent->synchLeave();
119 return;
120 }
121 else if (first == 's' && last == 'y') {
122 uint32_t errorCode = 0;
123 ZrtpPacketSASrelay* srly = new ZrtpPacketSASrelay(pkt);
124 ZrtpPacketRelayAck* rapkt = parent->prepareRelayAck(srly, &errorCode);
125 parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(rapkt));
126 parent->synchLeave();
127 return;
128 }
Alexandre Lisione24852d2014-02-04 13:13:02 -0500129
Alexandre Lision51140e12013-12-02 10:54:09 -0500130 }
131 /*
132 * Shut down protocol state engine: cancel outstanding timer, further
133 * processing in current state.
134 */
135 else if (event->type == ZrtpClose) {
136 cancelTimer();
137 }
138 engine->processEvent(*this);
139 parent->synchLeave();
140}
141
142
143void ZrtpStateClass::evInitial(void) {
144 DEBUGOUT((cout << "Checking for match in Initial.\n"));
145
146 if (event->type == ZrtpInitial) {
Alexandre Lisione24852d2014-02-04 13:13:02 -0500147 ZrtpPacketHello* hello = parent->prepareHello();
Alexandre Lision51140e12013-12-02 10:54:09 -0500148
Alexandre Lisione24852d2014-02-04 13:13:02 -0500149 // remember packet for easy resend in case timer triggers
150 sentPacket = static_cast<ZrtpPacketBase *>(hello);
Alexandre Lision51140e12013-12-02 10:54:09 -0500151
152 if (!parent->sendPacketZRTP(sentPacket)) {
153 sendFailed(); // returns to state Initial
154 return;
155 }
156 if (startTimer(&T1) <= 0) {
157 timerFailed(SevereNoTimer); // returns to state Initial
158 return;
159 }
Alexandre Lisione24852d2014-02-04 13:13:02 -0500160 nextState(Detect);
Alexandre Lision51140e12013-12-02 10:54:09 -0500161 }
162}
163
164/*
165 * Detect state.
166 *
167 * When in this state the protocol engine sent an initial Hello packet
168 * to the peer.
169 *
170 * When entering this state transition function then:
171 * - Assume Initiator mode, mode may change later on peer reaction
172 * - Instance variable sentPacket contains the sent Hello packet
173 * - Hello timer T1 may be active. This is the case if the other peer
174 * has prepared its RTP session and answers our Hello packets nearly
175 * immediately, i.e. before the Hello timeout counter expires. If the
176 * other peer does not send a Hello during this time the state engine
177 * reports "other peer does not support ZRTP" but stays
178 * in state Detect with no active timer (passiv mode). Staying in state
179 * Detect allows another peer to start its detect phase any time later.
180 *
181 * This restart capability is the reason why we use "startTimer(&T1)" in
182 * case we received a Hello packet from another peer. This effectively
183 * restarts the Hello timeout counter.
184 *
185 * In this state we also handle ZrtpInitialize event. This forces a
186 * restart of ZRTP discovery if an application calls ZrtpQueue#startZrtp
187 * again. This may happen after a previous discovery phase were not
188 * successful.
189 *
190 * Usually applications use some sort of signaling protocol, for example
191 * SIP, to negotiate the RTP parameters. Thus the RTP sessions setup is
192 * fairly sychronized and thus also the ZRTP detection phase. Applications
193 * that use some other ways to setup the RTP sessions this restart capability
194 * comes in handy because no RTP setup sychronization is necessary.
195 *
196 * Possible events in this state are:
197 * - timeout for sent Hello packet: causes a resend check and
198 * repeat sending of Hello packet
199 * - received a HelloAck: stop active timer, prepare and send Hello packet,
200 * switch to state AckDeteced.
201 * - received a Hello: stop active timer, send HelloAck, prepare Commit
202 * packet, switch to state AckSent.
203 *
204 */
205void ZrtpStateClass::evDetect(void) {
206
207 DEBUGOUT((cout << "Checking for match in Detect.\n"));
208
209 char *msg, first, last;
210 uint8_t *pkt;
211 uint32_t errorCode = 0;
212
213 /*
214 * First check the general event type, then discrimnate
215 * the real event.
216 */
217 if (event->type == ZrtpPacket) {
218 pkt = event->packet;
219 msg = (char *)pkt + 4;
220
221 first = tolower(*msg);
222 last = tolower(*(msg+7));
223 /*
224 * HelloAck:
225 * - our peer acknowledged our Hello packet, we have not seen the peer's Hello yet
226 * - cancel timer T1 to stop resending Hello
227 * - switch to state AckDetected, wait for peer's Hello (F3)
228 */
229 if (first == 'h' && last =='k') {
230 cancelTimer();
231 sentPacket = NULL;
232 nextState(AckDetected);
233 return;
234 }
235 /*
236 * Hello:
Alexandre Lisione24852d2014-02-04 13:13:02 -0500237 * - send HelloAck packet to acknowledge the received Hello packet
Alexandre Lision51140e12013-12-02 10:54:09 -0500238 * - use received Hello packet to prepare own Commit packet. We need to
239 * do it at this point because we need the hash value computed from
240 * peer's Hello packet. Follwing states my use the prepared Commit.
241 * - switch to new state AckSent which sends own Hello packet until
242 * peer acknowledges this
243 * - Don't clear sentPacket, points to Hello
244 */
245 if (first == 'h' && last ==' ') {
246 cancelTimer();
247 ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck();
248
249 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
250 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
251 return;
252 }
253 // Use peer's Hello packet to create my commit packet, store it
254 // for possible later usage in state AckSent
Alexandre Lisione24852d2014-02-04 13:13:02 -0500255 ZrtpPacketHello hpkt(pkt);
Alexandre Lision51140e12013-12-02 10:54:09 -0500256 commitPkt = parent->prepareCommit(&hpkt, &errorCode);
257
258 nextState(AckSent);
259 if (commitPkt == NULL) {
260 sendErrorPacket(errorCode); // switches to Error state
261 return;
262 }
263 if (startTimer(&T1) <= 0) { // restart own Hello timer/counter
264 timerFailed(SevereNoTimer); // returns to state Initial
265 }
266 T1.maxResend = 60; // more retries to extend time, see chap. 6
267 }
268 return; // unknown packet for this state - Just ignore it
269 }
270 // Timer event triggered - this is Timer T1 to resend Hello
271 else if (event->type == Timer) {
272 if (!parent->sendPacketZRTP(sentPacket)) {
273 sendFailed(); // returns to state Initial
274 return;
275 }
276 if (nextTimer(&T1) <= 0) {
277 commitPkt = NULL;
278 parent->zrtpNotSuppOther();
279 nextState(Detect);
280 }
281 }
Alexandre Lisione24852d2014-02-04 13:13:02 -0500282 // If application call zrtpStart() to restart discovery
Alexandre Lision51140e12013-12-02 10:54:09 -0500283 else if (event->type == ZrtpInitial) {
284 cancelTimer();
285 if (!parent->sendPacketZRTP(sentPacket)) {
286 sendFailed(); // returns to state Initial
287 return;
288 }
289 if (startTimer(&T1) <= 0) {
290 timerFailed(SevereNoTimer); // returns to state Initial
291 }
292 }
293 else { // unknown Event type for this state (covers Error and ZrtpClose)
294 if (event->type != ZrtpClose) {
295 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
296 }
297 sentPacket = NULL;
298 nextState(Initial);
299 }
300}
301
302/*
303 * AckSent state.
304 *
305 * The protocol engine got a Hello packet from peer and answered with a
306 * HelloAck response. According to the protocol we must also send a
Alexandre Lisione24852d2014-02-04 13:13:02 -0500307 * Hello after HelloAck (refer to figure 1 in ZRTP RFC xxxx, message
Alexandre Lision51140e12013-12-02 10:54:09 -0500308 * HelloACK (F2) must be followed by Hello (F3)). We use the timeout in
309 * this state to send the required Hello (F3).
310 *
311 * Our peer must acknowledge the Hello with HelloAck. In earlier versions
312 * also a Commit was a valid packet thus the code covers this.
313 * Figure 1 in the RFC shows the HelloAck, chapter 7 states that a Commit
314 * may be send to acknowledge Hello. There is one constraint when using a Commit to
315 * acknowledge Hello: refer to chapter 4.1 that requires that both parties
316 * have completed the Hello/HelloAck discovery handshake. This implies that
317 * only message F4 may be replaced by a Commit. This constraint guarantees
318 * that both peers have seen at least one Hello.
319 *
320 * When entering this transition function:
321 * - The instance variabe sentPacket contains own Hello packet
322 * - The instance variabe commitPkt points to prepared Commit packet
323 * - Timer T1 is active
324 *
325 * Possible events in this state are:
326 * - timeout for sent Hello packet: causes a resend check and repeat sending
327 * of Hello packet
328 * - HelloAck: The peer answered with HelloAck to own HelloAck/Hello. Send
329 * prepared Commit packet and try Initiator mode.
330 * - Commit: The peer answered with Commit to HelloAck/Hello, thus switch to
331 * responder mode.
332 * - Hello: If the protcol engine receives another Hello it repeats the
333 * HelloAck/Hello response until Timer T1 exceeds its maximum. This may
334 * happen if the other peer sends Hello only (maybe due to network problems)
335 */
336void ZrtpStateClass::evAckSent(void) {
337
338 DEBUGOUT((cout << "Checking for match in AckSent.\n"));
339
340 char *msg, first, last;
341 uint8_t *pkt;
342 uint32_t errorCode = 0;
343
344 /*
345 * First check the general event type, then discrimnate
346 * the real event.
347 */
348 if (event->type == ZrtpPacket) {
349 pkt = event->packet;
Alexandre Lisione24852d2014-02-04 13:13:02 -0500350 msg = (char *)pkt + 4;
Alexandre Lision51140e12013-12-02 10:54:09 -0500351
Alexandre Lisione24852d2014-02-04 13:13:02 -0500352 first = tolower(*msg);
353 last = tolower(*(msg+7));
Alexandre Lision51140e12013-12-02 10:54:09 -0500354
Alexandre Lisione24852d2014-02-04 13:13:02 -0500355 /*
Alexandre Lision51140e12013-12-02 10:54:09 -0500356 * HelloAck:
357 * The peer answers with HelloAck to own HelloAck/Hello. Send Commit
358 * and try Initiator mode. The requirement defined in chapter 4.1 to
359 * have a complete Hello/HelloAck is fulfilled.
Alexandre Lisione24852d2014-02-04 13:13:02 -0500360 * - stop Hello timer T1
361 * - send own Commit message
362 * - switch state to CommitSent, start Commit timer, assume Initiator
363 */
364 if (first == 'h' && last =='k') {
365 cancelTimer();
Alexandre Lision51140e12013-12-02 10:54:09 -0500366
367 // remember packet for easy resend in case timer triggers
368 // Timer trigger received in new state CommitSend
369 sentPacket = static_cast<ZrtpPacketBase *>(commitPkt);
370 commitPkt = NULL; // now stored in sentPacket
Alexandre Lisione24852d2014-02-04 13:13:02 -0500371 nextState(CommitSent);
Alexandre Lision51140e12013-12-02 10:54:09 -0500372 if (!parent->sendPacketZRTP(sentPacket)) {
373 sendFailed(); // returns to state Initial
374 return;
375 }
376 if (startTimer(&T2) <= 0) {
377 timerFailed(SevereNoTimer); // returns to state Initial
Alexandre Lisione24852d2014-02-04 13:13:02 -0500378 }
379 return;
Alexandre Lision51140e12013-12-02 10:54:09 -0500380 }
381 /*
382 * Hello:
383 * - peer didn't receive our HelloAck
384 * - repeat HelloAck/Hello response:
385 * -- get HelloAck packet, send it
386 * -- The timeout trigger of T1 sends our Hello packet
387 * -- stay in state AckSent
388 *
389 * Similar to Detect state: just acknowledge the Hello, the next
390 * timeout sends the following Hello.
391 */
392
393 if (first == 'h' && last ==' ') {
394 ZrtpPacketHelloAck* helloAck = parent->prepareHelloAck();
395
396 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
397 nextState(Detect);
398 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
399 }
400 return;
401 }
402 /*
403 * Commit:
404 * The peer answers with Commit to HelloAck/Hello, thus switch to
405 * responder mode.
406 * - stop timer T1
407 * - prepare and send our DHPart1
408 * - switch to state WaitDHPart2 and wait for peer's DHPart2
409 * - don't start timer, we are responder
410 */
Alexandre Lisione24852d2014-02-04 13:13:02 -0500411 if (first == 'c') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500412 cancelTimer();
413 ZrtpPacketCommit cpkt(pkt);
414
415 if (!multiStream) {
416 ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&cpkt, &errorCode);
417
418 // Something went wrong during processing of the Commit packet
419 if (dhPart1 == NULL) {
420 if (errorCode != IgnorePacket) {
421 sendErrorPacket(errorCode);
422 }
423 return;
424 }
425 commitPkt = NULL;
426 sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
427 nextState(WaitDHPart2);
428 }
429 else {
430 ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&cpkt, &errorCode);
431
432 // Something went wrong during processing of the Commit packet
433 if (confirm == NULL) {
434 if (errorCode != IgnorePacket) {
435 sendErrorPacket(errorCode);
436 }
437 return;
438 }
439 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
440 nextState(WaitConfirm2);
441 }
442 if (!parent->sendPacketZRTP(sentPacket)) {
443 sendFailed(); // returns to state Initial
444 }
445 }
446 }
447 /*
448 * Timer:
Alexandre Lisione24852d2014-02-04 13:13:02 -0500449 * - resend Hello packet, stay in state, restart timer until repeat
Alexandre Lision51140e12013-12-02 10:54:09 -0500450 * counter triggers
451 * - if repeat counter triggers switch to state Detect, con't clear
452 * sentPacket, Detect requires it to point to own Hello message
453 */
454 else if (event->type == Timer) {
455 if (!parent->sendPacketZRTP(sentPacket)) {
456 return sendFailed(); // returns to state Initial
457 }
458 if (nextTimer(&T1) <= 0) {
459 parent->zrtpNotSuppOther();
460 commitPkt = NULL;
461 // Stay in state Detect to be prepared get an hello from
462 // other peer any time later
463 nextState(Detect);
464 }
465 }
466 else { // unknown Event type for this state (covers Error and ZrtpClose)
467 if (event->type != ZrtpClose) {
468 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
469 }
470 commitPkt = NULL;
471 sentPacket = NULL;
472 nextState(Initial);
473 }
474}
475/*
476 * AckDetected state.
477 *
478 * The protocol engine received a HelloAck in state Detect, thus the peer
Alexandre Lisione24852d2014-02-04 13:13:02 -0500479 * acknowledged our the Hello. According to ZRT RFC xxxx our peer must send
Alexandre Lision51140e12013-12-02 10:54:09 -0500480 * its Hello until our protocol engine sees it (refer also to comment for
481 * state AckSent). This protocol sequence gurantees that both peers got at
482 * least one Hello.
483 *
484 * When entering this transition function
485 * - instance variable sentPacket is NULL, Hello timer stopped
486 *
487 * Possible events in this state are:
488 * Hello: we have to choices
489 * 1) we can acknowledge the peer's Hello with a HelloAck
490 * 2) we can acknowledge the peer's Hello with a Commit
491 * Both choices are implemented and may be enabled by setting a compile
492 * time #if (see code below). Currently we use choice 1) here because
493 * it's more aligned to the ZRTP specification
494 */
495void ZrtpStateClass::evAckDetected(void) {
496
497 DEBUGOUT((cout << "Checking for match in AckDetected.\n"));
498
499 char *msg, first, last;
500 uint8_t *pkt;
501 uint32_t errorCode = 0;
502
503 if (event->type == ZrtpPacket) {
504 pkt = event->packet;
505 msg = (char *)pkt + 4;
506
507 first = tolower(*msg);
508 last = tolower(*(msg+7));
509
510#if 1
511 /*
512 * Implementation for choice 1)
513 * Hello:
Alexandre Lisione24852d2014-02-04 13:13:02 -0500514 * - Acknowledge peers Hello, sending HelloACK (F4)
Alexandre Lision51140e12013-12-02 10:54:09 -0500515 * - switch to state WaitCommit, wait for peer's Commit
516 * - we are going to be in the Responder role
517 */
518
519 if (first == 'h' && last ==' ') {
520 // Parse Hello packet and build an own Commit packet even if the
521 // Commit is not send to the peer. We need to do this to check the
522 // Hello packet and prepare the shared secret stuff.
523 ZrtpPacketHello hpkt(pkt);
524 ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode);
525
526 // Something went wrong during processing of the Hello packet, for
527 // example wrong version, duplicate ZID.
528 if (commit == NULL) {
529 sendErrorPacket(errorCode);
530 return;
531 }
532 ZrtpPacketHelloAck *helloAck = parent->prepareHelloAck();
533 nextState(WaitCommit);
534
535 // remember packet for easy resend
536 sentPacket = static_cast<ZrtpPacketBase *>(helloAck);
537 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(helloAck))) {
538 sendFailed();
539 }
540 }
541#else
542 /*
543 * Implementation for choice 2)
544 * Hello:
Alexandre Lisione24852d2014-02-04 13:13:02 -0500545 * - Acknowledge peers Hello by sending Commit (F5)
Alexandre Lision51140e12013-12-02 10:54:09 -0500546 * instead of HelloAck (F4)
547 * - switch to state CommitSent
548 * - Initiator role, thus start timer T2 to monitor timeout for Commit
549 */
550
Alexandre Lisione24852d2014-02-04 13:13:02 -0500551 if (first == 'h') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500552 // Parse peer's packet data into a Hello packet
553 ZrtpPacketHello hpkt(pkt);
554 ZrtpPacketCommit* commit = parent->prepareCommit(&hpkt, &errorCode);
555 // Something went wrong during processing of the Hello packet
556 if (commit == NULL) {
557 sendErrorPacket(errorCode);
558 return;
559 }
560 nextState(CommitSent);
561
562 // remember packet for easy resend in case timer triggers
563 // Timer trigger received in new state CommitSend
564 sentPacket = static_cast<ZrtpPacketBase *>(commit);
565 if (!parent->sendPacketZRTP(sentPacket)) {
566 sendFailed();
567 return;
568 }
569 if (startTimer(&T2) <= 0) {
570 timerFailed(SevereNoTimer);
571 }
572 }
573#endif
574 }
575 else { // unknown Event type for this state (covers Error and ZrtpClose)
576 if (event->type != ZrtpClose) {
577 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
578 }
579 nextState(Initial);
580 }
581}
582
583/*
584 * WaitCommit state.
585 *
586 * This state is only used if we use choice 1) in AckDetected.
587 *
588 * When entering this transition function
589 * - instance variable sentPacket contains a HelloAck packet
590 *
591 * Possible events in this state are:
592 * - Hello: just resend our HelloAck
593 * - Commit: prepare and send our DHPart1 message to start first
594 * half of DH key agreement. Switch to state WaitDHPart2, don't
595 * start any timer, we a Responder.
596 */
597void ZrtpStateClass::evWaitCommit(void) {
598
599 DEBUGOUT((cout << "Checking for match in WaitCommit.\n"));
600
Alexandre Lisione24852d2014-02-04 13:13:02 -0500601 char *msg, first;
Alexandre Lision51140e12013-12-02 10:54:09 -0500602 uint8_t *pkt;
603 uint32_t errorCode = 0;
604
605 if (event->type == ZrtpPacket) {
606 pkt = event->packet;
607 msg = (char *)pkt + 4;
608
609 first = tolower(*msg);
610 /*
611 * Hello:
612 * - resend HelloAck
613 * - stay in WaitCommit
614 */
Alexandre Lisione24852d2014-02-04 13:13:02 -0500615 if (first == 'h') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500616 if (!parent->sendPacketZRTP(sentPacket)) {
617 sendFailed(); // returns to state Initial
618 }
619 return;
620 }
621 /*
622 * Commit:
623 * - prepare DH1Part packet or Confirm1 if multi stream mode
624 * - send it to peer
625 * - switch state to WaitDHPart2 or WaitConfirm2 if multi stream mode
626 * - don't start timer, we are responder
627 */
Alexandre Lisione24852d2014-02-04 13:13:02 -0500628 if (first == 'c') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500629 ZrtpPacketCommit cpkt(pkt);
630
631 if (!multiStream) {
632 ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&cpkt, &errorCode);
633
634 // Something went wrong during processing of the Commit packet
635 if (dhPart1 == NULL) {
636 if (errorCode != IgnorePacket) {
637 sendErrorPacket(errorCode);
638 }
639 return;
640 }
641 sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
642 nextState(WaitDHPart2);
643 }
644 else {
645 ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&cpkt, &errorCode);
646
647 // Something went wrong during processing of the Commit packet
648 if (confirm == NULL) {
649 if (errorCode != IgnorePacket) {
650 sendErrorPacket(errorCode);
651 }
652 return;
653 }
654 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
655 nextState(WaitConfirm2);
656 }
657 if (!parent->sendPacketZRTP(sentPacket)) {
658 sendFailed(); // returns to state Initial
659 }
660 }
661 }
662 else { // unknown Event type for this state (covers Error and ZrtpClose)
663 if (event->type != ZrtpClose) {
664 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
665 }
666 sentPacket = NULL;
667 nextState(Initial);
668 }
669}
670
671/*
672 * CommitSent state.
673 *
674 * This state either handles a DH1Part1 message to start the first
675 * half of DH key agreement or it handles a Commit clash. If handling a
676 * Commit clash it may happen that we change our role from Initiator to
677 * Responder.
678 *
679 * When entering this transition function
680 * - assume Initiator mode, may change if we reveice a Commit here
681 * - sentPacket contains Commit packet
682 * - Commit timer (T2) active
683 *
684 * Possible events in this state are:
685 * - timeout for sent Commit packet: causes a resend check and repeat sending
686 * of Commit packet
687 * - Commit: This is a Commit clash. Break the tie accroding to chapter 5.2
688 * - DHPart1: start first half of DH key agreement. Perpare and send own DHPart2
689 * and switch to state WaitConfirm1.
690 */
691
692void ZrtpStateClass::evCommitSent(void) {
693
694 DEBUGOUT((cout << "Checking for match in CommitSend.\n"));
695
Alexandre Lisione24852d2014-02-04 13:13:02 -0500696 char *msg, first, last;
Alexandre Lision51140e12013-12-02 10:54:09 -0500697 uint8_t *pkt;
698 uint32_t errorCode = 0;
699
700 if (event->type == ZrtpPacket) {
701 pkt = event->packet;
702 msg = (char *)pkt + 4;
703
704 first = tolower(*msg);
705 last = tolower(*(msg+7));
706
707 /*
708 * HelloAck or Hello:
709 * - delayed "HelloAck" or "Hello", maybe due to network latency, just
710 * ignore it
711 * - no switch in state, leave timer as it is
712 */
Alexandre Lisione24852d2014-02-04 13:13:02 -0500713 if (first == 'h' && (last =='k' || last == ' ')) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500714 return;
715 }
716
717 /*
718 * Commit:
719 * We have a "Commit" clash. Resolve it.
720 *
721 * - switch off resending Commit
722 * - compare my hvi with peer's hvi
723 * - if my hvi is greater
724 * - we are Initiator, stay in state, wait for peer's DHPart1 packet
725 * - else
726 * - we are Responder, stop timer
727 * - prepare and send DH1Packt,
728 * - switch to state WaitDHPart2, implies Responder path
729 */
730 if (first == 'c' && last == ' ') {
731 ZrtpPacketCommit zpCo(pkt);
732
733 if (!parent->verifyH2(&zpCo)) {
734 return;
735 }
736 cancelTimer(); // this cancels the Commit timer T2
737
738 // if our hvi is less than peer's hvi: switch to Responder mode and
739 // send DHPart1 or Confirm1 packet. Peer (as Initiator) will retrigger if
740 // necessary
741 //
742 if (parent->compareCommit(&zpCo) < 0) {
743 if (!multiStream) {
744 ZrtpPacketDHPart* dhPart1 = parent->prepareDHPart1(&zpCo, &errorCode);
745
746 // Something went wrong during processing of the Commit packet
747 if (dhPart1 == NULL) {
748 if (errorCode != IgnorePacket) {
749 sendErrorPacket(errorCode);
750 }
751 return;
752 }
753 nextState(WaitDHPart2);
754 sentPacket = static_cast<ZrtpPacketBase *>(dhPart1);
755 }
756 else {
757 ZrtpPacketConfirm* confirm = parent->prepareConfirm1MultiStream(&zpCo, &errorCode);
758
759 // Something went wrong during processing of the Commit packet
760 if (confirm == NULL) {
761 if (errorCode != IgnorePacket) {
762 sendErrorPacket(errorCode);
763 }
764 return;
765 }
766 nextState(WaitConfirm2);
767 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
768 }
769 if (!parent->sendPacketZRTP(sentPacket)) {
770 sendFailed(); // returns to state Initial
771 }
772 }
773 // Stay in state, we are Initiator, wait for DHPart1 of Confirm1 packet from peer.
774 // Resend Commit after timeout until we get a DHPart1 or Confirm1
775 else {
776 if (startTimer(&T2) <= 0) { // restart the Commit timer, gives peer more time to react
777 timerFailed(SevereNoTimer); // returns to state Initial
778 }
779 }
780 return;
781 }
782
783 /*
784 * DHPart1:
785 * - switch off resending Commit
786 * - Prepare and send DHPart2
787 * - switch to WaitConfirm1
788 * - start timer to resend DHPart2 if necessary, we are Initiator
789 */
Alexandre Lisione24852d2014-02-04 13:13:02 -0500790 if (first == 'd') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500791 cancelTimer();
792 sentPacket = NULL;
793 ZrtpPacketDHPart dpkt(pkt);
794 ZrtpPacketDHPart* dhPart2 = parent->prepareDHPart2(&dpkt, &errorCode);
795
796 // Something went wrong during processing of the DHPart1 packet
797 if (dhPart2 == NULL) {
798 if (errorCode != IgnorePacket) {
799 sendErrorPacket(errorCode);
800 }
801 else {
802 if (startTimer(&T2) <= 0) {
803 timerFailed(SevereNoTimer); // switches to state Initial
804 }
805 }
806
807 return;
808 }
809 sentPacket = static_cast<ZrtpPacketBase *>(dhPart2);
810 nextState(WaitConfirm1);
811
812 if (!parent->sendPacketZRTP(sentPacket)) {
813 sendFailed(); // returns to state Initial
814 return;
815 }
816 if (startTimer(&T2) <= 0) {
817 timerFailed(SevereNoTimer); // switches to state Initial
818 }
819 return;
820 }
821
822 if (multiStream && (first == 'c' && last == '1')) {
823 cancelTimer();
824 ZrtpPacketConfirm cpkt(pkt);
825
826 ZrtpPacketConfirm* confirm = parent->prepareConfirm2MultiStream(&cpkt, &errorCode);
827
828 // Something went wrong during processing of the Confirm1 packet
829 if (confirm == NULL) {
830 sendErrorPacket(errorCode);
831 return;
832 }
833 nextState(WaitConfAck);
834 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
835
836 if (!parent->sendPacketZRTP(sentPacket)) {
837 sendFailed(); // returns to state Initial
838 return;
839 }
840 if (startTimer(&T2) <= 0) {
841 timerFailed(SevereNoTimer); // returns to state Initial
842 return;
843 }
844 // according to chap 5.6: after sending Confirm2 the Initiator must
845 // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck
846 // state.
847 if (!parent->srtpSecretsReady(ForReceiver)) {
848 parent->sendInfo(Severe, CriticalSWError);
849 sendErrorPacket(CriticalSWError);
850 return;
851 }
852 }
853 }
854 // Timer event triggered, resend the Commit packet
855 else if (event->type == Timer) {
856 if (!parent->sendPacketZRTP(sentPacket)) {
857 sendFailed(); // returns to state Initial
858 return;
859 }
860 if (nextTimer(&T2) <= 0) {
861 timerFailed(SevereTooMuchRetries); // returns to state Initial
862 }
863 }
864 else { // unknown Event type for this state (covers Error and ZrtpClose)
865 if (event->type != ZrtpClose) {
866 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
867 }
868 sentPacket = NULL;
869 nextState(Initial);
870 }
871}
872
873/*
874 * WaitDHPart2 state.
875 *
876 * This state handles the second part of SH key agreement. Only the Resonder
877 * can enter this state.
878 *
879 * When entering this transition function
880 * - sentPacket contains DHPart1 packet, no timer active
881 *
882 * Possible events in this state are:
883 * - Commit: Our peer didn't receive out DHPart1 thus the peer sends Commit again.
884 * Just repeat our DHPart1.
885 * - DHPart2: start second half of DH key agreement. Perpare and send own Confirm1
886 * and switch to state WaitConfirm2.
887 */
888void ZrtpStateClass::evWaitDHPart2(void) {
889
890 DEBUGOUT((cout << "Checking for match in DHPart2.\n"));
891
Alexandre Lisione24852d2014-02-04 13:13:02 -0500892 char *msg, first;
Alexandre Lision51140e12013-12-02 10:54:09 -0500893 uint8_t *pkt;
894 uint32_t errorCode = 0;
895
896 if (event->type == ZrtpPacket) {
897 pkt = event->packet;
898 msg = (char *)pkt + 4;
899
900 first = tolower(*msg);
901 /*
902 * Commit:
903 * - resend DHPart1
904 * - stay in state
905 */
Alexandre Lisione24852d2014-02-04 13:13:02 -0500906 if (first == 'c') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500907 if (!parent->sendPacketZRTP(sentPacket)) {
908 return sendFailed(); // returns to state Initial
909 }
910 return;
911 }
912 /*
913 * DHPart2:
914 * - prepare Confirm1 packet
915 * - switch to WaitConfirm2
916 * - No timer, we are responder
917 */
Alexandre Lisione24852d2014-02-04 13:13:02 -0500918 if (first == 'd') {
Alexandre Lision51140e12013-12-02 10:54:09 -0500919 ZrtpPacketDHPart dpkt(pkt);
920 ZrtpPacketConfirm* confirm = parent->prepareConfirm1(&dpkt, &errorCode);
921
922 if (confirm == NULL) {
923 if (errorCode != IgnorePacket) {
924 sendErrorPacket(errorCode);
925 }
926 return;
927 }
928 nextState(WaitConfirm2);
929 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
930 if (!parent->sendPacketZRTP(sentPacket)) {
931 sendFailed(); // returns to state Initial
932 }
933 }
934 }
935 else { // unknown Event type for this state (covers Error and ZrtpClose)
936 if (event->type != ZrtpClose) {
937 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
938 }
939 sentPacket = NULL;
940 nextState(Initial);
941 }
942}
943
944/*
945 * WaitConirm1 state.
946 *
947 * This state handles a received Confirm1 message and only the Initiator
948 * can enter this state.
949 *
950 * When entering this transition function in DH mode:
951 * - Initiator mode
952 * - sentPacket contains DHPart2 packet, DHPart2 timer active
953 *
954 * When entering this transition function in Multi stream mode via AckSent:
955 * - Initiator mode
956 * - sentPacket contains my Commit packet, Commit timer active
957 *
958* Possible events in this state are:
959 * - timeout for sent DHPart2 packet: causes a resend check and repeat sending
960 * of DHPart2 packet.
961 * - Confirm1: Check Confirm1 message. If it is ok then prepare and send own
962 * Confirm2 packet and switch to state WaitConfAck.
963 */
964void ZrtpStateClass::evWaitConfirm1(void) {
965
966 DEBUGOUT((cout << "Checking for match in WaitConfirm1.\n"));
967
968 char *msg, first, last;
969 uint8_t *pkt;
970 uint32_t errorCode = 0;
971
972 if (event->type == ZrtpPacket) {
973 pkt = event->packet;
974 msg = (char *)pkt + 4;
975
976 first = tolower(*msg);
977 last = tolower(*(msg+7));
978
979 /*
980 * Confirm1:
981 * - Switch off resending DHPart2
982 * - prepare a Confirm2 packet
983 * - switch to state WaitConfAck
984 * - set timer to monitor Confirm2 packet, we are initiator
985 */
986 if (first == 'c' && last == '1') {
987 cancelTimer();
988 ZrtpPacketConfirm cpkt(pkt);
989
990 ZrtpPacketConfirm* confirm = parent->prepareConfirm2(&cpkt, &errorCode);
991
992 // Something went wrong during processing of the Confirm1 packet
993 if (confirm == NULL) {
994 sendErrorPacket(errorCode);
995 return;
996 }
997 nextState(WaitConfAck);
998 sentPacket = static_cast<ZrtpPacketBase *>(confirm);
999
1000 if (!parent->sendPacketZRTP(sentPacket)) {
1001 sendFailed(); // returns to state Initial
1002 return;
1003 }
1004 if (startTimer(&T2) <= 0) {
Alexandre Lisione24852d2014-02-04 13:13:02 -05001005 timerFailed(SevereNoTimer); // returns to state Initial TODO check for return following this line
1006 }
1007 // according to chap 5.8: after sending Confirm2 the Initiator must
1008 // be ready to receive SRTP data. SRTP sender will be enabled in WaitConfAck
1009 // state.
1010 if (!parent->srtpSecretsReady(ForReceiver)) {
1011 parent->sendInfo(Severe, CriticalSWError);
1012 sendErrorPacket(CriticalSWError);
1013 return;
Alexandre Lision51140e12013-12-02 10:54:09 -05001014 }
1015 }
1016 }
1017 else if (event->type == Timer) {
1018 if (!parent->sendPacketZRTP(sentPacket)) {
1019 sendFailed(); // returns to state Initial
1020 return;
1021 }
1022 if (nextTimer(&T2) <= 0) {
1023 timerFailed(SevereTooMuchRetries); // returns to state Initial
1024 }
1025 }
1026 else { // unknown Event type for this state (covers Error and ZrtpClose)
1027 if (event->type != ZrtpClose) {
1028 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1029 }
1030 sentPacket = NULL;
1031 nextState(Initial);
1032 }
1033}
1034
1035/*
1036 * WaitConfirm2 state.
1037 *
1038 * Handles the Confirm2 message that closes the key agreement handshake. Only
1039 * the Responder can enter this state. If the Confirm2 message is ok send a
1040 * Conf2Ack to our peer. Switch to secure mode after sending Conf2Ack, our
1041 * peer switches to secure mode after receiving Conf2Ack.
1042 *
1043 * TODO - revise documentation comments
1044 *
1045 * When entering this transition function
1046 * - Responder mode
1047 * - sentPacket contains Confirm1 packet, no timer active
1048 *
1049 * Possible events in this state are:
1050 * - DHPart2: Our peer didn't receive our Confirm1 thus sends DHPart2 again.
1051 * Just repeat our Confirm1.
1052 * - Confirm2: close DH key agreement. Perpare and send own Conf2Ack
1053 * and switch to state SecureState.
1054 */
1055void ZrtpStateClass::evWaitConfirm2(void) {
1056
1057 DEBUGOUT((cout << "Checking for match in WaitConfirm2.\n"));
1058
Alexandre Lisione24852d2014-02-04 13:13:02 -05001059 char *msg, first, last;
Alexandre Lision51140e12013-12-02 10:54:09 -05001060 uint8_t *pkt;
1061 uint32_t errorCode = 0;
1062
1063 if (event->type == ZrtpPacket) {
1064 pkt = event->packet;
1065 msg = (char *)pkt + 4;
1066
1067 first = tolower(*msg);
1068 last = tolower(*(msg+7));
1069
1070 /*
1071 * DHPart2 or Commit in multi stream mode:
1072 * - resend Confirm1 packet
1073 * - stay in state
1074 */
Alexandre Lisione24852d2014-02-04 13:13:02 -05001075 if (first == 'd' || (multiStream && (first == 'c' && last == ' '))) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001076 if (!parent->sendPacketZRTP(sentPacket)) {
1077 sendFailed(); // returns to state Initial
1078 }
1079 return;
1080 }
1081 /*
1082 * Confirm2:
1083 * - prepare ConfAck
1084 * - switch on security (SRTP)
1085 * - switch to SecureState
1086 */
1087 if (first == 'c' && last == '2') {
1088 ZrtpPacketConfirm cpkt(pkt);
1089 ZrtpPacketConf2Ack* confack = parent->prepareConf2Ack(&cpkt, &errorCode);
1090
1091 // Something went wrong during processing of the confirm2 packet
1092 if (confack == NULL) {
1093 sendErrorPacket(errorCode);
1094 return;
1095 }
1096 sentPacket = static_cast<ZrtpPacketBase *>(confack);
1097
1098 if (!parent->sendPacketZRTP(sentPacket)) {
1099 sendFailed(); // returns to state Initial
1100 return;
1101 }
Alexandre Lisione24852d2014-02-04 13:13:02 -05001102 if (!parent->srtpSecretsReady(ForSender) ||
1103 !parent->srtpSecretsReady(ForReceiver)) {
Alexandre Lision51140e12013-12-02 10:54:09 -05001104 parent->sendInfo(Severe, CriticalSWError);
1105 sendErrorPacket(CriticalSWError);
1106 return;
1107 }
1108 nextState(SecureState);
1109 parent->sendInfo(Info, InfoSecureStateOn);
1110 }
1111 }
1112 else { // unknown Event type for this state (covers Error and ZrtpClose)
1113 if (event->type != ZrtpClose) {
1114 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1115 }
1116 sentPacket = NULL;
1117 nextState(Initial);
1118 }
1119}
1120
1121/*
1122 * WaitConf2Ack state.
1123 *
1124 * This state handles the Conf2Ack message that acknowledges the successfull
1125 * processing of Confirm2. Only the Initiator can enter this state. Switch on
1126 * secure mode and switch to state SecureState.
1127 *
1128 * When entering this transition function
1129 * - Initiator mode
1130 * - sentPacket contains Confirm2 packet, Confirm2 timer active
1131 * - receiver security switched on
1132 *
1133 * Possible events in this state are:
1134 * - timeout for sent Confirm2 packet: causes a resend check and repeat sending
1135 * of Confirm2 packet
1136 * - Conf2Ack: Key agreement was successfull, switch to secure mode.
1137 */
1138void ZrtpStateClass::evWaitConfAck(void) {
1139
1140 DEBUGOUT((cout << "Checking for match in WaitConfAck.\n"));
1141
Alexandre Lisione24852d2014-02-04 13:13:02 -05001142 char *msg, first;
Alexandre Lision51140e12013-12-02 10:54:09 -05001143 uint8_t *pkt;
1144
1145 if (event->type == ZrtpPacket) {
1146 pkt = event->packet;
1147 msg = (char *)pkt + 4;
1148
1149 first = tolower(*msg);
1150 /*
1151 * ConfAck:
1152 * - Switch off resending Confirm2
1153 * - switch to SecureState
1154 */
Alexandre Lisione24852d2014-02-04 13:13:02 -05001155 if (first == 'c') {
Alexandre Lision51140e12013-12-02 10:54:09 -05001156 cancelTimer();
1157 sentPacket = NULL;
1158 // Receiver was already enabled after sending Confirm2 packet
1159 // see previous states.
1160 if (!parent->srtpSecretsReady(ForSender)) {
1161 parent->sendInfo(Severe, CriticalSWError);
1162 sendErrorPacket(CriticalSWError);
1163 return;
1164 }
1165 nextState(SecureState);
1166 // TODO: call parent to clear signature data at initiator
1167 parent->sendInfo(Info, InfoSecureStateOn);
1168 }
1169 }
1170 else if (event->type == Timer) {
1171 if (!parent->sendPacketZRTP(sentPacket)) {
1172 sendFailed(); // returns to state Initial
1173 parent->srtpSecretsOff(ForReceiver);
1174 return;
1175 }
1176 if (nextTimer(&T2) <= 0) {
1177 timerFailed(SevereTooMuchRetries); // returns to state Initial
1178 parent->srtpSecretsOff(ForReceiver);
1179 }
1180 }
1181 else { // unknown Event type for this state (covers Error and ZrtpClose)
1182 if (event->type != ZrtpClose) {
1183 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1184 }
1185 sentPacket = NULL;
1186 nextState(Initial);
1187 parent->srtpSecretsOff(ForReceiver);
1188 }
1189}
1190
1191/*
1192 * When entering this transition function
1193 * - sentPacket contains GoClear packet, GoClear timer active
1194 */
1195
1196void ZrtpStateClass::evWaitClearAck(void) {
1197 DEBUGOUT((cout << "Checking for match in ClearAck.\n"));
1198
Alexandre Lisione24852d2014-02-04 13:13:02 -05001199 char *msg, first, last;
1200 uint8_t *pkt;
1201
1202 if (event->type == ZrtpPacket) {
1203 pkt = event->packet;
1204 msg = (char *)pkt + 4;
1205
1206 first = tolower(*msg);
1207 last = tolower(*(msg+7));
1208
1209 /*
1210 * ClearAck:
1211 * - stop resending GoClear,
1212 * - switch to state AckDetected, wait for peer's Hello
1213 */
1214 if (first == 'c' && last =='k') {
1215 cancelTimer();
1216 sentPacket = NULL;
1217 nextState(Initial);
1218 }
1219 }
1220 // Timer event triggered - this is Timer T2 to resend GoClear w/o HMAC
1221 else if (event->type == Timer) {
1222 if (!parent->sendPacketZRTP(sentPacket)) {
1223 sendFailed(); // returns to state Initial
1224 return;
1225 }
1226 if (nextTimer(&T2) <= 0) {
1227 timerFailed(SevereTooMuchRetries); // returns to state Initial
1228 }
1229 }
1230 else { // unknown Event type for this state (covers Error and ZrtpClose)
1231 if (event->type != ZrtpClose) {
1232 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1233 }
1234 sentPacket = NULL;
1235 nextState(Initial);
1236 }
Alexandre Lision51140e12013-12-02 10:54:09 -05001237}
1238
1239
1240/*
1241 * WaitErrorAck state.
1242 *
1243 * This state belongs to the "error handling state overlay" and handle
1244 * ErrorAck message. Most of the ZRTP states can send Error message for
1245 * example if they detect wrong packets. After sending an Error message
1246 * the protocol engine switches to WaitErrorAck state. Receiving an
1247 * ErrorAck message completes the ZRTP error handling.
1248 *
1249 * When entering this transition function
1250 * - sentPacket contains Error packet, Error timer active
1251 *
1252 * Possible events in this state are:
1253 * - timeout for sent Error packet: causes a resend check and repeat sending
1254 * of Error packet
1255 * - ErrorAck: Stop timer and switch to state Initial.
1256 */
1257
1258void ZrtpStateClass::evWaitErrorAck(void) {
1259 DEBUGOUT((cout << "Checking for match in ErrorAck.\n"));
1260
1261 char *msg, first, last;
1262 uint8_t *pkt;
1263
1264 if (event->type == ZrtpPacket) {
1265 pkt = event->packet;
1266 msg = (char *)pkt + 4;
1267
1268 first = tolower(*msg);
1269 last = tolower(*(msg+7));
1270
1271 /*
1272 * Errorck:
1273 * - stop resending Error,
1274 * - switch to state Initial
1275 */
1276 if (first == 'e' && last =='k') {
1277 cancelTimer();
1278 sentPacket = NULL;
1279 nextState(Initial);
1280 }
1281 }
1282 // Timer event triggered - this is Timer T2 to resend Error.
1283 else if (event->type == Timer) {
1284 if (!parent->sendPacketZRTP(sentPacket)) {
1285 sendFailed(); // returns to state Initial
1286 return;
1287 }
1288 if (nextTimer(&T2) <= 0) {
1289 timerFailed(SevereTooMuchRetries); // returns to state Initial
1290 }
1291 }
1292 else { // unknown Event type for this state (covers Error and ZrtpClose)
1293 if (event->type != ZrtpClose) {
1294 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1295 }
1296 sentPacket = NULL;
1297 nextState(Initial);
1298 }
1299}
1300
1301void ZrtpStateClass::evSecureState(void) {
1302
1303 DEBUGOUT((cout << "Checking for match in SecureState.\n"));
1304
1305 char *msg, first, last;
1306 uint8_t *pkt;
1307
1308 /*
1309 * Handle a possible substate. If substate handling was ok just return.
1310 */
1311 if (secSubstate == WaitSasRelayAck) {
1312 if (subEvWaitRelayAck())
1313 return;
1314 }
1315
1316 if (event->type == ZrtpPacket) {
1317 pkt = event->packet;
1318 msg = (char *)pkt + 4;
1319
1320 first = tolower(*msg);
1321 last = tolower(*(msg+7));
1322
1323 /*
1324 * Confirm2:
1325 * - resend Conf2Ack packet
1326 * - stay in state
1327 */
1328 if (first == 'c' && last == '2') {
1329 if (sentPacket != NULL && !parent->sendPacketZRTP(sentPacket)) {
1330 sentPacket = NULL;
1331 nextState(Initial);
1332 parent->srtpSecretsOff(ForSender);
1333 parent->srtpSecretsOff(ForReceiver);
1334 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
1335 }
1336 return;
1337 }
1338 /*
1339 * GoClear received, handle it. TODO fix go clear handling
Alexandre Lisione24852d2014-02-04 13:13:02 -05001340 */
Alexandre Lision51140e12013-12-02 10:54:09 -05001341 if (first == 'g' && last == 'r') {
1342 ZrtpPacketGoClear gpkt(pkt);
1343 ZrtpPacketClearAck* clearAck = parent->prepareClearAck(&gpkt);
1344
1345 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(clearAck))) {
1346 return;
1347 }
1348 // TODO Timeout to resend clear ack until user user confirmation
1349 }
1350 }
Alexandre Lisione24852d2014-02-04 13:13:02 -05001351 else { // unknown Event type for this state (covers Error and ZrtpClose)
Alexandre Lision51140e12013-12-02 10:54:09 -05001352 sentPacket = NULL;
1353 parent->srtpSecretsOff(ForSender);
1354 parent->srtpSecretsOff(ForReceiver);
1355 nextState(Initial);
1356 if (event->type != ZrtpClose) {
1357 parent->zrtpNegotiationFailed(Severe, SevereProtocolError);
1358 }
1359 parent->sendInfo(Info, InfoSecureStateOff);
1360 }
1361}
1362
1363bool ZrtpStateClass::subEvWaitRelayAck() {
1364 char *msg, first, last;
1365 uint8_t* pkt;
1366
1367 /*
1368 * First check the general event type, then discrimnate the real event.
1369 */
1370 if (event->type == ZrtpPacket) {
1371 pkt = event->packet;
1372 msg = (char *)pkt + 4;
1373
1374 first = tolower(*msg);
1375 last = tolower(*(msg+7));
1376
1377 /*
1378 * SAS relayAck:
1379 * - stop resending SASRelay,
1380 * - switch to secure substate Normal
1381 */
1382 if (first == 'r' && last =='k') {
1383 cancelTimer();
1384 secSubstate = Normal;
1385 sentPacket = NULL;
1386 }
1387 return true;
1388 }
1389 // Timer event triggered - this is Timer T2 to resend Error.
1390 else if (event->type == Timer) {
1391 if (!parent->sendPacketZRTP(sentPacket)) {
1392 sendFailed(); // returns to state Initial
1393 return false;
1394 }
1395 if (nextTimer(&T2) <= 0) {
1396 // returns to state initial
1397 // timerFailed(ZrtpCodes.SevereCodes.SevereTooMuchRetries);
1398 return false;
1399 }
1400 return true;
1401 }
1402 return false;
1403}
1404
1405int32_t ZrtpStateClass::startTimer(zrtpTimer_t *t) {
1406
1407 t->time = t->start;
1408 t->counter = 0;
1409 return parent->activateTimer(t->time);
1410}
1411
1412int32_t ZrtpStateClass::nextTimer(zrtpTimer_t *t) {
1413
1414 t->time += t->time;
1415 t->time = (t->time > t->capping)? t->capping : t->time;
1416 t->counter++;
1417 if (t->counter > t->maxResend) {
1418 return -1;
1419 }
1420 return parent->activateTimer(t->time);
1421}
1422
1423void ZrtpStateClass::sendErrorPacket(uint32_t errorCode) {
1424 cancelTimer();
1425
1426 ZrtpPacketError* err = parent->prepareError(errorCode);
1427 parent->zrtpNegotiationFailed(ZrtpError, errorCode);
1428
1429 sentPacket = static_cast<ZrtpPacketBase *>(err);
1430 nextState(WaitErrorAck);
1431 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(err)) || (startTimer(&T2) <= 0)) {
1432 sendFailed();
1433 }
1434}
1435
1436void ZrtpStateClass::sendSASRelay(ZrtpPacketSASrelay* relay) {
1437 cancelTimer();
1438 sentPacket = static_cast<ZrtpPacketBase *>(relay);
1439 secSubstate = WaitSasRelayAck;
1440 if (!parent->sendPacketZRTP(static_cast<ZrtpPacketBase *>(relay)) || (startTimer(&T2) <= 0)) {
1441 sendFailed();
1442 }
1443}
1444
1445void ZrtpStateClass::sendFailed() {
1446 sentPacket = NULL;
1447 nextState(Initial);
1448 parent->zrtpNegotiationFailed(Severe, SevereCannotSend);
1449}
1450
1451void ZrtpStateClass::timerFailed(int32_t subCode) {
1452 sentPacket = NULL;
1453 nextState(Initial);
1454 parent->zrtpNegotiationFailed(Severe, subCode);
1455}
1456
1457void ZrtpStateClass::setMultiStream(bool multi) {
1458 multiStream = multi;
1459}
1460
1461bool ZrtpStateClass::isMultiStream() {
1462 return multiStream;
1463}
1464
1465/** EMACS **
1466 * Local variables:
1467 * mode: c++
1468 * c-default-style: ellemtel
1469 * c-basic-offset: 4
1470 * End:
1471 */