ccRTP 2.1.2
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SrtpSymCrypto.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2005, 2004, 2012 Erik Eliasson, Johan Bilien, Werner Dittmann
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  * In addition, as a special exception, the copyright holders give
19  * permission to link the code of portions of this program with the
20  * OpenSSL library under certain conditions as described in each
21  * individual source file, and distribute linked combinations
22  * including the two.
23  * You must obey the GNU General Public License in all respects
24  * for all of the code used other than OpenSSL. If you modify
25  * file(s) with this exception, you may extend this exception to your
26  * version of the file(s), but you are not obligated to do so. If you
27  * do not wish to do so, delete this exception statement from your
28  * version. If you delete this exception statement from all source
29  * files in the program, then also delete it here.
30  */
31 
38 #define MAKE_F8_TEST
39 
40 #include <stdlib.h>
41 #include <openssl/aes.h> // the include of openSSL
42 #include <crypto/SrtpSymCrypto.h>
43 #include <crypto/twofish.h>
44 #include <string.h>
45 #include <stdio.h>
46 
47 #if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
48 #include <windows.h>
49 #else
50 #include <arpa/inet.h>
51 #endif
52 
53 SrtpSymCrypto::SrtpSymCrypto(int algo):key(NULL), algorithm(algo) {
54 }
55 
56 SrtpSymCrypto::SrtpSymCrypto( uint8_t* k, int32_t keyLength, int algo ):
57  key(NULL), algorithm(algo) {
58 
59  setNewKey(k, keyLength);
60 }
61 
63  if (key != NULL) {
65  memset(key, 0, sizeof(AES_KEY) );
66  }
68  memset(key, 0, sizeof(Twofish_key));
69  }
70  delete[] (uint8_t*)key;
71  key = NULL;
72  }
73 }
74 
75 static int twoFishInit = 0;
76 
77 bool SrtpSymCrypto::setNewKey(const uint8_t* k, int32_t keyLength) {
78  // release an existing key before setting a new one
79  if (key != NULL)
80  delete[] (uint8_t*)key;
81 
82  if (!(keyLength == 16 || keyLength == 32)) {
83  return false;
84  }
86  key = new uint8_t[sizeof(AES_KEY)];
87  memset(key, 0, sizeof(AES_KEY) );
88  AES_set_encrypt_key(k, keyLength*8, (AES_KEY *)key);
89  }
91  if (!twoFishInit) {
93  twoFishInit = 1;
94  }
95  key = new uint8_t[sizeof(Twofish_key)];
96  memset(key, 0, sizeof(Twofish_key));
98  }
99  else
100  return false;
101 
102  return true;
103 }
104 
105 
106 void SrtpSymCrypto::encrypt(const uint8_t* input, uint8_t* output ) {
108  AES_encrypt(input, output, (AES_KEY *)key);
109  }
112  (Twofish_Byte*)output);
113  }
114 }
115 
116 void SrtpSymCrypto::get_ctr_cipher_stream(uint8_t* output, uint32_t length,
117  uint8_t* iv ) {
118  uint16_t ctr = 0;
119  unsigned char temp[SRTP_BLOCK_SIZE];
120 
121  for(ctr = 0; ctr < length/SRTP_BLOCK_SIZE; ctr++) {
122  //compute the cipher stream
123  iv[14] = (uint8_t)((ctr & 0xFF00) >> 8);
124  iv[15] = (uint8_t)((ctr & 0x00FF));
125 
126  encrypt(iv, &output[ctr*SRTP_BLOCK_SIZE]);
127  }
128  if ((length % SRTP_BLOCK_SIZE) > 0) {
129  // Treat the last bytes:
130  iv[14] = (uint8_t)((ctr & 0xFF00) >> 8);
131  iv[15] = (uint8_t)((ctr & 0x00FF));
132 
133  encrypt(iv, temp);
134  memcpy(&output[ctr*SRTP_BLOCK_SIZE], temp, length % SRTP_BLOCK_SIZE );
135  }
136 }
137 
138 void SrtpSymCrypto::ctr_encrypt(const uint8_t* input, uint32_t input_length,
139  uint8_t* output, uint8_t* iv ) {
140 
141  if (key == NULL)
142  return;
143 
144  uint16_t ctr = 0;
145  unsigned char temp[SRTP_BLOCK_SIZE];
146 
147  int l = input_length/SRTP_BLOCK_SIZE;
148  for (ctr = 0; ctr < l; ctr++ ) {
149  iv[14] = (uint8_t)((ctr & 0xFF00) >> 8);
150  iv[15] = (uint8_t)((ctr & 0x00FF));
151 
152  encrypt(iv, temp);
153  for (int i = 0; i < SRTP_BLOCK_SIZE; i++ ) {
154  *output++ = temp[i] ^ *input++;
155  }
156 
157  }
158  l = input_length % SRTP_BLOCK_SIZE;
159  if (l > 0) {
160  // Treat the last bytes:
161  iv[14] = (uint8_t)((ctr & 0xFF00) >> 8);
162  iv[15] = (uint8_t)((ctr & 0x00FF));
163 
164  encrypt(iv, temp);
165  for (int i = 0; i < l; i++ ) {
166  *output++ = temp[i] ^ *input++;
167  }
168  }
169 }
170 
171 void SrtpSymCrypto::ctr_encrypt( uint8_t* data, uint32_t data_length, uint8_t* iv ) {
172 
173  if (key == NULL)
174  return;
175 
176  uint16_t ctr = 0;
177  unsigned char temp[SRTP_BLOCK_SIZE];
178 
179  int l = data_length/SRTP_BLOCK_SIZE;
180  for (ctr = 0; ctr < l; ctr++ ) {
181  iv[14] = (uint8_t)((ctr & 0xFF00) >> 8);
182  iv[15] = (uint8_t)((ctr & 0x00FF));
183 
184  encrypt(iv, temp);
185  for (int i = 0; i < SRTP_BLOCK_SIZE; i++ ) {
186  *data++ ^= temp[i];
187  }
188 
189  }
190  l = data_length % SRTP_BLOCK_SIZE;
191  if (l > 0) {
192  // Treat the last bytes:
193  iv[14] = (uint8_t)((ctr & 0xFF00) >> 8);
194  iv[15] = (uint8_t)((ctr & 0x00FF));
195 
196  encrypt(iv, temp);
197  for (int i = 0; i < l; i++ ) {
198  *data++ ^= temp[i];
199  }
200  }
201 }
202 
203 void SrtpSymCrypto::f8_encrypt(const uint8_t* data, uint32_t data_length,
204  uint8_t* iv, SrtpSymCrypto* f8Cipher ) {
205 
206  f8_encrypt(data, data_length, const_cast<uint8_t*>(data), iv, f8Cipher);
207 }
208 
209 #define MAX_KEYLEN 32
210 
211 void SrtpSymCrypto::f8_deriveForIV(SrtpSymCrypto* f8Cipher, uint8_t* key, int32_t keyLen,
212  uint8_t* salt, int32_t saltLen) {
213 
214  unsigned char *cp_in, *cp_in1, *cp_out;
215 
216  unsigned char maskedKey[MAX_KEYLEN];
217  unsigned char saltMask[MAX_KEYLEN];
218 
219  if (keyLen > MAX_KEYLEN)
220  return;
221 
222  if (saltLen > keyLen)
223  return;
224  /*
225  * First copy the salt into the mask field, then fill with 0x55 to
226  * get a full key.
227  */
228  memcpy(saltMask, salt, saltLen);
229  memset(saltMask+saltLen, 0x55, keyLen-saltLen);
230 
231  /*
232  * XOR the original key with the above created mask to
233  * get the special key.
234  */
235  cp_out = maskedKey;
236  cp_in = key;
237  cp_in1 = saltMask;
238  for (int i = 0; i < keyLen; i++) {
239  *cp_out++ = *cp_in++ ^ *cp_in1++;
240  }
241  /*
242  * Prepare the a new AES cipher with the special key to compute IV'
243  */
244  f8Cipher->setNewKey(maskedKey, keyLen);
245 }
246 
247 void SrtpSymCrypto::f8_encrypt(const uint8_t* in, uint32_t in_length, uint8_t* out,
248  uint8_t* iv, SrtpSymCrypto* f8Cipher ) {
249 
250 
251  int offset = 0;
252 
253  unsigned char ivAccent[SRTP_BLOCK_SIZE];
254  unsigned char S[SRTP_BLOCK_SIZE];
255 
256  F8_CIPHER_CTX f8ctx;
257 
258  if (key == NULL)
259  return;
260  /*
261  * Get memory for the derived IV (IV')
262  */
263  f8ctx.ivAccent = ivAccent;
264  /*
265  * Use the derived IV encryption setup to encrypt the original IV to produce IV'.
266  */
267  f8Cipher->encrypt(iv, f8ctx.ivAccent);
268 
269  f8ctx.J = 0; // initialize the counter
270  f8ctx.S = S; // get the key stream buffer
271 
272  memset(f8ctx.S, 0, SRTP_BLOCK_SIZE); // initial value for key stream
273 
274  while (in_length >= SRTP_BLOCK_SIZE) {
275  processBlock(&f8ctx, in+offset, SRTP_BLOCK_SIZE, out+offset);
276  in_length -= SRTP_BLOCK_SIZE;
277  offset += SRTP_BLOCK_SIZE;
278  }
279  if (in_length > 0) {
280  processBlock(&f8ctx, in+offset, in_length, out+offset);
281  }
282 }
283 
284 int SrtpSymCrypto::processBlock(F8_CIPHER_CTX *f8ctx, const uint8_t* in, int32_t length, uint8_t* out) {
285 
286  int i;
287  const uint8_t *cp_in;
288  uint8_t* cp_in1, *cp_out;
289  uint32_t *ui32p;
290 
291  /*
292  * XOR the previous key stream with IV'
293  * ( S(-1) xor IV' )
294  */
295  cp_in = f8ctx->ivAccent;
296  cp_out = f8ctx->S;
297  for (i = 0; i < SRTP_BLOCK_SIZE; i++) {
298  *cp_out++ ^= *cp_in++;
299  }
300  /*
301  * Now XOR (S(n-1) xor IV') with the current counter, then increment the counter
302  */
303  ui32p = (uint32_t *)f8ctx->S;
304  ui32p[3] ^= htonl(f8ctx->J);
305  f8ctx->J++;
306  /*
307  * Now compute the new key stream using AES encrypt
308  */
309  encrypt(f8ctx->S, f8ctx->S);
310  /*
311  * as the last step XOR the plain text with the key stream to produce
312  * the ciphertext.
313  */
314  cp_out = out;
315  cp_in = in;
316  cp_in1 = f8ctx->S;
317  for (i = 0; i < length; i++) {
318  *cp_out++ = *cp_in++ ^ *cp_in1++;
319  }
320  return length;
321 }
322 
323 
Implments the SRTP encryption modes as defined in RFC3711.
Definition: SrtpSymCrypto.h:77
bool setNewKey(const uint8_t *key, int32_t keyLength)
Set new key.
Structure that contains a prepared Twofish key.
Definition: twofish.h:95
unsigned char Twofish_Byte
A Twofish_Byte must be an unsigned 8-bit integer.
Definition: twofish.h:40
int Twofish_initialise()
Initialise and test the Twofish implementation.
unsigned char * ivAccent
second IV
Definition: SrtpSymCrypto.h:54
const int SrtpEncryptionAESF8
Definition: CryptoContext.h:36
void get_ctr_cipher_stream(uint8_t *output, uint32_t length, uint8_t *iv)
Computes the cipher stream for AES CM mode.
#define SRTP_BLOCK_SIZE
Definition: SrtpSymCrypto.h:49
const int SrtpEncryptionTWOF8
Definition: CryptoContext.h:38
int processBlock(F8_CIPHER_CTX *f8ctx, const uint8_t *in, int32_t length, uint8_t *out)
uint32_t J
Counter.
Definition: SrtpSymCrypto.h:55
int32_t algorithm
const int SrtpEncryptionTWOCM
Definition: CryptoContext.h:37
SrtpSymCrypto(int algo=SrtpEncryptionAESCM)
void ctr_encrypt(const uint8_t *input, uint32_t inputLen, uint8_t *output, uint8_t *iv)
Counter-mode encryption.
void f8_encrypt(const uint8_t *data, uint32_t dataLen, uint8_t *iv, SrtpSymCrypto *f8Cipher)
AES F8 mode encryption, in place.
#define MAX_KEYLEN
unsigned char * S
Intermetiade buffer.
Definition: SrtpSymCrypto.h:53
Class which implements SRTP AES cryptographic functions.
void Twofish_encrypt(Twofish_key *xkey, Twofish_Byte p[16], Twofish_Byte c[16])
Encrypt a single block of data.
int Twofish_prepare_key(Twofish_Byte key[], int key_len, Twofish_key *xkey)
Convert a cipher key to the internal form used for encryption and decryption.
void f8_deriveForIV(SrtpSymCrypto *f8Cipher, uint8_t *key, int32_t keyLen, uint8_t *salt, int32_t saltLen)
Derive a AES context to compute the IV'.
const int SrtpEncryptionAESCM
Definition: CryptoContext.h:35
void encrypt(const uint8_t *input, uint8_t *output)
Encrypts the inpout to the output.