Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

833 lines
27 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // File: cryptfnc.cpp
  4. //
  5. // Contents: This file implements the cryptfnc class that provides
  6. // easy to use interfaces on the CryptoAPI.
  7. //
  8. // History: AshishS Created 12/03/96
  9. //
  10. //----------------------------------------------------------------------------
  11. #ifdef THIS_FILE
  12. #undef THIS_FILE
  13. #endif
  14. static char __szTraceSourceFile[] = __FILE__;
  15. #define THIS_FILE __szTraceSourceFile
  16. #include <windows.h>
  17. #include <cryptfnc.h>
  18. #include <wincrypt.h>
  19. #include <dbgtrace.h>
  20. #ifndef CRYPT_MACHINE_KEYSET
  21. #define CRYPT_MACHINE_KEYSET 0x00000020
  22. #endif
  23. // this function Generates a SessionKey using the pszPassword
  24. // parameter
  25. // Returns FALSE if a Fatal error occured, TRUE otherwise
  26. BOOL CCryptFunctions::GenerateSessionKeyFromPassword(
  27. HCRYPTKEY * phKey, // location to store the session key
  28. TCHAR * pszPassword) // password to generate the session key from
  29. {
  30. DWORD dwLength;
  31. HCRYPTHASH hHash = 0;
  32. TraceFunctEnter("GenerateSessionKeyFromPassword");
  33. // Init should have been successfully called before
  34. _ASSERT(m_hProv);
  35. // Create hash object.
  36. if(!CryptCreateHash(m_hProv, // handle to CSP
  37. CALG_SHA, // use SHA hash algorithm
  38. 0, // not keyed hash
  39. 0, // flags - always 0
  40. &hHash)) // address where hash object should be created
  41. {
  42. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptCreateHash",
  43. GetLastError());
  44. goto cleanup;
  45. }
  46. // Hash password string.
  47. dwLength = lstrlen(pszPassword) * sizeof(TCHAR);
  48. if(!CryptHashData(hHash, // handle to hash object
  49. (BYTE *)pszPassword, // address of data to be hashed
  50. dwLength, // length of data
  51. 0)) // flags
  52. {
  53. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptHashData",
  54. GetLastError());
  55. goto cleanup;
  56. }
  57. // Create block cipher session key based on hash of the password.
  58. if(!CryptDeriveKey(m_hProv, //CSP provider
  59. CALG_RC2, // use RC2 block cipher algorithm
  60. hHash, //handle to hash object
  61. 0, // no flags - we do not need the key to be exportable
  62. phKey)) //address the newly created key should be copied
  63. {
  64. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptDeriveKey",
  65. GetLastError());
  66. goto cleanup;
  67. }
  68. // Destroy hash object.
  69. _VERIFY(CryptDestroyHash(hHash));
  70. TraceFunctLeave();
  71. return TRUE;
  72. cleanup:
  73. // Destroy hash object.
  74. if(hHash != 0)
  75. _VERIFY(CryptDestroyHash(hHash));
  76. TraceFunctLeave();
  77. return FALSE;
  78. }
  79. // This function generates a Hash using the SHA hashing
  80. // algorithm. Four seperate buffers of data can be given to this
  81. // function. Data of length 0 will not be used in calculation of HASH.
  82. // Returns FALSE if a Fatal error occured, TRUE otherwise
  83. BOOL CCryptFunctions::GenerateHash(
  84. BYTE * pbData, // data to hash
  85. DWORD dwDataLength, // length of data to hash
  86. BYTE * pbData1, // another data to hash
  87. DWORD dwData1Length, // length of above data
  88. BYTE * pbData2, // another data to hash
  89. DWORD dwData2Length, // length of above data
  90. BYTE * pbData3, // another data to hash
  91. DWORD dwData3Length, // length of above data
  92. BYTE * pbHashBuffer, // buffer to store hash
  93. DWORD * pdwHashBufLen)//length of buffer to store Hash
  94. {
  95. DWORD dwLength, dwResult;
  96. BOOL fResult;
  97. HCRYPTHASH hHash = 0;
  98. TraceFunctEnter("GenerateHash");
  99. // Init should have been successfully called before
  100. _ASSERT(m_hProv);
  101. dwResult = WaitForSingleObject( m_hSemaphore,// handle of object to wait for
  102. INFINITE); // no time-out
  103. _ASSERT(WAIT_OBJECT_0 == dwResult);
  104. // At least one of the Data Pairs should be valid
  105. if (! (( pbData && dwDataLength ) || ( pbData1 && dwData1Length )
  106. || ( pbData2 && dwData2Length ) || ( pbData3 && dwData3Length ) ) )
  107. {
  108. ErrorTrace(CRYPT_FNC_ID, "No Data to hash");
  109. goto cleanup;
  110. }
  111. // now ask the user for a password and generate a session key based
  112. // on the password. This session key will be used to encrypt the secret
  113. // key.
  114. // Create hash object.
  115. if(!CryptCreateHash(m_hProv, // handle to CSP
  116. CALG_SHA, // use SHA hash algorithm
  117. 0, // not keyed hash
  118. 0, // flags - always 0
  119. &hHash)) // address where hash object should be created
  120. {
  121. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptCreateHash",
  122. GetLastError());
  123. goto cleanup;
  124. }
  125. if ( pbData && dwDataLength )
  126. {
  127. if(!CryptHashData(hHash, // handle to hash object
  128. pbData, // address of data to be hashed
  129. dwDataLength, // length of data
  130. 0)) // flags
  131. {
  132. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptHashData",
  133. GetLastError());
  134. goto cleanup;
  135. }
  136. }
  137. if ( pbData1 && dwData1Length )
  138. {
  139. if(!CryptHashData(hHash, // handle to hash object
  140. pbData1, // address of data to be hashed
  141. dwData1Length, // length of data
  142. 0)) // flags
  143. {
  144. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptHashData",
  145. GetLastError());
  146. goto cleanup;
  147. }
  148. }
  149. if (pbData2)
  150. {
  151. if(!CryptHashData(hHash, // handle to hash object
  152. pbData2, // address of data to be hashed
  153. dwData2Length, // length of data
  154. 0)) // flags
  155. {
  156. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptHashData",
  157. GetLastError());
  158. goto cleanup;
  159. }
  160. }
  161. if (pbData3)
  162. {
  163. if(!CryptHashData(hHash, // handle to hash object
  164. pbData3, // address of data to be hashed
  165. dwData3Length, // length of data
  166. 0)) // flags
  167. {
  168. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptHashData",
  169. GetLastError());
  170. goto cleanup;
  171. }
  172. }
  173. if (! CryptGetHashParam( hHash,// handle to hash object
  174. HP_HASHVAL,// get the hash value
  175. pbHashBuffer, // hash buffer
  176. pdwHashBufLen, // hash buffer length
  177. 0 )) // flags
  178. {
  179. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptGetHashParam",
  180. GetLastError());
  181. goto cleanup;
  182. }
  183. // Destroy hash object.
  184. _VERIFY(CryptDestroyHash(hHash));
  185. _VERIFY(fResult = ReleaseSemaphore(m_hSemaphore, 1, NULL));
  186. TraceFunctLeave();
  187. return TRUE;
  188. cleanup:
  189. // Destroy hash object.
  190. if(hHash != 0)
  191. _VERIFY(CryptDestroyHash(hHash));
  192. _VERIFY(fResult = ReleaseSemaphore(m_hSemaphore, 1, NULL));
  193. TraceFunctLeave();
  194. return FALSE;
  195. }
  196. // This function must be called before any member functions of the
  197. // class are used.
  198. // Returns FALSE if a Fatal error occured, TRUE otherwise
  199. // this always gets the machine keyset
  200. BOOL CCryptFunctions::InitCrypt()
  201. {
  202. TraceFunctEnter("InitCrypt");
  203. TCHAR szSemaphoreName[100];
  204. SECURITY_ATTRIBUTES sa;
  205. SECURITY_DESCRIPTOR sd;
  206. BOOL fResult;
  207. if (m_hProv)
  208. {
  209. DebugTrace(CRYPT_FNC_ID,"Already been inited before");
  210. TraceFunctLeave();
  211. return TRUE;
  212. }
  213. // create a Unique semaphore name for each process
  214. wsprintf(szSemaphoreName, TEXT("%s%d"), CRYPTFNC_SEMAPHORE_NAME,
  215. GetCurrentProcessId());
  216. // also create a security descriptor so that everyone has access
  217. // to the semaphore. Otherwise if the semaphore is created in a
  218. // service running in system context, then only system can use
  219. // this semaphore.
  220. fResult = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  221. _ASSERT(fResult);
  222. // if the security descriptor has a NULL DACL, then this gives
  223. // everyone access to this semaphore.
  224. fResult = SetSecurityDescriptorDacl(&sd,
  225. TRUE,
  226. NULL, // NULL ACL
  227. FALSE);
  228. _ASSERT(fResult);
  229. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  230. sa.bInheritHandle = FALSE;
  231. sa.lpSecurityDescriptor = & sd;
  232. m_hSemaphore = CreateSemaphore(&sa, // pointer to security attributes
  233. 1, // initial count
  234. 1, // maximum count
  235. szSemaphoreName);// pointer to Semaphore-object name
  236. if ( NULL == m_hSemaphore)
  237. {
  238. DWORD dwError;
  239. dwError = GetLastError();
  240. ErrorTrace(CRYPT_FNC_ID, "CreateSemaphore failed 0x%x", dwError);
  241. _ASSERT(0);
  242. goto cleanup;
  243. }
  244. if(!CryptAcquireContext(&m_hProv, // address to get the handle to CSP
  245. NULL, // contianer name - use default container
  246. NULL, // provider
  247. PROV_RSA_FULL, // type of provider
  248. CRYPT_VERIFYCONTEXT))
  249. {
  250. ErrorTrace(CRYPT_FNC_ID, "Fatal Error 0x%x during first"
  251. "call to CryptAcquireContext", GetLastError());
  252. goto cleanup;
  253. }
  254. #if 0 // This code is being commented out since there are problems
  255. // getting the machine keyset from an ASP app running in the IIS
  256. // anonymous user context. This means that we will not be able to
  257. // do any signing or in some cases encryption. This is fine since
  258. // we do not want to do this currently.
  259. // Get handle to machine default provider.
  260. if(!CryptAcquireContext(&m_hProv, // address to get the handle to CSP
  261. NULL, // contianer name - use default container
  262. MS_DEF_PROV, // provider
  263. PROV_RSA_FULL, // type of provider
  264. CRYPT_MACHINE_KEYSET))
  265. {
  266. DWORD dwError;
  267. dwError = GetLastError();
  268. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptAcquireContext",
  269. dwError);
  270. DebugTrace(CRYPT_FNC_ID, "Calling CryptAcquireContext again"
  271. "to create keyset");
  272. if (! CryptAcquireContext(&m_hProv,// handle to CSP
  273. NULL,// contianer name - use default
  274. MS_DEF_PROV, // provider
  275. PROV_RSA_FULL, // type of provider
  276. CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET) )
  277. // create the keyset
  278. {
  279. ErrorTrace(CRYPT_FNC_ID, "Fatal Error 0x%x during second"
  280. "call to CryptAcquireContext", GetLastError());
  281. goto cleanup;
  282. }
  283. }
  284. #endif
  285. TraceFunctLeave();
  286. return TRUE;
  287. cleanup:
  288. // Release provider handle.
  289. if(m_hProv != 0)
  290. {
  291. _VERIFY(CryptReleaseContext(m_hProv, 0));
  292. m_hProv =0 ;
  293. }
  294. TraceFunctLeave();
  295. return FALSE;
  296. }
  297. CCryptFunctions::~CCryptFunctions()
  298. {
  299. TraceFunctEnter("~CCryptFunctions");
  300. // Release provider handle.
  301. if(m_hProv != 0)
  302. {
  303. _VERIFY(CryptReleaseContext(m_hProv, 0));
  304. }
  305. if (NULL != m_hSemaphore)
  306. {
  307. _VERIFY(CloseHandle(m_hSemaphore));
  308. }
  309. TraceFunctLeave();
  310. }
  311. CCryptFunctions::CCryptFunctions()
  312. {
  313. m_hProv = 0;
  314. m_hSemaphore = NULL;
  315. }
  316. // This function generates random data of length dwLength bytes. This
  317. // data is guaranteed by CryptoAPI to be truly random.
  318. // Returns FALSE if a Fatal error occured, TRUE otherwise
  319. BOOL CCryptFunctions::GenerateSecretKey(
  320. BYTE * pbData,// Buffer to store secret key
  321. //buffer must be long enough for dwLength bits
  322. DWORD dwLength ) // length of secret key in bytes
  323. {
  324. DWORD dwResult;
  325. BOOL fResult;
  326. // Init should have been successfully called before
  327. _ASSERT(m_hProv);
  328. TraceFunctEnter("GenerateSecretKey");
  329. dwResult = WaitForSingleObject( m_hSemaphore,//handle of object to wait for
  330. INFINITE); // no time-out
  331. _ASSERT(WAIT_OBJECT_0 == dwResult);
  332. // Create a random dwLength byte number for a secret.
  333. if(!CryptGenRandom(m_hProv, // handle to CSP
  334. dwLength , // number of bytes of
  335. // random data to be generated
  336. pbData )) // buffer - uninitialized
  337. {
  338. _VERIFY(fResult = ReleaseSemaphore(m_hSemaphore, 1, NULL));
  339. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptGenRandom",
  340. GetLastError());
  341. TraceFunctLeave();
  342. return FALSE;
  343. }
  344. _VERIFY(fResult = ReleaseSemaphore(m_hSemaphore, 1, NULL));
  345. TraceFunctLeave();
  346. return TRUE;
  347. }
  348. // Given a password, and data to encrypt this function generates a
  349. // session key from the password. This session key is then used to
  350. // encrypt the data.
  351. // Returns FALSE if a Fatal error occured, TRUE otherwise
  352. BOOL CCryptFunctions::EncryptDataWithPassword(
  353. TCHAR * pszPassword, // password
  354. BYTE * pbData, // Data to be encrypted
  355. DWORD dwDataLength, // Length of data in bytes
  356. BYTE * pbEncryptedData, // Encrypted secret key will be stored here
  357. DWORD * pdwEncrytedBufferLen // Length of this buffer
  358. )
  359. {
  360. DWORD dwBufferLength;
  361. HCRYPTKEY hKey = 0;
  362. TraceFunctEnter("EncryptDataWithPassword");
  363. // Init should have been successfully called before
  364. _ASSERT(m_hProv);
  365. if (!GenerateSessionKeyFromPassword(&hKey, pszPassword))
  366. goto cleanup;
  367. if (dwDataLength > * pdwEncrytedBufferLen )
  368. {
  369. ErrorTrace(CRYPT_FNC_ID, "Buffer not large enough");
  370. goto cleanup;
  371. }
  372. // copy the data into another buffer to encrypt it
  373. memcpy (pbEncryptedData, pbData, dwDataLength);
  374. dwBufferLength = *pdwEncrytedBufferLen;
  375. *pdwEncrytedBufferLen = dwDataLength;
  376. // now encrypt the secret key using the key generated
  377. if ( ! CryptEncrypt(hKey,
  378. 0, // no hash required
  379. TRUE, // Final packet
  380. 0, // Flags - always 0
  381. pbEncryptedData, // data buffer
  382. pdwEncrytedBufferLen, // length of data
  383. dwBufferLength ) ) // size of buffer
  384. {
  385. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptEncrypt",
  386. GetLastError());
  387. goto cleanup;
  388. }
  389. // destroy session key
  390. _VERIFY(CryptDestroyKey(hKey));
  391. TraceFunctLeave();
  392. return TRUE;
  393. cleanup:
  394. // destroy session key
  395. if (hKey != 0)
  396. _VERIFY(CryptDestroyKey(hKey));
  397. TraceFunctLeave();
  398. return FALSE;
  399. }
  400. // Given a password, and encrypted data using EncryptDataWithPassword,
  401. // this function generates a session key from the password. This
  402. // session key is then used to decrypt the data.
  403. // returns
  404. // CRYPT_FNC_NO_ERROR no error
  405. // CRYPT_FNC_BAD_PASSWORD password bad try again
  406. // CRYPT_FNC_INSUFFICIENT_BUFFER larger buffer is required
  407. // *pdwEncrytedBufferLen is set to required length
  408. // CRYPT_FNC_INIT_NOT_CALLED InitCrypt not successfully called
  409. // CRYPT_FNC_INTERNAL_ERROR
  410. DWORD CCryptFunctions::DecryptDataWithPassword(
  411. TCHAR * pszPassword, // password
  412. BYTE * pbData, // Decrypted Data will be stored here
  413. DWORD *pdwDataBufferLength, // Length of the above buffer in bytes
  414. BYTE * pbEncryptedData, // Encrypted data
  415. DWORD dwEncrytedDataLen // Length of encrypted data
  416. )
  417. {
  418. DWORD dwBufferLength;
  419. HCRYPTKEY hKey = 0;
  420. TraceFunctEnter("DecryptDataWithPassword");
  421. DWORD dwError;
  422. // Init should have been successfully called before
  423. if (m_hProv== 0)
  424. {
  425. dwError = CRYPT_FNC_INIT_NOT_CALLED;
  426. goto cleanup;
  427. }
  428. if (!GenerateSessionKeyFromPassword(&hKey, pszPassword))
  429. {
  430. dwError = CRYPT_FNC_INTERNAL_ERROR;
  431. goto cleanup;
  432. }
  433. // check if buffer is large enough
  434. if ( dwEncrytedDataLen > *pdwDataBufferLength )
  435. {
  436. dwError = CRYPT_FNC_INSUFFICIENT_BUFFER;
  437. *pdwDataBufferLength = dwEncrytedDataLen;
  438. goto cleanup;
  439. }
  440. // copy the data into another buffer to encrypt it
  441. memcpy (pbData, pbEncryptedData, dwEncrytedDataLen);
  442. *pdwDataBufferLength = dwEncrytedDataLen;
  443. // now decrypt the secret key using the key generated
  444. if ( ! CryptDecrypt(hKey,
  445. 0, // no hash required
  446. TRUE, // Final packet
  447. 0, // Flags - always 0
  448. pbData, // data buffer
  449. pdwDataBufferLength )) // length of data
  450. {
  451. DWORD dwCryptError = GetLastError();
  452. DebugTrace(CRYPT_FNC_ID, "Error 0x%x during CryptDecrypt",
  453. dwCryptError);
  454. // CryptDecrypt fails with error NTE_BAD_DATA if the password
  455. // is incorrect. Hence we should check for this error and prompt the
  456. // user again for the password
  457. // Issue: if the data is garbled in transit, then the secret key
  458. // will still be decrypted into a wrong value and the user will not
  459. // know about it.
  460. if ( dwCryptError == NTE_BAD_DATA )
  461. {
  462. dwError = CRYPT_FNC_BAD_PASSWORD;
  463. }
  464. else
  465. {
  466. dwError = CRYPT_FNC_INTERNAL_ERROR;
  467. }
  468. goto cleanup;
  469. }
  470. // destroy session key
  471. _VERIFY(CryptDestroyKey(hKey));
  472. TraceFunctLeave();
  473. return CRYPT_FNC_NO_ERROR;
  474. cleanup:
  475. // destroy session key
  476. if (hKey != 0)
  477. _VERIFY(CryptDestroyKey(hKey));
  478. TraceFunctLeave();
  479. return dwError;
  480. }
  481. /*
  482. This function:
  483. 1. Generates a session key to encrypt the secret data
  484. 2. Encrypts the secret data using this session key - return this
  485. value in the pbEncryptedData parameter
  486. 3. Encrypts the session key using the public key in the CSP -
  487. only the private key can decrypt this value. Return the encrypted
  488. session key in the pbEncryptedSessionKey parameter.
  489. returns
  490. CRYPT_FNC_NO_ERROR no error
  491. CRYPT_FNC_INSUFFICIENT_BUFFER larger buffer is required
  492. *pdwEncrytedBufferLen and are set to required length
  493. CRYPT_FNC_INIT_NOT_CALLED InitCrypt not successfully called
  494. CRYPT_FNC_INTERNAL_ERROR
  495. */
  496. DWORD CCryptFunctions::EncryptDataAndExportSessionKey(
  497. BYTE * pbData, // Secret Data
  498. DWORD dwDataLen, // Secret Data Length
  499. BYTE * pbEncryptedData, // Buffer to store Encrypted Data
  500. DWORD * pdwEncrytedBufferLen, // Length of above buffer
  501. BYTE * pbEncryptedSessionKey, // Buffer to store encrypted session key
  502. DWORD * pdwEncrytedSessionKeyLength) // Length of above buffer
  503. {
  504. HCRYPTKEY hXchgKey = 0;
  505. HCRYPTKEY hKey = 0;
  506. DWORD dwBufferLen, dwError;
  507. TraceFunctEnter("EncryptDataAndExportSessionKey");
  508. // Init should have been successfully called before
  509. if (m_hProv== 0)
  510. {
  511. dwError = CRYPT_FNC_INIT_NOT_CALLED;
  512. goto cleanup;
  513. }
  514. // now get the public key to encrypt Secret key for storage
  515. // Get handle to exahange key.
  516. if(!CryptGetUserKey(m_hProv, // CSP provider
  517. AT_KEYEXCHANGE, // we need the exchange public key
  518. &hXchgKey))
  519. {
  520. DWORD dwCryptError;
  521. dwCryptError = GetLastError();
  522. if ( dwCryptError == NTE_NO_KEY )
  523. {
  524. DebugTrace(CRYPT_FNC_ID, "Error NTE_NO_KEY during"
  525. "CryptGetUserKey");
  526. DebugTrace(CRYPT_FNC_ID, "Calling CryptGenKey to generate key");
  527. if (!CryptGenKey( m_hProv,// CSP provider
  528. AT_KEYEXCHANGE, // generate the exchange
  529. //public key
  530. 0, //no flags
  531. &hXchgKey ) )
  532. {
  533. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptGenKey",
  534. GetLastError());
  535. dwError = CRYPT_FNC_INTERNAL_ERROR;
  536. goto cleanup;
  537. }
  538. }
  539. else
  540. {
  541. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptGetUserKey",
  542. GetLastError());
  543. dwError = CRYPT_FNC_INTERNAL_ERROR;
  544. goto cleanup;
  545. }
  546. }
  547. // now generate a random session key to encrypt the secret key
  548. // Create block cipher session key.
  549. if (!CryptGenKey(m_hProv, // CSP provider
  550. CALG_RC2, // use RC2 block cipher algorithm
  551. CRYPT_EXPORTABLE, // flags
  552. &hKey)) // address of key
  553. {
  554. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptGenKey",
  555. GetLastError());
  556. dwError = CRYPT_FNC_INTERNAL_ERROR;
  557. goto cleanup;
  558. }
  559. // Export key into a simple key blob.
  560. if(!CryptExportKey(hKey, // key to export
  561. hXchgKey, // our exchange public key
  562. SIMPLEBLOB, // type of blob
  563. 0, // flags (always 0)
  564. pbEncryptedSessionKey, // buffer to store blob
  565. pdwEncrytedSessionKeyLength)) // length of above buffer
  566. {
  567. // BUGBUG check here if insufficient buffer error
  568. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptExportKey",
  569. GetLastError());
  570. goto cleanup;
  571. }
  572. // check if buffer is large enough
  573. if ( dwDataLen > *pdwEncrytedBufferLen )
  574. {
  575. dwError = CRYPT_FNC_INSUFFICIENT_BUFFER;
  576. *pdwEncrytedBufferLen = dwDataLen;
  577. goto cleanup;
  578. }
  579. // copy the data into another buffer to encrypt it
  580. memcpy (pbEncryptedData, pbData, dwDataLen);
  581. dwBufferLen = *pdwEncrytedBufferLen;
  582. *pdwEncrytedBufferLen = dwDataLen;
  583. // now encrypt the secret key using the key generated
  584. if ( ! CryptEncrypt(hKey,
  585. 0, // no hash required
  586. TRUE, // Final packet
  587. 0, // Flags - always 0
  588. pbEncryptedData, // data buffer
  589. pdwEncrytedBufferLen, // length of data
  590. dwBufferLen ) ) // size of buffer
  591. {
  592. ErrorTrace(CRYPT_FNC_ID, "Error 0x%x during CryptEncrypt",
  593. GetLastError());
  594. dwError = CRYPT_FNC_INTERNAL_ERROR;
  595. goto cleanup;
  596. }
  597. _VERIFY(CryptDestroyKey(hKey));
  598. _VERIFY(CryptDestroyKey(hXchgKey));
  599. TraceFunctLeave();
  600. return CRYPT_FNC_NO_ERROR;
  601. cleanup:
  602. // Destroy key exchange key handle.
  603. if(hXchgKey != 0)
  604. _VERIFY(CryptDestroyKey(hXchgKey));
  605. // destroy session key
  606. if (hKey != 0)
  607. _VERIFY(CryptDestroyKey(hKey));
  608. TraceFunctLeave();
  609. return dwError;
  610. }
  611. /*
  612. This function performs the reverse of EncryptDataAndExportSessionKey:
  613. 1. It imports the session key using the private key in the CSP that
  614. was used to encrypt the secret data.
  615. 2. It decrypts the secret data using this session key - return this
  616. value in the pbData parameter
  617. returns
  618. CRYPT_FNC_NO_ERROR no error
  619. CRYPT_FNC_INSUFFICIENT_BUFFER larger buffer is required
  620. *pdwDataLen is set to required length
  621. CRYPT_FNC_INIT_NOT_CALLED InitCrypt not successfully called
  622. CRYPT_FNC_INTERNAL_ERROR
  623. */
  624. DWORD CCryptFunctions::ImportSessionKeyAndDecryptData(
  625. BYTE * pbData, // Buffer to store secret Data
  626. DWORD * pdwDataLen, // Length of Above buffer
  627. BYTE * pbEncryptedData, // Buffer that stores Encrypted Data
  628. DWORD dwEncrytedBufferLen, // Length of above data
  629. BYTE * pbEncryptedSessionKey, // Buffer that stores encrypted session key
  630. DWORD dwEncrytedSessionKeyLength) // Length of above data
  631. {
  632. HCRYPTKEY hKey = 0;
  633. DWORD dwError;
  634. TraceFunctEnter("ImportSessionKeyAndDecryptData");
  635. // Init should have been successfully called before
  636. if (m_hProv== 0)
  637. {
  638. dwError = CRYPT_FNC_INIT_NOT_CALLED;
  639. goto cleanup;
  640. }
  641. // now import the key from the registry
  642. // Import key blob into CSP.
  643. if(!CryptImportKey( m_hProv, // CSP provider
  644. pbEncryptedSessionKey,// buffer that stores encrypted
  645. // session key
  646. dwEncrytedSessionKeyLength,// length of data in
  647. // above buffer
  648. 0, // since we have a SIMPLEBLOB and the key blob
  649. // is encrypted with the key exchange key pair, this
  650. // parameter is zero
  651. 0, // flags
  652. &hKey)) // key to export to
  653. {
  654. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptImportKey",
  655. GetLastError());
  656. dwError = CRYPT_FNC_INTERNAL_ERROR;
  657. goto cleanup;
  658. }
  659. // check if buffer is large enough
  660. if ( dwEncrytedBufferLen > *pdwDataLen )
  661. {
  662. dwError = CRYPT_FNC_INSUFFICIENT_BUFFER;
  663. *pdwDataLen = dwEncrytedBufferLen;
  664. goto cleanup;
  665. }
  666. // copy the data into another buffer to encrypt it
  667. memcpy (pbData, pbEncryptedData, dwEncrytedBufferLen);
  668. *pdwDataLen = dwEncrytedBufferLen;
  669. // now decrypt the secret key using the key generated
  670. if ( ! CryptDecrypt(hKey,
  671. 0, // no hash required
  672. TRUE, // Final packet
  673. 0, // Flags - always 0
  674. pbData, // data buffer
  675. pdwDataLen )) // length of data
  676. {
  677. ErrorTrace(CRYPT_FNC_ID,"Error 0x%x during CryptDecrypt",
  678. GetLastError());
  679. dwError = CRYPT_FNC_INTERNAL_ERROR;
  680. goto cleanup;
  681. }
  682. _VERIFY(CryptDestroyKey(hKey));
  683. TraceFunctLeave();
  684. return CRYPT_FNC_NO_ERROR;
  685. cleanup:
  686. // destroy session key
  687. if (hKey != 0)
  688. _VERIFY(CryptDestroyKey(hKey));
  689. TraceFunctLeave();
  690. return dwError;
  691. }