summaryrefslogtreecommitdiff
path: root/src/libzrtpcpp/ZrtpStateClass.h
blob: fba061d68ce6489e3ff5fdaae1c82224e641d842 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
/*
  Copyright (C) 2006-2010 Werner Dittmann

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _ZRTPSTATECLASS_H_
#define _ZRTPSTATECLASS_H_

/**
 * @file ZrtpStateClass.h
 * @brief The ZRTP state handling class
 *
 * @ingroup GNU_ZRTP
 * @{
 */

#include <libzrtpcpp/ZrtpStates.h>
#include <libzrtpcpp/ZrtpPacketBase.h>

/**
 * The ZRTP states
 *
 * Depending on the role of this state engine and the actual protocl flow
 * not all states are processed during a ZRTP handshake.
 */
enum zrtpStates {
    Initial,            ///< Initial state after starting the state engine
    Detect,             ///< State sending Hello, try to detect answer message
    AckDetected,        ///< HelloAck received
    AckSent,            ///< HelloAck sent after Hello received
    WaitCommit,         ///< Wait for a Commit message
    CommitSent,         ///< Commit message sent
    WaitDHPart2,        ///< Wait for a DHPart2 message
    WaitConfirm1,       ///< Wait for a Confirm1 message
    WaitConfirm2,       ///< Wait for a confirm2 message
    WaitConfAck,        ///< Wait for Conf2Ack
    WaitClearAck,       ///< Wait for clearAck - not used
    SecureState,        ///< This is the secure state - SRTP active
    WaitErrorAck,       ///< Wait for ErrorAck message
    numberOfStates      ///< Gives total number of protocol states
};

enum EventReturnCodes {
    Fail = 0,           ///< ZRTP event processing failed.
    Done = 1            ///< Event processing ok.
};

enum EventDataType {
    ZrtpInitial = 1,    ///< Initial event, enter Initial state
    ZrtpClose,          ///< Close event, shut down state engine
    ZrtpPacket,         ///< Normal ZRTP message event, process according to state
    Timer,              ///< Timer event
    ErrorPkt            ///< Error packet event
};

enum SecureSubStates {
    Normal,
    WaitSasRelayAck,
    numberofSecureSubStates
};

/// A ZRTP state event
typedef struct Event {
    EventDataType type; ///< Type of event
    uint8_t* packet;    ///< Event data if availabe, usually a ZRTP message
} Event_t;


/**
 * The ZRTP timer structure.
 *
 * This structure holds all necessary data to compute the timer for
 * the protocol timers. The state engine allocate one structure for
 * each timer. ZRTP uses two timers, T1 and T2, to monitor protocol
 * timeouts. As a slight misuse but to make overall handling a bit
 * simpler this structure also contains the resend counter. This is
 * possible in ZRTP because it uses a simple timeout strategy.
 */
typedef struct zrtpTimer {
    int32_t time,       ///< Current timeout value
    start,              ///< Start value for timeout
    increment,          ///< increment timeout after each timeout event (not used anymore)
    capping,            ///< Maximum timeout value
    counter,            ///< Current number of timeouts
    maxResend;          ///< Maximum number of timeout resends
} zrtpTimer_t;


class ZRtp;

/**
 * This class is the ZRTP protocol state engine.
 *
 * This class is responsible to handle the ZRTP protocol. It does not
 * handle the ZRTP HMAC, DH, and other data management. This is done in
 * class ZRtp, which is the parent of this class.
 *
 * The methods of this class implement the ZRTP state actions.
 *
 */


class __EXPORT ZrtpStateClass {

private:
    ZRtp* parent;           ///< The ZRTP implmentation
    ZrtpStates* engine;     ///< The state switching engine
    Event_t* event;         ///< Current event to process

    /**
     * The last packet that was sent.
     *
     * If we are <code>Initiator</code> then resend this packet in case of
     * timeout.
     */
    ZrtpPacketBase* sentPacket;

    /**
     * Points to prepared Commit packet after receiving a Hello packet
     */
    ZrtpPacketCommit* commitPkt;

    zrtpTimer_t T1;         ///< The Hello message timeout timer
    zrtpTimer_t T2;         ///< Timeout timer for other messages

    /*
     * If this is set to true the protocol engine handle the multi-stream
     * variant of ZRTP. Refer to chapter 5.4.2 in the ZRTP specification.
     */
    bool multiStream;
    
