ccRTP 2.1.2
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CryptoContextCtrl.cpp
Go to the documentation of this file.
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
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>
40 #include <ccrtp/base.h>
41 
42 NAMESPACE_COMMONCPP
43 
45 ssrcCtx(ssrc),
46 using_mki(false),mkiLength(0),mki(NULL), s_l(0),
47 replay_window(0),
48 master_key(NULL), master_key_length(0),
49 master_salt(NULL), master_salt_length(0),
50 n_e(0),k_e(NULL),n_a(0),k_a(NULL),n_s(0),k_s(NULL),
52 ekeyl(0), akeyl(0), skeyl(0),
53 macCtx(NULL), cipher(NULL), f8Cipher(NULL)
54 {}
55 
56 #ifdef SRTP_SUPPORT
58  const int32 ealg,
59  const int32 aalg,
60  uint8* master_key,
61  int32 master_key_length,
62  uint8* master_salt,
63  int32 master_salt_length,
64  int32 ekeyl,
65  int32 akeyl,
66  int32 skeyl,
67  int32 tagLength):
68 
69 ssrcCtx(ssrc),using_mki(false),mkiLength(0),mki(NULL),
70 replay_window(0), macCtx(NULL), cipher(NULL), f8Cipher(NULL)
71 {
72  this->ealg = ealg;
73  this->aalg = aalg;
74  this->ekeyl = ekeyl;
75  this->akeyl = akeyl;
76  this->skeyl = skeyl;
77 
78  this->master_key_length = master_key_length;
79  this->master_key = new uint8[master_key_length];
80  memcpy(this->master_key, master_key, master_key_length);
81 
82  this->master_salt_length = master_salt_length;
83  this->master_salt = new uint8[master_salt_length];
84  memcpy(this->master_salt, master_salt, master_salt_length);
85 
86  switch( ealg ) {
87  case SrtpEncryptionNull:
88  n_e = 0;
89  k_e = NULL;
90  n_s = 0;
91  k_s = NULL;
92  break;
93 
96  // fall through
97 
99  n_e = ekeyl;
100  k_e = new uint8[n_e];
101  n_s = skeyl;
102  k_s = new uint8[n_s];
104  break;
105 
106  case SrtpEncryptionAESF8:
108  // fall through
109 
110  case SrtpEncryptionAESCM:
111  n_e = ekeyl;
112  k_e = new uint8[n_e];
113  n_s = skeyl;
114  k_s = new uint8[n_s];
116  break;
117  }
118 
119  switch( aalg ) {
121  n_a = 0;
122  k_a = NULL;
123  this->tagLength = 0;
124  break;
125 
128  n_a = akeyl;
129  k_a = new uint8[n_a];
130  this->tagLength = tagLength;
131  break;
132  }
133 }
134 
135 #endif
136 
138 
139 #ifdef SRTP_SUPPORT
140  if (mki)
141  delete [] mki;
142 
143  if (master_key_length > 0) {
144  memset(master_key, 0, master_key_length);
145  master_key_length = 0;
146  delete [] master_key;
147  }
148  if (master_salt_length > 0) {
149  memset(master_salt, 0, master_salt_length);
150  master_salt_length = 0;
151  delete [] master_salt;
152  }
153  if (n_e > 0) {
154  memset(k_e, 0, n_e);
155  n_e = 0;
156  delete [] k_e;
157  }
158  if (n_s > 0) {
159  memset(k_s, 0, n_s);
160  n_s = 0;
161  delete [] k_s;
162  }
163  if (n_a > 0) {
164  memset(k_a, 0, n_a);
165  n_a = 0;
166  delete [] k_a;
167  }
168  if (cipher != NULL) {
169  delete cipher;
170  cipher = NULL;
171  }
172  if (f8Cipher != NULL) {
173  delete f8Cipher;
174  f8Cipher = NULL;
175  }
176  if (macCtx != NULL) {
177  switch(aalg) {
180  break;
181 
184  break;
185  }
186  }
187 #endif
188 
189  ealg = SrtpEncryptionNull;
190  aalg = SrtpAuthenticationNull;
191 }
192 
193 void CryptoContextCtrl::srtcpEncrypt( uint8* rtp, size_t len, uint64 index, uint32 ssrc )
194 {
195  if (ealg == SrtpEncryptionNull) {
196  return;
197  }
198 #ifdef SRTP_SUPPORT
199  if (ealg == SrtpEncryptionAESCM || ealg == SrtpEncryptionTWOCM) {
200 
201  /* Compute the CM IV (refer to chapter 4.1.1 in RFC 3711):
202  *
203  * k_s XX XX XX XX XX XX XX XX XX XX XX XX XX XX
204  * SSRC XX XX XX XX
205  * index XX XX XX XX
206  * ------------------------------------------------------XOR
207  * IV XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
208  * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
209  */
210  unsigned char iv[16];
211 
212  iv[0] = k_s[0];
213  iv[1] = k_s[1];
214  iv[2] = k_s[2];
215  iv[3] = k_s[3];
216 
217  // The shifts transform the ssrc and index into network order
218  iv[4] = ((ssrc >> 24) & 0xff) ^ k_s[4];
219  iv[5] = ((ssrc >> 16) & 0xff) ^ k_s[5];
220  iv[6] = ((ssrc >> 8) & 0xff) ^ k_s[6];
221  iv[7] = (ssrc & 0xff) ^ k_s[7];
222 
223  iv[8] = k_s[8];
224  iv[9] = k_s[9];
225 
226  iv[10] = ((index >> 24) & 0xff) ^ k_s[10];
227  iv[11] = ((index >> 16) & 0xff) ^ k_s[11];
228  iv[12] = ((index >> 8) & 0xff) ^ k_s[12];
229  iv[13] = (index & 0xff) ^ k_s[13];
230 
231  iv[14] = iv[15] = 0;
232 
233  cipher->ctr_encrypt(rtp, len, iv);
234  }
235 
236  if (ealg == SrtpEncryptionAESF8 || ealg == SrtpEncryptionTWOF8) {
237 
238  unsigned char iv[16];
239 
240  // 4 bytes of the iv are zero
241  // the first byte of the RTP header is not used.
242  iv[0] = 0;
243  iv[1] = 0;
244  iv[2] = 0;
245  iv[3] = 0;
246 
247  // Need the encryption flag
248  index = index | 0x80000000;
249 
250  // set the index and the encrypt flag in network order into IV
251  iv[4] = index >> 24;
252  iv[5] = index >> 16;
253  iv[6] = index >> 8;
254  iv[7] = index;
255 
256  // The fixed header follows and fills the rest of the IV
257  memcpy(iv+8, rtp, 8);
258 
259  cipher->f8_encrypt(rtp, len, iv, f8Cipher);
260  }
261 #endif
262 }
263 
264 /* Warning: tag must have been initialized */
265 void CryptoContextCtrl::srtcpAuthenticate(uint8* rtp, size_t len, uint32 index, uint8* tag )
266 {
267  if (aalg == SrtpAuthenticationNull) {
268  return;
269  }
270 #ifdef SRTP_SUPPORT
271  int32_t macL;
272 
273  unsigned char temp[20];
274  const unsigned char* chunks[3];
275  unsigned int chunkLength[3];
276  uint32_t beIndex = htonl(index);
277 
278  chunks[0] = rtp;
279  chunkLength[0] = len;
280 
281  chunks[1] = (unsigned char *)&beIndex;
282  chunkLength[1] = 4;
283  chunks[2] = NULL;
284 
285  switch (aalg) {
288  chunks, // data chunks to hash
289  chunkLength, // length of the data to hash
290  temp, &macL);
291  /* truncate the result */
292  memcpy(tag, temp, getTagLength());
293  break;
296  chunks, // data chunks to hash
297  chunkLength, // length of the data to hash
298  temp);
299  /* truncate the result */
300  memcpy(tag, temp, getTagLength());
301  break;
302  }
303 #endif
304 }
305 
306 #ifdef SRTP_SUPPORT
307 /* used by the key derivation method */
308 static void computeIv(unsigned char* iv, uint8 label, uint8* master_salt)
309 {
310  //printf( "Key_ID: %llx\n", key_id );
311 
312  /* compute the IV
313  key_id: XX XX XX XX XX XX XX
314  master_salt: XX XX XX XX XX XX XX XX XX XX XX XX XX XX
315  ------------------------------------------------------------ XOR
316  IV: XX XX XX XX XX XX XX XX XX XX XX XX XX XX 00 00
317  */
318 
319  memcpy(iv, master_salt, 14);
320  iv[7] ^= label;
321 
322  iv[14] = iv[15] = 0;
323 }
324 #endif
325 
326 /* Derives the srtp session keys from the master key */
328 {
329 #ifdef SRTP_SUPPORT
330  uint8 iv[16];
331 
332  // prepare AES cipher to compute derived keys.
333  cipher->setNewKey(master_key, master_key_length);
334  memset(master_key, 0, master_key_length);
335 
336  // compute the session encryption key
337  uint8 label = 3;
338  computeIv(iv, label, master_salt);
339  cipher->get_ctr_cipher_stream(k_e, n_e, iv);
340 
341  // compute the session authentication key
342  label = 4;
343  computeIv(iv, label, master_salt);
344  cipher->get_ctr_cipher_stream(k_a, n_a, iv);
345 
346  // Initialize MAC context with the derived key
347  switch (aalg) {
350  break;
352  // Skein MAC uses number of bits as MAC size, not just bytes
353  macCtx = createSkeinMacContext(k_a, n_a, tagLength*8, Skein512);
354  break;
355  }
356  memset(k_a, 0, n_a);
357 
358  // compute the session salt
359  label = 5;
360  computeIv(iv, label, master_salt);
361  cipher->get_ctr_cipher_stream(k_s, n_s, iv);
362  memset(master_salt, 0, master_salt_length);
363 
364  // as last step prepare ciphers with derived key.
365  cipher->setNewKey(k_e, n_e);
366  if (f8Cipher != NULL)
367  cipher->f8_deriveForIV(f8Cipher, k_e, n_e, k_s, n_s);
368  memset(k_e, 0, n_e);
369 #endif
370 }
371 
372 bool CryptoContextCtrl::checkReplay( uint32 index )
373 {
374 #ifdef SRTP_SUPPORT
375  if ( aalg == SrtpAuthenticationNull && ealg == SrtpEncryptionNull ) {
376  /* No security policy, don't use the replay protection */
377  return true;
378  }
379 
380  int64 delta = s_l - index;
381  if (delta > 0) {
382  /* Packet not yet received*/
383  return true;
384  }
385  else {
386  if( -delta > REPLAY_WINDOW_SIZE ) {
387  /* Packet too old */
388  return false;
389  }
390  else {
391  if((replay_window >> (-delta)) & 0x1) {
392  /* Packet already received ! */
393  return false;
394  }
395  else {
396  /* Packet not yet received */
397  return true;
398  }
399  }
400 }
401 #else
402  return true;
403 #endif
404 }
405 
406 void CryptoContextCtrl::update(uint32 index)
407 {
408 #ifdef SRTP_SUPPORT
409  int64 delta = index - s_l;
410 
411  /* update the replay bitmask */
412  if( delta > 0 ){
413  replay_window = replay_window << delta;
414  replay_window |= 1;
415  }
416  else {
417  replay_window |= ( 1 << delta );
418  }
419  s_l = index;
420 
421 #endif
422 }
423 
425 {
426 #ifdef SRTP_SUPPORT
428  ssrc,
429  this->ealg, // encryption algo
430  this->aalg, // authentication algo
431  this->master_key, // Master Key
432  this->master_key_length, // Master Key length
433  this->master_salt, // Master Salt
434  this->master_salt_length, // Master Salt length
435  this->ekeyl, // encryption keyl
436  this->akeyl, // authentication key len
437  this->skeyl, // session salt len
438  this->tagLength); // authentication tag len
439 
440  return pcc;
441 #else
442  return NULL;
443 #endif
444 }
445 
446 END_NAMESPACE
447 
Implments the SRTP encryption modes as defined in RFC3711.
Definition: SrtpSymCrypto.h:77
void deriveSrtcpKeys()
Perform key derivation according to SRTP specification.
The implementation for a SRTCP cryptographic context.
int32 getTagLength() const
Get the length of the SRTP authentication tag in bytes.
CryptoContextCtrl(uint32 ssrc)
Constructor for empty SRTP cryptographic context.
RTPAudio * rtp
Definition: rtp.cpp:88
#define REPLAY_WINDOW_SIZE
Definition: CryptoContext.h:28
void hmacSha1Ctx(void *ctx, const uint8_t *data, uint32_t data_length, uint8_t *mac, int32_t *mac_length)
Compute SHA1 HMAC.
Definition: gcrypthmac.cpp:79
const int SrtpEncryptionAESF8
Definition: CryptoContext.h:36
void srtcpEncrypt(uint8 *rtp, size_t len, uint64 index, uint32 ssrc)
Perform SRTP encryption.
void * createSha1HmacContext(uint8_t *key, int32_t key_length)
Create and initialize a SHA1 HMAC context.
Definition: gcrypthmac.cpp:70
void macSkeinCtx(void *ctx, const uint8_t *data, uint32_t data_length, uint8_t *mac)
Compute Skein MAC.
Definition: macSkein.cpp:61
void freeSkeinMacContext(void *ctx)
Free Skein MAC context.
Definition: macSkein.cpp:85
void freeSha1HmacContext(void *ctx)
Free SHA1 HMAC context.
Definition: gcrypthmac.cpp:113
void * createSkeinMacContext(uint8_t *key, int32_t key_length, int32_t mac_length, SkeinSize_t skeinSize)
Create and initialize a Skein MAC context.
Definition: macSkein.cpp:51
const int SrtpEncryptionTWOF8
Definition: CryptoContext.h:38
Functions to compute SHA1 HAMAC.
const int SrtpEncryptionTWOCM
Definition: CryptoContext.h:37
Function that provide Skein MAC support.
const int SrtpAuthenticationSkeinHmac
Definition: CryptoContext.h:32
bool checkReplay(uint32 newSeqNumber)
Check for packet replay.
void srtcpAuthenticate(uint8 *rtp, size_t len, uint32 roc, uint8 *tag)
Compute the authentication tag.
const int SrtpEncryptionNull
Definition: CryptoContext.h:34
const int SrtpAuthenticationSha1Hmac
Definition: CryptoContext.h:31
Base elements for RTP stacks: constants, types and global functions.
CryptoContextCtrl * newCryptoContextForSSRC(uint32 ssrc)
Derive a new Crypto Context for use with a new SSRC.
const int SrtpAuthenticationNull
Definition: CryptoContext.h:30
void update(uint32 newSeqNumber)
Update the SRTP packet index.
const int SrtpEncryptionAESCM
Definition: CryptoContext.h:35
~CryptoContextCtrl()
Destructor.