Source code of Windows XP (NT5)
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.

1178 lines
32 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : nt_crypt.c //
  3. // DESCRIPTION : Crypto CP interfaces: //
  4. // CPEncrypt //
  5. // CPDecrypt //
  6. // AUTHOR : //
  7. // HISTORY : //
  8. // Jan 25 1995 larrys Changed from Nametag //
  9. // Jan 30 1995 larrys Cleanup code //
  10. // Feb 23 1995 larrys Changed NTag_SetLastError to SetLastError //
  11. // Apr 10 1995 larrys Added freeing of RC4 key data on final flag //
  12. // May 8 1995 larrys Changes for MAC hashing //
  13. // May 9 1995 larrys Added check for double encryption //
  14. // May 10 1995 larrys added private api calls //
  15. // Jul 13 1995 larrys Changed MAC stuff //
  16. // Aug 16 1995 larrys Removed exchange key stuff //
  17. // Oct 05 1995 larrys Fixed bugs 50 & 51 //
  18. // Nov 8 1995 larrys Fixed SUR bug 10769 //
  19. // May 15 1996 larrys Changed NTE_NO_MEMORY to ERROR_NOT_ENOUGH... //
  20. // May 3 2000 dbarlow Fix return codes //
  21. // //
  22. // Copyright (C) 1993 Microsoft Corporation All Rights Reserved //
  23. /////////////////////////////////////////////////////////////////////////////
  24. #include "precomp.h"
  25. #include "nt_rsa.h"
  26. #include "mac.h"
  27. #include "tripldes.h"
  28. #include "swnt_pk.h"
  29. #include "protstor.h"
  30. #include "ntagum.h"
  31. #include "aes.h"
  32. #define DE_BLOCKLEN 8 // size of double encrypt block
  33. BYTE dbDEncrypt[DE_BLOCKLEN]; // First 8 bytes of last encrypt
  34. BOOL fDEncrypt = FALSE; // Flag for Double encrypt
  35. BYTE dbDDecrypt[DE_BLOCKLEN]; // First 8 bytes of last Decrypt
  36. DWORD fDDecrypt = FALSE; // Flag for Double Decrypt
  37. extern CSP_STRINGS g_Strings;
  38. extern BOOL
  39. FIsLegalKey(
  40. PNTAGUserList pTmpUser,
  41. PNTAGKeyList pKey,
  42. BOOL fRC2BigKeyOK);
  43. extern DWORD
  44. InflateKey(
  45. IN PNTAGKeyList pTmpKey);
  46. /* BlockEncrypt -
  47. Run a block cipher over a block of size *pdwDataLen.
  48. */
  49. DWORD
  50. BlockEncrypt(
  51. void EncFun(BYTE *In, BYTE *Out, void *key, int op),
  52. PNTAGKeyList pKey,
  53. int BlockLen,
  54. BOOL Final,
  55. BYTE *pbData,
  56. DWORD *pdwDataLen,
  57. DWORD dwBufLen)
  58. {
  59. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  60. DWORD cbPartial, dwPadVal, dwDataLen;
  61. BYTE *pbBuf;
  62. dwDataLen = *pdwDataLen;
  63. // Check to see if we are encrypting something already
  64. if (pKey->InProgress == FALSE)
  65. {
  66. pKey->InProgress = TRUE;
  67. if (pKey->Mode == CRYPT_MODE_CBC || pKey->Mode == CRYPT_MODE_CFB)
  68. memcpy(pKey->FeedBack, pKey->IV, BlockLen);
  69. }
  70. // check length of the buffer and calculate the pad
  71. // (if multiple of blocklen, do a full block of pad)
  72. cbPartial = (dwDataLen % BlockLen);
  73. if (Final)
  74. {
  75. dwPadVal = BlockLen - cbPartial;
  76. if (pbData == NULL || dwBufLen < dwDataLen + dwPadVal)
  77. {
  78. // set what we need
  79. *pdwDataLen = dwDataLen + dwPadVal;
  80. dwReturn = (NULL == pbData) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  81. goto ErrorExit;
  82. }
  83. else
  84. {
  85. // Clear encryption flag
  86. pKey->InProgress = FALSE;
  87. }
  88. }
  89. else
  90. {
  91. if (pbData == NULL)
  92. {
  93. *pdwDataLen = dwDataLen;
  94. dwReturn = ERROR_SUCCESS;
  95. goto ErrorExit;
  96. }
  97. // Non-Final make multiple of the blocklen
  98. if (cbPartial)
  99. {
  100. // set what we need
  101. *pdwDataLen = dwDataLen + cbPartial;
  102. ASSERT((*pdwDataLen % BlockLen) == 0);
  103. dwReturn = (DWORD)NTE_BAD_DATA;
  104. goto ErrorExit;
  105. }
  106. dwPadVal = 0;
  107. }
  108. // allocate memory for a temporary buffer
  109. if ((pbBuf = (BYTE *)_nt_malloc(BlockLen)) == NULL)
  110. {
  111. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  112. goto ErrorExit;
  113. }
  114. if (dwPadVal)
  115. {
  116. // Fill the pad with a value equal to the
  117. // length of the padding, so decrypt will
  118. // know the length of the original data
  119. // and as a simple integrity check.
  120. memset(pbData + dwDataLen, (int)dwPadVal, (size_t)dwPadVal);
  121. }
  122. dwDataLen += dwPadVal;
  123. *pdwDataLen = dwDataLen;
  124. ASSERT((dwDataLen % BlockLen) == 0);
  125. // pump the full blocks of data through
  126. while (dwDataLen)
  127. {
  128. ASSERT(dwDataLen >= (DWORD)BlockLen);
  129. // put the plaintext into a temporary
  130. // buffer, then encrypt the data
  131. // back into the caller's buffer
  132. memcpy(pbBuf, pbData, BlockLen);
  133. switch (pKey->Mode)
  134. {
  135. case CRYPT_MODE_CBC:
  136. CBC(EncFun, BlockLen, pbData, pbBuf, pKey->pData,
  137. ENCRYPT, pKey->FeedBack);
  138. break;
  139. case CRYPT_MODE_ECB:
  140. EncFun(pbData, pbBuf, pKey->pData, ENCRYPT);
  141. break;
  142. case CRYPT_MODE_CFB:
  143. CFB(EncFun, BlockLen, pbData, pbBuf, pKey->pData,
  144. ENCRYPT, pKey->FeedBack);
  145. break;
  146. default:
  147. _nt_free(pbBuf, BlockLen);
  148. dwReturn = (DWORD) NTE_BAD_ALGID;
  149. goto ErrorExit;
  150. }
  151. pbData += BlockLen;
  152. dwDataLen -= BlockLen;
  153. }
  154. _nt_free(pbBuf, BlockLen);
  155. dwReturn = ERROR_SUCCESS;
  156. ErrorExit:
  157. return dwReturn;
  158. }
  159. DWORD
  160. BlockDecrypt(
  161. void DecFun(BYTE *In, BYTE *Out, void *key, int op),
  162. PNTAGKeyList pKey,
  163. int BlockLen,
  164. BOOL Final,
  165. BYTE *pbData,
  166. DWORD *pdwDataLen)
  167. {
  168. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  169. BYTE *pbBuf;
  170. DWORD dwDataLen, BytePos, dwPadVal, i;
  171. dwDataLen = *pdwDataLen;
  172. // Check to see if we are decrypting something already
  173. if (pKey->InProgress == FALSE)
  174. {
  175. pKey->InProgress = TRUE;
  176. if (pKey->Mode == CRYPT_MODE_CBC ||
  177. pKey->Mode == CRYPT_MODE_CFB)
  178. {
  179. memcpy(pKey->FeedBack, pKey->IV, BlockLen);
  180. }
  181. }
  182. // The data length must be a multiple of the algorithm
  183. // pad size.
  184. if (dwDataLen % BlockLen)
  185. {
  186. dwReturn = (DWORD)NTE_BAD_DATA;
  187. goto ErrorExit;
  188. }
  189. // allocate memory for a temporary buffer
  190. if ((pbBuf = (BYTE *)_nt_malloc(BlockLen)) == NULL)
  191. {
  192. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  193. goto ErrorExit;
  194. }
  195. // pump the data through the decryption, including padding
  196. // NOTE: the total length is a multiple of BlockLen
  197. for (BytePos = 0; (BytePos + BlockLen) <= dwDataLen; BytePos += BlockLen)
  198. {
  199. // put the encrypted text into a temp buffer
  200. memcpy (pbBuf, pbData + BytePos, BlockLen);
  201. switch (pKey->Mode)
  202. {
  203. case CRYPT_MODE_CBC:
  204. CBC(DecFun, BlockLen, pbData + BytePos, pbBuf, pKey->pData,
  205. DECRYPT, pKey->FeedBack);
  206. break;
  207. case CRYPT_MODE_ECB:
  208. DecFun(pbData + BytePos, pbBuf, pKey->pData, DECRYPT);
  209. break;
  210. case CRYPT_MODE_CFB:
  211. CFB(DecFun, BlockLen, pbData + BytePos, pbBuf, pKey->pData,
  212. DECRYPT, pKey->FeedBack);
  213. break;
  214. default:
  215. _nt_free(pbBuf, BlockLen);
  216. dwReturn = (DWORD)NTE_BAD_ALGID;
  217. goto ErrorExit;
  218. }
  219. }
  220. _nt_free(pbBuf, BlockLen);
  221. // if this is the final block of data then
  222. // verify the padding and remove the pad size
  223. // from the data length. NOTE: The padding is
  224. // filled with a value equal to the length
  225. // of the padding and we are guaranteed >= 1
  226. // byte of pad.
  227. // ## NOTE: if the pad is wrong, the user's
  228. // buffer is hosed, because
  229. // ## we've decrypted into the user's
  230. // buffer -- can we re-encrypt it?
  231. if (Final)
  232. {
  233. pKey->InProgress = FALSE;
  234. dwPadVal = (DWORD)*(pbData + dwDataLen - 1);
  235. if (dwPadVal == 0 || dwPadVal > (DWORD) BlockLen)
  236. {
  237. dwReturn = (DWORD)NTE_BAD_DATA;
  238. goto ErrorExit;
  239. }
  240. // Make sure all the (rest of the) pad bytes are correct.
  241. for (i=1; i<dwPadVal; i++)
  242. {
  243. if (pbData[dwDataLen - (i + 1)] != dwPadVal)
  244. {
  245. dwReturn = (DWORD)NTE_BAD_DATA;
  246. goto ErrorExit;
  247. }
  248. }
  249. // Only need to update the length on final
  250. *pdwDataLen -= dwPadVal;
  251. }
  252. dwReturn = ERROR_SUCCESS;
  253. ErrorExit:
  254. return dwReturn;
  255. }
  256. /*
  257. - SymEncrypt
  258. -
  259. * Purpose:
  260. * Encrypt data with symmetric algorithms. This function is used
  261. * by the LocalEncrypt function as well as the WrapSymKey (nt_key.c)
  262. * function.
  263. *
  264. * Parameters:
  265. * IN pKey - Handle to the key
  266. * IN fFinal - Boolean indicating if this is the final
  267. * block of plaintext
  268. * IN OUT pbData - Data to be encrypted
  269. * IN OUT pcbData - Pointer to the length of the data to be
  270. * encrypted
  271. * IN cbBuf - Size of Data buffer
  272. *
  273. * Returns:
  274. */
  275. DWORD
  276. SymEncrypt(
  277. IN PNTAGKeyList pKey,
  278. IN BOOL fFinal,
  279. IN OUT BYTE *pbData,
  280. IN OUT DWORD *pcbData,
  281. IN DWORD cbBuf)
  282. {
  283. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  284. DWORD dwSts;
  285. // determine which algorithm is to be used
  286. switch (pKey->Algid)
  287. {
  288. #ifdef CSP_USE_RC2
  289. case CALG_RC2:
  290. dwSts = BlockEncrypt(RC2, pKey, RC2_BLOCKLEN, fFinal, pbData,
  291. pcbData, cbBuf);
  292. if (ERROR_SUCCESS != dwSts)
  293. {
  294. dwReturn = dwSts;
  295. goto ErrorExit;
  296. }
  297. break;
  298. #endif
  299. #ifdef CSP_USE_DES
  300. case CALG_DES:
  301. dwSts = BlockEncrypt(des, pKey, DES_BLOCKLEN, fFinal, pbData,
  302. pcbData, cbBuf);
  303. if (ERROR_SUCCESS != dwSts)
  304. {
  305. dwReturn = dwSts;
  306. goto ErrorExit;
  307. }
  308. break;
  309. #endif
  310. #ifdef CSP_USE_3DES
  311. case CALG_3DES_112:
  312. case CALG_3DES:
  313. dwSts = BlockEncrypt(tripledes, pKey, DES_BLOCKLEN, fFinal, pbData,
  314. pcbData, cbBuf);
  315. if (ERROR_SUCCESS != dwSts)
  316. {
  317. dwReturn = dwSts;
  318. goto ErrorExit;
  319. }
  320. break;
  321. #endif
  322. #ifdef CSP_USE_RC4
  323. case CALG_RC4:
  324. if (pbData == NULL)
  325. {
  326. dwReturn = ERROR_SUCCESS;
  327. goto ErrorExit;
  328. }
  329. if (*pcbData > cbBuf)
  330. {
  331. dwReturn = ERROR_MORE_DATA;
  332. goto ErrorExit;
  333. }
  334. rc4((struct RC4_KEYSTRUCT *)pKey->pData, *pcbData, pbData);
  335. if (fFinal)
  336. {
  337. if (pKey->pData)
  338. _nt_free (pKey->pData, pKey->cbDataLen);
  339. pKey->pData = 0;
  340. pKey->cbDataLen = 0;
  341. }
  342. break;
  343. #endif
  344. #ifdef CSP_USE_AES
  345. case CALG_AES_128:
  346. case CALG_AES_192:
  347. case CALG_AES_256:
  348. dwSts = BlockEncrypt(aes, pKey, pKey->dwBlockLen, fFinal, pbData,
  349. pcbData, cbBuf);
  350. if (ERROR_SUCCESS != dwSts)
  351. {
  352. dwReturn = dwSts;
  353. goto ErrorExit;
  354. }
  355. break;
  356. #endif
  357. default:
  358. dwReturn = (DWORD)NTE_BAD_ALGID;
  359. goto ErrorExit;
  360. }
  361. dwReturn = ERROR_SUCCESS;
  362. ErrorExit:
  363. return dwReturn;
  364. }
  365. /*
  366. - LocalEncrypt
  367. -
  368. * Purpose:
  369. * Encrypt data
  370. *
  371. *
  372. * Parameters:
  373. * IN hUID - Handle to the CSP user
  374. * IN hKey - Handle to the key
  375. * IN hHash - Optional handle to a hash
  376. * IN Final - Boolean indicating if this is the final
  377. * block of plaintext
  378. * IN OUT pbData - Data to be encrypted
  379. * IN OUT pdwDataLen - Pointer to the length of the data to be
  380. * encrypted
  381. * IN dwBufLen - Size of Data buffer
  382. * IN fIsExternal - Flag to tell if the call is for internal
  383. * CSP use or external caller
  384. *
  385. * Returns:
  386. */
  387. DWORD
  388. LocalEncrypt(
  389. IN HCRYPTPROV hUID,
  390. IN HCRYPTKEY hKey,
  391. IN HCRYPTHASH hHash,
  392. IN BOOL Final,
  393. IN DWORD dwFlags,
  394. IN OUT BYTE *pbData,
  395. IN OUT DWORD *pdwDataLen,
  396. IN DWORD dwBufSize,
  397. IN BOOL fIsExternal)
  398. {
  399. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  400. DWORD dwDataLen;
  401. PNTAGUserList pTmpUser;
  402. PNTAGKeyList pTmpKey;
  403. PNTAGKeyList pTmpKey2;
  404. PNTAGHashList pTmpHash;
  405. DWORD dwLen;
  406. MACstate *pMAC;
  407. BSAFE_PUB_KEY *pBsafePubKey;
  408. BYTE *pbOutput = NULL;
  409. DWORD dwSts;
  410. if (0 != (dwFlags & ~CRYPT_OAEP))
  411. // && (0x9C580000 != dwFlags))
  412. {
  413. dwReturn = (DWORD)NTE_BAD_FLAGS;
  414. goto ErrorExit;
  415. }
  416. dwDataLen = *pdwDataLen;
  417. if ((Final == FALSE) && (dwDataLen == 0))
  418. {
  419. // If no data to encrypt and this isn't the last block,
  420. // then we're done. (if Final, we need to pad)
  421. dwReturn = ERROR_SUCCESS;
  422. goto ErrorExit;
  423. }
  424. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  425. if (NULL == pTmpUser)
  426. {
  427. dwReturn = (DWORD)NTE_BAD_UID;
  428. goto ErrorExit;
  429. }
  430. //
  431. // Check if encryption allowed
  432. //
  433. if (fIsExternal &&
  434. (PROV_RSA_SCHANNEL != pTmpUser->dwProvType) &&
  435. ((pTmpUser->Rights & CRYPT_DISABLE_CRYPT) == CRYPT_DISABLE_CRYPT))
  436. {
  437. dwReturn = (DWORD)NTE_PERM;
  438. goto ErrorExit;
  439. }
  440. dwSts = NTLValidate(hKey, hUID, KEY_HANDLE, &pTmpKey);
  441. if (ERROR_SUCCESS != dwSts)
  442. {
  443. dwSts= NTLValidate(hKey, hUID, EXCHPUBKEY_HANDLE, &pTmpKey);
  444. if (ERROR_SUCCESS != dwSts)
  445. {
  446. // NTLValidate doesn't know what error to set
  447. // so it set NTE_FAIL -- fix it up.
  448. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_KEY : dwSts;
  449. goto ErrorExit;
  450. }
  451. }
  452. if ((pTmpKey->Algid != CALG_RSA_KEYX) &&
  453. (!FIsLegalKey(pTmpUser, pTmpKey, FALSE)))
  454. {
  455. dwReturn = (DWORD)NTE_BAD_KEY;
  456. goto ErrorExit;
  457. }
  458. if ((Final == FALSE) && (pTmpKey->Algid != CALG_RC4))
  459. {
  460. if (dwDataLen < pTmpKey->dwBlockLen)
  461. {
  462. *pdwDataLen = pTmpKey->dwBlockLen;
  463. dwReturn = (DWORD)NTE_BAD_DATA;
  464. goto ErrorExit;
  465. }
  466. }
  467. if ((POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  468. && (fDEncrypt && pbData != NULL && *pdwDataLen != 0))
  469. {
  470. if (memcmp(dbDEncrypt, pbData, DE_BLOCKLEN) == 0)
  471. {
  472. dwReturn = (DWORD)NTE_DOUBLE_ENCRYPT;
  473. goto ErrorExit;
  474. }
  475. }
  476. // Check if we should do an auto-inflate
  477. if ((pTmpKey->pData == NULL) && (pTmpKey->Algid != CALG_RSA_KEYX))
  478. {
  479. dwSts = InflateKey(pTmpKey);
  480. if (ERROR_SUCCESS != dwSts)
  481. {
  482. dwReturn = dwSts;
  483. goto ErrorExit;
  484. }
  485. }
  486. if ((hHash != 0) && (NULL != pbData))
  487. {
  488. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  489. if (ERROR_SUCCESS != dwSts)
  490. {
  491. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_HASH : dwSts;
  492. goto ErrorExit;
  493. }
  494. if (pTmpHash->Algid == CALG_MAC)
  495. {
  496. // Check if we should do an auto-inflate
  497. pMAC = pTmpHash->pHashData;
  498. dwSts = NTLValidate(pTmpHash->hKey, hUID, KEY_HANDLE, &pTmpKey2);
  499. if (ERROR_SUCCESS != dwSts)
  500. {
  501. // NTLValidate doesn't know what error to set
  502. // so it set NTE_FAIL -- fix it up.
  503. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  504. goto ErrorExit;
  505. }
  506. if (pTmpKey2->pData == NULL)
  507. {
  508. dwSts = InflateKey(pTmpKey2);
  509. if (ERROR_SUCCESS != dwSts)
  510. {
  511. dwReturn = dwSts;
  512. goto ErrorExit;
  513. }
  514. }
  515. }
  516. if (!CPHashData(hUID, hHash, pbData, *pdwDataLen, 0))
  517. {
  518. dwReturn = GetLastError();
  519. goto ErrorExit;
  520. }
  521. }
  522. // determine which algorithm is to be used
  523. switch (pTmpKey->Algid)
  524. {
  525. case CALG_RSA_KEYX:
  526. pBsafePubKey = (BSAFE_PUB_KEY *) pTmpKey->pKeyValue;
  527. if (pBsafePubKey == NULL)
  528. {
  529. dwReturn = (DWORD)NTE_BAD_KEY;
  530. goto ErrorExit;
  531. }
  532. // compute length of resulting data
  533. dwLen = (pBsafePubKey->bitlen + 7) / 8;
  534. if (!CheckDataLenForRSAEncrypt(dwLen, *pdwDataLen, dwFlags))
  535. {
  536. dwReturn = (DWORD)NTE_BAD_LEN;
  537. goto ErrorExit;
  538. }
  539. if (pbData == NULL || dwBufSize < dwLen)
  540. {
  541. *pdwDataLen = dwLen; // set what we need
  542. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  543. goto ErrorExit;
  544. }
  545. pbOutput = (BYTE*)_nt_malloc(dwLen);
  546. if (NULL == pbOutput)
  547. {
  548. dwReturn =ERROR_NOT_ENOUGH_MEMORY;
  549. goto ErrorExit;
  550. }
  551. // perform the RSA encryption
  552. dwSts = RSAEncrypt(pTmpUser, pBsafePubKey, pbData, *pdwDataLen,
  553. pTmpKey->pbParams, pTmpKey->cbParams, dwFlags,
  554. pbOutput);
  555. if (ERROR_SUCCESS != dwSts)
  556. {
  557. dwReturn = dwSts;
  558. goto ErrorExit;
  559. }
  560. *pdwDataLen = dwLen;
  561. memcpy(pbData, pbOutput, *pdwDataLen);
  562. break;
  563. default:
  564. dwSts = SymEncrypt(pTmpKey, Final, pbData, pdwDataLen, dwBufSize);
  565. if (ERROR_SUCCESS != dwSts)
  566. {
  567. dwReturn = dwSts;
  568. goto ErrorExit;
  569. }
  570. }
  571. if ((POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  572. && (pbData != NULL && *pdwDataLen >= DE_BLOCKLEN))
  573. {
  574. memcpy(dbDEncrypt, pbData, DE_BLOCKLEN);
  575. fDEncrypt = TRUE;
  576. }
  577. else
  578. {
  579. fDEncrypt = FALSE;
  580. }
  581. dwReturn = ERROR_SUCCESS;
  582. ErrorExit:
  583. if (pbOutput)
  584. _nt_free(pbOutput, dwLen);
  585. return dwReturn;
  586. }
  587. /*
  588. - CPEncrypt
  589. -
  590. * Purpose:
  591. * Encrypt data
  592. *
  593. *
  594. * Parameters:
  595. * IN hUID - Handle to the CSP user
  596. * IN hKey - Handle to the key
  597. * IN hHash - Optional handle to a hash
  598. * IN Final - Boolean indicating if this is the final
  599. * block of plaintext
  600. * IN dwFlags - Flags values
  601. * IN OUT pbData - Data to be encrypted
  602. * IN OUT pdwDataLen - Pointer to the length of the data to be
  603. * encrypted
  604. * IN dwBufLen - Size of Data buffer
  605. *
  606. * Returns:
  607. */
  608. BOOL WINAPI
  609. CPEncrypt(
  610. IN HCRYPTPROV hUID,
  611. IN HCRYPTKEY hKey,
  612. IN HCRYPTHASH hHash,
  613. IN BOOL Final,
  614. IN DWORD dwFlags,
  615. IN OUT BYTE *pbData,
  616. IN OUT DWORD *pdwDataLen,
  617. IN DWORD dwBufSize)
  618. {
  619. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  620. DWORD dwSts;
  621. DWORD fRet;
  622. EntryPoint
  623. dwSts = LocalEncrypt(hUID, hKey, hHash, Final, dwFlags,
  624. pbData, pdwDataLen, dwBufSize, TRUE);
  625. if (ERROR_SUCCESS != dwSts)
  626. {
  627. dwReturn = dwSts;
  628. goto ErrorExit;
  629. }
  630. dwReturn = ERROR_SUCCESS;
  631. ErrorExit:
  632. fRet = (ERROR_SUCCESS == dwReturn);
  633. if (!fRet)
  634. SetLastError(dwReturn);
  635. return fRet;
  636. }
  637. /*
  638. - SymDecrypt
  639. -
  640. * Purpose:
  641. * Decrypt data with symmetric algorithms. This function is used
  642. * by the LocalDecrypt function as well as the UnWrapSymKey (nt_key.c)
  643. * function.
  644. *
  645. * Parameters:
  646. * IN pKey - Handle to the key
  647. * IN pHash - Handle to a hash if needed
  648. * IN fFinal - Boolean indicating if this is the final
  649. * block of plaintext
  650. * IN OUT pbData - Data to be decrypted
  651. * IN OUT pcbData - Pointer to the length of the data to be
  652. * decrypted
  653. *
  654. * Returns:
  655. */
  656. DWORD
  657. SymDecrypt(
  658. IN PNTAGKeyList pKey,
  659. IN PNTAGHashList pHash,
  660. IN BOOL fFinal,
  661. IN OUT BYTE *pbData,
  662. IN OUT DWORD *pcbData)
  663. {
  664. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  665. MACstate *pMAC;
  666. DWORD dwSts;
  667. // determine which algorithm is to be used
  668. switch (pKey->Algid)
  669. {
  670. #ifdef CSP_USE_RC2
  671. // the decryption is to be done with the RC2 algorithm
  672. case CALG_RC2:
  673. dwSts = BlockDecrypt(RC2, pKey, RC2_BLOCKLEN, fFinal, pbData,
  674. pcbData);
  675. if (ERROR_SUCCESS != dwSts)
  676. {
  677. dwReturn = dwSts;
  678. goto ErrorExit;
  679. }
  680. if ((fFinal) && (NULL != pHash) && (pHash->Algid == CALG_MAC) &&
  681. (pKey->Mode == CRYPT_MODE_CBC))
  682. {
  683. pMAC = (MACstate *)pHash->pHashData;
  684. memcpy(pMAC->Feedback, pKey->FeedBack, RC2_BLOCKLEN);
  685. pHash->dwHashState |= DATA_IN_HASH;
  686. }
  687. break;
  688. #endif
  689. #ifdef CSP_USE_DES
  690. // the decryption is to be done with DES
  691. case CALG_DES:
  692. dwSts = BlockDecrypt(des, pKey, DES_BLOCKLEN, fFinal, pbData,
  693. pcbData);
  694. if (ERROR_SUCCESS != dwSts)
  695. {
  696. dwReturn = dwSts;
  697. goto ErrorExit;
  698. }
  699. if ((fFinal) && (NULL != pHash) && (pHash->Algid == CALG_MAC) &&
  700. (pKey->Mode == CRYPT_MODE_CBC))
  701. {
  702. pMAC = (MACstate *)pHash->pHashData;
  703. memcpy(pMAC->Feedback, pKey->FeedBack, DES_BLOCKLEN);
  704. pHash->dwHashState |= DATA_IN_HASH;
  705. }
  706. break;
  707. #endif
  708. #ifdef CSP_USE_3DES
  709. // the decryption is to be done with the triple DES
  710. case CALG_3DES_112:
  711. case CALG_3DES:
  712. dwSts = BlockDecrypt(tripledes, pKey, DES_BLOCKLEN, fFinal, pbData,
  713. pcbData);
  714. if (ERROR_SUCCESS != dwSts)
  715. {
  716. dwReturn = dwSts;
  717. goto ErrorExit;
  718. }
  719. if ((fFinal) && (NULL != pHash) && (pHash->Algid == CALG_MAC) &&
  720. (pKey->Mode == CRYPT_MODE_CBC))
  721. {
  722. pMAC = (MACstate *)pHash->pHashData;
  723. memcpy(pMAC->Feedback, pKey->FeedBack, DES_BLOCKLEN);
  724. pHash->dwHashState |= DATA_IN_HASH;
  725. }
  726. break;
  727. #endif
  728. #ifdef CSP_USE_RC4
  729. case CALG_RC4:
  730. rc4((struct RC4_KEYSTRUCT *)pKey->pData, *pcbData, pbData);
  731. if (fFinal)
  732. {
  733. _nt_free (pKey->pData, pKey->cbDataLen);
  734. pKey->pData = 0;
  735. pKey->cbDataLen = 0;
  736. }
  737. break;
  738. #endif
  739. #ifdef CSP_USE_AES
  740. case CALG_AES_128:
  741. case CALG_AES_192:
  742. case CALG_AES_256:
  743. dwSts = BlockDecrypt(aes, pKey, pKey->dwBlockLen, fFinal, pbData,
  744. pcbData);
  745. if (ERROR_SUCCESS != dwSts)
  746. {
  747. dwReturn = dwSts;
  748. goto ErrorExit;
  749. }
  750. if ((fFinal) && (NULL != pHash) && (pHash->Algid == CALG_MAC) &&
  751. (pKey->Mode == CRYPT_MODE_CBC))
  752. {
  753. pMAC = (MACstate *)pHash->pHashData;
  754. memcpy(pMAC->Feedback, pKey->FeedBack, pKey->dwBlockLen);
  755. pHash->dwHashState |= DATA_IN_HASH;
  756. }
  757. break;
  758. #endif
  759. default:
  760. dwReturn = (DWORD)NTE_BAD_ALGID;
  761. goto ErrorExit;
  762. }
  763. dwReturn = ERROR_SUCCESS;
  764. ErrorExit:
  765. return dwReturn;
  766. }
  767. /*
  768. - LocalDecrypt
  769. -
  770. * Purpose:
  771. * Decrypt data
  772. *
  773. *
  774. * Parameters:
  775. * IN hUID - Handle to the CSP user
  776. * IN hKey - Handle to the key
  777. * IN hHash - Optional handle to a hash
  778. * IN Final - Boolean indicating if this is the final
  779. * block of ciphertext
  780. * IN dwFlags - Flags values
  781. * IN OUT pbData - Data to be decrypted
  782. * IN OUT pdwDataLen - Pointer to the length of the data to be
  783. * decrypted
  784. * IN fIsExternal - Flag to tell if the call is for internal
  785. * CSP use or external caller
  786. *
  787. * Returns:
  788. */
  789. DWORD
  790. LocalDecrypt(
  791. IN HCRYPTPROV hUID,
  792. IN HCRYPTKEY hKey,
  793. IN HCRYPTHASH hHash,
  794. IN BOOL Final,
  795. IN DWORD dwFlags,
  796. IN OUT BYTE *pbData,
  797. IN OUT DWORD *pdwDataLen,
  798. IN BOOL fIsExternal)
  799. {
  800. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  801. PNTAGUserList pTmpUser;
  802. PNTAGKeyList pTmpKey;
  803. PNTAGKeyList pTmpKey2;
  804. MACstate *pMAC;
  805. PNTAGHashList pTmpHash = NULL;
  806. BSAFE_PRV_KEY *pBsafePrvKey = NULL;
  807. BYTE *pbNewData = NULL;
  808. DWORD cbNewData;
  809. DWORD dwSts;
  810. if (0 != (dwFlags & ~CRYPT_OAEP))
  811. // && (0x9C580000 != dwFlags))
  812. {
  813. dwReturn = (DWORD)NTE_BAD_FLAGS;
  814. goto ErrorExit;
  815. }
  816. // We're done if decrypting 0 bytes.
  817. if (*pdwDataLen == 0)
  818. {
  819. dwReturn = (Final == TRUE) ? (DWORD)NTE_BAD_LEN : ERROR_SUCCESS;
  820. goto ErrorExit;
  821. }
  822. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  823. if (NULL == pTmpUser)
  824. {
  825. dwReturn = (DWORD)NTE_BAD_UID;
  826. goto ErrorExit;
  827. }
  828. //
  829. // Check if decryption allowed
  830. //
  831. if (fIsExternal &&
  832. (PROV_RSA_SCHANNEL != pTmpUser->dwProvType) &&
  833. ((pTmpUser->Rights & CRYPT_DISABLE_CRYPT) == CRYPT_DISABLE_CRYPT))
  834. {
  835. dwReturn = (DWORD)NTE_PERM;
  836. goto ErrorExit;
  837. }
  838. // Check the key against the user.
  839. dwSts = NTLValidate(hKey, hUID, KEY_HANDLE, &pTmpKey);
  840. if (ERROR_SUCCESS != dwSts)
  841. {
  842. dwSts = NTLValidate(hKey, hUID, EXCHPUBKEY_HANDLE, &pTmpKey);
  843. if (ERROR_SUCCESS != dwSts)
  844. {
  845. // NTLValidate doesn't know what error to set
  846. // so it set NTE_FAIL -- fix it up.
  847. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  848. goto ErrorExit;
  849. }
  850. }
  851. if ((POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  852. && fDDecrypt)
  853. {
  854. if (memcmp(dbDDecrypt, pbData, DE_BLOCKLEN) == 0)
  855. {
  856. dwReturn = (DWORD)NTE_DOUBLE_ENCRYPT;
  857. goto ErrorExit;
  858. }
  859. }
  860. if ((pTmpKey->Algid != CALG_RSA_KEYX) &&
  861. (!FIsLegalKey(pTmpUser, pTmpKey, TRUE)))
  862. {
  863. dwReturn = (DWORD)NTE_BAD_KEY;
  864. goto ErrorExit;
  865. }
  866. // Check if we should do an auto-inflate
  867. if ((pTmpKey->pData == NULL) && (pTmpKey->Algid != CALG_RSA_KEYX))
  868. {
  869. dwSts = InflateKey(pTmpKey);
  870. if (ERROR_SUCCESS != dwSts)
  871. {
  872. dwReturn = dwSts;
  873. goto ErrorExit;
  874. }
  875. }
  876. // determine which algorithm is to be used
  877. switch (pTmpKey->Algid)
  878. {
  879. case CALG_RSA_KEYX:
  880. // check if the public key matches the private key
  881. if (pTmpUser->ContInfo.pbExchPub == NULL)
  882. {
  883. dwReturn = (DWORD)NTE_NO_KEY;
  884. goto ErrorExit;
  885. }
  886. if ((pTmpUser->ContInfo.ContLens.cbExchPub != pTmpKey->cbKeyLen) ||
  887. memcmp(pTmpUser->ContInfo.pbExchPub, pTmpKey->pKeyValue,
  888. pTmpUser->ContInfo.ContLens.cbExchPub))
  889. {
  890. dwReturn = (DWORD)NTE_BAD_KEY;
  891. goto ErrorExit;
  892. }
  893. // if using protected store then load the key now
  894. dwSts = UnprotectPrivKey(pTmpUser, g_Strings.pwszImportSimple,
  895. FALSE, FALSE);
  896. if (ERROR_SUCCESS != dwSts)
  897. {
  898. dwReturn = dwSts; // NTE_BAD_KEYSET
  899. goto ErrorExit;
  900. }
  901. pBsafePrvKey = (BSAFE_PRV_KEY *)pTmpUser->pExchPrivKey;
  902. if (NULL == pBsafePrvKey)
  903. {
  904. dwReturn = (DWORD)NTE_NO_KEY;
  905. goto ErrorExit;
  906. }
  907. // perform the RSA decryption
  908. dwSts= RSADecrypt(pTmpUser, pBsafePrvKey, pbData, *pdwDataLen,
  909. pTmpKey->pbParams, pTmpKey->cbParams,
  910. dwFlags, &pbNewData, &cbNewData);
  911. if (ERROR_SUCCESS != dwSts)
  912. {
  913. dwReturn = dwSts;
  914. goto ErrorExit;
  915. }
  916. *pdwDataLen = cbNewData;
  917. memcpy(pbData, pbNewData, *pdwDataLen);
  918. break;
  919. default:
  920. dwSts = SymDecrypt(pTmpKey, NULL, Final, pbData, pdwDataLen);
  921. if (ERROR_SUCCESS != dwSts)
  922. {
  923. dwReturn = dwSts;
  924. goto ErrorExit;
  925. }
  926. }
  927. if (hHash != 0)
  928. {
  929. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  930. if (ERROR_SUCCESS != dwSts)
  931. {
  932. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_HASH : dwSts;
  933. goto ErrorExit;
  934. }
  935. if (pTmpHash->Algid == CALG_MAC)
  936. {
  937. // Check if we should do an auto-inflate
  938. pMAC = pTmpHash->pHashData;
  939. dwSts = NTLValidate(pTmpHash->hKey, hUID, KEY_HANDLE, &pTmpKey2);
  940. if (ERROR_SUCCESS != dwSts)
  941. {
  942. // NTLValidate doesn't know what error to set
  943. // so it set NTE_FAIL -- fix it up.
  944. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  945. goto ErrorExit;
  946. }
  947. if (pTmpKey2->pData == NULL)
  948. {
  949. dwSts = InflateKey(pTmpKey2);
  950. if (ERROR_SUCCESS != dwSts)
  951. {
  952. dwReturn = dwSts;
  953. goto ErrorExit;
  954. }
  955. }
  956. }
  957. if (!CPHashData(hUID, hHash, pbData, *pdwDataLen, 0))
  958. {
  959. dwReturn = GetLastError();
  960. goto ErrorExit;
  961. }
  962. }
  963. if ((POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  964. && (*pdwDataLen >= DE_BLOCKLEN))
  965. {
  966. memcpy(dbDDecrypt, pbData, DE_BLOCKLEN);
  967. fDDecrypt = TRUE;
  968. }
  969. else
  970. {
  971. fDDecrypt = FALSE;
  972. }
  973. dwReturn = ERROR_SUCCESS;
  974. ErrorExit:
  975. if (pbNewData)
  976. _nt_free(pbNewData, cbNewData);
  977. return dwReturn;
  978. }
  979. /*
  980. - CPDecrypt
  981. -
  982. * Purpose:
  983. * Decrypt data
  984. *
  985. *
  986. * Parameters:
  987. * IN hUID - Handle to the CSP user
  988. * IN hKey - Handle to the key
  989. * IN hHash - Optional handle to a hash
  990. * IN Final - Boolean indicating if this is the final
  991. * block of ciphertext
  992. * IN dwFlags - Flags values
  993. * IN OUT pbData - Data to be decrypted
  994. * IN OUT pdwDataLen - Pointer to the length of the data to be
  995. * decrypted
  996. *
  997. * Returns:
  998. */
  999. BOOL WINAPI
  1000. CPDecrypt(
  1001. IN HCRYPTPROV hUID,
  1002. IN HCRYPTKEY hKey,
  1003. IN HCRYPTHASH hHash,
  1004. IN BOOL Final,
  1005. IN DWORD dwFlags,
  1006. IN OUT BYTE *pbData,
  1007. IN OUT DWORD *pdwDataLen)
  1008. {
  1009. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1010. BOOL fRet;
  1011. DWORD dwSts;
  1012. EntryPoint
  1013. dwSts = LocalDecrypt(hUID, hKey, hHash, Final,
  1014. dwFlags, pbData, pdwDataLen, TRUE);
  1015. if (ERROR_SUCCESS != dwSts)
  1016. {
  1017. dwReturn = dwSts;
  1018. goto ErrorExit;
  1019. }
  1020. dwReturn = ERROR_SUCCESS;
  1021. ErrorExit:
  1022. fRet = (ERROR_SUCCESS == dwReturn);
  1023. if (!fRet)
  1024. SetLastError(dwReturn);
  1025. return fRet;
  1026. }