blob: 8e9bbc6c7fcd08f656afd67c50ee36587c974402 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001/*
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
33#include <ccrtp/crypto/hmac.h>
34#include <ccrtp/crypto/macSkein.h>
35#endif
36
37#include <commoncpp/config.h>
38#include <commoncpp/export.h>
39#include <ccrtp/CryptoContext.h>
40
41NAMESPACE_COMMONCPP
42
43CryptoContext::CryptoContext( uint32 ssrc ):
44ssrcCtx(ssrc),
45using_mki(false),mkiLength(0),mki(NULL),
46roc(0),guessed_roc(0),s_l(0),key_deriv_rate(0),
47replay_window(0),
48master_key(NULL), master_key_length(0),
49master_key_srtp_use_nb(0), master_key_srtcp_use_nb(0),
50master_salt(NULL), master_salt_length(0),
51n_e(0),k_e(NULL),n_a(0),k_a(NULL),n_s(0),k_s(NULL),
52ealg(SrtpEncryptionNull), aalg(SrtpAuthenticationNull),
53ekeyl(0), akeyl(0), skeyl(0),
54seqNumSet(false), macCtx(NULL), cipher(NULL), f8Cipher(NULL)
55{}
56
57#ifdef SRTP_SUPPORT
58CryptoContext::CryptoContext( uint32 ssrc,
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
72ssrcCtx(ssrc),using_mki(false),mkiLength(0),mki(NULL),
73roc(roc),guessed_roc(0),s_l(0),key_deriv_rate(key_deriv_rate),
74replay_window(0),
75master_key_srtp_use_nb(0), master_key_srtcp_use_nb(0), seqNumSet(false),
76macCtx(NULL), cipher(NULL), f8Cipher(NULL)
77{
78 this->ealg = ealg;
79 this->aalg = aalg;
80 this->ekeyl = ekeyl;
81 this->akeyl = akeyl;
82 this->skeyl = skeyl;
83
84 this->master_key_length = master_key_length;
85 this->master_key = new uint8[master_key_length];
86 memcpy(this->master_key, master_key, master_key_length);
87
88 this->master_salt_length = master_salt_length;
89 this->master_salt = new uint8[master_salt_length];
90 memcpy(this->master_salt, master_salt, master_salt_length);
91
92 switch( ealg ) {
93 case SrtpEncryptionNull:
94 n_e = 0;
95 k_e = NULL;
96 n_s = 0;
97 k_s = NULL;
98 break;
99
100 case SrtpEncryptionTWOF8:
101 f8Cipher = new SrtpSymCrypto(SrtpEncryptionTWOF8);
102
103 case SrtpEncryptionTWOCM:
104 n_e = ekeyl;
105 k_e = new uint8[n_e];
106 n_s = skeyl;
107 k_s = new uint8[n_s];
108 cipher = new SrtpSymCrypto(SrtpEncryptionTWOCM);
109 break;
110
111 case SrtpEncryptionAESF8:
112 f8Cipher = new SrtpSymCrypto(SrtpEncryptionAESF8);
113
114 case SrtpEncryptionAESCM:
115 n_e = ekeyl;
116 k_e = new uint8[n_e];
117 n_s = skeyl;
118 k_s = new uint8[n_s];
119 cipher = new SrtpSymCrypto(SrtpEncryptionAESCM);
120 break;
121 }
122
123 switch( aalg ) {
124 case SrtpAuthenticationNull:
125 n_a = 0;
126 k_a = NULL;
127 this->tagLength = 0;
128 break;
129
130 case SrtpAuthenticationSha1Hmac:
131 case SrtpAuthenticationSkeinHmac:
132 n_a = akeyl;
133 k_a = new uint8[n_a];
134 this->tagLength = tagLength;
135 break;
136 }
137}
138
139#endif
140
141CryptoContext::~CryptoContext(){
142
143#ifdef SRTP_SUPPORT
144 if (mki)
145 delete [] mki;
146
147 if (master_key_length > 0) {
148 memset(master_key, 0, master_key_length);
149 master_key_length = 0;
150 delete [] master_key;
151 }
152 if (master_salt_length > 0) {
153 memset(master_salt, 0, master_salt_length);
154 master_salt_length = 0;
155 delete [] master_salt;
156 }
157 if (n_e > 0) {
158 memset(k_e, 0, n_e);
159 n_e = 0;
160 delete [] k_e;
161 }
162 if (n_s > 0) {
163 memset(k_s, 0, n_s);
164 n_s = 0;
165 delete [] k_s;
166 }
167 if (n_a > 0) {
168 memset(k_a, 0, n_a);
169 n_a = 0;
170 delete [] k_a;
171 }
172 if (cipher != NULL) {
173 delete cipher;
174 cipher = NULL;
175 }
176 if (f8Cipher != NULL) {
177 delete f8Cipher;
178 f8Cipher = NULL;
179 }
180 if (macCtx != NULL) {
181 switch(aalg) {
182 case SrtpAuthenticationSha1Hmac:
183 freeSha1HmacContext(macCtx);
184 break;
185
186 case SrtpAuthenticationSkeinHmac:
187 freeSkeinMacContext(macCtx);
188 break;
189 }
190 }
191#endif
192
193 ealg = SrtpEncryptionNull;
194 aalg = SrtpAuthenticationNull;
195}
196
197void CryptoContext::srtpEncrypt(RTPPacket* rtp, uint64 index, uint32 ssrc)
198{
199 if (ealg == SrtpEncryptionNull) {
200 return;
201 }
202#ifdef SRTP_SUPPORT
203 if (ealg == SrtpEncryptionAESCM || ealg == SrtpEncryptionTWOCM) {
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
226 int32 pad = rtp->isPadded() ? rtp->getPaddingSize() : 0;
227 cipher->ctr_encrypt(const_cast<uint8*>(rtp->getPayload()),
228 rtp->getPayloadSize()+pad, iv);
229 }
230
231 if (ealg == SrtpEncryptionAESF8 || ealg == SrtpEncryptionTWOF8) {
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
244 memcpy(iv, rtp->getRawPacket(), 12);
245 iv[0] = 0;
246
247 // set ROC in network order into IV
248 ui32p[3] = htonl(roc);
249
250 int32 pad = rtp->isPadded() ? rtp->getPaddingSize() : 0;
251 cipher->f8_encrypt(rtp->getPayload(), rtp->getPayloadSize()+pad, iv, f8Cipher);
252 }
253#endif
254}
255
256/* Warning: tag must have been initialized */
257void CryptoContext::srtpAuthenticate(RTPPacket* rtp, uint32 roc, uint8* tag )
258{
259 if (aalg == SrtpAuthenticationNull) {
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
270 chunks[0] = rtp->getRawPacket();
271 chunkLength[0] = rtp->getRawPacketSize();
272
273 chunks[1] = (unsigned char *)&beRoc;
274 chunkLength[1] = 4;
275 chunks[2] = NULL;
276
277 switch (aalg) {
278 case SrtpAuthenticationSha1Hmac:
279 hmacSha1Ctx(macCtx,
280 chunks, // data chunks to hash
281 chunkLength, // length of the data to hash
282 temp, &macL);
283 /* truncate the result */
284 memcpy(tag, temp, getTagLength());
285 break;
286 case SrtpAuthenticationSkeinHmac:
287 macSkeinCtx(macCtx,
288 chunks, // data chunks to hash
289 chunkLength, // length of the data to hash
290 temp);
291 /* truncate the result */
292 memcpy(tag, temp, getTagLength());
293 break;
294 }
295#endif
296}
297
298#ifdef SRTP_SUPPORT
299/* used by the key derivation method */
300static 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 */
337void CryptoContext::deriveSrtpKeys(uint64 index)
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);
349 cipher->get_ctr_cipher_stream(k_e, n_e, iv);
350
351 // compute the session authentication key
352 label = 0x01;
353 computeIv(iv, label, index, key_deriv_rate, master_salt);
354 cipher->get_ctr_cipher_stream(k_a, n_a, iv);
355
356 // Initialize MAC context with the derived key
357 switch (aalg) {
358 case SrtpAuthenticationSha1Hmac:
359 macCtx = createSha1HmacContext(k_a, n_a);
360 break;
361 case SrtpAuthenticationSkeinHmac:
362 // Skein MAC uses number of bits as MAC size, not just bytes
363 macCtx = createSkeinMacContext(k_a, n_a, tagLength*8, Skein512);
364 break;
365 }
366 memset(k_a, 0, n_a);
367
368 // compute the session salt
369 label = 0x02;
370 computeIv(iv, label, index, key_deriv_rate, master_salt);
371 cipher->get_ctr_cipher_stream(k_s, n_s, iv);
372 memset(master_salt, 0, master_salt_length);
373
374 // as last step prepare ciphers with derived key.
375 cipher->setNewKey(k_e, n_e);
376 if (f8Cipher != NULL)
377 cipher->f8_deriveForIV(f8Cipher, k_e, n_e, k_s, n_s);
378 memset(k_e, 0, n_e);
379
380#endif
381}
382
383/* Based on the algorithm provided in Appendix A - draft-ietf-srtp-05.txt */
384uint64_t CryptoContext::guessIndex(uint16 new_seq_nb )
385{
386 /*
387 * Initialize the sequences number on first call that uses the
388 * sequence number. Either GuessIndex() or checkReplay().
389 */
390 if (!seqNumSet) {
391 seqNumSet = true;
392 s_l = new_seq_nb;
393 }
394 if (s_l < 32768){
395 if (new_seq_nb - s_l > 32768) {
396 guessed_roc = roc - 1;
397 }
398 else {
399 guessed_roc = roc;
400 }
401 }
402 else {
403 if (s_l - 32768 > new_seq_nb) {
404 guessed_roc = roc + 1;
405 }
406 else {
407 guessed_roc = roc;
408 }
409 }
410
411 return ((uint64)guessed_roc) << 16 | new_seq_nb;
412}
413
414bool CryptoContext::checkReplay( uint16 new_seq_nb )
415{
416#ifdef SRTP_SUPPORT
417 if ( aalg == SrtpAuthenticationNull && ealg == SrtpEncryptionNull ) {
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 */
426 if (!seqNumSet) {
427 seqNumSet = true;
428 s_l = new_seq_nb;
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 {
439 if( -delta > REPLAY_WINDOW_SIZE ) {
440 /* Packet too old */
441 return false;
442 }
443 else {
444 if((replay_window >> (-delta)) & 0x1) {
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
459void CryptoContext::update(uint16 new_seq_nb)
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 ){
466 replay_window = replay_window << delta;
467 replay_window |= 1;
468 }
469 else {
470 replay_window |= ( 1 << delta );
471 }
472
473 /* update the locally stored ROC and highest sequence number */
474 if( new_seq_nb > s_l ) {
475 s_l = new_seq_nb;
476 }
477 if( guessed_roc > roc ) {
478 roc = guessed_roc;
479 s_l = new_seq_nb;
480 }
481#endif
482}
483
484CryptoContext* CryptoContext::newCryptoContextForSSRC(uint32 ssrc, int roc, int64 keyDerivRate)
485{
486#ifdef SRTP_SUPPORT
487 CryptoContext* pcc = new CryptoContext(
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
508END_NAMESPACE
509
510/** EMACS **
511 * Local variables:
512 * mode: c++
513 * c-default-style: ellemtel
514 * c-basic-offset: 4
515 * End:
516 */
517