summaryrefslogtreecommitdiff
path: root/src/libzrtpcpp/ZIDRecord.h
blob: eb2d190dcc6e87fde264a2c8285076cd7142800c (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
/*
  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 _ZIDRECORD_H_
#define _ZIDRECORD_H_


/**
 * @file ZIDRecord.h
 * @brief ZID record management
 *
 * A ZID record stores (caches) ZID (ZRTP ID) specific data that helps ZRTP
 * to achives its key continuity feature. Please refer to the ZRTP
 * specification to get detailed information about the ZID.
 *
 * @ingroup GNU_ZRTP
 * @{
 */

#include <string.h>
#include <stdint.h>

#define IDENTIFIER_LEN  12
#define RS_LENGTH       32
#define TIME_LENGTH      8      // 64 bit, can hold time on 64 bit systems

/**
 * This is the recod structure of version 1 ZID records.
 *
 * This is not longer in use - only during migration.
 */
typedef struct zidrecord1 {
    char recValid;  //!< if 1 record is valid, if 0: invalid
    char ownZid;    //!< if >1 record contains own ZID, usually 1st record
    char rs1Valid;  //!< if 1 RS1 contains valid data
    char rs2Valid;  //!< if 1 RS2 contains valid data
    unsigned char identifier[IDENTIFIER_LEN]; ///< the peer's ZID or own ZID
    unsigned char rs1Data[RS_LENGTH], rs2Data[RS_LENGTH]; ///< the peer's RS data
} zidrecord1_t;

/**
 * This is the recod structure of version 2 ZID records.
 */
typedef struct zidrecord2 {
    char version;   ///< version number of file format, this is #2
    char flags;     ///< bit field holding various flags, see below
    char filler1;   ///< round up to next 32 bit
    char filler2;   ///< round up to next 32 bit
    unsigned char identifier[IDENTIFIER_LEN]; ///< the peer's ZID or own ZID
    unsigned char rs1Interval[TIME_LENGTH];   ///< expiration time of RS1; -1 means indefinite
    unsigned char rs1Data[RS_LENGTH];         ///< the peer's RS2 data
    unsigned char rs2Interval[TIME_LENGTH];   ///< expiration time of RS2; -1 means indefinite
    unsigned char rs2Data[RS_LENGTH];         ///< the peer's RS2 data
    unsigned char mitmKey[RS_LENGTH];         ///< MiTM key if available
} zidrecord2_t;


#ifndef __EXPORT
  #if __GNUC__ >= 4
    #define __EXPORT    __attribute__ ((visibility("default")))
    #define __LOCAL     __attribute__ ((visibility("hidden")))
  #elif defined _WIN32 || defined __CYGWIN__
    #define __EXPORT    __declspec(dllimport)
    #define __LOCAL
  #else
    #define __EXPORT
    #define __LOCAL
  #endif
#endif

static const int Valid            = 0x1;
static const int SASVerified      = 0x2;
static const int RS1Valid         = 0x4;
static const int RS2Valid         = 0x8;
static const int MITMKeyAvailable = 0x10;
static const int OwnZIDRecord     = 0x20;

/**
 * This class implements the ZID record.
 *
 * The ZID record holds data about a peer. According to ZRTP specification
 * we use a ZID to identify a peer. ZRTP uses the RS (Retained Secret) data
 * to construct shared secrets.
 * <p>
 * NOTE: ZIDRecord has ZIDFile as friend. ZIDFile knows about the private
 *   data of ZIDRecord - please keep both classes synchronized.
 *
 * @author: Werner Dittmann <Werner.Dittmann@t-online.de>
 */
class __EXPORT ZIDRecord {
    friend class ZIDFile;

private:
    zidrecord2_t record;
    unsigned long position;

    /*
     * The default constructor is private
     */
    ZIDRecord() {
    record.version = 2;
    }

    /**
     * Functions for I/O availabe for ZID file handling
     *
     * These functions are private, thus only friends may use it.
     */
    void setPosition(long pos) {position = pos;}
    long getPosition()         {return position; }

    zidrecord2_t* getRecordData() {return &record; }
    int getRecordLength()         {return sizeof(zidrecord2_t); }

    bool isValid()    { return ((record.flags & Valid) == Valid); }
    void setValid()   { record.flags |= Valid; }

public:
    /**
     * Create a ZID Record with given ZID data
     *
     * The method creates a new ZID record and initializes its ZID
     * data field. All other fields are set to null.
     *
     * An application can use this pre-initialized record to look
     * up the associated record in the ZID file. If the record is
     * available, the ZID record fields are filled with the stored
     * data.
     *
     * @param idData
     *     Pointer to the fixed length ZID data
     * @see ZIDFile::getRecord
     */
    ZIDRecord(const unsigned char *idData) {
    memset(&record, 0, sizeof(zidrecord2_t));
    memcpy(record.identifier, idData, IDENTIFIER_LEN);
    record.version = 2;
    }

    /**
     * Set @c valid flag in RS1
     */
    void setRs1Valid()   { record.flags |= RS1Valid; }

    /**
     * reset @c valid flag in RS1
     */
    void resetRs1Valid() { record.flags &= ~RS1Valid; }

    /**
     * Check @c valid flag in RS1
     */
    bool isRs1Valid()    { return ((record.flags & RS1Valid) == RS1Valid); }

    /**
     * Set @c valid flag in RS2
     */
    void setRs2Valid()   { record.flags |= RS2Valid; }

    /**
     * Reset @c valid flag in RS2
     */
    void resetRs2Valid() { record.flags &= ~RS2Valid; }

    /**
     * Check @c valid flag in RS2
     */
    bool isRs2Valid()    { return ((record.flags & RS2Valid) == RS2Valid); }

    /**
     * Set MITM key available
     */
    void setMITMKeyAvailable()    { record.flags |= MITMKeyAvailable; }

    /**
     * Reset MITM key available
     */
    void resetMITMKeyAvailable()  { record.flags &= ~MITMKeyAvailable; }

    /**
     * Check MITM key available is set
     */
    bool isMITMKeyAvailable()     { return ((record.flags & MITMKeyAvailable) == MITMKeyAvailable); }

    /**
     * Mark this as own ZID record
     */
    void setOwnZIDRecord()  { record.flags = OwnZIDRecord; }
    /**
     * Reset own ZID record marker
     */
    void resetOwnZIDRecord(){ record.flags = 0; }

    /**
     * Check own ZID record marker
     */
    bool isOwnZIDRecord()   { return (record.flags == OwnZIDRecord); }  // no other flag allowed if own ZID

    /**
     * Set SAS for this ZID as verified
     */
    void setSasVerified()   { record.flags |= SASVerified; }
    /**
     * Reset SAS for this ZID as verified
     */
    void resetSasVerified() { record.flags &= ~SASVerified; }

    /**
     * Check if SAS for this ZID was verified
     */
    bool isSasVerified()    { return ((record.flags & SASVerified) == SASVerified); }

    /**
     * Return the ZID for this record
     */
    const uint8_t* getIdentifier() {return record.identifier; }

    /**
     * Check if RS1 is still valid
     *
     * Returns true if RS1 is still valid, false otherwise.
     *
     * @return
     *    Returns true is RS1 is not expired (valid), false otherwise.
     */
    const bool isRs1NotExpired();

    /**
     * Returns pointer to RS1 data.
     */
    const unsigned char* getRs1() { return record.rs1Data; }

    /**
     * Check if RS2 is still valid
     *
     * Returns true if RS2 is still valid, false otherwise.
     *
     * @return
     *    Returns true is RS2 is not expired (valid), false otherwise.
     */
    const bool isRs2NotExpired();

    /**
     * Returns pointer to RS1 data.
     */
    const unsigned char* getRs2() { return record.rs2Data; }

    /**
     * Sets new RS1 data and associated expiration value.
     *
     * If the expiration value is >0 or -1 the method stores the new
     * RS1. Before it stores the new RS1 it shifts the exiting RS1
     * into RS2 (together with its expiration time). Then it computes
     * the expiration time of the and stores the result together with
     * the new RS1.
     *
     * If the expiration value is -1 then this RS will never expire.
     *
     * If the expiration value is 0 then the expiration value of a
     * stored RS1 is cleared and no new RS1 value is stored. Also RS2
     * is left unchanged.
     *
     * @param data
     *    Points to the new RS1 data.
     * @param expire
     *    The expiration interval in seconds. Default is -1.
     *
     */
    void setNewRs1(const unsigned char* data, int32_t expire =-1);

    /**
     * Set MiTM key data.
     *
     */
    void setMiTMData(const unsigned char* data);

    /**
     * Get MiTM key data.
     *
     */
    const unsigned char* getMiTMData() {return record.mitmKey; }
};

#endif // ZIDRECORD


/** EMACS **
 * Local variables:
 * mode: c++
 * c-default-style: ellemtel
 * c-basic-offset: 4
 * End:
 */