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.

1083 lines
30 KiB

  1. #include "global.hxx"
  2. // crypto defs
  3. #include <wincrypt.h>
  4. #include "randlib.h"
  5. #include "pfxhelp.h"
  6. #include "pfxcmn.h"
  7. #include "pfxcrypt.h"
  8. #include "sha.h"
  9. #include "shacomm.h"
  10. #include "rc2.h"
  11. #include "modes.h"
  12. #include "des.h"
  13. #include "tripldes.h"
  14. // constants used in PKCS5-like key derivation
  15. #define DERIVE_ENCRYPT_DECRYPT 0x1
  16. #define DERIVE_INITIAL_VECTOR 0x2
  17. #define DERIVE_INTEGRITY_KEY 0x3
  18. #define HMAC_K_PADSIZE 64
  19. BOOL FMyPrimitiveSHA(
  20. PBYTE pbData,
  21. DWORD cbData,
  22. BYTE rgbHash[A_SHA_DIGEST_LEN])
  23. {
  24. BOOL fRet = FALSE;
  25. A_SHA_CTX sSHAHash;
  26. A_SHAInit(&sSHAHash);
  27. A_SHAUpdate(&sSHAHash, (BYTE *) pbData, cbData);
  28. A_SHAFinal(&sSHAHash, rgbHash);
  29. fRet = TRUE;
  30. //Ret:
  31. return fRet;
  32. }
  33. BOOL FMyPrimitiveHMACParam(
  34. PBYTE pbKeyMaterial,
  35. DWORD cbKeyMaterial,
  36. PBYTE pbData,
  37. DWORD cbData,
  38. BYTE rgbHMAC[A_SHA_DIGEST_LEN])
  39. {
  40. BOOL fRet = FALSE;
  41. BYTE rgbKipad[HMAC_K_PADSIZE];
  42. BYTE rgbKopad[HMAC_K_PADSIZE];
  43. // truncate
  44. if (cbKeyMaterial > HMAC_K_PADSIZE)
  45. cbKeyMaterial = HMAC_K_PADSIZE;
  46. ZeroMemory(rgbKipad, HMAC_K_PADSIZE);
  47. CopyMemory(rgbKipad, pbKeyMaterial, cbKeyMaterial);
  48. ZeroMemory(rgbKopad, HMAC_K_PADSIZE);
  49. CopyMemory(rgbKopad, pbKeyMaterial, cbKeyMaterial);
  50. BYTE rgbHMACTmp[HMAC_K_PADSIZE+A_SHA_DIGEST_LEN];
  51. // assert we're a multiple
  52. assert( (HMAC_K_PADSIZE % sizeof(DWORD)) == 0);
  53. // Kipad, Kopad are padded sMacKey. Now XOR across...
  54. for(DWORD dwBlock=0; dwBlock<HMAC_K_PADSIZE/sizeof(DWORD); dwBlock++)
  55. {
  56. ((DWORD*)rgbKipad)[dwBlock] ^= 0x36363636;
  57. ((DWORD*)rgbKopad)[dwBlock] ^= 0x5C5C5C5C;
  58. }
  59. // prepend Kipad to data, Hash to get H1
  60. {
  61. // do this inline, don't call MyPrimitiveSHA since it would require data copy
  62. A_SHA_CTX sSHAHash;
  63. BYTE HashVal[A_SHA_DIGEST_LEN];
  64. A_SHAInit(&sSHAHash);
  65. A_SHAUpdate(&sSHAHash, rgbKipad, HMAC_K_PADSIZE);
  66. A_SHAUpdate(&sSHAHash, pbData, cbData);
  67. // Finish off the hash
  68. A_SHAFinal(&sSHAHash, HashVal);
  69. // prepend Kopad to H1, hash to get HMAC
  70. CopyMemory(rgbHMACTmp, rgbKopad, HMAC_K_PADSIZE);
  71. CopyMemory(rgbHMACTmp+HMAC_K_PADSIZE, HashVal, A_SHA_DIGEST_LEN);
  72. }
  73. if (!FMyPrimitiveSHA(
  74. rgbHMACTmp,
  75. sizeof(rgbHMACTmp),
  76. rgbHMAC))
  77. goto Ret;
  78. fRet = TRUE;
  79. Ret:
  80. return fRet;
  81. }
  82. static
  83. BOOL
  84. CopyPassword(
  85. BYTE *pbLocation,
  86. LPCWSTR szPassword,
  87. DWORD dwMaxBytes
  88. )
  89. {
  90. DWORD i = 0;
  91. DWORD cbWideChars = WSZ_BYTECOUNT(szPassword);
  92. BYTE *pbWideChars = (BYTE *) szPassword;
  93. while ((i<cbWideChars) && (i<dwMaxBytes))
  94. {
  95. pbLocation[i] = pbWideChars[i+1];
  96. pbLocation[i+1] = pbWideChars[i];
  97. i+=2;
  98. }
  99. return TRUE;
  100. }
  101. //+ --------------------------------------------------------------
  102. // in NSCP's initial implementation of PFX020, this
  103. // is the algorithm they used to derive a key from a password.
  104. // We include it so we can interoperate.
  105. BOOL NSCPDeriveKey(
  106. LPCWSTR szPassword,
  107. PBYTE pbPrivacySalt,
  108. DWORD cbPrivacySalt,
  109. int iPKCS5Iterations,
  110. PBYTE pbPKCS5Salt,
  111. DWORD cbPKCS5Salt,
  112. PBYTE pbDerivedMaterial,
  113. DWORD cbDerivedMaterial)
  114. {
  115. BOOL fRet = FALSE;
  116. BYTE rgbPKCS5Key[A_SHA_DIGEST_LEN];
  117. DWORD cbVirtualPW = cbPrivacySalt + WSZ_BYTECOUNT(szPassword);
  118. PBYTE pbVirtualPW = (PBYTE)SSAlloc(cbVirtualPW);
  119. if (pbVirtualPW == NULL)
  120. goto Ret;
  121. // Virtual PW = (salt | szPW)
  122. CopyMemory(pbVirtualPW, pbPrivacySalt, cbPrivacySalt);
  123. CopyPassword(&pbVirtualPW[cbPrivacySalt], szPassword, WSZ_BYTECOUNT(szPassword));
  124. // use PKCS#5 to generate initial bit stream (seed)
  125. if (!PKCS5_GenKey(
  126. iPKCS5Iterations,
  127. pbVirtualPW, cbVirtualPW,
  128. pbPKCS5Salt, cbPKCS5Salt,
  129. rgbPKCS5Key))
  130. goto Ret;
  131. if (cbDerivedMaterial > sizeof(rgbPKCS5Key))
  132. {
  133. // P_hash (secret, seed) = HMAC_hash (secret, A(0) + seed),
  134. // HMAC_hash (secret, A(1) + seed),
  135. // HMAC_hash (secret, A(2) + seed),
  136. // HMAC_hash (secret, A(3) + seed) ...
  137. // where
  138. // A(0) = seed
  139. // A(i) = HMAC_hash(secret, A(i-1))
  140. // seed = PKCS5 salt for PKCS5 PBE param
  141. // secret = normal PKCS5 hashed key
  142. if (!P_Hash (
  143. rgbPKCS5Key,
  144. sizeof(rgbPKCS5Key),
  145. pbPKCS5Salt,
  146. cbPKCS5Salt,
  147. pbDerivedMaterial, // output
  148. cbDerivedMaterial, // # of output bytes requested
  149. TRUE) ) // NSCP compat mode?
  150. goto Ret;
  151. }
  152. else
  153. {
  154. // we already have enough bits to satisfy the request
  155. CopyMemory(pbDerivedMaterial, rgbPKCS5Key, cbDerivedMaterial);
  156. }
  157. fRet = TRUE;
  158. Ret:
  159. if (pbVirtualPW)
  160. SSFree(pbVirtualPW);
  161. return fRet;
  162. }
  163. static
  164. BYTE
  165. AddWithCarry(
  166. BYTE byte1,
  167. BYTE byte2,
  168. BYTE *carry // IN and OUT
  169. )
  170. {
  171. BYTE tempCarry = *carry;
  172. if (((DWORD)byte1 + (DWORD)byte2 + (DWORD)tempCarry) >= 256) {
  173. *carry = 1;
  174. }
  175. else {
  176. *carry = 0;
  177. }
  178. return (byte1 + byte2 + tempCarry);
  179. }
  180. // 512 bits = ? bytes
  181. #define SHA_INTERNAL_BLOCKLEN (512/8)
  182. #define SHA_V_LENGTH (512/8)
  183. //+ --------------------------------------------------------------
  184. // In PKCS12 v1.0 Draft, this is the way they describe to
  185. // derive a key from a password.
  186. BOOL
  187. PKCS12DeriveKey(
  188. LPCWSTR szPassword,
  189. BYTE bID,
  190. int iIterations,
  191. PBYTE pbSalt,
  192. DWORD cbSalt,
  193. PBYTE pbDerivedMaterial,
  194. DWORD cbDerivedMaterial)
  195. {
  196. #if DBG
  197. if (iIterations>1)
  198. OutputDebugString("Perf hit: iterating key derivation! (pfxcrypt:PKCS12DeriveKey())\n");
  199. #endif
  200. BOOL fRet = FALSE;
  201. BYTE rgSaltPwd[2*SHA_INTERNAL_BLOCKLEN];
  202. DWORD cbSaltPwd;
  203. BYTE rgDiversifier[SHA_INTERNAL_BLOCKLEN];
  204. BYTE B[SHA_V_LENGTH];
  205. DWORD i;
  206. DWORD cbPassword = WSZ_BYTECOUNT(szPassword);
  207. BYTE bCarry;
  208. DWORD vBlocks;
  209. A_SHA_CTX sSHAHash;
  210. // construct D
  211. FillMemory(rgDiversifier, sizeof(rgDiversifier), bID);
  212. // concat salt to create string of length 64*(cb/64) bytes
  213. // copy salt (multiple) times, don't copy the last time
  214. for (i=0; i<(SHA_INTERNAL_BLOCKLEN-cbSalt); i+=cbSalt)
  215. {
  216. CopyMemory(&rgSaltPwd[i], pbSalt, cbSalt);
  217. }
  218. // do final copy (assert we have less than cbSalt bytes left to copy)
  219. assert(cbSalt >= (SHA_INTERNAL_BLOCKLEN - (i%SHA_INTERNAL_BLOCKLEN)) );
  220. CopyMemory(&rgSaltPwd[i], pbSalt, (SHA_INTERNAL_BLOCKLEN-(i%SHA_INTERNAL_BLOCKLEN)));
  221. // if the password is not NULL, concat pwd to create string of length 64*(cbPwd/64) bytes
  222. // copy pwd (multiple) times, don't copy the last time
  223. if (szPassword)
  224. {
  225. // truncate if necessary
  226. if (cbPassword > SHA_INTERNAL_BLOCKLEN)
  227. cbPassword = SHA_INTERNAL_BLOCKLEN;
  228. for (i=SHA_INTERNAL_BLOCKLEN; i<( (2*SHA_INTERNAL_BLOCKLEN)-cbPassword); i+=cbPassword)
  229. {
  230. // use CopyPassword because bytes need to be swapped
  231. CopyPassword(&rgSaltPwd[i], szPassword, cbPassword);
  232. }
  233. // do final copy (assert we have less than cbSalt bytes left to copy)
  234. assert(cbPassword >= (SHA_INTERNAL_BLOCKLEN - (i%SHA_INTERNAL_BLOCKLEN)) );
  235. CopyPassword(&rgSaltPwd[i], szPassword, (SHA_INTERNAL_BLOCKLEN-(i%SHA_INTERNAL_BLOCKLEN)));
  236. cbSaltPwd = sizeof(rgSaltPwd);
  237. }
  238. else
  239. {
  240. cbSaltPwd = sizeof(rgSaltPwd) / 2;
  241. }
  242. // concat S|P
  243. // done, available in rgSaltPwd
  244. // set c = cbDerivedMaterial/A_SHA_DIGEST_LEN
  245. //assert(0 == cbDerivedMaterial%A_SHA_DIGEST_LEN);
  246. // compute working size >= output size
  247. DWORD cBlocks = (DWORD)((cbDerivedMaterial/A_SHA_DIGEST_LEN) +1);
  248. DWORD cbTmpBuf = cBlocks * A_SHA_DIGEST_LEN;
  249. PBYTE pbTmpBuf = (PBYTE)LocalAlloc(LPTR, cbTmpBuf);
  250. if (pbTmpBuf == NULL)
  251. goto Ret;
  252. // now do only full blocks
  253. for (i=0; i< cBlocks; i++)
  254. {
  255. int iIter;
  256. int iCount;
  257. A_SHAInit(&sSHAHash);
  258. for (iIter=0; iIter<iIterations; iIter++)
  259. {
  260. // Tmp = Hash(D | I);
  261. if (iIter==0)
  262. {
  263. A_SHAUpdate(&sSHAHash, rgDiversifier, sizeof(rgDiversifier));
  264. A_SHAUpdate(&sSHAHash, rgSaltPwd, cbSaltPwd);
  265. }
  266. else
  267. {
  268. // rehash last output
  269. A_SHAUpdate(&sSHAHash, &pbTmpBuf[i*A_SHA_DIGEST_LEN], A_SHA_DIGEST_LEN);
  270. }
  271. // spit iteration output to final buffer
  272. A_SHAFinal(&sSHAHash, &pbTmpBuf[i*A_SHA_DIGEST_LEN]);
  273. }
  274. // concat A[x] | A[x] | ... and truncate to get 64 bytes
  275. iCount = 0;
  276. while (iCount+A_SHA_DIGEST_LEN <= sizeof(B)) {
  277. CopyMemory(&B[iCount], &pbTmpBuf[i*A_SHA_DIGEST_LEN], A_SHA_DIGEST_LEN);
  278. iCount += A_SHA_DIGEST_LEN;
  279. }
  280. CopyMemory(&B[iCount], &pbTmpBuf[i*A_SHA_DIGEST_LEN], sizeof(B) % A_SHA_DIGEST_LEN);
  281. // modify I by setting Ij += (B + 1) (mod 2^512)
  282. for (vBlocks = 0; vBlocks < cbSaltPwd; vBlocks += SHA_V_LENGTH) {
  283. bCarry = 1;
  284. for (iCount = SHA_V_LENGTH-1; iCount >= 0; iCount--)
  285. {
  286. rgSaltPwd[iCount+vBlocks] = AddWithCarry(rgSaltPwd[iCount+vBlocks], B[iCount], &bCarry);
  287. }
  288. }
  289. }
  290. // copy from (larger) working buffer to output buffer
  291. CopyMemory(pbDerivedMaterial, pbTmpBuf, cbDerivedMaterial);
  292. fRet = TRUE;
  293. Ret:
  294. if (pbTmpBuf)
  295. LocalFree(pbTmpBuf);
  296. return fRet;
  297. }
  298. //+ --------------------------------------------------------------
  299. // in NSCP's initial implementation of PFX020, this
  300. // is the algorithm they used to decrypt data. This uses the
  301. // key derivation code above.
  302. // We include it so we can interoperate.
  303. BOOL NSCPPasswordDecryptData(
  304. int iEncrType,
  305. LPCWSTR szPassword,
  306. PBYTE pbPrivacySalt, // privacy salt
  307. DWORD cbPrivacySalt,
  308. int iPKCS5Iterations, // pkcs5 data
  309. PBYTE pbPKCS5Salt,
  310. DWORD cbPKCS5Salt,
  311. PBYTE* ppbData, // in/out
  312. DWORD* pcbData)
  313. {
  314. BOOL fRet = FALSE;
  315. BYTE rgbDerivedKeyMatl[40]; // 320 bits is enough for 128 bit key, 64 bit IV
  316. DWORD cbNeeded;
  317. if (iEncrType == RC2_40)
  318. cbNeeded = (40/8)+RC2_BLOCKLEN; // key + IV
  319. else
  320. cbNeeded = 0;
  321. // make next muliple of SHA dig len
  322. if (cbNeeded % A_SHA_DIGEST_LEN)
  323. {
  324. cbNeeded += (A_SHA_DIGEST_LEN - (cbNeeded % A_SHA_DIGEST_LEN));
  325. }
  326. assert(0 == (cbNeeded % A_SHA_DIGEST_LEN));
  327. assert(cbNeeded <= sizeof(rgbDerivedKeyMatl));
  328. if (!NSCPDeriveKey(
  329. szPassword,
  330. pbPrivacySalt,
  331. cbPrivacySalt,
  332. iPKCS5Iterations,
  333. pbPKCS5Salt,
  334. cbPKCS5Salt,
  335. rgbDerivedKeyMatl,
  336. cbNeeded) )
  337. goto Ret;
  338. // NOW decrypt data
  339. if (iEncrType == RC2_40)
  340. {
  341. DWORD dwDataPos;
  342. DWORD cbToBeDec = *pcbData;
  343. WORD rc2Table[RC2_TABLESIZE];
  344. BYTE rc2Fdbk [RC2_BLOCKLEN];
  345. assert( (40/8) <= sizeof(rgbDerivedKeyMatl));
  346. assert( 0 == cbToBeDec % RC2_BLOCKLEN ); // must be even multiple
  347. // key setup
  348. RC2Key(rc2Table, rgbDerivedKeyMatl, (40/8)); // take first 40 bits of keying material
  349. CopyMemory(rc2Fdbk, &rgbDerivedKeyMatl[cbNeeded - sizeof(rc2Fdbk)], sizeof(rc2Fdbk)); // fdbk is last chunk
  350. // decryption
  351. for (dwDataPos=0; cbToBeDec > 0; dwDataPos+=RC2_BLOCKLEN, cbToBeDec -= RC2_BLOCKLEN)
  352. {
  353. BYTE rgbDec[RC2_BLOCKLEN];
  354. CBC(
  355. RC2,
  356. RC2_BLOCKLEN,
  357. rgbDec,
  358. &(*ppbData)[dwDataPos],
  359. rc2Table,
  360. DECRYPT,
  361. rc2Fdbk);
  362. CopyMemory(&(*ppbData)[dwDataPos], rgbDec, RC2_BLOCKLEN);
  363. }
  364. }
  365. else
  366. goto Ret;
  367. fRet = TRUE;
  368. Ret:
  369. return fRet;
  370. }
  371. //+ --------------------------------------------------------------
  372. // in the PKCS12 v1.0 Draft, this is how they describe how to
  373. // encrypt data.
  374. BOOL PFXPasswordEncryptData(
  375. int iEncrType,
  376. LPCWSTR szPassword,
  377. int iPKCS5Iterations, // pkcs5 data
  378. PBYTE pbPKCS5Salt,
  379. DWORD cbPKCS5Salt,
  380. PBYTE* ppbData,
  381. DWORD* pcbData)
  382. {
  383. BOOL fRet = FALSE;
  384. BOOL fIsBlockCipher = FALSE;
  385. DWORD cbToBeEnc;
  386. BYTE rgbDerivedKey[A_SHA_DIGEST_LEN*2]; // 320 bits is enough for 256 bit key
  387. BYTE rgbDerivedIV[A_SHA_DIGEST_LEN*2]; // 320 bits is enough for 256 bit IV
  388. DWORD cbKeyNeeded, cbIVNeeded, cbBlockLen;
  389. if (iEncrType == RC2_40)
  390. {
  391. cbKeyNeeded = (40/8); // key
  392. cbIVNeeded = RC2_BLOCKLEN; // IV
  393. cbBlockLen = RC2_BLOCKLEN;
  394. fIsBlockCipher = TRUE;
  395. }
  396. else if (iEncrType == TripleDES)
  397. {
  398. cbKeyNeeded = (64/8) * 3;
  399. cbIVNeeded = DES_BLOCKLEN;
  400. cbBlockLen = DES_BLOCKLEN;
  401. fIsBlockCipher = TRUE;
  402. }
  403. else
  404. {
  405. cbKeyNeeded = 0;
  406. cbIVNeeded = 0;
  407. cbBlockLen = 0;
  408. }
  409. // make next muliple of SHA dig len
  410. if (cbKeyNeeded % A_SHA_DIGEST_LEN)
  411. cbKeyNeeded += (A_SHA_DIGEST_LEN - (cbKeyNeeded % A_SHA_DIGEST_LEN));
  412. if (cbIVNeeded % A_SHA_DIGEST_LEN)
  413. cbIVNeeded += (A_SHA_DIGEST_LEN - (cbIVNeeded % A_SHA_DIGEST_LEN));
  414. assert(0 == (cbKeyNeeded % A_SHA_DIGEST_LEN));
  415. assert(0 == (cbIVNeeded % A_SHA_DIGEST_LEN));
  416. assert(cbKeyNeeded <= sizeof(rgbDerivedKey));
  417. assert(cbIVNeeded <= sizeof(rgbDerivedIV));
  418. if (!PKCS12DeriveKey(
  419. szPassword,
  420. DERIVE_ENCRYPT_DECRYPT,
  421. iPKCS5Iterations,
  422. pbPKCS5Salt,
  423. cbPKCS5Salt,
  424. rgbDerivedKey,
  425. cbKeyNeeded) )
  426. goto Ret;
  427. if (!PKCS12DeriveKey(
  428. szPassword,
  429. DERIVE_INITIAL_VECTOR,
  430. iPKCS5Iterations,
  431. pbPKCS5Salt,
  432. cbPKCS5Salt,
  433. rgbDerivedIV,
  434. cbIVNeeded) )
  435. goto Ret;
  436. if (fIsBlockCipher)
  437. {
  438. PBYTE pTemp = *ppbData;
  439. // extend buffer to multiple of blocklen
  440. cbToBeEnc = *pcbData;
  441. cbToBeEnc += cbBlockLen - (cbToBeEnc%cbBlockLen); // {1..BLOCKLEN}
  442. #pragma prefast(suppress:308, "the pointer was saved above (PREfast bug 506)")
  443. *ppbData = (PBYTE)SSReAlloc(*ppbData, cbToBeEnc);
  444. if (NULL == *ppbData)
  445. {
  446. SSFree(pTemp);
  447. goto Ret;
  448. }
  449. // pad remaining bytes with length
  450. FillMemory(&((*ppbData)[*pcbData]), cbToBeEnc-(*pcbData), (BYTE)(cbToBeEnc-(*pcbData)));
  451. *pcbData = cbToBeEnc;
  452. assert( cbBlockLen <= sizeof(rgbDerivedKey));
  453. assert( 0 == cbToBeEnc % cbBlockLen ); // must be even multiple
  454. }
  455. // NOW encrypt data
  456. if (iEncrType == RC2_40)
  457. {
  458. DWORD dwDataPos;
  459. WORD rc2Table[RC2_TABLESIZE];
  460. BYTE rc2Fdbk [RC2_BLOCKLEN];
  461. // already done: extend buffer, add PKCS byte padding
  462. // key setup
  463. RC2Key(rc2Table, rgbDerivedKey, (40/8)); // take first 40 bits of keying material
  464. CopyMemory(rc2Fdbk, rgbDerivedIV, sizeof(rc2Fdbk));
  465. // decryption
  466. for (dwDataPos=0; cbToBeEnc > 0; dwDataPos+=RC2_BLOCKLEN, cbToBeEnc -= RC2_BLOCKLEN)
  467. {
  468. BYTE rgbEnc[RC2_BLOCKLEN];
  469. CBC(
  470. RC2,
  471. RC2_BLOCKLEN,
  472. rgbEnc,
  473. &(*ppbData)[dwDataPos],
  474. rc2Table,
  475. ENCRYPT,
  476. rc2Fdbk);
  477. CopyMemory(&(*ppbData)[dwDataPos], rgbEnc, sizeof(rgbEnc));
  478. }
  479. }
  480. else if (iEncrType == TripleDES)
  481. {
  482. DWORD dwDataPos;
  483. DES3TABLE des3Table;
  484. BYTE des3Fdbk [DES_BLOCKLEN];
  485. // already done: extend buffer, add PKCS byte padding
  486. // key setup
  487. tripledes3key(&des3Table, rgbDerivedKey);
  488. CopyMemory(des3Fdbk, rgbDerivedIV, sizeof(des3Fdbk)); // fdbk is last chunk
  489. for (dwDataPos=0; cbToBeEnc > 0; dwDataPos+=DES_BLOCKLEN, cbToBeEnc -= DES_BLOCKLEN)
  490. {
  491. BYTE rgbEnc[DES_BLOCKLEN];
  492. CBC(
  493. tripledes,
  494. DES_BLOCKLEN,
  495. rgbEnc,
  496. &(*ppbData)[dwDataPos],
  497. (void *) &des3Table,
  498. ENCRYPT,
  499. des3Fdbk);
  500. CopyMemory(&(*ppbData)[dwDataPos], rgbEnc, DES_BLOCKLEN);
  501. }
  502. }
  503. else
  504. goto Ret;
  505. fRet = TRUE;
  506. Ret:
  507. return fRet;
  508. }
  509. //+ --------------------------------------------------------------
  510. // in the PKCS12 v1.0 Draft, this is how they describe how to
  511. // decrypt data.
  512. BOOL PFXPasswordDecryptData(
  513. int iEncrType,
  514. LPCWSTR szPassword,
  515. int iPKCS5Iterations, // pkcs5 data
  516. PBYTE pbPKCS5Salt,
  517. DWORD cbPKCS5Salt,
  518. PBYTE* ppbData,
  519. DWORD* pcbData)
  520. {
  521. BOOL fRet = FALSE;
  522. BOOL fIsBlockCipher = FALSE;
  523. BYTE rgbDerivedKey[A_SHA_DIGEST_LEN*2]; // 320 bits is enough for 256 bit key
  524. BYTE rgbDerivedIV[A_SHA_DIGEST_LEN*2]; // 320 bits is enough for 256 bit IV
  525. DWORD cbKeyNeeded, cbIVNeeded, cbBlockLen;
  526. if (iEncrType == RC2_40)
  527. {
  528. cbKeyNeeded = (40/8); // key
  529. cbIVNeeded = RC2_BLOCKLEN; // IV
  530. cbBlockLen = RC2_BLOCKLEN;
  531. fIsBlockCipher = TRUE;
  532. }
  533. else if (iEncrType == TripleDES)
  534. {
  535. cbKeyNeeded = (64/8) * 3;
  536. cbIVNeeded = DES_BLOCKLEN;
  537. cbBlockLen = DES_BLOCKLEN;
  538. fIsBlockCipher = TRUE;
  539. }
  540. else
  541. {
  542. cbKeyNeeded = 0;
  543. cbIVNeeded = 0;
  544. cbBlockLen = 0;
  545. }
  546. // make next muliple of SHA dig len
  547. if (cbKeyNeeded % A_SHA_DIGEST_LEN)
  548. cbKeyNeeded += (A_SHA_DIGEST_LEN - (cbKeyNeeded % A_SHA_DIGEST_LEN));
  549. if (cbIVNeeded % A_SHA_DIGEST_LEN)
  550. cbIVNeeded += (A_SHA_DIGEST_LEN - (cbIVNeeded % A_SHA_DIGEST_LEN));
  551. assert(0 == (cbKeyNeeded % A_SHA_DIGEST_LEN));
  552. assert(0 == (cbIVNeeded % A_SHA_DIGEST_LEN));
  553. assert(cbKeyNeeded <= sizeof(rgbDerivedKey));
  554. assert(cbIVNeeded <= sizeof(rgbDerivedIV));
  555. if (!PKCS12DeriveKey(
  556. szPassword,
  557. DERIVE_ENCRYPT_DECRYPT,
  558. iPKCS5Iterations,
  559. pbPKCS5Salt,
  560. cbPKCS5Salt,
  561. rgbDerivedKey,
  562. cbKeyNeeded) )
  563. goto Ret;
  564. if (!PKCS12DeriveKey(
  565. szPassword,
  566. DERIVE_INITIAL_VECTOR,
  567. iPKCS5Iterations,
  568. pbPKCS5Salt,
  569. cbPKCS5Salt,
  570. rgbDerivedIV,
  571. cbIVNeeded) )
  572. goto Ret;
  573. // NOW decrypt data
  574. if (iEncrType == RC2_40)
  575. {
  576. BYTE rgbDec[RC2_BLOCKLEN];
  577. DWORD dwDataPos;
  578. DWORD cbToBeDec = *pcbData;
  579. WORD rc2Table[RC2_TABLESIZE];
  580. BYTE rc2Fdbk [RC2_BLOCKLEN];
  581. assert( (40/8) <= sizeof(rgbDerivedKey));
  582. assert( 0 == cbToBeDec % RC2_BLOCKLEN ); // must be even multiple
  583. // key setup
  584. RC2Key(rc2Table, rgbDerivedKey, (40/8)); // take first 40 bits of keying material
  585. CopyMemory(rc2Fdbk, rgbDerivedIV, sizeof(rc2Fdbk));
  586. // decryption
  587. for (dwDataPos=0; cbToBeDec > 0; dwDataPos+=RC2_BLOCKLEN, cbToBeDec -= RC2_BLOCKLEN)
  588. {
  589. CBC(
  590. RC2,
  591. RC2_BLOCKLEN,
  592. rgbDec,
  593. &(*ppbData)[dwDataPos],
  594. rc2Table,
  595. DECRYPT,
  596. rc2Fdbk);
  597. CopyMemory(&(*ppbData)[dwDataPos], rgbDec, sizeof(rgbDec));
  598. }
  599. }
  600. else if (iEncrType == TripleDES) {
  601. DWORD dwDataPos;
  602. DWORD cbToBeDec = *pcbData;
  603. DES3TABLE des3Table;
  604. BYTE des3Fdbk [DES_BLOCKLEN];
  605. // key setup
  606. tripledes3key(&des3Table, rgbDerivedKey);
  607. CopyMemory(des3Fdbk, rgbDerivedIV, sizeof(des3Fdbk)); // fdbk is last chunk
  608. for (dwDataPos=0; cbToBeDec > 0; dwDataPos += DES_BLOCKLEN, cbToBeDec -= DES_BLOCKLEN)
  609. {
  610. BYTE rgbDec[DES_BLOCKLEN];
  611. CBC(
  612. tripledes,
  613. DES_BLOCKLEN,
  614. rgbDec,
  615. &(*ppbData)[dwDataPos],
  616. (void *) &des3Table,
  617. DECRYPT,
  618. des3Fdbk);
  619. CopyMemory(&(*ppbData)[dwDataPos], rgbDec, DES_BLOCKLEN);
  620. }
  621. }
  622. else
  623. goto Ret;
  624. // Remove padding
  625. if (fIsBlockCipher)
  626. {
  627. PBYTE pTemp = *ppbData;
  628. // last byte of decr is pad byte
  629. BYTE iPadBytes;
  630. iPadBytes = (*ppbData)[*pcbData-1];
  631. if (iPadBytes > cbBlockLen)
  632. goto Ret;
  633. #pragma prefast(suppress:308, "the pointer was saved above (PREfast bug 506)")
  634. *ppbData = (PBYTE)SSReAlloc( (*ppbData), *pcbData - iPadBytes);
  635. if (NULL == *ppbData)
  636. {
  637. SSFree(pTemp);
  638. goto Ret;
  639. }
  640. *pcbData -= iPadBytes;
  641. }
  642. fRet = TRUE;
  643. Ret:
  644. return fRet;
  645. }
  646. //+ --------------------------------------------------------------
  647. // in the PKCS12 v1.0 Draft, this is how they describe how to
  648. // generate a checksum that will prove data integrid.
  649. BOOL FGenerateMAC(
  650. LPCWSTR szPassword,
  651. PBYTE pbPKCS5Salt,
  652. DWORD cbPKCS5Salt,
  653. DWORD iterationCount,
  654. PBYTE pbData, // pb data
  655. DWORD cbData, // cb data
  656. BYTE rgbMAC[]) // output
  657. {
  658. // UNDONE UNDONE: Use RSABase
  659. BOOL fRet = FALSE;
  660. BYTE rgbDerivedKey[A_SHA_DIGEST_LEN]; // 160 bits is enough for a MAC key
  661. DWORD cbKeyNeeded = A_SHA_DIGEST_LEN;
  662. assert(0 == (cbKeyNeeded % A_SHA_DIGEST_LEN));
  663. assert(cbKeyNeeded <= sizeof(rgbDerivedKey));
  664. if (!PKCS12DeriveKey(
  665. szPassword,
  666. DERIVE_INTEGRITY_KEY,
  667. iterationCount, // no other way to determine iterations: HARDCODE
  668. pbPKCS5Salt,
  669. cbPKCS5Salt,
  670. rgbDerivedKey,
  671. cbKeyNeeded) )
  672. goto Ret;
  673. if (!FMyPrimitiveHMACParam(
  674. rgbDerivedKey,
  675. cbKeyNeeded,
  676. pbData,
  677. cbData,
  678. rgbMAC))
  679. goto Ret;
  680. fRet = TRUE;
  681. Ret:
  682. return fRet;
  683. }
  684. /////////////////////////////////////////////////////////////////
  685. // begin tls1key.cpp
  686. /*-----------------------------------------------------------------------------
  687. * Copyright (C) Microsoft Corporation, 1995 - 1999
  688. * All rights reserved.
  689. *----------------------------------------------------------------------------*/
  690. // the original PKCS5 algorithm for generating a key from a password
  691. BOOL PKCS5_GenKey
  692. (
  693. int iIterations,
  694. PBYTE pbPW,
  695. DWORD cbPW,
  696. PBYTE pbSalt,
  697. DWORD cbSalt,
  698. BYTE rgbPKCS5Key[A_SHA_DIGEST_LEN]
  699. )
  700. {
  701. BOOL fRet = FALSE;
  702. int i;
  703. DWORD cbTmp = cbSalt + cbPW;
  704. PBYTE pbTmp = (PBYTE) SSAlloc(cbTmp);
  705. if (pbTmp == NULL)
  706. goto Ret;
  707. // pbTmp is ( PW | Salt )
  708. CopyMemory(pbTmp, pbPW, cbPW);
  709. CopyMemory(&pbTmp[cbPW], pbSalt, cbSalt);
  710. for (i=0; i<iIterations; i++)
  711. {
  712. if (i == 0) {
  713. if (!FMyPrimitiveSHA(
  714. pbTmp, // in
  715. cbTmp, // in
  716. rgbPKCS5Key))
  717. goto Ret;
  718. }
  719. else {
  720. if (!FMyPrimitiveSHA(
  721. rgbPKCS5Key, // in
  722. A_SHA_DIGEST_LEN, // in
  723. rgbPKCS5Key))
  724. goto Ret;
  725. }
  726. }
  727. fRet = TRUE;
  728. Ret:
  729. SSFree(pbTmp);
  730. return fRet;
  731. }
  732. //+ ---------------------------------------------------------------------
  733. // the P_Hash algorithm from TLS that was used in NSCP's PFX020 version
  734. // to derive a key from a password. It is included here for completeness.
  735. // NSCP made some implementation errors when they coded this up; to interop,
  736. // use the fNSCPInteropMode parameter. The real P_Hash algorithm is used
  737. // when fNSCPInteropMode is FALSE.
  738. BOOL P_Hash
  739. (
  740. PBYTE pbSecret,
  741. DWORD cbSecret,
  742. PBYTE pbSeed,
  743. DWORD cbSeed,
  744. PBYTE pbKeyOut, //Buffer to copy the result...
  745. DWORD cbKeyOut, //# of bytes of key length they want as output.
  746. BOOL fNSCPInteropMode
  747. )
  748. {
  749. BOOL fRet = FALSE;
  750. BYTE rgbDigest[A_SHA_DIGEST_LEN];
  751. DWORD iKey;
  752. PBYTE pbAofiDigest = (PBYTE)SSAlloc(cbSeed + A_SHA_DIGEST_LEN);
  753. if (pbAofiDigest == NULL)
  754. goto Ret;
  755. ZeroMemory(pbAofiDigest, cbSeed+A_SHA_DIGEST_LEN);
  756. // First, we define a data expansion function, P_hash(secret, data)
  757. // which uses a single hash function to expand a secret and seed into
  758. // an arbitrary quantity of output:
  759. // P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
  760. // HMAC_hash(secret, A(2) + seed) +
  761. // HMAC_hash(secret, A(3) + seed) + ...
  762. // Where + indicates concatenation.
  763. // A() is defined as:
  764. // A(0) = seed
  765. // A(i) = HMAC_hash(secret, A(i-1))
  766. if (fNSCPInteropMode)
  767. {
  768. // NSCP interop mode: 7/7/97
  769. // nscp leaves (A_SHA_DIGEST_LEN-cbSeed) bytes zeroed between
  770. // the seed and the appended seed. For interop, do derivation this way
  771. // Also, they use A(0) to derive key bytes, whereas TLS spec
  772. // specifies to wait for A(1).
  773. CopyMemory(pbAofiDigest, pbSeed, cbSeed);
  774. }
  775. else
  776. {
  777. // build A(1)
  778. if (!FMyPrimitiveHMACParam(pbSecret, cbSecret, pbSeed, cbSeed, pbAofiDigest))
  779. goto Ret;
  780. }
  781. // create Aofi: ( A(i) | seed )
  782. CopyMemory(&pbAofiDigest[A_SHA_DIGEST_LEN], pbSeed, cbSeed);
  783. // make sure that cbKeyOut is a multiple of A_SHA_DIGEST_LEN
  784. if ((cbKeyOut % A_SHA_DIGEST_LEN) != 0)
  785. {
  786. goto Ret;
  787. }
  788. for (iKey=0; cbKeyOut; iKey++)
  789. {
  790. // build Digest = HMAC(key | A(i) | seed);
  791. if (!FMyPrimitiveHMACParam(pbSecret, cbSecret, pbAofiDigest, cbSeed + A_SHA_DIGEST_LEN, rgbDigest))
  792. goto Ret;
  793. // append to pbKeyOut
  794. CopyMemory(pbKeyOut, rgbDigest, A_SHA_DIGEST_LEN);
  795. pbKeyOut += A_SHA_DIGEST_LEN;
  796. cbKeyOut -= A_SHA_DIGEST_LEN;
  797. // build A(i) = HMAC(key, A(i-1))
  798. if (!FMyPrimitiveHMACParam(pbSecret, cbSecret, pbAofiDigest, A_SHA_DIGEST_LEN, pbAofiDigest))
  799. goto Ret;
  800. }
  801. fRet = TRUE;
  802. Ret:
  803. if (pbAofiDigest)
  804. SSFree(pbAofiDigest);
  805. return fRet;
  806. }
  807. #if DBG
  808. // test vector for real P_Hash
  809. BOOL FTestPHASH_and_HMAC()
  810. {
  811. BYTE rgbKey[] = {0x33, 0x62, 0xf9, 0x42, 0x43};
  812. CHAR szPwd[] = "My Password";
  813. BYTE rgbKeyOut[7*A_SHA_DIGEST_LEN];
  814. static BYTE rgbTestVectorOutput[] = {
  815. 0x24, 0xF2, 0x98, 0x75, 0xE1, 0x90, 0x6D, 0x49,
  816. 0x96, 0x5B, 0x87, 0xB8, 0xBC, 0xD3, 0x11, 0x6C,
  817. 0x13, 0xDC, 0xBD, 0xC2, 0x7E, 0x56, 0xD0, 0x3C,
  818. 0xAC, 0xCD, 0x86, 0x58, 0x31, 0x67, 0x7B, 0x23,
  819. 0x19, 0x6E, 0x36, 0x65, 0xBF, 0x9F, 0x3D, 0x03,
  820. 0x5A, 0x9C, 0x6E, 0xD7, 0xEB, 0x3E, 0x5A, 0xE6,
  821. 0x05, 0x86, 0x84, 0x5A, 0xC3, 0x97, 0xFC, 0x17,
  822. 0xF5, 0xF0, 0xF5, 0x16, 0x67, 0xAD, 0x7C, 0xED,
  823. 0x65, 0xDC, 0x0B, 0x99, 0x58, 0x5D, 0xCA, 0x66,
  824. 0x28, 0xAD, 0xA5, 0x39, 0x54, 0x44, 0x36, 0x13,
  825. 0x91, 0xCE, 0xE9, 0x73, 0x23, 0x43, 0x2E, 0xEC,
  826. 0xA2, 0xC3, 0xE7, 0xFA, 0x74, 0xA7, 0xB6, 0x75,
  827. 0x77, 0xF5, 0xF5, 0x16, 0xC2, 0xEE, 0xED, 0x7A,
  828. 0x21, 0x86, 0x1D, 0x84, 0x6F, 0xC6, 0x03, 0xF3,
  829. 0xCC, 0x77, 0x02, 0xFA, 0x76, 0x46, 0x64, 0x57,
  830. 0xBB, 0x56, 0x3A, 0xF7, 0x7E, 0xB4, 0xD6, 0x52,
  831. 0x72, 0x8C, 0x34, 0xF1, 0xA4, 0x1E, 0xA7, 0xA6,
  832. 0xCD, 0xBD, 0x3C, 0x16, 0x4D, 0x79, 0x20, 0x50 };
  833. P_Hash(
  834. rgbKey, sizeof(rgbKey),
  835. (PBYTE)szPwd, strlen(szPwd),
  836. rgbKeyOut, sizeof(rgbKeyOut), FALSE);
  837. if (0 != memcmp(rgbKeyOut, rgbTestVectorOutput, sizeof(rgbKeyOut)) )
  838. {
  839. OutputDebugString("ERROR: phash vector test invalid!!!\n");
  840. return FALSE;
  841. }
  842. return TRUE;
  843. }
  844. // test vector for NSCP P_Hash
  845. BOOL F_NSCP_TestPHASH_and_HMAC()
  846. {
  847. BYTE rgbKey[] = { 0xc9, 0xc1, 0x69, 0x6e, 0x30, 0xa8, 0x91, 0x0d,
  848. 0x12, 0x19, 0x48, 0xef, 0x23, 0xac, 0x5b, 0x1f,
  849. 0x2e, 0xc4, 0x0e, 0xc2 };
  850. BYTE rgbSalt[] = { 0x1a, 0xb5, 0xf1, 0x1a, 0x5b, 0x6a, 0x6a, 0x5e };
  851. BYTE rgbKeyOut[7*A_SHA_DIGEST_LEN];
  852. static BYTE rgbTestVectorOutput[] = {
  853. 0x52, 0x7c, 0xbf, 0x90, 0xb1, 0xa1, 0xd0, 0xbf,
  854. 0x21, 0x56, 0x34, 0xf2, 0x1f, 0x5c, 0x98, 0xcf,
  855. 0x55, 0x95, 0xb1, 0x35, 0x65, 0xe3, 0x31, 0x44,
  856. 0x78, 0xc5, 0x41, 0xa9, 0x2a, 0x14, 0x80, 0x19,
  857. 0x56, 0x86, 0xa4, 0x71, 0x07, 0x24, 0x2d, 0x64 };
  858. assert(sizeof(rgbKeyOut) > sizeof(rgbTestVectorOutput));
  859. P_Hash(
  860. rgbKey, sizeof(rgbKey),
  861. rgbSalt, sizeof(rgbSalt),
  862. rgbKeyOut, sizeof(rgbTestVectorOutput),
  863. TRUE);
  864. if (0 != memcmp(rgbKeyOut, rgbTestVectorOutput, sizeof(rgbTestVectorOutput)) )
  865. {
  866. OutputDebugString("ERROR: NSCP phash vector test invalid!!!\n");
  867. return FALSE;
  868. }
  869. return TRUE;
  870. }
  871. #endif // DBG