    // Secure substate to handle SAS relay packets
    SecureSubStates secSubstate;

    /**
     * Secure Sub state WaitSasRelayAck.
     *
     * This state belongs to the secure substates and handles
     * SAS Relay Ack. 
     *
     * When entering this transition function
     * - sentPacket contains Error packet, Error timer active
     *
     * Possible events in this state are:
     * - timeout for sent SAS Relay packet: causes a resend check and repeat sending
     *   of packet
     * - SASRelayAck: Stop timer and switch to secure substate Normal.
     */
    bool subEvWaitRelayAck();

public:
    /// Create a ZrtpStateClass
    ZrtpStateClass(ZRtp *p);
    ~ZrtpStateClass();

    /// Check if in a specified state
    bool inState(const int32_t state) { return engine->inState(state); };

    /// Switch to the specified state
    void nextState(int32_t state)        { engine->nextState(state); };

    /// Process an event, the main entry point into the state engine
    void processEvent(Event_t *ev);

    /**
     * The state event handling methods.
     *
     * Refer to the protocol state diagram for further documentation.
     */
    /// Initial event state
    void evInitial();

    /// Detect state
    void evDetect();

    /// HelloAck detected state
    void evAckDetected();

    /// HelloAck sent state
    void evAckSent();

    /// Wait for Commit message
    void evWaitCommit();

    /// Commit sent state
    void evCommitSent();

    /// Wait for DHPart2 message
    void evWaitDHPart2();

    /// Wait for Confirm2 message
    void evWaitConfirm1();

    /// Wait for Confirm2 message
    void evWaitConfirm2();

    /// Wait for ConfAck message
    void evWaitConfAck();

    /// Wait for ClearAck message (not used)
    void evWaitClearAck();

    /// Secure reached state
    void evSecureState();

    /// Wait for ErrorAck message
    void evWaitErrorAck();

    /**
     * Initialize and activate a timer.
     *
     * @param t
     *    The ZRTP timer structure to use for the timer.
     * @return
     *    1 timer was activated
     *    0 activation failed
     */
    int32_t startTimer(zrtpTimer_t *t);

    /**
     * Compute and set the next timeout value.
     *
     * @param t
     *    The ZRTP timer structure to use for the timer.
     * @return
     *    1 timer was activated
     *    0 activation failed
     *   -1 resend counter exceeded
     */
    int32_t nextTimer(zrtpTimer_t *t);

    /**
     * Cancel the active timer.
     *
     * @return
     *    1 timer was canceled
     *    0 cancelation failed
     */
    int32_t cancelTimer() {return parent->cancelTimer(); };

    /**
     * Prepare and send an Error packet.
     *
     * Preparse an Error packet and sends it. It stores the Error
     * packet in the sentPacket variable to enable resending. The
     * method switches to protocol state Initial.
     */
    void sendErrorPacket(uint32_t errorCode);

    /**
     * Set status if an error occured while sending a ZRTP packet.
     *
     * This functions clears data and set the state to Initial after the engine
     * detected a problem while sending a ZRTP packet.
     *
     * @return
     *    Fail code
     */
    void sendFailed();

    /**
     * Set status if a timer problems occure.
     *
     * This functions clears data and set state to Initial after a timer
     * error occured. Either no timer available or resend counter exceedeed.
     *
     * @return
     *    Fail code
     */
    void timerFailed(int32_t subCode);

    /**
     * Set multi-stream mode flag.
     *
     * This functions set the multi-stream mode. The protocol
     * engine will run the multi-stream mode variant of the ZRTP
     * protocol if this flag is set to true.
     *
     * @param multi
     *    Set the multi-stream mode flag to true or false.
     */
    void setMultiStream(bool multi);

    /**
     * Status of multi-stream mode flag.
     *
     * This functions returns the value of the multi-stream mode flag.
     *
     * @return
     *    Value of the multi-stream mode flag.
     */
    bool isMultiStream();

    /**
     * Send a SAS relay packet.
     *
     * the functions stores sends the SAS relay packet and stores the pointer in
     * the sentPacket variable to enable resending.
     *
     * The method switches to secure substate WaitSasRelayAck.
     * 
     * @param relay
     *    Pointer to the SAS relay packet.
     */
    void sendSASRelay(ZrtpPacketSASrelay* relay);
};

/**
 * @}
 */
#endif // _ZRTPSTATECLASS_H_