"alarm details" view mostly working; event history for active alarms preserved; minor...
[public/netxms.git] / src / libnetxms / crypto.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003-2012 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: crypto.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25 #include "ice.h"
26
27 /**
28 * Constants
29 */
30 #define KEY_BUFFER_SIZE 4096
31
32 /**
33 * Supported ciphers. By default, we support all ciphers compiled
34 * into OpenSSL library.
35 */
36 static DWORD m_dwSupportedCiphers =
37 #ifdef _WITH_ENCRYPTION
38 #ifndef OPENSSL_NO_AES
39 CSCP_SUPPORT_AES_256 |
40 CSCP_SUPPORT_AES_128 |
41 #endif
42 #ifndef OPENSSL_NO_BF
43 CSCP_SUPPORT_BLOWFISH |
44 #endif
45 #ifndef OPENSSL_NO_IDEA
46 CSCP_SUPPORT_IDEA |
47 #endif
48 #ifndef OPENSSL_NO_DES
49 CSCP_SUPPORT_3DES |
50 #endif
51 #endif /* _WITH_ENCRYPTION */
52 0;
53
54 /**
55 * Static data
56 */
57 #ifdef _WITH_ENCRYPTION
58
59 typedef OPENSSL_CONST EVP_CIPHER * (*CIPHER_FUNC)();
60 static CIPHER_FUNC m_pfCipherList[NETXMS_MAX_CIPHERS] =
61 {
62 #ifndef OPENSSL_NO_AES
63 EVP_aes_256_cbc,
64 #else
65 NULL,
66 #endif
67 #ifndef OPENSSL_NO_BF
68 EVP_bf_cbc,
69 #else
70 NULL,
71 #endif
72 #ifndef OPENSSL_NO_IDEA
73 EVP_idea_cbc,
74 #else
75 NULL,
76 #endif
77 #ifndef OPENSSL_NO_DES
78 EVP_des_ede3_cbc,
79 #else
80 NULL,
81 #endif
82 #ifndef OPENSSL_NO_AES
83 EVP_aes_128_cbc
84 #else
85 NULL
86 #endif
87 };
88 static WORD m_wNoEncryptionFlag = 0;
89 static MUTEX *m_pCryptoMutexList = NULL;
90
91 /**
92 * Locking callback for CRYPTO library
93 */
94 static void CryptoLockingCallback(int nMode, int nLock, const char *pszFile, int nLine)
95 {
96 if (nMode & CRYPTO_LOCK)
97 MutexLock(m_pCryptoMutexList[nLock]);
98 else
99 MutexUnlock(m_pCryptoMutexList[nLock]);
100 }
101
102 /**
103 * ID callback for CRYPTO library
104 */
105 #ifndef _WIN32
106
107 static unsigned long CryptoIdCallback()
108 {
109 return (unsigned long)GetCurrentThreadId();
110 }
111
112 #endif
113
114 #endif /* _WITH_ENCRYPTION */
115
116 /**
117 * Initialize OpenSSL library
118 */
119 BOOL LIBNETXMS_EXPORTABLE InitCryptoLib(DWORD dwEnabledCiphers)
120 {
121 #ifdef _WITH_ENCRYPTION
122 BYTE random[8192];
123 int i;
124
125 CRYPTO_malloc_init();
126 ERR_load_CRYPTO_strings();
127 OpenSSL_add_all_algorithms();
128 RAND_seed(random, 8192);
129 m_dwSupportedCiphers &= dwEnabledCiphers;
130 m_wNoEncryptionFlag = htons(MF_DONT_ENCRYPT);
131 m_pCryptoMutexList = (MUTEX *)malloc(sizeof(MUTEX) * CRYPTO_num_locks());
132 for(i = 0; i < CRYPTO_num_locks(); i++)
133 m_pCryptoMutexList[i] = MutexCreate();
134 CRYPTO_set_locking_callback(CryptoLockingCallback);
135 #ifndef _WIN32
136 CRYPTO_set_id_callback(CryptoIdCallback);
137 #endif /* _WIN32 */
138 #endif /* _WITH_ENCRYPTION */
139 return TRUE;
140 }
141
142 /**
143 * Get supported ciphers
144 */
145 DWORD LIBNETXMS_EXPORTABLE CSCPGetSupportedCiphers()
146 {
147 return m_dwSupportedCiphers;
148 }
149
150 /**
151 * Encrypt message
152 */
153 CSCP_ENCRYPTED_MESSAGE LIBNETXMS_EXPORTABLE *CSCPEncryptMessage(NXCPEncryptionContext *pCtx, CSCP_MESSAGE *pMsg)
154 {
155 #ifdef _WITH_ENCRYPTION
156 CSCP_ENCRYPTED_MESSAGE *pEnMsg;
157 CSCP_ENCRYPTED_PAYLOAD_HEADER header;
158 int nSize;
159 EVP_CIPHER_CTX cipher;
160 DWORD dwMsgSize;
161
162 if (pMsg->wFlags & m_wNoEncryptionFlag)
163 return (CSCP_ENCRYPTED_MESSAGE *)nx_memdup(pMsg, ntohl(pMsg->dwSize));
164
165 if (m_pfCipherList[pCtx->getCipher()] == NULL)
166 return NULL; // Unsupported cipher
167
168 EVP_EncryptInit(&cipher, m_pfCipherList[pCtx->getCipher()](), pCtx->getSessionKey(), pCtx->getIV());
169 EVP_CIPHER_CTX_set_key_length(&cipher, pCtx->getKeyLength());
170
171 dwMsgSize = ntohl(pMsg->dwSize);
172 pEnMsg = (CSCP_ENCRYPTED_MESSAGE *)malloc(dwMsgSize + CSCP_ENCRYPTION_HEADER_SIZE +
173 EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(&cipher)) + 8);
174 pEnMsg->wCode = htons(CMD_ENCRYPTED_MESSAGE);
175 pEnMsg->nReserved = 0;
176
177 header.dwChecksum = htonl(CalculateCRC32((BYTE *)pMsg, dwMsgSize, 0));
178 header.dwReserved = 0;
179 EVP_EncryptUpdate(&cipher, pEnMsg->data, &nSize, (BYTE *)&header, CSCP_EH_ENCRYPTED_BYTES);
180 dwMsgSize = nSize;
181 EVP_EncryptUpdate(&cipher, pEnMsg->data + dwMsgSize, &nSize, (BYTE *)pMsg, ntohl(pMsg->dwSize));
182 dwMsgSize += nSize;
183 EVP_EncryptFinal(&cipher, pEnMsg->data + dwMsgSize, &nSize);
184 dwMsgSize += nSize + CSCP_EH_UNENCRYPTED_BYTES;
185 EVP_CIPHER_CTX_cleanup(&cipher);
186
187 if (dwMsgSize % 8 != 0)
188 {
189 pEnMsg->nPadding = (BYTE)(8 - (dwMsgSize % 8));
190 dwMsgSize += pEnMsg->nPadding;
191 }
192 else
193 {
194 pEnMsg->nPadding = 0;
195 }
196 pEnMsg->dwSize = htonl(dwMsgSize);
197
198 return pEnMsg;
199 #else /* _WITH_ENCRYPTION */
200 return NULL;
201 #endif
202 }
203
204
205 //
206 // Decrypt message
207 //
208
209 BOOL LIBNETXMS_EXPORTABLE CSCPDecryptMessage(NXCPEncryptionContext *pCtx,
210 CSCP_ENCRYPTED_MESSAGE *pMsg,
211 BYTE *pDecryptionBuffer)
212 {
213 #ifdef _WITH_ENCRYPTION
214 int nSize;
215 EVP_CIPHER_CTX cipher;
216 DWORD dwChecksum, dwMsgSize;
217 CSCP_MESSAGE *pClearMsg;
218
219 if (m_pfCipherList[pCtx->getCipher()] == NULL)
220 return FALSE; // Unsupported cipher
221
222 pMsg->dwSize = ntohl(pMsg->dwSize);
223 EVP_DecryptInit(&cipher, m_pfCipherList[pCtx->getCipher()](), pCtx->getSessionKey(), pCtx->getIV());
224 EVP_CIPHER_CTX_set_key_length(&cipher, pCtx->getKeyLength());
225 EVP_DecryptUpdate(&cipher, pDecryptionBuffer, &nSize, pMsg->data,
226 pMsg->dwSize - CSCP_EH_UNENCRYPTED_BYTES - pMsg->nPadding);
227 EVP_DecryptFinal(&cipher, pDecryptionBuffer + nSize, &nSize);
228 EVP_CIPHER_CTX_cleanup(&cipher);
229
230 pClearMsg = (CSCP_MESSAGE *)(pDecryptionBuffer + CSCP_EH_ENCRYPTED_BYTES);
231 dwMsgSize = ntohl(pClearMsg->dwSize);
232 if (dwMsgSize > pMsg->dwSize)
233 return FALSE; // Message decrypted incorrectly, because it can't be larger than encrypted
234 dwChecksum = CalculateCRC32((BYTE *)pClearMsg, dwMsgSize, 0);
235 if (dwChecksum != ntohl(((CSCP_ENCRYPTED_PAYLOAD_HEADER *)pDecryptionBuffer)->dwChecksum))
236 return FALSE; // Bad checksum
237
238 memcpy(pMsg, pClearMsg, dwMsgSize);
239 return TRUE;
240 #else /* _WITH_ENCRYPTION */
241 return FALSE;
242 #endif
243 }
244
245 /**
246 * Setup encryption context
247 * Function will determine is it called on initiator or responder side
248 * by message code. Initiator should provide it's private key,
249 * and responder should provide pointer to response message.
250 */
251 DWORD LIBNETXMS_EXPORTABLE SetupEncryptionContext(CSCPMessage *pMsg,
252 NXCPEncryptionContext **ppCtx,
253 CSCPMessage **ppResponse,
254 RSA *pPrivateKey, int nNXCPVersion)
255 {
256 DWORD dwResult = RCC_NOT_IMPLEMENTED;
257
258 *ppCtx = NULL;
259 #ifdef _WITH_ENCRYPTION
260 if (pMsg->GetCode() == CMD_REQUEST_SESSION_KEY)
261 {
262 DWORD dwCiphers;
263
264 *ppResponse = new CSCPMessage(nNXCPVersion);
265 (*ppResponse)->SetCode(CMD_SESSION_KEY);
266 (*ppResponse)->SetId(pMsg->GetId());
267 (*ppResponse)->DisableEncryption();
268
269 dwCiphers = pMsg->GetVariableLong(VID_SUPPORTED_ENCRYPTION) & m_dwSupportedCiphers;
270 if (dwCiphers == 0)
271 {
272 (*ppResponse)->SetVariable(VID_RCC, RCC_NO_CIPHERS);
273 dwResult = RCC_NO_CIPHERS;
274 }
275 else
276 {
277 BYTE *pBufPos, ucKeyBuffer[KEY_BUFFER_SIZE];
278 RSA *pServerKey;
279 DWORD dwKeySize;
280
281 *ppCtx = NXCPEncryptionContext::create(dwCiphers);
282
283 // Encrypt key
284 dwKeySize = pMsg->GetVariableBinary(VID_PUBLIC_KEY, ucKeyBuffer, KEY_BUFFER_SIZE);
285 pBufPos = ucKeyBuffer;
286 pServerKey = d2i_RSAPublicKey(NULL, (OPENSSL_CONST BYTE **)&pBufPos, dwKeySize);
287 if (pServerKey != NULL)
288 {
289 (*ppResponse)->SetVariable(VID_RCC, RCC_SUCCESS);
290 dwKeySize = RSA_public_encrypt((*ppCtx)->getKeyLength(), (*ppCtx)->getSessionKey(),
291 ucKeyBuffer, pServerKey, RSA_PKCS1_OAEP_PADDING);
292 (*ppResponse)->SetVariable(VID_SESSION_KEY, ucKeyBuffer, dwKeySize);
293 dwKeySize = RSA_public_encrypt(EVP_MAX_IV_LENGTH, (*ppCtx)->getIV(),
294 ucKeyBuffer, pServerKey, RSA_PKCS1_OAEP_PADDING);
295 (*ppResponse)->SetVariable(VID_SESSION_IV, ucKeyBuffer, dwKeySize);
296 (*ppResponse)->SetVariable(VID_CIPHER, (WORD)(*ppCtx)->getCipher());
297 (*ppResponse)->SetVariable(VID_KEY_LENGTH, (WORD)(*ppCtx)->getKeyLength());
298 (*ppResponse)->SetVariable(VID_IV_LENGTH, (WORD)EVP_MAX_IV_LENGTH);
299 RSA_free(pServerKey);
300 dwResult = RCC_SUCCESS;
301 }
302 else
303 {
304 (*ppResponse)->SetVariable(VID_RCC, RCC_INVALID_PUBLIC_KEY);
305 dwResult = RCC_INVALID_PUBLIC_KEY;
306 }
307 }
308 }
309 else if (pMsg->GetCode() == CMD_SESSION_KEY)
310 {
311 dwResult = pMsg->GetVariableLong(VID_RCC);
312 if (dwResult == RCC_SUCCESS)
313 {
314 *ppCtx = NXCPEncryptionContext::create(pMsg, pPrivateKey);
315 if (*ppCtx == NULL)
316 {
317 dwResult = RCC_INVALID_SESSION_KEY;
318 }
319 }
320 }
321
322 if ((dwResult != RCC_SUCCESS) && (*ppCtx != NULL))
323 {
324 delete *ppCtx;
325 *ppCtx = NULL;
326 }
327 #else
328 if (pMsg->GetCode() == CMD_REQUEST_SESSION_KEY)
329 {
330 *ppResponse = new CSCPMessage(nNXCPVersion);
331 (*ppResponse)->SetCode(CMD_SESSION_KEY);
332 (*ppResponse)->SetId(pMsg->GetId());
333 (*ppResponse)->DisableEncryption();
334 (*ppResponse)->SetVariable(VID_RCC, dwResult);
335 }
336 #endif
337
338 return dwResult;
339 }
340
341 /**
342 * Prepare session key request message
343 */
344 void LIBNETXMS_EXPORTABLE PrepareKeyRequestMsg(CSCPMessage *pMsg, RSA *pServerKey, bool useX509Format)
345 {
346 #ifdef _WITH_ENCRYPTION
347 int iLen;
348 BYTE *pKeyBuffer, *pBufPos;
349
350 pMsg->SetCode(CMD_REQUEST_SESSION_KEY);
351 pMsg->SetVariable(VID_SUPPORTED_ENCRYPTION, m_dwSupportedCiphers);
352
353 if (useX509Format)
354 {
355 iLen = i2d_RSA_PUBKEY(pServerKey, NULL);
356 pKeyBuffer = (BYTE *)malloc(iLen);
357 pBufPos = pKeyBuffer;
358 i2d_RSA_PUBKEY(pServerKey, &pBufPos);
359 }
360 else
361 {
362 iLen = i2d_RSAPublicKey(pServerKey, NULL);
363 pKeyBuffer = (BYTE *)malloc(iLen);
364 pBufPos = pKeyBuffer;
365 i2d_RSAPublicKey(pServerKey, &pBufPos);
366 }
367 pMsg->SetVariable(VID_PUBLIC_KEY, pKeyBuffer, iLen);
368 free(pKeyBuffer);
369 #endif
370 }
371
372
373 //
374 // Load RSA key(s) from file
375 //
376
377 RSA LIBNETXMS_EXPORTABLE *LoadRSAKeys(const TCHAR *pszKeyFile)
378 {
379 #ifdef _WITH_ENCRYPTION
380 FILE *fp;
381 BYTE *pKeyBuffer, *pBufPos, hash[SHA1_DIGEST_SIZE];
382 DWORD dwLen;
383 RSA *pKey = NULL;
384
385 fp = _tfopen(pszKeyFile, _T("rb"));
386 if (fp != NULL)
387 {
388 if (fread(&dwLen, 1, sizeof(DWORD), fp) == sizeof(DWORD) && dwLen < 10 * 1024)
389 {
390 pKeyBuffer = (BYTE *)malloc(dwLen);
391 pBufPos = pKeyBuffer;
392 if (fread(pKeyBuffer, 1, dwLen, fp) == dwLen)
393 {
394 BYTE hash2[SHA1_DIGEST_SIZE];
395
396 fread(hash, 1, SHA1_DIGEST_SIZE, fp);
397 CalculateSHA1Hash(pKeyBuffer, dwLen, hash2);
398 if (!memcmp(hash, hash2, SHA1_DIGEST_SIZE))
399 {
400 pKey = d2i_RSAPublicKey(NULL, (OPENSSL_CONST BYTE **)&pBufPos, dwLen);
401 if (pKey != NULL)
402 {
403 if (d2i_RSAPrivateKey(&pKey, (OPENSSL_CONST BYTE **)&pBufPos,
404 dwLen - CAST_FROM_POINTER((pBufPos - pKeyBuffer), DWORD)) == NULL)
405 {
406 RSA_free(pKey);
407 pKey = NULL;
408 }
409 }
410 }
411 }
412 free(pKeyBuffer);
413 }
414 fclose(fp);
415 }
416
417 return pKey;
418 #else
419 return NULL;
420 #endif
421 }
422
423
424 //
425 // Create signature for message using certificate (MS CAPI version)
426 // Paraeters:
427 // pMsg and dwMsgLen - message to sign and it's length
428 // pCert - certificate
429 // pBuffer - output buffer
430 // dwBufSize - buffer size
431 // pdwSigLen - actual signature size
432 //
433
434 #ifdef _WIN32
435
436 BOOL LIBNETXMS_EXPORTABLE SignMessageWithCAPI(BYTE *pMsg, DWORD dwMsgLen, const CERT_CONTEXT *pCert,
437 BYTE *pBuffer, DWORD dwBufSize, DWORD *pdwSigLen)
438 {
439 BOOL bFreeProv, bRet = FALSE;
440 DWORD i, j, dwLen, dwKeySpec;
441 HCRYPTPROV hProv;
442 HCRYPTHASH hHash;
443 BYTE *pTemp;
444
445 if (CryptAcquireCertificatePrivateKey(pCert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
446 NULL, &hProv, &dwKeySpec, &bFreeProv))
447 {
448 if (CryptCreateHash(hProv, CALG_SHA1, NULL, 0, &hHash))
449 {
450 if (CryptHashData(hHash, pMsg, dwMsgLen, 0))
451 {
452 dwLen = dwBufSize;
453 pTemp = (BYTE *)malloc(dwBufSize);;
454 bRet = CryptSignHash(hHash, dwKeySpec, NULL, 0, pTemp, &dwLen);
455 *pdwSigLen = dwLen;
456 // we have to reverse the byte-order in the result from CryptSignHash()
457 for(i = 0, j = dwLen - 1; i < dwLen; i++, j--)
458 pBuffer[i] = pTemp[j];
459 }
460 CryptDestroyHash(hHash);
461 }
462
463 if (bFreeProv)
464 CryptReleaseContext(hProv, 0);
465 }
466 return bRet;
467 }
468
469 #endif
470
471
472 //
473 // Encrypt data block with ICE
474 //
475
476 void LIBNETXMS_EXPORTABLE ICEEncryptData(const BYTE *in, int inLen, BYTE *out, const BYTE *key)
477 {
478 ICE_KEY *ice = ice_key_create(1);
479 ice_key_set(ice, key);
480
481 int stopPos = inLen - (inLen % 8);
482 const BYTE *curr = in;
483 for(int pos = 0; pos < stopPos; pos += 8)
484 ice_key_encrypt(ice, &in[pos], &out[pos]);
485
486 if (stopPos < inLen)
487 {
488 BYTE plainText[8], encrypted[8];
489
490 memcpy(plainText, &in[stopPos], inLen - stopPos);
491 ice_key_encrypt(ice, plainText, encrypted);
492 memcpy(&out[stopPos], encrypted, inLen - stopPos);
493 }
494
495 ice_key_destroy(ice);
496 }
497
498
499 //
500 // Decrypt data block with ICE
501 //
502
503 void LIBNETXMS_EXPORTABLE ICEDecryptData(const BYTE *in, int inLen, BYTE *out, const BYTE *key)
504 {
505 ICE_KEY *ice = ice_key_create(1);
506 ice_key_set(ice, key);
507
508 int stopPos = inLen - (inLen % 8);
509 const BYTE *curr = in;
510 for(int pos = 0; pos < stopPos; pos += 8)
511 ice_key_decrypt(ice, &in[pos], &out[pos]);
512
513 if (stopPos < inLen)
514 {
515 BYTE plainText[8], encrypted[8];
516
517 memcpy(encrypted, &in[stopPos], inLen - stopPos);
518 ice_key_decrypt(ice, encrypted, plainText);
519 memcpy(&out[stopPos], plainText, inLen - stopPos);
520 }
521
522 ice_key_destroy(ice);
523 }
524
525
526 //
527 // Encryption context constructor
528 //
529
530 NXCPEncryptionContext::NXCPEncryptionContext()
531 {
532 m_sessionKey = NULL;
533 }
534
535
536 //
537 // Encryption context destructor
538 //
539
540 NXCPEncryptionContext::~NXCPEncryptionContext()
541 {
542 safe_free(m_sessionKey);
543 }
544
545
546 //
547 // Create encryption context from CMD_SESSION_KEY NXCP message
548 //
549
550 NXCPEncryptionContext *NXCPEncryptionContext::create(CSCPMessage *msg, RSA *privateKey)
551 {
552 #ifdef _WITH_ENCRYPTION
553 BYTE ucKeyBuffer[KEY_BUFFER_SIZE], ucSessionKey[KEY_BUFFER_SIZE];
554 DWORD dwKeySize;
555 int nSize, nIVLen;
556 NXCPEncryptionContext *ctx = new NXCPEncryptionContext;
557
558 ctx->m_cipher = msg->GetVariableShort(VID_CIPHER);
559 ctx->m_keyLength = msg->GetVariableShort(VID_KEY_LENGTH);
560 ctx->m_sessionKey = (BYTE *)malloc(ctx->m_keyLength);
561
562 // Decrypt session key
563 dwKeySize = msg->GetVariableBinary(VID_SESSION_KEY, ucKeyBuffer, KEY_BUFFER_SIZE);
564 nSize = RSA_private_decrypt(dwKeySize, ucKeyBuffer, ucSessionKey, privateKey, RSA_PKCS1_OAEP_PADDING);
565 if (nSize == ctx->m_keyLength)
566 {
567 memcpy(ctx->m_sessionKey, ucSessionKey, nSize);
568
569 // Decrypt session IV
570 nIVLen = msg->GetVariableShort(VID_IV_LENGTH);
571 if (nIVLen == 0) // Versions prior to 0.2.13 don't send IV length, assume 16
572 nIVLen = 16;
573 dwKeySize = msg->GetVariableBinary(VID_SESSION_IV, ucKeyBuffer, KEY_BUFFER_SIZE);
574 nSize = RSA_private_decrypt(dwKeySize, ucKeyBuffer, ucSessionKey, privateKey, RSA_PKCS1_OAEP_PADDING);
575 if ((nSize == nIVLen) &&
576 (nIVLen <= EVP_CIPHER_iv_length(m_pfCipherList[ctx->m_cipher]())))
577 {
578 memcpy(ctx->m_iv, ucSessionKey, min(EVP_MAX_IV_LENGTH, nIVLen));
579 }
580 else
581 {
582 delete_and_null(ctx);
583 }
584 }
585 else
586 {
587 delete_and_null(ctx);
588 }
589 return ctx;
590 #else
591 return new NXCPEncryptionContext;
592 #endif
593 }
594
595
596 //
597 // Create encryption context from CMD_REQUEST_SESSION_KEY NXCP message
598 //
599
600 NXCPEncryptionContext *NXCPEncryptionContext::create(DWORD ciphers)
601 {
602 NXCPEncryptionContext *ctx = new NXCPEncryptionContext;
603
604 #ifdef _WITH_ENCRYPTION
605 // Select cipher
606 if (ciphers & CSCP_SUPPORT_AES_256)
607 {
608 ctx->m_cipher = CSCP_CIPHER_AES_256;
609 ctx->m_keyLength = 32;
610 }
611 else if (ciphers & CSCP_SUPPORT_BLOWFISH)
612 {
613 ctx->m_cipher = CSCP_CIPHER_BLOWFISH;
614 ctx->m_keyLength = 32;
615 }
616 else if (ciphers & CSCP_SUPPORT_AES_128)
617 {
618 ctx->m_cipher = CSCP_CIPHER_AES_128;
619 ctx->m_keyLength = 16;
620 }
621 else if (ciphers & CSCP_SUPPORT_IDEA)
622 {
623 ctx->m_cipher = CSCP_CIPHER_IDEA;
624 ctx->m_keyLength = 16;
625 }
626 else if (ciphers & CSCP_SUPPORT_3DES)
627 {
628 ctx->m_cipher = CSCP_CIPHER_3DES;
629 ctx->m_keyLength = 24;
630 }
631
632 // Generate key
633 ctx->m_sessionKey = (BYTE *)malloc(ctx->m_keyLength);
634 RAND_bytes(ctx->m_sessionKey, ctx->m_keyLength);
635 RAND_bytes(ctx->m_iv, EVP_MAX_IV_LENGTH);
636 #endif
637
638 return ctx;
639 }