1 /*
2 Copyright (C) 2004-2006 the Minisip Team
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 /* Copyright (C) 2004-2012
20 *
21 * Authors: Israel Abad <i_abad@terra.es>
22 * Erik Eliasson <eliasson@it.kth.se>
23 * Johan Bilien <jobi@via.ecp.fr>
24 * Joachim Orrblad <joachim@orrblad.com>
25 * Werner Dittmann <Werner.Dittmann@t-online.de>
26 */
27
28 #include <iostream>
29
30 #include <ccrtp-config.h>
31
32 #ifdef SRTP_SUPPORT
35 #endif
36
37 #include <commoncpp/config.h>
38 #include <commoncpp/export.h>
40
41 NAMESPACE_COMMONCPP
42
44 ssrcCtx(ssrc),
45 using_mki(false),mkiLength(0),mki(NULL),
46 roc(0),guessed_roc(0),s_l(0),key_deriv_rate(0),
47 replay_window(0),
48 master_key(NULL), master_key_length(0),
49 master_key_srtp_use_nb(0), master_key_srtcp_use_nb(0),
50 master_salt(NULL), master_salt_length(0),
51 n_e(0),k_e(NULL),n_a(0),k_a(NULL),n_s(0),k_s(NULL),
53 ekeyl(0), akeyl(0), skeyl(0),
54 seqNumSet(false), macCtx(NULL), cipher(NULL), f8Cipher(NULL)
55 {}
56
57 #ifdef SRTP_SUPPORT
59 int32 roc,
60 int64 key_deriv_rate,
61 const int32 ealg,
62 const int32 aalg,
63 uint8* master_key,
64 int32 master_key_length,
65 uint8* master_salt,
66 int32 master_salt_length,
67 int32 ekeyl,
68 int32 akeyl,
69 int32 skeyl,
70 int32 tagLength):
71
72 ssrcCtx(ssrc),using_mki(false),mkiLength(0),mki(NULL),
73 roc(roc),guessed_roc(0),s_l(0),key_deriv_rate(key_deriv_rate),
74 replay_window(0),
75 master_key_srtp_use_nb(0), master_key_srtcp_use_nb(0), seqNumSet(false),
76 macCtx(NULL), cipher(NULL), f8Cipher(NULL)
77 {
83
86 memcpy(this->master_key, master_key, master_key_length);
87
90 memcpy(this->master_salt, master_salt, master_salt_length);
91
92 switch( ealg ) {
98 break;
99
102
109 break;
110
113
120 break;
121 }
122
123 switch( aalg ) {
127 this->tagLength = 0;
128 break;
129
135 break;
136 }
137 }
138
139 #endif
140
142
143 #ifdef SRTP_SUPPORT
146
147 if (master_key_length > 0) {
148 memset(master_key, 0, master_key_length);
149 master_key_length = 0;
151 }
152 if (master_salt_length > 0) {
153 memset(master_salt, 0, master_salt_length);
154 master_salt_length = 0;
156 }
161 }
166 }
171 }
175 }
179 }
181 switch(aalg) {
184 break;
185
188 break;
189 }
190 }
191 #endif
192
195 }
196
198 {
200 return;
201 }
202 #ifdef SRTP_SUPPORT
204
205 /* Compute the CM IV (refer to chapter 4.1.1 in RFC 3711):
206 *
207 * k_s XX XX XX XX XX XX XX XX XX XX XX XX XX XX
208 * SSRC XX XX XX XX
209 * index XX XX XX XX XX XX
210 * ------------------------------------------------------XOR
211 * IV XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
212 */
213
214 unsigned char iv[16];
215 memcpy( iv,
k_s, 4 );
216
217 int i;
218 for(i = 4; i < 8; i++ ){
219 iv[i] = ( 0xFF & ( ssrc >> ((7-i)*8) ) ) ^
k_s[i];
220 }
221 for(i = 8; i < 14; i++ ){
222 iv[i] = ( 0xFF & (
unsigned char)( index >> ((13-i)*8) ) ) ^
k_s[i];
223 }
224 iv[14] = iv[15] = 0;
225
229 }
230
232
233 /* Create the F8 IV (refer to chapter 4.1.2.2 in RFC 3711):
234 *
235 * IV = 0x00 || M || PT || SEQ || TS || SSRC || ROC
236 * 8Bit 1bit 7bit 16bit 32bit 32bit 32bit
237 * ------------\ /--------------------------------------------------
238 * XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
239 */
240
241 unsigned char iv[16];
242 uint32 *ui32p = (uint32 *)iv;
243
245 iv[0] = 0;
246
247 // set ROC in network order into IV
248 ui32p[3] = htonl(roc);
249
252 }
253 #endif
254 }
255
256 /* Warning: tag must have been initialized */
258 {
260 return;
261 }
262 #ifdef SRTP_SUPPORT
263 int32_t macL;
264
265 unsigned char temp[20];
266 const unsigned char* chunks[3];
267 unsigned int chunkLength[3];
268 uint32_t beRoc = htonl(roc);
269
272
273 chunks[1] = (unsigned char *)&beRoc;
274 chunkLength[1] = 4;
275 chunks[2] = NULL;
276
277 switch (aalg) {
280 chunks, // data chunks to hash
281 chunkLength, // length of the data to hash
282 temp, &macL);
283 /* truncate the result */
285 break;
288 chunks, // data chunks to hash
289 chunkLength, // length of the data to hash
290 temp);
291 /* truncate the result */
293 break;
294 }
295 #endif
296 }
297
298 #ifdef SRTP_SUPPORT
299 /* used by the key derivation method */
300 static void computeIv(unsigned char* iv, uint64 label, uint64 index,
301 int64 kdv, unsigned char* master_salt)
302 {
303
304 uint64 key_id;
305
306 if (kdv == 0) {
307 key_id = label << 48;
308 }
309 else {
310 key_id = ((label << 48) | (index / kdv));
311 }
312
313 //printf( "Key_ID: %llx\n", key_id );
314
315 /* compute the IV
316 key_id: XX XX XX XX XX XX XX
317 master_salt: XX XX XX XX XX XX XX XX XX XX XX XX XX XX
318 ------------------------------------------------------------ XOR
319 IV: XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
320 */
321
322 int i;
323 for(i = 0; i < 7 ; i++ ) {
324 iv[i] = master_salt[i];
325 }
326
327 for(i = 7; i < 14 ; i++ ) {
328 iv[i] = (unsigned char)(0xFF & (key_id >> (8*(13-i)))) ^
329 master_salt[i];
330 }
331
332 iv[14] = iv[15] = 0;
333 }
334 #endif
335
336 /* Derives the srtp session keys from the master key */
338 {
339 #ifdef SRTP_SUPPORT
340 uint8 iv[16];
341
342 // prepare AES cipher to compute derived keys.
343 cipher->setNewKey(master_key, master_key_length);
344 memset(master_key, 0, master_key_length);
345
346 // compute the session encryption key
347 uint64 label = 0;
348 computeIv(iv, label, index, key_deriv_rate, master_salt);
350
351 // compute the session authentication key
352 label = 0x01;
353 computeIv(iv, label, index, key_deriv_rate, master_salt);
355
356 // Initialize MAC context with the derived key
357 switch (aalg) {
360 break;
362 // Skein MAC uses number of bits as MAC size, not just bytes
364 break;
365 }
367
368 // compute the session salt
369 label = 0x02;
370 computeIv(iv, label, index, key_deriv_rate, master_salt);
372 memset(master_salt, 0, master_salt_length);
373
374 // as last step prepare ciphers with derived key.
379
380 #endif
381 }
382
383 /* Based on the algorithm provided in Appendix A - draft-ietf-srtp-05.txt */
385 {
386 /*
387 * Initialize the sequences number on first call that uses the
388 * sequence number. Either GuessIndex() or checkReplay().
389 */
393 }
395 if (new_seq_nb -
s_l > 32768) {
397 }
398 else {
400 }
401 }
402 else {
403 if (
s_l - 32768 > new_seq_nb) {
405 }
406 else {
408 }
409 }
410
412 }
413
415 {
416 #ifdef SRTP_SUPPORT
418 /* No security policy, don't use the replay protection */
419 return true;
420 }
421
422 /*
423 * Initialize the sequences number on first call that uses the
424 * sequence number. Either guessIndex() or checkReplay().
425 */
429 }
430 uint64 guessed_index =
guessIndex( new_seq_nb );
431 uint64 local_index = (((uint64_t)roc) << 16) |
s_l;
432
433 int64 delta = guessed_index - local_index;
434 if (delta > 0) {
435 /* Packet not yet received*/
436 return true;
437 }
438 else {
440 /* Packet too old */
441 return false;
442 }
443 else {
445 /* Packet already received ! */
446 return false;
447 }
448 else {
449 /* Packet not yet received */
450 return true;
451 }
452 }
453 }
454 #else
455 return true;
456 #endif
457 }
458
460 {
461 #ifdef SRTP_SUPPORT
462 int64 delta =
guessIndex(new_seq_nb) - (((uint64)roc) << 16 |
s_l );
463
464 /* update the replay bitmask */
465 if( delta > 0 ){
468 }
469 else {
471 }
472
473 /* update the locally stored ROC and highest sequence number */
474 if( new_seq_nb >
s_l ) {
476 }
480 }
481 #endif
482 }
483
485 {
486 #ifdef SRTP_SUPPORT
488 ssrc,
489 roc, // Roll over Counter,
490 keyDerivRate, // keyderivation << 48,
491 this->ealg, // encryption algo
492 this->aalg, // authentication algo
493 this->master_key, // Master Key
494 this->master_key_length, // Master Key length
495 this->master_salt, // Master Salt
496 this->master_salt_length, // Master Salt length
497 this->ekeyl, // encryption keyl
498 this->akeyl, // authentication key len
499 this->skeyl, // session salt len
500 this->tagLength); // authentication tag len
501
502 return pcc;
503 #else
504 return NULL;
505 #endif
506 }
507
508 END_NAMESPACE
509
Implments the SRTP encryption modes as defined in RFC3711.
bool isPadded() const
Ask whether the packet contains padding bytes at the end.
A base class for both IncomingRTPPkt and OutgoingRTPPkt.
void srtpAuthenticate(RTPPacket *rtp, uint32 roc, uint8 *tag)
Compute the authentication tag.
#define REPLAY_WINDOW_SIZE
The implementation for a SRTP cryptographic context.
void hmacSha1Ctx(void *ctx, const uint8_t *data, uint32_t data_length, uint8_t *mac, int32_t *mac_length)
Compute SHA1 HMAC.
const int SrtpEncryptionAESF8
void * createSha1HmacContext(uint8_t *key, int32_t key_length)
Create and initialize a SHA1 HMAC context.
void macSkeinCtx(void *ctx, const uint8_t *data, uint32_t data_length, uint8_t *mac)
Compute Skein MAC.
void freeSkeinMacContext(void *ctx)
Free Skein MAC context.
void freeSha1HmacContext(void *ctx)
Free SHA1 HMAC context.
void * createSkeinMacContext(uint8_t *key, int32_t key_length, int32_t mac_length, SkeinSize_t skeinSize)
Create and initialize a Skein MAC context.
const int SrtpEncryptionTWOF8
Functions to compute SHA1 HAMAC.
bool checkReplay(uint16 newSeqNumber)
Check for packet replay.
void srtpEncrypt(RTPPacket *rtp, uint64 index, uint32 ssrc)
Perform SRTP encryption.
const uint8 *const getPayload() const
~CryptoContext()
Destructor.
uint32 master_salt_length
const int SrtpEncryptionTWOCM
CryptoContext * newCryptoContextForSSRC(uint32 ssrc, int roc, int64 keyDerivRate)
Derive a new Crypto Context for use with a new SSRC.
Function that provide Skein MAC support.
uint32 getRawPacketSize() const
Get the raw packet length, including header, extension, payload and padding.
const int SrtpAuthenticationSkeinHmac
const unsigned char *const getRawPacket() const
Get the raw packet as it will be sent through the network.
uint8 getPaddingSize() const
Get the number of octets padding the end of the payload section.
CryptoContext(uint32 ssrc)
Constructor for empty SRTP cryptographic context.
void update(uint16 newSeqNumber)
Update the SRTP packet index.
uint32 getPayloadSize() const
const int SrtpEncryptionNull
int32 getTagLength() const
Get the length of the SRTP authentication tag in bytes.
const int SrtpAuthenticationSha1Hmac
void deriveSrtpKeys(uint64 index)
Perform key derivation according to SRTP specification.
uint64 guessIndex(uint16 newSeqNumber)
Compute (guess) the new SRTP index based on the sequence number of a received RTP packet...
const int SrtpAuthenticationNull
const int SrtpEncryptionAESCM