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.

6833 lines
156 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 2000
  6. //
  7. // File: epf.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include <winldap.h>
  13. #define EXPORT_CONTROL DOMESTIC
  14. #include "csber.h"
  15. #include "csldap.h"
  16. #include "cainfop.h"
  17. #include "crcutil.h"
  18. #include "cast3.h"
  19. #define __dwFILE__ __dwFILE_CERTUTIL_EPF_CPP__
  20. #define CBTOKEN 8
  21. CRC16 g_CrcTable[256];
  22. typedef struct {
  23. DWORD dwAlgId;
  24. #define EPFALG_CAST_MD5 0x10
  25. #define EPFALG_RC2_SHA 0x20
  26. #define EPFALG_3DES 0x40
  27. // if EPFALG_RC2_SHA, this will be the key
  28. HCRYPTKEY hKey;
  29. // if EPFALG_CAST_MD5, we'll have a CAST context ready
  30. CAST3_CTX sCastContext;
  31. } EPF_SYM_KEY_STRUCT;
  32. #define wszSIGNING L"Signing"
  33. #define wszEXCHANGE L"Exchange"
  34. #if 0
  35. Entrust - CAST3 return codes
  36. #define C3E_OK 0 // No error
  37. #define C3E_DEPAD_FAILURE -1 // The de-padding operation failed
  38. #define C3E_BAD_KEYLEN -2 // Key length not supported
  39. #define C3E_SELFTEST_FAILED -3 // Self-test failed
  40. #define C3E_NOT_SUPPORTED -4 // Function not supported
  41. #endif
  42. #define EPFALG_EXPORT 0
  43. #define EPFALG_DOMESTIC 0x01000000
  44. static const WCHAR s_wszHeader[] = L"================================================================\n";
  45. VOID
  46. InitCrcTable()
  47. {
  48. static BOOL s_fInit = FALSE;
  49. if (!s_fInit)
  50. {
  51. USHORT ccitt_crc_poly = 0x8404; // CCITT crc16 polynominal
  52. I_CRC16(g_CrcTable, &ccitt_crc_poly); // initialize CRC generator
  53. s_fInit = TRUE;
  54. }
  55. }
  56. HRESULT
  57. IterateHash(
  58. IN DWORD dwSymAlgId,
  59. IN HCRYPTPROV hProv,
  60. IN int iIterations,
  61. IN BYTE const *rgbHash,
  62. IN DWORD cbBufferSize,
  63. IN DWORD cbInternalHashBuffer)
  64. {
  65. HRESULT hr;
  66. HCRYPTHASH hIterativeHash = NULL;
  67. BYTE *pbBufferExtension = NULL;
  68. DWORD cbBufferExtension;
  69. DWORD cbHash = cbBufferSize;
  70. int i;
  71. // use later to extend internal buffer during hash iteration
  72. if (cbInternalHashBuffer > cbHash)
  73. {
  74. pbBufferExtension = (BYTE *) LocalAlloc(
  75. LMEM_FIXED | LMEM_ZEROINIT,
  76. cbInternalHashBuffer - cbHash);
  77. if (NULL == pbBufferExtension)
  78. {
  79. hr = E_OUTOFMEMORY;
  80. _JumpError(hr, error, "LocalAlloc");
  81. }
  82. }
  83. // iterate to get output
  84. // 99 more times -- we've already done one hash
  85. for (i = 1; i < iIterations; i++)
  86. {
  87. if (!CryptCreateHash(
  88. hProv,
  89. EPFALG_CAST_MD5 == dwSymAlgId? CALG_MD5 : CALG_SHA1,
  90. 0,
  91. 0,
  92. &hIterativeHash))
  93. {
  94. hr = myHLastError();
  95. _JumpError(hr, error, "CryptCreateHash");
  96. }
  97. // hash the intermediate result
  98. if (!CryptHashData(hIterativeHash, rgbHash, cbHash, 0))
  99. {
  100. hr = myHLastError();
  101. _JumpError(hr, error, "CryptHashData");
  102. }
  103. if (cbInternalHashBuffer > cbHash)
  104. {
  105. // If hash buffer param is larger than hash length, do something
  106. // about it. Fill a buffer with the iteration count & tack it on
  107. // the end of the hash.
  108. memset(pbBufferExtension, i, cbInternalHashBuffer-cbHash);
  109. if (!CryptHashData(
  110. hIterativeHash,
  111. pbBufferExtension,
  112. cbInternalHashBuffer - cbHash,
  113. 0))
  114. {
  115. hr = myHLastError();
  116. _JumpError(hr, error, "CryptHashData");
  117. }
  118. }
  119. // done with this round, continue to the next
  120. cbHash = cbBufferSize;
  121. if (!CryptGetHashParam(
  122. hIterativeHash,
  123. HP_HASHVAL,
  124. const_cast<BYTE *>(rgbHash),
  125. &cbHash,
  126. 0))
  127. {
  128. hr = myHLastError();
  129. _JumpError(hr, error, "CryptGetHashParam");
  130. }
  131. CryptDestroyHash(hIterativeHash);
  132. hIterativeHash = NULL;
  133. }
  134. hr = S_OK;
  135. error:
  136. if (NULL != pbBufferExtension)
  137. {
  138. LocalFree(pbBufferExtension);
  139. }
  140. if (NULL != hIterativeHash)
  141. {
  142. CryptDestroyHash(hIterativeHash);
  143. }
  144. #if 0
  145. wprintf(L"FinalHash output\n");
  146. DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 4, rgbHash, cbBufferSize);
  147. wprintf(wszNewLine);
  148. #endif
  149. return(hr);
  150. }
  151. // derive sym encr key
  152. HRESULT
  153. EPFDeriveKey(
  154. IN DWORD dwAlgId,
  155. IN DWORD dwKeyLen,
  156. IN HCRYPTPROV hProv,
  157. IN WCHAR const *pwszPassword,
  158. IN WCHAR const *pwszSaltValue,
  159. IN BYTE const *pbSaltValue,
  160. IN DWORD cbSaltValue,
  161. IN DWORD cbHashSize,
  162. IN OUT EPF_SYM_KEY_STRUCT *psKey)
  163. {
  164. HRESULT hr;
  165. char *pszPassword = NULL;
  166. char *pszSaltValue = NULL;
  167. HCRYPTHASH hHash = NULL;
  168. HCRYPTHASH hIVHash = NULL;
  169. BYTE rgbHash[20]; // hash output
  170. DWORD cbHash;
  171. BYTE rgbIV[8]; // IV
  172. BYTE rgbKeyBlob[sizeof(BLOBHEADER) + sizeof(DWORD) + 16]; // 128 bit key
  173. BYTE *pbWritePtr;
  174. DWORD cbPwdBuf;
  175. BYTE *pbPwdBuf = NULL;
  176. switch (dwAlgId)
  177. {
  178. case EPFALG_CAST_MD5:
  179. case EPFALG_RC2_SHA:
  180. case EPFALG_3DES:
  181. break;
  182. default:
  183. hr = E_UNEXPECTED;
  184. _JumpError(hr, error, "dwAlgId");
  185. }
  186. if (NULL == pwszPassword || NULL == pwszSaltValue)
  187. {
  188. hr = E_POINTER;
  189. _JumpError(hr, error, "SaltValue");
  190. }
  191. if (!myConvertWszToSz(&pszPassword, pwszPassword, -1))
  192. {
  193. hr = E_OUTOFMEMORY;
  194. _JumpError(hr, error, "myConvertWszToSz");
  195. }
  196. if (!myConvertWszToSz(&pszSaltValue, pwszSaltValue, -1))
  197. {
  198. hr = E_OUTOFMEMORY;
  199. _JumpError(hr, error, "myConvertWszToSz");
  200. }
  201. //wprintf(L"password=\"%hs\", salt=\"%hs\"\n", pszPassword, pszSaltValue);
  202. cbPwdBuf = strlen(pszPassword) + strlen(pszSaltValue) + 1;
  203. pbPwdBuf = (BYTE *) LocalAlloc(LMEM_FIXED, cbPwdBuf);
  204. if (pbPwdBuf == NULL)
  205. {
  206. hr = E_OUTOFMEMORY;
  207. _JumpError(hr, error, "pbPwdBuf");
  208. }
  209. strcpy((char *) pbPwdBuf, pszPassword);
  210. strcat((char *) pbPwdBuf, pszSaltValue); // pszPassword + pszSaltValue
  211. if (!CryptCreateHash(
  212. hProv,
  213. EPFALG_CAST_MD5 == dwAlgId? CALG_MD5 : CALG_SHA1,
  214. 0,
  215. 0,
  216. &hHash))
  217. {
  218. hr = myHLastError();
  219. _JumpError(hr, error, "CryptCreateHash");
  220. }
  221. // hash pwd | salt
  222. if (!CryptHashData(hHash, pbPwdBuf, cbPwdBuf - 1, 0))
  223. {
  224. hr = myHLastError();
  225. _JumpError(hr, error, "CryptHashData");
  226. }
  227. // wprintf(L"\npbPwdBuf: %hs, len: %d\n", (char const *) pbPwdBuf, cbPwdBuf - 1);
  228. cbHash = sizeof(rgbHash);
  229. if (!CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
  230. {
  231. hr = myHLastError();
  232. _JumpError(hr, error, "CryptGetHashParam");
  233. }
  234. #if 0
  235. wprintf(L"=====KEY======\n");
  236. wprintf(L"FirstHash output\n");
  237. DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 4, rgbHash, cbHash);
  238. wprintf(wszNewLine);
  239. #endif
  240. hr = IterateHash(dwAlgId, hProv, 100, rgbHash, cbHash, cbHashSize);
  241. _JumpIfError(hr, error, "IterateHash");
  242. // now rgbHash[0..15] is raw key
  243. psKey->dwAlgId = dwAlgId;
  244. if (EPFALG_RC2_SHA == dwAlgId)
  245. {
  246. // set up rgbKeyBlob as a contiguous, plaintext blob
  247. pbWritePtr = rgbKeyBlob + sizeof(BLOBHEADER);
  248. ((BLOBHEADER *) rgbKeyBlob)->bType = PLAINTEXTKEYBLOB;
  249. ((BLOBHEADER *) rgbKeyBlob)->bVersion = 2;
  250. ((BLOBHEADER *) rgbKeyBlob)->reserved = 0;
  251. ((BLOBHEADER *) rgbKeyBlob)->aiKeyAlg = CALG_RC2;
  252. // size
  253. *(DWORD *) pbWritePtr = 16;
  254. pbWritePtr += sizeof(DWORD);
  255. // data
  256. CopyMemory(pbWritePtr, rgbHash, 16); // 128 bit key
  257. // save last 4 bytes for the first half of the IV
  258. CopyMemory(rgbIV, &rgbHash[16], 4);
  259. // PLAINTEXTKEYBLOB
  260. if (!CryptImportKey(
  261. hProv,
  262. rgbKeyBlob,
  263. sizeof(rgbKeyBlob),
  264. 0, // no wrapper key
  265. 0,
  266. &psKey->hKey))
  267. {
  268. hr = myHLastError();
  269. _JumpError(hr, error, "CryptImportKey");
  270. }
  271. {
  272. DWORD cbEffectiveLen = 128;
  273. if (!CryptSetKeyParam(
  274. psKey->hKey,
  275. KP_EFFECTIVE_KEYLEN,
  276. (BYTE *) &cbEffectiveLen,
  277. 0))
  278. {
  279. hr = myHLastError();
  280. _JumpError(hr, error, "CryptSetKeyParam(eff keylen)");
  281. }
  282. }
  283. {
  284. DWORD cbMode = CRYPT_MODE_CBC;
  285. if (!CryptSetKeyParam(psKey->hKey, KP_MODE, (BYTE *) &cbMode, 0))
  286. {
  287. hr = myHLastError();
  288. _JumpError(hr, error, "CryptSetKeyParam(mode)");
  289. }
  290. }
  291. }
  292. else // gen CAST context
  293. {
  294. if (g_fVerbose)
  295. {
  296. wprintf(
  297. L"CAST KeyMatl: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
  298. rgbHash[0],
  299. rgbHash[1],
  300. rgbHash[2],
  301. rgbHash[3],
  302. rgbHash[4],
  303. rgbHash[5],
  304. rgbHash[6],
  305. rgbHash[7]);
  306. }
  307. // Set up key schedule. No errors since SetNumBits already checked length
  308. hr = CAST3SetKeySchedule(&psKey->sCastContext, rgbHash, 64); // 64 bit for now
  309. _JumpIfError(hr, error, "CAST3SetKeySchedule");
  310. }
  311. // compute IV
  312. if (EPFALG_RC2_SHA == dwAlgId)
  313. {
  314. // now, generate IV. Start with new hash, hash in (pwd buf | 0x1)
  315. if (!CryptCreateHash(
  316. hProv,
  317. EPFALG_CAST_MD5 == dwAlgId? CALG_MD5 : CALG_SHA1,
  318. 0,
  319. 0,
  320. &hIVHash))
  321. {
  322. hr = myHLastError();
  323. _JumpError(hr, error, "CryptCreateHash");
  324. }
  325. // hash pwd | salt
  326. if (!CryptHashData(hIVHash, pbPwdBuf, cbPwdBuf - 1, 0))
  327. {
  328. hr = myHLastError();
  329. _JumpError(hr, error, "CryptHashData");
  330. }
  331. // hash 0x1 this time (internally, this is 2nd iteration for
  332. // ExtendedHash)
  333. BYTE bAppendage = 0x1;
  334. if (!CryptHashData(hIVHash, &bAppendage, sizeof(bAppendage), 0))
  335. {
  336. hr = myHLastError();
  337. _JumpError(hr, error, "CryptHashData");
  338. }
  339. if (!CryptGetHashParam(hIVHash, HP_HASHVAL, rgbHash, &cbHash, 0))
  340. {
  341. hr = myHLastError();
  342. _JumpError(hr, error, "CryptGetHashParam");
  343. }
  344. hr = IterateHash(dwAlgId, hProv, 100, rgbHash, cbHash, cbHashSize);
  345. _JumpIfError(hr, error, "IterateHash");
  346. // DONE! previous rgbHash[16..20] and rgbHash[0..4] is IV
  347. CopyMemory(&rgbIV[4], rgbHash, 4);
  348. if (!CryptSetKeyParam(psKey->hKey, KP_IV, rgbIV, 0))
  349. {
  350. hr = myHLastError();
  351. _JumpError(hr, error, "CryptSetKeyParam(iv)");
  352. }
  353. }
  354. else
  355. {
  356. // DONE! rgbHash[0..8] is IV
  357. if (g_fVerbose)
  358. {
  359. wprintf(
  360. L"IV: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
  361. rgbHash[8],
  362. rgbHash[9],
  363. rgbHash[10],
  364. rgbHash[11],
  365. rgbHash[12],
  366. rgbHash[13],
  367. rgbHash[14],
  368. rgbHash[15]);
  369. }
  370. // Start CAST in CBC mode w/ IV
  371. hr = CAST3StartEncryptCBC(&psKey->sCastContext, &rgbHash[8]);
  372. _JumpIfError(hr, error, "CAST3SetKeySchedule");
  373. }
  374. hr = S_OK;
  375. error:
  376. SecureZeroMemory(rgbHash, cbHash); // Key material
  377. SecureZeroMemory(rgbKeyBlob, sizeof(rgbKeyBlob)); // Key material
  378. if (NULL != pszPassword)
  379. {
  380. myZeroDataStringA(pszPassword); // password data
  381. LocalFree(pszPassword);
  382. }
  383. if (NULL != pszSaltValue)
  384. {
  385. LocalFree(pszSaltValue);
  386. }
  387. if (NULL != pbPwdBuf)
  388. {
  389. SecureZeroMemory(pbPwdBuf, cbPwdBuf); // password data
  390. LocalFree(pbPwdBuf);
  391. }
  392. if (NULL != hHash)
  393. {
  394. CryptDestroyHash(hHash);
  395. }
  396. if (NULL != hIVHash)
  397. {
  398. CryptDestroyHash(hIVHash);
  399. }
  400. return(hr);
  401. }
  402. // generate token from password-dependent key
  403. HRESULT
  404. EPFGenerateKeyToken(
  405. IN EPF_SYM_KEY_STRUCT const *psKey,
  406. OUT BYTE *pbToken,
  407. IN DWORD cbToken)
  408. {
  409. HRESULT hr;
  410. HCRYPTKEY hLocalKey = NULL;
  411. if (CBTOKEN != cbToken)
  412. {
  413. hr = E_INVALIDARG;
  414. _JumpError(hr, error, "cbToken");
  415. }
  416. if (EPFALG_RC2_SHA == psKey->dwAlgId)
  417. {
  418. if (!CryptDuplicateKey(psKey->hKey, NULL, 0, &hLocalKey))
  419. {
  420. hr = myHLastError();
  421. _JumpError(hr, error, "CryptDuplicateKey");
  422. }
  423. // We have the key already set up.
  424. // Just CBC encrypt one block of zeros as the token.
  425. ZeroMemory(pbToken, CBTOKEN);
  426. if (!CryptEncrypt(hLocalKey, 0, FALSE, 0, pbToken, &cbToken, CBTOKEN))
  427. {
  428. hr = myHLastError();
  429. _JumpError(hr, error, "CryptEncrypt");
  430. }
  431. // and one block of 8s as padding...
  432. memset(pbToken, 8, CBTOKEN);
  433. cbToken = CBTOKEN;
  434. if (!CryptEncrypt(hLocalKey, 0, FALSE, 0, pbToken, &cbToken, CBTOKEN))
  435. {
  436. hr = myHLastError();
  437. _JumpError(hr, error, "CryptEncrypt");
  438. }
  439. }
  440. else // generate CAST token
  441. {
  442. // duplicate key state
  443. CAST3_CTX sLocalKey;
  444. CopyMemory(&sLocalKey, (BYTE *) &psKey->sCastContext, sizeof(sLocalKey));
  445. // We have the key already set up.
  446. // Just CBC encrypt one block of zeros as the token.
  447. ZeroMemory(pbToken, CBTOKEN);
  448. // MAC 0
  449. hr = CAST3UpdateMAC(&sLocalKey, (BYTE *) pbToken, CBTOKEN);
  450. _JumpIfError(hr, error, "CAST3UpdateEncryptCBC");
  451. hr = CAST3EndMAC(&sLocalKey);
  452. _JumpIfError(hr, error, "CAST3UpdateEncryptCBC");
  453. // and copy intermediate out
  454. CopyMemory(pbToken, sLocalKey.cbcBuffer.asBYTE, CBTOKEN);
  455. CAST3Cleanup(&sLocalKey);
  456. }
  457. hr = S_OK;
  458. error:
  459. if (NULL != hLocalKey)
  460. {
  461. CryptDestroyKey(hLocalKey);
  462. }
  463. return(hr);
  464. }
  465. // check pwd via token
  466. HRESULT
  467. EPFVerifyKeyToken(
  468. IN EPF_SYM_KEY_STRUCT const *psKey,
  469. IN BYTE const *pbToken,
  470. IN DWORD cbToken)
  471. {
  472. HRESULT hr;
  473. BYTE rgbComputedToken[CBTOKEN];
  474. hr = EPFGenerateKeyToken(psKey, rgbComputedToken, sizeof(rgbComputedToken));
  475. _JumpIfError(hr, error, "EPFGenerateKeyToken");
  476. if (sizeof(rgbComputedToken) != cbToken ||
  477. 0 != memcmp(pbToken, rgbComputedToken, sizeof(rgbComputedToken)))
  478. {
  479. wprintf(L"pbToken\n");
  480. DumpHex(DH_NOTABPREFIX | 4, pbToken, cbToken);
  481. wprintf(wszNewLine);
  482. wprintf(L"rgbComputedToken\n");
  483. DumpHex(DH_NOTABPREFIX | 4, rgbComputedToken, sizeof(rgbComputedToken));
  484. wprintf(wszNewLine);
  485. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD);
  486. _JumpError(hr, error, "bad password");
  487. }
  488. if (g_fVerbose)
  489. {
  490. wprintf(myLoadResourceString(IDS_TOKENMATCH)); // "Token match"
  491. wprintf(wszNewLine);
  492. DumpHex(DH_NOTABPREFIX | 4, pbToken, cbToken);
  493. wprintf(wszNewLine);
  494. }
  495. hr = S_OK;
  496. error:
  497. return(hr);
  498. }
  499. // decrypt a section
  500. HRESULT
  501. EPFDecryptSection(
  502. IN EPF_SYM_KEY_STRUCT const *psKey,
  503. IN BYTE const *pbSection,
  504. IN DWORD cbSection,
  505. OUT BYTE **ppbDecrypted,
  506. OUT DWORD *pcbDecrypted)
  507. {
  508. HRESULT hr;
  509. HCRYPTKEY hLocalKey = NULL;
  510. switch (psKey->dwAlgId)
  511. {
  512. case EPFALG_CAST_MD5:
  513. case EPFALG_RC2_SHA:
  514. break;
  515. case EPFALG_3DES:
  516. DumpHex(DH_NOTABPREFIX | 4, pbSection, cbSection);
  517. wprintf(wszNewLine);
  518. // FALLTHROUGH
  519. default:
  520. hr = E_UNEXPECTED;
  521. _JumpError(hr, error, "dwAlgId");
  522. }
  523. // add extra block just in case
  524. *ppbDecrypted = (BYTE *) LocalAlloc(LMEM_FIXED, cbSection + 8);
  525. if (NULL == *ppbDecrypted)
  526. {
  527. hr = E_OUTOFMEMORY;
  528. _JumpError(hr, error, "*ppbDecrypted");
  529. }
  530. *pcbDecrypted = cbSection; // input len
  531. // copy into working area
  532. CopyMemory(*ppbDecrypted, pbSection, cbSection);
  533. if (EPFALG_RC2_SHA == psKey->dwAlgId)
  534. {
  535. if (!CryptDuplicateKey(psKey->hKey, NULL, 0, &hLocalKey))
  536. {
  537. hr = myHLastError();
  538. _JumpError(hr, error, "CryptDuplicateKey");
  539. }
  540. // We have the key already set up
  541. if (!CryptDecrypt(
  542. hLocalKey,
  543. 0,
  544. TRUE,
  545. 0, // flags
  546. *ppbDecrypted,
  547. pcbDecrypted))
  548. {
  549. hr = myHLastError();
  550. _JumpError(hr, error, "CryptDecrypt");
  551. }
  552. }
  553. else // CAST MD5
  554. {
  555. // duplicate key state
  556. CAST3_CTX sLocalKey;
  557. CopyMemory(
  558. &sLocalKey,
  559. (BYTE *) &psKey->sCastContext,
  560. sizeof(sLocalKey));
  561. // We have the key already set up.
  562. CAST3UpdateDecryptCBC(
  563. &sLocalKey,
  564. pbSection,
  565. *ppbDecrypted,
  566. (UINT *) pcbDecrypted);
  567. // decrypt call is a void return
  568. // _JumpIfError(hr, error, "CAST3UpdateDecryptCBC");
  569. // handle anything still left in the cipher state
  570. BYTE *pbTmp = *ppbDecrypted + *pcbDecrypted; // point to known end
  571. DWORD cbTmp = 0;
  572. hr = CAST3EndDecryptCBC(
  573. &sLocalKey,
  574. pbTmp,
  575. (UINT *) &cbTmp); // tack any extra on the end
  576. _JumpIfError(hr, error, "CAST3EndDecryptCBC");
  577. *pcbDecrypted += cbTmp;
  578. CAST3Cleanup(&sLocalKey);
  579. }
  580. #if 0
  581. wprintf(L"pbDecrypted Data\n");
  582. DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 4, *ppbDecrypted, *pcbDecrypted);
  583. wprintf(wszNewLine);
  584. #endif
  585. hr = S_OK;
  586. error:
  587. if (NULL != hLocalKey)
  588. {
  589. CryptDestroyKey(hLocalKey);
  590. }
  591. if (S_OK != hr && NULL != *ppbDecrypted)
  592. {
  593. LocalFree(*ppbDecrypted);
  594. *ppbDecrypted = NULL;
  595. }
  596. return(hr);
  597. }
  598. // Encrypt a section
  599. HRESULT
  600. EPFEncryptSection(
  601. IN EPF_SYM_KEY_STRUCT const *psKey,
  602. IN BYTE const *pbToBeEncrypted,
  603. IN DWORD cbToBeEncrypted,
  604. OUT BYTE **ppbEncrypted,
  605. OUT DWORD *pcbEncrypted)
  606. {
  607. HRESULT hr;
  608. HCRYPTKEY hLocalKey = NULL;
  609. *ppbEncrypted = NULL;
  610. *pcbEncrypted = cbToBeEncrypted;
  611. if (EPFALG_CAST_MD5 != psKey->dwAlgId && EPFALG_RC2_SHA != psKey->dwAlgId)
  612. {
  613. hr = E_UNEXPECTED;
  614. _JumpError(hr, error, "dwAlgId");
  615. }
  616. if (EPFALG_RC2_SHA == psKey->dwAlgId)
  617. {
  618. if (!CryptDuplicateKey(psKey->hKey, NULL, 0, &hLocalKey))
  619. {
  620. hr = myHLastError();
  621. _JumpError(hr, error, "CryptDuplicateKey");
  622. }
  623. // We have the key already set up. Just CBC encrypt one block of zeros
  624. // as the token.
  625. if (!CryptEncrypt(
  626. hLocalKey,
  627. 0,
  628. TRUE,
  629. 0, // flags
  630. NULL,
  631. pcbEncrypted,
  632. 0))
  633. {
  634. hr = myHLastError();
  635. _JumpError(hr, error, "CryptDecrypt");
  636. }
  637. *ppbEncrypted = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbEncrypted);
  638. if (NULL == *ppbEncrypted)
  639. {
  640. hr = E_OUTOFMEMORY;
  641. _JumpError(hr, error, "*ppbEncrypted");
  642. }
  643. // copy data into slightly larger buffer
  644. CopyMemory(*ppbEncrypted, pbToBeEncrypted, cbToBeEncrypted);
  645. if (!CryptEncrypt(
  646. hLocalKey,
  647. 0,
  648. TRUE,
  649. 0, // flags
  650. *ppbEncrypted,
  651. &cbToBeEncrypted,
  652. *pcbEncrypted))
  653. {
  654. hr = myHLastError();
  655. _JumpError(hr, error, "CryptDecrypt");
  656. }
  657. }
  658. else // CAST & SHA
  659. {
  660. // duplicate key state
  661. CAST3_CTX sLocalKey;
  662. CopyMemory(
  663. &sLocalKey,
  664. (BYTE *) &psKey->sCastContext,
  665. sizeof(sLocalKey));
  666. // allow for final block to run over
  667. *ppbEncrypted = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbEncrypted + 8);
  668. if (NULL == *ppbEncrypted)
  669. {
  670. hr = E_OUTOFMEMORY;
  671. _JumpError(hr, error, "*ppbEncrypted");
  672. }
  673. // We have the key already set up.
  674. hr = CAST3UpdateEncryptCBC(
  675. &sLocalKey,
  676. pbToBeEncrypted,
  677. *ppbEncrypted,
  678. (UINT *) pcbEncrypted);
  679. _JumpIfError(hr, error, "CAST3UpdateEncryptCBC");
  680. // handle anything still left in the cipher state
  681. BYTE *pbTmp = *ppbEncrypted + *pcbEncrypted; // point to known end
  682. DWORD cbTmp = 0;
  683. hr = CAST3EndEncryptCBC(
  684. &sLocalKey,
  685. pbTmp,
  686. (UINT *) &cbTmp); // tack any extra on the end
  687. _JumpIfError(hr, error, "CAST3EndEncryptCBC");
  688. *pcbEncrypted += cbTmp;
  689. CAST3Cleanup(&sLocalKey);
  690. }
  691. hr = S_OK;
  692. error:
  693. if (NULL != hLocalKey)
  694. {
  695. CryptDestroyKey(hLocalKey);
  696. }
  697. if (S_OK != hr && NULL != *ppbEncrypted)
  698. {
  699. LocalFree(*ppbEncrypted);
  700. *ppbEncrypted = NULL;
  701. }
  702. return(hr);
  703. }
  704. // char section and key name strings:
  705. #define szINFSECTION_PASSWORDTOKEN "Password Token"
  706. #define szINFKEY_PROTECTION "Protection"
  707. #define szINFKEY_PROFILEVERSION "Profile Version"
  708. #define szINFKEY_CAST "CAST"
  709. #define szINFKEY_TOKEN "Token"
  710. #define szINFKEY_SALTVALUE "SaltValue"
  711. #define szINFKEY_HASHSIZE "HashSize"
  712. // 3DES keys:
  713. #define szINFKEY_MACALGORITHM "MAC Algorithm"
  714. #define szINFKEY_HASHCOUNT "HashCount"
  715. #define szINFKEY_CRC "CRC"
  716. #define szINFKEY_OPTIONSMAC "Options MAC"
  717. #define szINFKEY_USERX500NAMEMAC "User X.500 Name MAC"
  718. // 3DES section:
  719. #define szINFSECTION_PROTECTED "Protected"
  720. #define szINFKEY_RANDOMSEED "randomSeed"
  721. #define szINFKEY_PWHISTORY "pwHistory"
  722. // 3DES section:
  723. #define szINFSECTION_OPTIONS "Options"
  724. #define szINFKEY_PROFILETYPE "ProfileType"
  725. #define szINFKEY_CERTPUBLICATIONPENDING "CertificatePublicationPending"
  726. #define szINFKEY_USESMIME "UseSMIME"
  727. #define szINFKEY_ENCRYPTWITH "EncryptWith"
  728. #define szINFKEY_SMIMEENCRYPTWITH "SMIMEEncryptWith"
  729. #define szINFKEY_DELETEAFTERDECRYPT "DeleteAfterDecrypt"
  730. #define szINFKEY_DELETEAFTERENCRYPT "DeleteAfterEncrypt"
  731. // 3DES section:
  732. #define szINFSECTION_CACERTIFICATES "CA Certificates"
  733. //#define szINFKEY_CERTIFICATE "Certificate"
  734. #define szINFSECTION_USERX500NAME "User X.500 Name"
  735. #define szINFKEY_X500NAME "X500Name"
  736. #define szINFSECTION_DIGITALSIGNATURE "Digital Signature"
  737. #define szINFKEY_CERTIFICATE "Certificate"
  738. #define szINFKEY_KEY "Key"
  739. #define szINFSECTION_PRIVATEKEYS "Private Keys"
  740. #define szINFKEY_KEY_FORMAT "Key%u"
  741. //#define szINFKEY_KEYCOUNT "KeyCount"
  742. #define szINFSECTION_CERTIFICATEHISTORY "Certificate History"
  743. #define szINFKEY_NAME_FORMAT "Name%u"
  744. #define szINFSECTION_USERCERTIFICATE "User Certificate"
  745. #define szINFKEY_CERTIFICATE "Certificate"
  746. #define szINFSECTION_CA "CA"
  747. //#define szINFKEY_CERTIFICATE "Certificate"
  748. // 40 bit only:
  749. #define szINFSECTION_MANAGER "Manager"
  750. //#define szINFKEY_CERTIFICATE "Certificate"
  751. #define szINFSECTION_MICROSOFTEXCHANGE "Microsoft Exchange"
  752. #define szINFKEY_FRIENDLYNAME "FriendlyName"
  753. #define szINFKEY_KEYALGID "KeyAlgId"
  754. // 40 bit only:
  755. #define szINFSECTION_REVOKATIONINFORMATION "Revokation Information"
  756. #define szINFKEY_CRL "CRL"
  757. #define szINFKEY_CRL1 "CRL1"
  758. #define szINFSECTION_SMIME "S/MIME"
  759. #define szINFKEY_SIGNINGCERTIFICATE "Signing Certificate"
  760. #define szINFKEY_SIGNINGKEY "Signing Key"
  761. #define szINFKEY_PRIVATEKEYS "Private Keys"
  762. #define szINFKEY_KEYCOUNT "KeyCount"
  763. #define szINFKEY_ISSUINGCERTIFICATES "Issuing Certificates"
  764. #define szINFKEY_TRUSTLISTCERTIFICATE "Trust List Certificate"
  765. #define szINFSECTION_FULLCERTIFICATEHISTORY "Full Certificate History"
  766. //#define szINFKEY_NAME_FORMAT "Name%u"
  767. #define szINFKEY_SMIME_FORMAT "SMIME_%u"
  768. // WCHAR section and key name strings:
  769. #define wszINFSECTION_PASSWORDTOKEN TEXT(szINFSECTION_PASSWORDTOKEN)
  770. #define wszINFKEY_PROTECTION TEXT(szINFKEY_PROTECTION)
  771. #define wszINFKEY_PROFILEVERSION TEXT(szINFKEY_PROFILEVERSION)
  772. #define wszINFKEY_CAST TEXT(szINFKEY_CAST)
  773. #define wszINFKEY_TOKEN TEXT(szINFKEY_TOKEN)
  774. #define wszINFKEY_SALTVALUE TEXT(szINFKEY_SALTVALUE)
  775. #define wszINFKEY_HASHSIZE TEXT(szINFKEY_HASHSIZE)
  776. // 3DES keys:
  777. #define wszINFKEY_MACALGORITHM TEXT(szINFKEY_MACALGORITHM)
  778. #define wszINFKEY_HASHCOUNT TEXT(szINFKEY_HASHCOUNT)
  779. #define wszINFKEY_CRC TEXT(szINFKEY_CRC)
  780. #define wszINFKEY_OPTIONSMAC TEXT(szINFKEY_OPTIONSMAC)
  781. #define wszINFKEY_USERX500NAMEMAC TEXT(szINFKEY_USERX500NAMEMAC)
  782. // 3DES section:
  783. #define wszINFSECTION_PROTECTED TEXT(szINFSECTION_PROTECTED)
  784. #define wszINFKEY_RANDOMSEED TEXT(szINFKEY_RANDOMSEED)
  785. #define wszINFKEY_PWHISTORY TEXT(szINFKEY_PWHISTORY)
  786. // 3DES section:
  787. #define wszINFSECTION_OPTIONS TEXT(szINFSECTION_OPTIONS)
  788. #define wszINFKEY_PROFILETYPE TEXT(szINFKEY_PROFILETYPE)
  789. #define wszINFKEY_CERTPUBLICATIONPENDING TEXT(szINFKEY_CERTPUBLICATIONPENDING)
  790. #define wszINFKEY_USESMIME TEXT(szINFKEY_USESMIME)
  791. #define wszINFKEY_ENCRYPTWITH TEXT(szINFKEY_ENCRYPTWITH)
  792. #define wszINFKEY_SMIMEENCRYPTWITH TEXT(szINFKEY_SMIMEENCRYPTWITH)
  793. #define wszINFKEY_DELETEAFTERDECRYPT TEXT(szINFKEY_DELETEAFTERDECRYPT)
  794. #define wszINFKEY_DELETEAFTERENCRYPT TEXT(szINFKEY_DELETEAFTERENCRYPT)
  795. // 3DES section:
  796. #define wszINFSECTION_CACERTIFICATES TEXT(szINFSECTION_CACERTIFICATES)
  797. //#define wszINFKEY_CERTIFICATE TEXT(szINFKEY_CERTIFICATE)
  798. #define wszINFSECTION_USERX500NAME TEXT(szINFSECTION_USERX500NAME)
  799. #define wszINFKEY_X500NAME TEXT(szINFKEY_X500NAME)
  800. #define wszINFSECTION_DIGITALSIGNATURE TEXT(szINFSECTION_DIGITALSIGNATURE)
  801. #define wszINFKEY_CERTIFICATE TEXT(szINFKEY_CERTIFICATE)
  802. #define wszINFKEY_KEY TEXT(szINFKEY_KEY)
  803. #define wszINFSECTION_PRIVATEKEYS TEXT(szINFSECTION_PRIVATEKEYS)
  804. #define wszINFKEY_KEY_FORMAT TEXT(szINFKEY_KEY_FORMAT)
  805. //#define wszINFKEY_KEYCOUNT TEXT(szINFKEY_KEYCOUNT)
  806. #define wszINFSECTION_CERTIFICATEHISTORY TEXT(szINFSECTION_CERTIFICATEHISTORY)
  807. #define wszINFKEY_NAME_FORMAT TEXT(szINFKEY_NAME_FORMAT)
  808. #define wszINFSECTION_USERCERTIFICATE TEXT(szINFSECTION_USERCERTIFICATE)
  809. #define wszINFKEY_CERTIFICATE TEXT(szINFKEY_CERTIFICATE)
  810. #define wszINFSECTION_CA TEXT(szINFSECTION_CA)
  811. //#define wszINFKEY_CERTIFICATE TEXT(szINFKEY_CERTIFICATE)
  812. // 40 bit only:
  813. #define wszINFSECTION_MANAGER TEXT(szINFSECTION_MANAGER)
  814. //#define szINFKEY_CERTIFICATE TEXT(szINFKEY_CERTIFICATE)
  815. #define wszINFSECTION_MICROSOFTEXCHANGE TEXT(szINFSECTION_MICROSOFTEXCHANGE)
  816. #define wszINFKEY_FRIENDLYNAME TEXT(szINFKEY_FRIENDLYNAME)
  817. #define wszINFKEY_KEYALGID TEXT(szINFKEY_KEYALGID)
  818. // 40 bit only:
  819. #define wszINFSECTION_REVOKATIONINFORMATION TEXT(szINFSECTION_REVOKATIONINFORMATION)
  820. #define wszINFKEY_CRL TEXT(szINFKEY_CRL)
  821. #define wszINFKEY_CRL1 TEXT(szINFKEY_CRL1)
  822. #define wszINFSECTION_SMIME TEXT(szINFSECTION_SMIME)
  823. #define wszINFKEY_SIGNINGCERTIFICATE TEXT(szINFKEY_SIGNINGCERTIFICATE)
  824. #define wszINFKEY_SIGNINGKEY TEXT(szINFKEY_SIGNINGKEY)
  825. #define wszINFKEY_PRIVATEKEYS TEXT(szINFKEY_PRIVATEKEYS)
  826. #define wszINFKEY_KEYCOUNT TEXT(szINFKEY_KEYCOUNT)
  827. #define wszINFKEY_ISSUINGCERTIFICATES TEXT(szINFKEY_ISSUINGCERTIFICATES)
  828. #define wszINFKEY_TRUSTLISTCERTIFICATE TEXT(szINFKEY_TRUSTLISTCERTIFICATE)
  829. #define wszINFSECTION_FULLCERTIFICATEHISTORY TEXT(szINFSECTION_FULLCERTIFICATEHISTORY)
  830. //#define wszINFKEY_NAME_FORMAT TEXT(szINFKEY_NAME_FORMAT)
  831. #define wszINFKEY_SMIME_FORMAT TEXT(szINFKEY_SMIME_FORMAT)
  832. // fixed maximum buffer lengths
  833. #define cwcINFKEY_KEY_FORMATTED \
  834. (ARRAYSIZE(wszINFKEY_KEY_FORMAT) + cwcDWORDSPRINTF)
  835. #define cwcINFKEY_NAME_FORMATTED \
  836. (ARRAYSIZE(wszINFKEY_NAME_FORMAT) + cwcDWORDSPRINTF)
  837. #define cwcINFKEY_SMIME_FORMATTED \
  838. (ARRAYSIZE(wszINFKEY_SMIME_FORMAT) + cwcDWORDSPRINTF)
  839. #define wszSECTION_KEY(Alg, wszSECTION, wszKEY) \
  840. (EPFALG_3DES == (Alg)? \
  841. wszLBRACKET wszSECTION wszRBRACKET L" &" wszKEY : \
  842. wszLBRACKET wszSECTION wszRBRACKET L" @" wszKEY)
  843. const WCHAR g_wszCACertCN[] = L"Certificate Authority";
  844. HRESULT
  845. cuPatchEPFFile(
  846. IN WCHAR const *pwszfnIn,
  847. OUT WCHAR **ppwszfnOut)
  848. {
  849. HRESULT hr;
  850. char *pszfnIn = NULL;
  851. char *pszfnOut = NULL;
  852. FILE *pfIn = NULL;
  853. FILE *pfOut = NULL;
  854. char *psz;
  855. char achLine[1024];
  856. WCHAR awcTempDir[MAX_PATH];
  857. WCHAR awcfnOut[MAX_PATH];
  858. BOOL fDeleteTempFile = FALSE;
  859. DWORD cwc;
  860. *ppwszfnOut = NULL;
  861. if (!myConvertWszToSz(&pszfnIn, pwszfnIn, -1))
  862. {
  863. hr = E_OUTOFMEMORY;
  864. _JumpError(hr, error, "myConvertWszToSz");
  865. }
  866. pfIn = fopen(pszfnIn, "r");
  867. if (NULL == pfIn)
  868. {
  869. DWORD dwFileAttr;
  870. // Ansi conversion lost characters & the ansi file cannot be found?
  871. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  872. dwFileAttr = GetFileAttributes(pwszfnIn);
  873. if (MAXDWORD != dwFileAttr)
  874. {
  875. hr = S_FALSE;
  876. }
  877. _JumpError2(hr, error, "fopen", S_FALSE);
  878. }
  879. hr = S_FALSE;
  880. if (NULL == fgets(achLine, ARRAYSIZE(achLine), pfIn))
  881. {
  882. _JumpError2(hr, error, "fgets", hr);
  883. }
  884. psz = strchr(achLine, chLBRACKET);
  885. if (NULL == psz ||
  886. NULL == strstr(psz, szINFSECTION_PASSWORDTOKEN) ||
  887. NULL == strchr(psz, chRBRACKET))
  888. {
  889. _JumpError2(hr, error, "[]", hr);
  890. }
  891. cwc = GetEnvironmentVariable(L"temp", awcTempDir, ARRAYSIZE(awcTempDir));
  892. if (0 == cwc)
  893. {
  894. cwc = GetEnvironmentVariable(L"tmp", awcTempDir, ARRAYSIZE(awcTempDir));
  895. }
  896. if (0 == cwc || ARRAYSIZE(awcTempDir) <= cwc)
  897. {
  898. hr = myHLastError();
  899. _PrintError(hr, "GetEnvironmentVariable");
  900. wcscpy(awcTempDir, L".");
  901. }
  902. if (!GetTempFileName(
  903. awcTempDir, // directory name
  904. L"epf", // lpPrefixString
  905. 0, // uUnique
  906. awcfnOut))
  907. {
  908. hr = myHLastError();
  909. _JumpError(hr, error, "GetTempFileName");
  910. }
  911. fDeleteTempFile = TRUE;
  912. if (!myConvertWszToSz(&pszfnOut, awcfnOut, -1))
  913. {
  914. hr = E_OUTOFMEMORY;
  915. _JumpError(hr, error, "myConvertWszToSz");
  916. }
  917. pfOut = fopen(pszfnOut, "w");
  918. if (NULL == pfOut)
  919. {
  920. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  921. _JumpError(hr, error, "fopen");
  922. }
  923. fputs("[Version]\nSignature=\"$Windows NT$\"\n\n", pfOut);
  924. if (fseek(pfIn, 0L, SEEK_SET))
  925. {
  926. hr = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
  927. _JumpError(hr, error, "fseek");
  928. }
  929. while (NULL != fgets(achLine, ARRAYSIZE(achLine), pfIn))
  930. {
  931. char *pszPrint;
  932. char *pszToken;
  933. BOOL fQuote;
  934. psz = strchr(achLine, '\n');
  935. if (NULL == psz)
  936. {
  937. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  938. _JumpError(hr, error, "Line overflow");
  939. }
  940. *psz = '\0';
  941. fQuote = FALSE;
  942. pszPrint = achLine;
  943. pszToken = achLine;
  944. while (' ' == *pszToken)
  945. {
  946. pszToken++;
  947. }
  948. psz = strchr(achLine, '=');
  949. if (';' != *pszToken && NULL != psz)
  950. {
  951. pszPrint = psz + 1;
  952. *psz = '\0';
  953. while (achLine < psz && ' ' == *--psz)
  954. {
  955. *psz = '\0';
  956. }
  957. fQuote = NULL != strchr(pszToken, ' ');
  958. if (fQuote)
  959. {
  960. fputs("\"", pfOut);
  961. }
  962. fputs(pszToken, pfOut);
  963. if (fQuote)
  964. {
  965. fputs("\"", pfOut);
  966. }
  967. fputs(" = ", pfOut);
  968. while (' ' == *pszPrint)
  969. {
  970. pszPrint++;
  971. }
  972. psz = &pszPrint[strlen(pszPrint)];
  973. while (pszPrint < psz && ' ' == *--psz)
  974. {
  975. *psz = '\0';
  976. }
  977. fQuote = '\0' != pszPrint[strcspn(pszPrint, " =")];
  978. }
  979. if (fQuote)
  980. {
  981. fputs("\"", pfOut);
  982. // if there's no equal sign after a comma, then we need to quote
  983. // only the first value, and leave the rest of the line alone.
  984. psz = strchr(pszPrint, ',');
  985. if (NULL != psz && NULL == strchr(psz, '='))
  986. {
  987. pszToken = psz + 1;
  988. while (' ' == *pszToken)
  989. {
  990. pszToken++;
  991. }
  992. *psz = '\0';
  993. while (pszPrint < psz && ' ' == *--psz)
  994. {
  995. *psz = '\0';
  996. }
  997. fputs(pszPrint, pfOut);
  998. fputs("\"", pfOut);
  999. fputs(",", pfOut);
  1000. pszPrint = pszToken;
  1001. fQuote = FALSE;
  1002. }
  1003. }
  1004. fputs(pszPrint, pfOut);
  1005. if (fQuote)
  1006. {
  1007. fputs("\"", pfOut);
  1008. }
  1009. fputs("\n", pfOut);
  1010. }
  1011. fflush(pfOut);
  1012. if (ferror(pfOut))
  1013. {
  1014. hr = E_OUTOFMEMORY;
  1015. _JumpError(hr, error, "I/O error");
  1016. }
  1017. hr = myDupString(awcfnOut, ppwszfnOut);
  1018. _JumpIfError(hr, error, "myDupString");
  1019. fDeleteTempFile = FALSE;
  1020. error:
  1021. if (NULL != pfIn)
  1022. {
  1023. fclose(pfIn);
  1024. }
  1025. if (NULL != pfOut)
  1026. {
  1027. fclose(pfOut);
  1028. }
  1029. if (fDeleteTempFile)
  1030. {
  1031. DeleteFile(awcfnOut);
  1032. }
  1033. if (NULL != pszfnIn)
  1034. {
  1035. LocalFree(pszfnIn);
  1036. }
  1037. if (NULL != pszfnOut)
  1038. {
  1039. LocalFree(pszfnOut);
  1040. }
  1041. return(hr);
  1042. }
  1043. HRESULT
  1044. BuildProtectedKey(
  1045. IN WCHAR const *pwszKey,
  1046. IN DWORD dwAlgId,
  1047. OUT WCHAR **ppwszProtectedKey)
  1048. {
  1049. HRESULT hr;
  1050. WCHAR *pwsz;
  1051. *ppwszProtectedKey = NULL;
  1052. pwsz = (WCHAR *) LocalAlloc(
  1053. LMEM_FIXED,
  1054. (1 + wcslen(pwszKey) + 1) * sizeof(WCHAR));
  1055. if (NULL == pwsz)
  1056. {
  1057. hr = E_OUTOFMEMORY;
  1058. _JumpError(hr, error, "LocalAlloc");
  1059. }
  1060. pwsz[0] = EPFALG_3DES == dwAlgId? L'&' : L'@';
  1061. wcscpy(&pwsz[1], pwszKey);
  1062. *ppwszProtectedKey = pwsz;
  1063. hr = S_OK;
  1064. error:
  1065. return(hr);
  1066. }
  1067. HRESULT
  1068. BuildProtectedHeader(
  1069. IN WCHAR const *pwszSection,
  1070. IN WCHAR const *pwszKey,
  1071. OUT BYTE **ppbHeader,
  1072. OUT DWORD *pcbHeader)
  1073. {
  1074. HRESULT hr;
  1075. WCHAR *pwszHeader = NULL;
  1076. char *pszHeader = NULL;
  1077. *ppbHeader = NULL;
  1078. pwszHeader = (WCHAR *) LocalAlloc(
  1079. LMEM_FIXED,
  1080. (wcslen(pwszSection) + wcslen(pwszKey) + 1) * sizeof(WCHAR));
  1081. if (NULL == pwszHeader)
  1082. {
  1083. hr = E_OUTOFMEMORY;
  1084. _JumpError(hr, error, "LocalAlloc");
  1085. }
  1086. wcscpy(pwszHeader, pwszSection);
  1087. wcscat(pwszHeader, pwszKey);
  1088. if (!myConvertWszToSz(&pszHeader, pwszHeader, -1))
  1089. {
  1090. hr = E_OUTOFMEMORY;
  1091. _JumpError(hr, error, "myConvertWszToSz");
  1092. }
  1093. *ppbHeader = (BYTE *) pszHeader;
  1094. *pcbHeader = strlen(pszHeader);
  1095. hr = S_OK;
  1096. error:
  1097. if (NULL != pwszHeader)
  1098. {
  1099. LocalFree(pwszHeader);
  1100. }
  1101. return(hr);
  1102. }
  1103. VOID
  1104. cuInfDisplayError()
  1105. {
  1106. WCHAR *pwszError = myInfGetError();
  1107. if (NULL != pwszError)
  1108. {
  1109. wprintf(L"%ws\n", pwszError);
  1110. LocalFree(pwszError);
  1111. }
  1112. }
  1113. HRESULT
  1114. cuInfDumpValue(
  1115. IN HINF hInf,
  1116. IN WCHAR const *pwszSection,
  1117. IN WCHAR const *pwszKey,
  1118. IN DWORD Index,
  1119. IN BOOL fLastValue,
  1120. IN HRESULT hrQuiet,
  1121. OPTIONAL OUT BYTE **ppbOut, // if non NULL, caller must call LocalFree
  1122. OPTIONAL OUT DWORD *pcbOut)
  1123. {
  1124. HRESULT hr;
  1125. WCHAR *pwszValue = NULL;
  1126. BYTE *pbValue = NULL;
  1127. DWORD cbValue;
  1128. hr = myInfGetKeyValue(
  1129. hInf,
  1130. TRUE, // fLog
  1131. pwszSection,
  1132. pwszKey,
  1133. Index,
  1134. fLastValue,
  1135. &pwszValue);
  1136. if (S_OK != hr)
  1137. {
  1138. cuInfDisplayError();
  1139. _PrintErrorStr2(hr, "myInfGetKeyValue", pwszSection, hrQuiet);
  1140. _JumpErrorStr2(hr, error, "myInfGetKeyValue", pwszKey, hrQuiet);
  1141. }
  1142. if (g_fVerbose)
  1143. {
  1144. wprintf(L"[%ws] %ws = %ws\n", pwszSection, pwszKey, pwszValue);
  1145. }
  1146. hr = myCryptStringToBinary(
  1147. pwszValue,
  1148. 0,
  1149. CRYPT_STRING_BASE64,
  1150. &pbValue,
  1151. &cbValue,
  1152. NULL,
  1153. NULL);
  1154. _JumpIfError(hr, error, "myCryptStringToBinary");
  1155. if (g_fVerbose)
  1156. {
  1157. DumpHex(DH_PRIVATEDATA, pbValue, cbValue);
  1158. }
  1159. if (NULL != ppbOut && NULL != pcbOut)
  1160. {
  1161. *pcbOut = cbValue;
  1162. *ppbOut = pbValue;
  1163. pbValue = NULL;
  1164. }
  1165. hr = S_OK;
  1166. error:
  1167. if (NULL != pwszValue)
  1168. {
  1169. LocalFree(pwszValue);
  1170. }
  1171. if (NULL != pbValue)
  1172. {
  1173. LocalFree(pbValue);
  1174. }
  1175. return(hr);
  1176. }
  1177. HRESULT
  1178. cuInfDumpProtectedValue(
  1179. IN HINF hInf,
  1180. IN WCHAR const *pwszSection,
  1181. IN WCHAR const *pwszKey,
  1182. IN EPF_SYM_KEY_STRUCT const *psKey,
  1183. IN HRESULT hrQuiet,
  1184. OPTIONAL OUT BYTE **ppbOut, // if non NULL, caller must call LocalFree
  1185. OPTIONAL OUT DWORD *pcbOut)
  1186. {
  1187. HRESULT hr;
  1188. WCHAR *pwszProtectedKey = NULL;
  1189. BYTE *pbHeader = NULL;
  1190. DWORD cbHeader;
  1191. BYTE *pbEncrypted = NULL;
  1192. DWORD cbEncrypted;
  1193. BYTE *pbDecrypted = NULL;
  1194. DWORD cbDecrypted;
  1195. DWORD cbData;
  1196. CRC16 CrcRead;
  1197. CRC16 CrcComputed;
  1198. if (NULL != ppbOut)
  1199. {
  1200. *ppbOut = NULL;
  1201. }
  1202. hr = BuildProtectedKey(pwszKey, psKey->dwAlgId, &pwszProtectedKey);
  1203. _JumpIfError(hr, error, "BuildProtectedKey");
  1204. hr = BuildProtectedHeader(pwszSection, pwszKey, &pbHeader, &cbHeader);
  1205. _JumpIfError(hr, error, "BuildProtectedHeader");
  1206. hr = cuInfDumpValue(
  1207. hInf,
  1208. pwszSection,
  1209. pwszProtectedKey,
  1210. 1, // Index
  1211. TRUE, // fLastValue
  1212. hrQuiet,
  1213. &pbEncrypted,
  1214. &cbEncrypted);
  1215. _JumpIfError2(hr, error, "cuInfDumpValue", hrQuiet);
  1216. hr = EPFDecryptSection(
  1217. psKey,
  1218. pbEncrypted,
  1219. cbEncrypted,
  1220. &pbDecrypted,
  1221. &cbDecrypted);
  1222. _JumpIfError(hr, error, "EPFDecryptSection");
  1223. if (g_fVerbose)
  1224. {
  1225. wprintf(wszNewLine);
  1226. DumpHex(DH_MULTIADDRESS | DH_NOTABPREFIX | DH_PRIVATEDATA | 4, pbDecrypted, cbDecrypted);
  1227. }
  1228. if (sizeof(CrcRead) + cbHeader > cbDecrypted ||
  1229. 0 != memcmp(&pbDecrypted[sizeof(CrcRead)], pbHeader, cbHeader))
  1230. {
  1231. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1232. _JumpError(hr, error, "bad header");
  1233. }
  1234. // Calculate the CRC
  1235. CrcComputed = 0xffff;
  1236. F_CRC16(
  1237. g_CrcTable,
  1238. &CrcComputed,
  1239. &pbDecrypted[sizeof(CrcRead)],
  1240. cbDecrypted - sizeof(CrcRead));
  1241. _swab((char *) pbDecrypted, (char *) &CrcRead, sizeof(CrcRead));
  1242. DBGPRINT((
  1243. CrcRead == CrcComputed? DBG_SS_CERTUTILI : DBG_SS_ERROR,
  1244. "[%ws] %ws: crc: Read=%x, Computed=%x\n",
  1245. pwszSection,
  1246. pwszProtectedKey,
  1247. CrcRead,
  1248. CrcComputed));
  1249. if (CrcRead != CrcComputed)
  1250. {
  1251. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1252. _JumpError(hr, error, "bad crc");
  1253. }
  1254. if (NULL != ppbOut && NULL != pcbOut)
  1255. {
  1256. cbData = cbDecrypted - (sizeof(CrcRead) + cbHeader);
  1257. if (0 != cbData)
  1258. {
  1259. *ppbOut = (BYTE *) LocalAlloc(LMEM_FIXED, cbData);
  1260. if (NULL == *ppbOut)
  1261. {
  1262. hr = E_OUTOFMEMORY;
  1263. _JumpError(hr, error, "LocalAlloc");
  1264. }
  1265. CopyMemory(
  1266. *ppbOut,
  1267. &pbDecrypted[sizeof(CrcRead) + cbHeader],
  1268. cbData);
  1269. }
  1270. *pcbOut = cbData;
  1271. }
  1272. error:
  1273. if (NULL != pwszProtectedKey)
  1274. {
  1275. LocalFree(pwszProtectedKey);
  1276. }
  1277. if (NULL != pbHeader)
  1278. {
  1279. LocalFree(pbHeader);
  1280. }
  1281. if (NULL != pbEncrypted)
  1282. {
  1283. LocalFree(pbEncrypted);
  1284. }
  1285. if (NULL != pbDecrypted)
  1286. {
  1287. LocalFree(pbDecrypted);
  1288. }
  1289. return(hr);
  1290. }
  1291. HRESULT
  1292. cuInfDumpNumericKeyValue(
  1293. IN HINF hInf,
  1294. IN WCHAR const *pwszSection,
  1295. IN WCHAR const *pwszKey,
  1296. IN DWORD Index,
  1297. IN BOOL fLastValue,
  1298. IN BOOL fDump,
  1299. IN HRESULT hrQuiet,
  1300. OUT DWORD *pdw)
  1301. {
  1302. HRESULT hr;
  1303. DWORD dw;
  1304. hr = myInfGetNumericKeyValue(
  1305. hInf,
  1306. TRUE, // fLog
  1307. pwszSection,
  1308. pwszKey,
  1309. Index,
  1310. fLastValue,
  1311. &dw);
  1312. if (S_OK != hr)
  1313. {
  1314. if (hrQuiet != hr)
  1315. {
  1316. cuInfDisplayError();
  1317. }
  1318. _JumpErrorStr2(hr, error, "myInfGetNumericKeyValue", pwszKey, hrQuiet);
  1319. }
  1320. if (fDump)
  1321. {
  1322. wprintf(L"[%ws] %ws = %u", pwszSection, pwszKey, dw);
  1323. if (9 < dw)
  1324. {
  1325. wprintf(L" (0x%x)", dw);
  1326. }
  1327. wprintf(wszNewLine);
  1328. }
  1329. *pdw = dw;
  1330. error:
  1331. return(hr);
  1332. }
  1333. HRESULT
  1334. cuInfDumpStringKeyValue(
  1335. IN HINF hInf,
  1336. IN WCHAR const *pwszSection,
  1337. IN WCHAR const *pwszKey,
  1338. IN BOOL fDump,
  1339. IN HRESULT hrQuiet,
  1340. OPTIONAL OUT WCHAR **ppwszValue)
  1341. {
  1342. HRESULT hr;
  1343. WCHAR *pwszValue = NULL;
  1344. hr = myInfGetKeyValue(
  1345. hInf,
  1346. TRUE, // fLog
  1347. pwszSection,
  1348. pwszKey,
  1349. 1, // Index
  1350. TRUE, // fLastValue
  1351. &pwszValue);
  1352. if (S_OK != hr)
  1353. {
  1354. if (hrQuiet != hr)
  1355. {
  1356. cuInfDisplayError();
  1357. }
  1358. _JumpErrorStr2(hr, error, "myInfGetKeyValue", pwszKey, hrQuiet);
  1359. }
  1360. if (fDump)
  1361. {
  1362. wprintf(L"[%ws] %ws = %ws\n", pwszSection, pwszKey, pwszValue);
  1363. }
  1364. if (NULL != ppwszValue)
  1365. {
  1366. *ppwszValue = pwszValue;
  1367. pwszValue = NULL;
  1368. }
  1369. error:
  1370. if (NULL != pwszValue)
  1371. {
  1372. LocalFree(pwszValue);
  1373. }
  1374. return(hr);
  1375. }
  1376. HRESULT
  1377. cuInfDumpDNKeyValue(
  1378. IN HINF hInf,
  1379. IN WCHAR const *pwszSection,
  1380. IN WCHAR const *pwszKey,
  1381. IN BOOL fDump)
  1382. {
  1383. HRESULT hr;
  1384. WCHAR *pwszValue = NULL;
  1385. WCHAR *pwszName = NULL;
  1386. CERT_NAME_BLOB Name;
  1387. Name.pbData = NULL;
  1388. hr = myInfGetKeyValue(
  1389. hInf,
  1390. TRUE, // fLog
  1391. pwszSection,
  1392. pwszKey,
  1393. 1, // Index
  1394. TRUE, // fLastValue
  1395. &pwszValue);
  1396. if (S_OK != hr)
  1397. {
  1398. cuInfDisplayError();
  1399. _JumpErrorStr(hr, error, "myInfGetKeyValue", pwszKey);
  1400. }
  1401. //wprintf(L"[%ws] %ws = %ws\n", pwszSection, pwszKey, pwszValue);
  1402. hr = myCertStrToName(
  1403. X509_ASN_ENCODING,
  1404. pwszValue, // pszX500
  1405. 0, // CERT_NAME_STR_REVERSE_FLAG
  1406. NULL, // pvReserved
  1407. &Name.pbData,
  1408. &Name.cbData,
  1409. NULL); // ppszError
  1410. _JumpIfErrorStr(hr, error, "myCertStrToName", pwszValue);
  1411. hr = myCertNameToStr(
  1412. X509_ASN_ENCODING,
  1413. &Name,
  1414. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  1415. &pwszName);
  1416. _JumpIfError(hr, error, "myCertNameToStr");
  1417. if (fDump)
  1418. {
  1419. wprintf(L"[%ws] %ws = ", pwszSection, pwszKey);
  1420. }
  1421. wprintf(L"%ws\n", pwszName);
  1422. error:
  1423. if (NULL != pwszName)
  1424. {
  1425. LocalFree(pwszName);
  1426. }
  1427. if (NULL != Name.pbData)
  1428. {
  1429. LocalFree(Name.pbData);
  1430. }
  1431. if (NULL != pwszValue)
  1432. {
  1433. LocalFree(pwszValue);
  1434. }
  1435. return(hr);
  1436. }
  1437. HRESULT
  1438. cuInfDumpBinaryNameKeyValue(
  1439. IN HINF hInf,
  1440. IN WCHAR const *pwszSection,
  1441. IN WCHAR const *pwszKey,
  1442. IN DWORD Index,
  1443. IN BOOL fLastValue,
  1444. IN BOOL fDump,
  1445. IN HRESULT hrQuiet)
  1446. {
  1447. HRESULT hr;
  1448. WCHAR *pwszName = NULL;
  1449. CERT_NAME_BLOB Name;
  1450. Name.pbData = NULL;
  1451. hr = cuInfDumpValue(
  1452. hInf,
  1453. pwszSection,
  1454. pwszKey,
  1455. Index,
  1456. fLastValue,
  1457. hrQuiet,
  1458. &Name.pbData,
  1459. &Name.cbData);
  1460. _JumpIfErrorStr(hr, error, "cuInfDumpValue", pwszKey);
  1461. hr = myCertNameToStr(
  1462. X509_ASN_ENCODING,
  1463. &Name,
  1464. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  1465. &pwszName);
  1466. _JumpIfError(hr, error, "myCertNameToStr");
  1467. if (fDump)
  1468. {
  1469. wprintf(L"[%ws] %ws = ", pwszSection, pwszKey);
  1470. }
  1471. wprintf(L"%ws\n", pwszName);
  1472. error:
  1473. if (NULL != pwszName)
  1474. {
  1475. LocalFree(pwszName);
  1476. }
  1477. if (NULL != Name.pbData)
  1478. {
  1479. LocalFree(Name.pbData);
  1480. }
  1481. return(hr);
  1482. }
  1483. HRESULT
  1484. cuInfDumpProtectedStringValue(
  1485. IN HINF hInf,
  1486. IN WCHAR const *pwszSection,
  1487. IN WCHAR const *pwszKey,
  1488. IN EPF_SYM_KEY_STRUCT const *psKey,
  1489. IN BOOL fDump,
  1490. IN HRESULT hrQuiet,
  1491. OUT WCHAR **ppwszValue)
  1492. {
  1493. HRESULT hr;
  1494. BYTE *pbValue = NULL;
  1495. DWORD cbValue;
  1496. *ppwszValue = NULL;
  1497. hr = cuInfDumpProtectedValue(
  1498. hInf,
  1499. pwszSection,
  1500. pwszKey,
  1501. psKey,
  1502. hrQuiet,
  1503. &pbValue,
  1504. &cbValue);
  1505. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  1506. if (!myConvertSzToWsz(ppwszValue, (char const *) pbValue, cbValue))
  1507. {
  1508. hr = E_OUTOFMEMORY;
  1509. _JumpError(hr, error, "myConvertSzToWsz");
  1510. }
  1511. hr = S_OK;
  1512. error:
  1513. if (NULL != pbValue)
  1514. {
  1515. LocalFree(pbValue);
  1516. }
  1517. return(hr);
  1518. }
  1519. HRESULT
  1520. cuInfDumpProtectedDwordValue(
  1521. IN HINF hInf,
  1522. IN WCHAR const *pwszSection,
  1523. IN WCHAR const *pwszKey,
  1524. IN EPF_SYM_KEY_STRUCT const *psKey,
  1525. IN BOOL fDump,
  1526. IN HRESULT hrQuiet,
  1527. OUT DWORD *pdwValue)
  1528. {
  1529. HRESULT hr;
  1530. BYTE *pbValue = NULL;
  1531. DWORD cbValue;
  1532. *pdwValue = 0;
  1533. hr = cuInfDumpProtectedValue(
  1534. hInf,
  1535. pwszSection,
  1536. pwszKey,
  1537. psKey,
  1538. hrQuiet,
  1539. &pbValue,
  1540. &cbValue);
  1541. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  1542. if (sizeof(*pdwValue) != cbValue)
  1543. {
  1544. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1545. _JumpError(hr, error, "cbValue");
  1546. }
  1547. CopyMemory(pdwValue, pbValue, sizeof(*pdwValue));
  1548. hr = S_OK;
  1549. error:
  1550. if (NULL != pbValue)
  1551. {
  1552. LocalFree(pbValue);
  1553. }
  1554. return(hr);
  1555. }
  1556. HRESULT
  1557. cuInfDumpHexKeyValue(
  1558. IN HINF hInf,
  1559. IN WCHAR const *pwszSection,
  1560. IN WCHAR const *pwszKey,
  1561. IN BOOL fDump,
  1562. OPTIONAL OUT BYTE **ppbOut,
  1563. OPTIONAL OUT DWORD *pcbOut)
  1564. {
  1565. HRESULT hr;
  1566. WCHAR *pwszValue = NULL;
  1567. BYTE *pbOut = NULL;
  1568. DWORD cbOut;
  1569. hr = myInfGetKeyValue(
  1570. hInf,
  1571. TRUE, // fLog
  1572. pwszSection,
  1573. pwszKey,
  1574. 1, // Index
  1575. TRUE, // fLastValue
  1576. &pwszValue);
  1577. if (S_OK != hr)
  1578. {
  1579. cuInfDisplayError();
  1580. _JumpErrorStr(hr, error, "myInfGetKeyValue", pwszKey);
  1581. }
  1582. if (fDump)
  1583. {
  1584. wprintf(L"[%ws] %ws = %ws\n", pwszSection, pwszKey, pwszValue);
  1585. }
  1586. hr = WszToMultiByteInteger(TRUE, pwszValue, &cbOut, &pbOut);
  1587. _JumpIfErrorStr(hr, error, "WszToMultiByteInteger", pwszValue);
  1588. if (g_fVerbose)
  1589. {
  1590. DumpHex(DH_PRIVATEDATA, pbOut, cbOut);
  1591. }
  1592. if (NULL != ppbOut && NULL != pcbOut)
  1593. {
  1594. *ppbOut = pbOut;
  1595. *pcbOut = cbOut;
  1596. pbOut = NULL;
  1597. }
  1598. error:
  1599. if (NULL != pbOut)
  1600. {
  1601. LocalFree(pbOut);
  1602. }
  1603. if (NULL != pwszValue)
  1604. {
  1605. LocalFree(pwszValue);
  1606. }
  1607. return(hr);
  1608. }
  1609. VOID
  1610. ExtraAsnBytes(
  1611. IN BYTE const *pbCert,
  1612. IN DWORD cbCert)
  1613. {
  1614. DWORD cbAsn = MAXDWORD;
  1615. if (6 < cbCert && BER_SEQUENCE == pbCert[0])
  1616. {
  1617. if (0x80 & pbCert[1])
  1618. {
  1619. switch (0x7f & pbCert[1])
  1620. {
  1621. case 1:
  1622. cbAsn = pbCert[2];
  1623. cbAsn += 3;
  1624. break;
  1625. case 2:
  1626. cbAsn = (pbCert[2] << 8) | pbCert[3];
  1627. cbAsn += 4;
  1628. break;
  1629. case 3:
  1630. cbAsn = (pbCert[2] << 16) | (pbCert[3] << 8) | pbCert[4];
  1631. cbAsn += 5;
  1632. break;
  1633. case 4:
  1634. cbAsn = (pbCert[2] << 24) | (pbCert[3] << 16) | (pbCert[4] << 8) | pbCert[5];
  1635. cbAsn += 6;
  1636. break;
  1637. }
  1638. }
  1639. else
  1640. {
  1641. cbAsn = pbCert[1];
  1642. cbAsn += 2;
  1643. }
  1644. }
  1645. if (MAXDWORD == cbAsn)
  1646. {
  1647. DumpHex(0, pbCert, min(6, cbCert));
  1648. wprintf(myLoadResourceString(IDS_BAD_ASN_LENGTH)); // "Bad Asn length encoding"
  1649. wprintf(wszNewLine);
  1650. }
  1651. else
  1652. {
  1653. if (cbCert != cbAsn)
  1654. {
  1655. wprintf(L"cbCert=%x cbAsn=%x\n", cbCert, cbAsn);
  1656. wprintf(
  1657. myLoadResourceString(IDS_FORMAT_ASN_EXTRA), // "Asn encoding: %x extra bytes"
  1658. cbCert - cbAsn);
  1659. wprintf(wszNewLine);
  1660. }
  1661. }
  1662. }
  1663. HRESULT
  1664. AddCertAndKeyToStore(
  1665. IN OUT HCERTSTORE hStore,
  1666. IN BYTE const *pbCert,
  1667. IN DWORD cbCert,
  1668. IN BYTE const *pbKey,
  1669. IN DWORD cbKey,
  1670. IN DWORD dwKeySpec)
  1671. {
  1672. HRESULT hr;
  1673. CERT_CONTEXT const *pcc = NULL;
  1674. GUID guid;
  1675. WCHAR *pwszKeyContainerName = NULL;
  1676. HCRYPTPROV hProv = NULL;
  1677. HCRYPTKEY hKey = NULL;
  1678. CRYPT_KEY_PROV_INFO kpi;
  1679. if (!CertAddEncodedCertificateToStore(
  1680. hStore,
  1681. X509_ASN_ENCODING,
  1682. pbCert,
  1683. cbCert,
  1684. CERT_STORE_ADD_REPLACE_EXISTING,
  1685. &pcc))
  1686. {
  1687. hr = myHLastError();
  1688. _JumpError(hr, error, "CertAddEncodedCertificateToStore");
  1689. }
  1690. // Use standard GUID key container names so they get cleaned up properly
  1691. myUuidCreate(&guid);
  1692. hr = StringFromCLSID(guid, &pwszKeyContainerName);
  1693. _JumpIfError(hr, error, "StringFromCLSID");
  1694. ZeroMemory(&kpi, sizeof(kpi));
  1695. kpi.pwszContainerName = pwszKeyContainerName;
  1696. kpi.pwszProvName = MS_STRONG_PROV;
  1697. kpi.dwProvType = PROV_RSA_FULL;
  1698. kpi.dwFlags = g_fUserRegistry? 0 : CRYPT_MACHINE_KEYSET;
  1699. kpi.dwKeySpec = dwKeySpec;
  1700. if (!CryptAcquireContext(
  1701. &hProv,
  1702. kpi.pwszContainerName,
  1703. kpi.pwszProvName,
  1704. kpi.dwProvType,
  1705. CRYPT_NEWKEYSET | kpi.dwFlags))
  1706. {
  1707. hr = myHLastError();
  1708. _JumpError(hr, error, "CryptAcquireContext");
  1709. }
  1710. if (!CryptImportKey(hProv, pbKey, cbKey, NULL, CRYPT_EXPORTABLE, &hKey))
  1711. {
  1712. hr = myHLastError();
  1713. _JumpError(hr, error, "CryptImportKey");
  1714. }
  1715. if (!CertSetCertificateContextProperty(
  1716. pcc,
  1717. CERT_KEY_PROV_INFO_PROP_ID,
  1718. 0,
  1719. &kpi))
  1720. {
  1721. hr = myHLastError();
  1722. _JumpError(hr, error, "CertSetCertificateContextProperty");
  1723. }
  1724. hr = S_OK;
  1725. error:
  1726. if (NULL != hKey)
  1727. {
  1728. CryptDestroyKey(hKey);
  1729. }
  1730. if (NULL != hProv)
  1731. {
  1732. CryptReleaseContext(hProv, 0);
  1733. }
  1734. if (NULL != pwszKeyContainerName)
  1735. {
  1736. CoTaskMemFree(pwszKeyContainerName);
  1737. }
  1738. if (NULL != pcc)
  1739. {
  1740. CertFreeCertificateContext(pcc);
  1741. }
  1742. return(hr);
  1743. }
  1744. // Define a structure to hold all of the private Key Exchange key material
  1745. // Commented out the pointer elements to match the binary data image.
  1746. typedef struct {
  1747. DWORD dwKeySpec;
  1748. DWORD cbPrivKey;
  1749. union {
  1750. //LPBYTE pbPrivKey;
  1751. DWORD obPrivKey;
  1752. };
  1753. DWORD cbPubKey;
  1754. union {
  1755. //LPBYTE pbPubKey;
  1756. DWORD obPubKey;
  1757. };
  1758. } OneKeyBlob;
  1759. #if 0
  1760. typedef struct {
  1761. DWORD dwSize;
  1762. DWORD cKeys;
  1763. OneKeyBlob rgKeyBlobs[0];
  1764. } ExchangeKeyBlob_Old;
  1765. #endif
  1766. typedef struct {
  1767. DWORD dwSize;
  1768. DWORD cKeys;
  1769. DWORD dwKeyAlg;
  1770. //OneKeyBlob rgKeyBlobs[0];
  1771. } ExchangeKeyBlobEx;
  1772. #define CBEKB CCSIZEOF_STRUCT(ExchangeKeyBlobEx, dwKeyAlg)
  1773. #define dwKEYSPEC_V1ENCRYPTION_BASE 1000
  1774. #define dwKEYSPEC_V1SIGNATURE 1500
  1775. #define dwKEYSPEC_V3ENCRYPTION_BASE 2000
  1776. #define dwKEYSPEC_V3SIGNATURE 2500
  1777. HRESULT
  1778. VerifyAndSaveCertAndKey(
  1779. OPTIONAL IN OUT HCERTSTORE hStore,
  1780. IN BOOL fDump,
  1781. IN WCHAR const *pwszKeyType,
  1782. IN BYTE const *pbCert,
  1783. IN DWORD cbCert,
  1784. IN BYTE const *pbEPFKey,
  1785. IN DWORD cbEPFKey,
  1786. IN DWORD cKey,
  1787. IN ALG_ID aiKeyAlg,
  1788. IN DWORD dwKeySpec)
  1789. {
  1790. HRESULT hr;
  1791. BYTE *pbKey = NULL;
  1792. DWORD cbKey;
  1793. ExchangeKeyBlobEx ekb;
  1794. BYTE const *pb;
  1795. DWORD cb;
  1796. OneKeyBlob okb;
  1797. DWORD i;
  1798. pb = pbEPFKey;
  1799. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1800. if (CBEKB > cbEPFKey)
  1801. {
  1802. _JumpError(hr, error, "ExchangeKeyBlobEx size");
  1803. }
  1804. //DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 4, pbEPFKey, CBEKB);
  1805. CopyMemory(&ekb, pbEPFKey, CBEKB);
  1806. if (aiKeyAlg != ekb.dwKeyAlg)
  1807. {
  1808. _JumpError(hr, error, "unexpected AlgId");
  1809. }
  1810. pb += CBEKB;
  1811. if (CBEKB != ekb.dwSize)
  1812. {
  1813. _JumpError(hr, error, "ExchangeKeyBlobEx.dwSize");
  1814. }
  1815. cb = CBEKB + sizeof(OneKeyBlob) * ekb.cKeys;
  1816. if (cb > cbEPFKey)
  1817. {
  1818. _JumpError(hr, error, "ExchangeKeyBlobEx size");
  1819. }
  1820. if (cKey != ekb.cKeys)
  1821. {
  1822. _JumpError(hr, error, "ExchangeKeyBlobEx.cKeys");
  1823. }
  1824. for (i = 0; i < ekb.cKeys; i++)
  1825. {
  1826. CopyMemory(&okb, &pb[sizeof(OneKeyBlob) * i], sizeof(okb));
  1827. if (cb != okb.obPrivKey)
  1828. {
  1829. _JumpError(hr, error, "OneKeyBlob.obPrivKey");
  1830. }
  1831. cb += okb.cbPrivKey;
  1832. if (cb > cbEPFKey)
  1833. {
  1834. _JumpError(hr, error, "OneKeyBlob.cbPrivKey");
  1835. }
  1836. if (0 != okb.obPubKey || 0 != okb.cbPubKey)
  1837. {
  1838. if (cb != okb.obPubKey)
  1839. {
  1840. _JumpError(hr, error, "OneKeyBlob.obPubKey");
  1841. }
  1842. cb += okb.cbPubKey;
  1843. if (cb > cbEPFKey)
  1844. {
  1845. _JumpError(hr, error, "OneKeyBlob.cbPubKey");
  1846. }
  1847. }
  1848. }
  1849. if (cb != cbEPFKey)
  1850. {
  1851. _JumpError(hr, error, "cbEPFKey");
  1852. }
  1853. for (i = 0; i < ekb.cKeys; i++)
  1854. {
  1855. CopyMemory(&okb, &pb[sizeof(OneKeyBlob) * i], sizeof(okb));
  1856. //DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 4, &pbEPFKey[okb.obPrivKey], okb.cbPrivKey);
  1857. if (NULL != pbKey)
  1858. {
  1859. SecureZeroMemory(pbKey, cbKey); // Key material
  1860. LocalFree(pbKey);
  1861. pbKey = NULL;
  1862. }
  1863. hr = myDecodeKMSRSAKey(
  1864. &pbEPFKey[okb.obPrivKey],
  1865. okb.cbPrivKey,
  1866. aiKeyAlg,
  1867. &pbKey,
  1868. &cbKey);
  1869. _JumpIfError(hr, error, "myDecodeKMSRSAKey");
  1870. hr = myVerifyKMSKey(pbCert, cbCert, pbKey, cbKey, dwKeySpec, TRUE);
  1871. _PrintIfError2(hr, "myVerifyKMSKey", HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
  1872. if (S_OK == hr)
  1873. {
  1874. if (fDump)
  1875. {
  1876. wprintf(L" dwKeySpec = %u\n", okb.dwKeySpec);
  1877. hr = cuDumpPrivateKeyBlob(pbKey, cbKey, FALSE);
  1878. _PrintIfError(hr, "cuDumpPrivateKeyBlob");
  1879. }
  1880. wprintf(
  1881. myLoadResourceString(IDS_FORMAT_VERIFIES_AGAINST_CERT), // "%ws key verifies against certificate"
  1882. pwszKeyType);
  1883. wprintf(wszNewLine);
  1884. if (fDump && 0 != okb.obPubKey && 0 != okb.cbPubKey)
  1885. {
  1886. wprintf(myLoadResourceString(IDS_PUBLIC_KEY_COLON)); // "Public key:"
  1887. wprintf(wszNewLine);
  1888. DumpHex(
  1889. DH_NOTABPREFIX | 4,
  1890. &pbEPFKey[okb.obPubKey],
  1891. okb.cbPubKey);
  1892. }
  1893. if (NULL != hStore)
  1894. {
  1895. hr = AddCertAndKeyToStore(
  1896. hStore,
  1897. pbCert,
  1898. cbCert,
  1899. pbKey,
  1900. cbKey,
  1901. dwKeySpec);
  1902. _JumpIfError(hr, error, "AddCertAndKeyToStore");
  1903. }
  1904. break; // success!
  1905. }
  1906. }
  1907. error:
  1908. if (S_OK != hr)
  1909. {
  1910. wprintf(
  1911. myLoadResourceString(IDS_FORMAT_NO_MATCH_CERT), // "%ws key does not match certifcate"
  1912. pwszKeyType);
  1913. wprintf(L": %x\n", hr);
  1914. wprintf(wszNewLine);
  1915. }
  1916. if (NULL != pbKey)
  1917. {
  1918. SecureZeroMemory(pbKey, cbKey); // Key material
  1919. LocalFree(pbKey);
  1920. }
  1921. return(hr);
  1922. }
  1923. HRESULT
  1924. VerifyAndSaveOneCertAndKey(
  1925. OPTIONAL IN OUT HCERTSTORE hStore,
  1926. IN BOOL fDump,
  1927. IN WCHAR const *pwszKeyType,
  1928. IN BYTE const *pbCert,
  1929. IN DWORD cbCert,
  1930. IN BYTE const *pbKMSKey,
  1931. IN DWORD cbKMSKey,
  1932. IN ALG_ID aiKeyAlg,
  1933. IN DWORD dwKeySpec)
  1934. {
  1935. HRESULT hr;
  1936. BYTE *pbKey = NULL;
  1937. DWORD cbKey;
  1938. BOOL fMatch;
  1939. hr = myDecodeKMSRSAKey(pbKMSKey, cbKMSKey, aiKeyAlg, &pbKey, &cbKey);
  1940. _JumpIfError(hr, error, "myDecodeKMSRSAKey");
  1941. hr = myVerifyKMSKey(pbCert, cbCert, pbKey, cbKey, dwKeySpec, TRUE);
  1942. if (S_OK != hr)
  1943. {
  1944. _PrintError(hr, "myVerifyKMSKey");
  1945. if (!g_fForce)
  1946. {
  1947. goto error; // -f ignores this error
  1948. }
  1949. }
  1950. fMatch = S_OK == hr;
  1951. if (fDump)
  1952. {
  1953. wprintf(L" dwKeySpec = %u\n", dwKeySpec);
  1954. hr = cuDumpPrivateKeyBlob(pbKey, cbKey, FALSE);
  1955. _PrintIfError(hr, "cuDumpPrivateKeyBlob");
  1956. }
  1957. wprintf(
  1958. myLoadResourceString(
  1959. fMatch?
  1960. IDS_FORMAT_VERIFIES_AGAINST_CERT : // "%ws key verifies against certificate"
  1961. IDS_FORMAT_NO_MATCH_CERT), // "%ws key does not match certificate"
  1962. pwszKeyType);
  1963. wprintf(wszNewLine);
  1964. if (NULL != hStore)
  1965. {
  1966. hr = AddCertAndKeyToStore(
  1967. hStore,
  1968. pbCert,
  1969. cbCert,
  1970. pbKey,
  1971. cbKey,
  1972. dwKeySpec);
  1973. _JumpIfError(hr, error, "AddCertAndKeyToStore");
  1974. }
  1975. error:
  1976. if (NULL != pbKey)
  1977. {
  1978. SecureZeroMemory(pbKey, cbKey); // Key material
  1979. LocalFree(pbKey);
  1980. }
  1981. return(hr);
  1982. }
  1983. HRESULT
  1984. AddCACertToStore(
  1985. IN BYTE const *pbCertCA,
  1986. IN DWORD cbCertCA)
  1987. {
  1988. HRESULT hr;
  1989. CERT_CONTEXT const *pccCA = NULL;
  1990. HCERTSTORE hStore = NULL;
  1991. pccCA = CertCreateCertificateContext(X509_ASN_ENCODING, pbCertCA, cbCertCA);
  1992. if (NULL == pccCA)
  1993. {
  1994. hr = myHLastError();
  1995. _JumpError(hr, error, "CertCreateCertificateContext");
  1996. }
  1997. hStore = CertOpenStore(
  1998. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  1999. X509_ASN_ENCODING,
  2000. NULL, // hProv
  2001. CERT_STORE_OPEN_EXISTING_FLAG |
  2002. CERT_STORE_ENUM_ARCHIVED_FLAG |
  2003. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  2004. wszCA_CERTSTORE);
  2005. if (NULL == hStore)
  2006. {
  2007. hr = myHLastError();
  2008. _JumpError(hr, error, "CertOpenStore");
  2009. }
  2010. if (!CertAddCertificateContextToStore(
  2011. hStore,
  2012. pccCA,
  2013. CERT_STORE_ADD_USE_EXISTING,
  2014. NULL))
  2015. {
  2016. hr = myHLastError();
  2017. _JumpError(hr, error, "CertAddCertificateContextToStore");
  2018. }
  2019. hr = S_OK;
  2020. error:
  2021. if (NULL != pccCA)
  2022. {
  2023. CertFreeCertificateContext(pccCA);
  2024. }
  2025. if (NULL != hStore)
  2026. {
  2027. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  2028. }
  2029. return(hr);
  2030. }
  2031. HRESULT
  2032. DumpSerializedCertStore(
  2033. IN BYTE const *pbStore,
  2034. IN DWORD cbStore)
  2035. {
  2036. HRESULT hr;
  2037. HCERTSTORE hStore = NULL;
  2038. CRYPT_DATA_BLOB Blob;
  2039. Blob.pbData = const_cast<BYTE *>(pbStore);
  2040. Blob.cbData = cbStore;
  2041. hStore = CertOpenStore(
  2042. CERT_STORE_PROV_SERIALIZED,
  2043. X509_ASN_ENCODING,
  2044. NULL, // hCryptProv
  2045. CERT_STORE_NO_CRYPT_RELEASE_FLAG |
  2046. CERT_STORE_ENUM_ARCHIVED_FLAG,
  2047. &Blob);
  2048. if (NULL == hStore)
  2049. {
  2050. hr = myHLastError();
  2051. _JumpError(hr, error, "CertOpenStore");
  2052. }
  2053. hr = cuDumpAndVerifyStore(
  2054. hStore,
  2055. DVNS_DUMP |
  2056. DVNS_DUMPKEYS |
  2057. DVNS_DUMPPROPERTIES,
  2058. NULL, // pwszCertName
  2059. MAXDWORD, // iCertSave
  2060. MAXDWORD, // iCRLSave
  2061. MAXDWORD, // iCTLSave
  2062. NULL, // pwszfnOut
  2063. NULL); // pwszPassword
  2064. _JumpIfError(hr, error, "cuDumpAndVerifyStore");
  2065. error:
  2066. if (NULL != hStore)
  2067. {
  2068. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  2069. }
  2070. return(hr);
  2071. }
  2072. HRESULT
  2073. GenerateV1Keys(
  2074. IN BOOL fRoot,
  2075. OUT HCRYPTPROV *phProv)
  2076. {
  2077. HRESULT hr;
  2078. HCRYPTKEY hKey = NULL;
  2079. *phProv = NULL;
  2080. // create verify container
  2081. if (!CryptAcquireContext(
  2082. phProv,
  2083. NULL, // pwszContainer
  2084. NULL, // pwszProvName
  2085. PROV_RSA_FULL,
  2086. CRYPT_VERIFYCONTEXT))
  2087. {
  2088. hr = myHLastError();
  2089. _JumpError(hr, error, "CryptAcquireContext");
  2090. }
  2091. // create signature keys
  2092. if (!CryptGenKey(
  2093. *phProv,
  2094. AT_SIGNATURE,
  2095. (512 << 16) | CRYPT_EXPORTABLE,
  2096. &hKey))
  2097. {
  2098. hr = myHLastError();
  2099. _JumpError(hr, error, "CryptGenKey");
  2100. }
  2101. hr = S_OK;
  2102. error:
  2103. if (NULL != hKey)
  2104. {
  2105. CryptDestroyKey(hKey);
  2106. }
  2107. return(hr);
  2108. }
  2109. // valid decrypted non-PKCS1 signature (512 bits/64 bytes):
  2110. // 1) Byte reversed hash
  2111. // 2) length of hash (0x10 bytes)
  2112. // 3) Octet string tag (BER_OCTET_STRING)
  2113. // 4) 0x00 byte
  2114. // 5) 0xff pad (as many bytes as necessary)
  2115. // 6) 0x01 pad byte
  2116. // 7) 0x00 pad byte
  2117. //
  2118. // 6e e3 f9 e8 83 e6 b1 a0-ff 63 96 df 2e 30 bb fe
  2119. // 10 04 00 ff ff ff ff ff-ff ff ff ff ff ff ff ff
  2120. // ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff
  2121. // ff ff ff ff ff ff ff ff-ff ff ff ff ff ff 01 00
  2122. HRESULT
  2123. mySignMD5HashOnly(
  2124. IN HCRYPTPROV hProv,
  2125. IN char const *pszAlgId,
  2126. IN BYTE const *pbEncoded,
  2127. IN DWORD cbEncoded,
  2128. OUT BYTE **ppbSigned,
  2129. OUT DWORD *pcbSigned)
  2130. {
  2131. HRESULT hr;
  2132. HCRYPTHASH hHash = NULL;
  2133. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  2134. DWORD cbHash;
  2135. BYTE abSig[64];
  2136. DWORD cbSig;
  2137. DWORD i;
  2138. HCRYPTKEY hKey = NULL;
  2139. #if 0
  2140. #else
  2141. BYTE *pbKey = NULL;
  2142. DWORD cbKey;
  2143. HCRYPTKEY hKeySig = NULL;
  2144. #endif
  2145. static BYTE abSigPrefix[] =
  2146. {
  2147. BER_SEQUENCE, 9,
  2148. BER_OBJECT_ID, 5, 0x2b, 0x0e, 0x03, 0x02, 0x03,
  2149. BER_NULL, 0,
  2150. BER_BIT_STRING, sizeof(abSig) + 1,
  2151. 0, // Unused bits
  2152. // encryted signature (sizeof(abSig))
  2153. };
  2154. BYTE abSigSequence[sizeof(abSigPrefix) + sizeof(abSig)];
  2155. CRYPT_SEQUENCE_OF_ANY Seq;
  2156. CRYPT_DER_BLOB rgBlob[2];
  2157. *ppbSigned = NULL;
  2158. if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
  2159. {
  2160. hHash = NULL;
  2161. hr = myHLastError();
  2162. _JumpError(hr, error, "CryptCreateHash");
  2163. }
  2164. if (!CryptHashData(hHash, pbEncoded, cbEncoded, 0))
  2165. {
  2166. hr = myHLastError();
  2167. _JumpError(hr, error, "CryptHashData");
  2168. }
  2169. cbHash = sizeof(abHash);
  2170. if (!CryptGetHashParam(hHash, HP_HASHVAL, abHash, &cbHash, 0))
  2171. {
  2172. hr = myHLastError();
  2173. _JumpError(hr, error, "CryptGetHashParam");
  2174. }
  2175. #if 0
  2176. wprintf(L"\nV1 Cert to-be-signed:\n");
  2177. DumpHex(DH_NOTABPREFIX | DH_NOASCIIHEX | 4, pbEncoded, cbEncoded);
  2178. wprintf(L"\nV1 Cert to-be-signed Hash:\n");
  2179. DumpHex(DH_NOTABPREFIX | DH_NOASCIIHEX | 4, abHash, cbHash);
  2180. #endif
  2181. memset(abSig, (BYTE) 0xff, sizeof(abSig));
  2182. for (i = 0; i < cbHash; i++)
  2183. {
  2184. abSig[i] = abHash[cbHash - i - 1];
  2185. }
  2186. abSig[cbHash] = (BYTE) cbHash;
  2187. abSig[cbHash + 1] = (BYTE) BER_OCTET_STRING;
  2188. abSig[cbHash + 2] = (BYTE) 0x00;
  2189. abSig[sizeof(abSig) - 2] = (BYTE) 0x01;
  2190. abSig[sizeof(abSig) - 1] = (BYTE) 0x00;
  2191. #if 0
  2192. wprintf(L"\nV1 clear text signature (padded hash):\n");
  2193. DumpHex(DH_NOTABPREFIX | DH_NOASCIIHEX | 4, abSig, sizeof(abSig));
  2194. #endif
  2195. #if 0
  2196. if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
  2197. {
  2198. hr = myHLastError();
  2199. _JumpError(hr, error, "CryptGetUserKey");
  2200. }
  2201. #else
  2202. if (!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey))
  2203. {
  2204. hr = myHLastError();
  2205. if (hr != NTE_NO_KEY)
  2206. {
  2207. _JumpError(hr, error, "CryptGetUserKey");
  2208. }
  2209. if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKeySig))
  2210. {
  2211. hr = myHLastError();
  2212. _JumpError(hr, error, "CryptGetUserKey - sig");
  2213. }
  2214. // UGH! migrate from AT_SIGNATURE container!
  2215. cbKey = 0;
  2216. hr = myCryptExportKey(
  2217. hKeySig, // hKey
  2218. NULL, // hKeyExp
  2219. PRIVATEKEYBLOB, // dwBlobType
  2220. 0, // dwFlags
  2221. &pbKey,
  2222. &cbKey);
  2223. _JumpIfError(hr, error, "myCryptExportKey");
  2224. // UGH! fix up the algid to signature...
  2225. ((PUBLICKEYSTRUC *) pbKey)->aiKeyAlg = CALG_RSA_KEYX;
  2226. // and re-import it
  2227. if (!CryptImportKey(
  2228. hProv,
  2229. pbKey,
  2230. cbKey,
  2231. NULL,
  2232. CRYPT_EXPORTABLE,
  2233. &hKey))
  2234. {
  2235. hr = myHLastError();
  2236. _JumpError(hr, error, "CryptImportKey");
  2237. }
  2238. }
  2239. #endif
  2240. //#define RSAENH_NOT_FIXED // should no longer be necessary...
  2241. #ifdef RSAENH_NOT_FIXED
  2242. BYTE abSig2[64 + 8];
  2243. ZeroMemory(abSig2, sizeof(abSig2));
  2244. CopyMemory(abSig2, abSig, sizeof(abSig));
  2245. #endif
  2246. cbSig = sizeof(abSig);
  2247. if (!CryptDecrypt(
  2248. hKey,
  2249. NULL, // hHash
  2250. TRUE, // Final
  2251. CRYPT_DECRYPT_RSA_NO_PADDING_CHECK, // dwFlags
  2252. #ifdef RSAENH_NOT_FIXED
  2253. abSig2,
  2254. #else
  2255. abSig,
  2256. #endif
  2257. &cbSig))
  2258. {
  2259. hr = myHLastError();
  2260. _JumpError(hr, error, "CryptDecrypt");
  2261. }
  2262. #ifdef RSAENH_NOT_FIXED
  2263. CopyMemory(abSig, abSig2, sizeof(abSig));
  2264. #endif
  2265. #if 0
  2266. wprintf(L"\nV1 encrypted signature:\n");
  2267. DumpHex(DH_NOTABPREFIX | DH_NOASCIIHEX | 4, abSig, cbSig);
  2268. #endif
  2269. // Append signature goop to cert.
  2270. CopyMemory(abSigSequence, abSigPrefix, sizeof(abSigPrefix));
  2271. //CopyMemory(&abSigSequence[sizeof(abSigPrefix)], abSig, sizeof(abSig));
  2272. for (i = 0; i < cbSig; i++)
  2273. {
  2274. abSigSequence[sizeof(abSigPrefix) + i] = abSig[cbSig - i - 1];
  2275. }
  2276. rgBlob[0].pbData = const_cast<BYTE *>(pbEncoded);
  2277. rgBlob[0].cbData = cbEncoded;
  2278. rgBlob[1].pbData = abSigSequence;
  2279. rgBlob[1].cbData = sizeof(abSigSequence);
  2280. Seq.cValue = ARRAYSIZE(rgBlob);
  2281. Seq.rgValue = rgBlob;
  2282. if (!myEncodeObject(
  2283. X509_ASN_ENCODING,
  2284. X509_SEQUENCE_OF_ANY,
  2285. &Seq,
  2286. 0,
  2287. CERTLIB_USE_LOCALALLOC,
  2288. ppbSigned,
  2289. pcbSigned))
  2290. {
  2291. hr = myHLastError();
  2292. _JumpError(hr, error, "myEncodeObject");
  2293. }
  2294. #if 0
  2295. wprintf(L"\nV1 Cert:\n");
  2296. DumpHex(DH_NOTABPREFIX | DH_NOASCIIHEX | 4, *ppbSigned, *pcbSigned);
  2297. #endif
  2298. hr = S_OK;
  2299. error:
  2300. if (NULL != hKey)
  2301. {
  2302. CryptDestroyKey(hKey);
  2303. }
  2304. if (NULL != hHash)
  2305. {
  2306. CryptDestroyHash(hHash);
  2307. }
  2308. #if 0
  2309. #else
  2310. if (NULL != pbKey)
  2311. {
  2312. LocalFree(pbKey);
  2313. }
  2314. if (NULL != hKeySig)
  2315. {
  2316. CryptDestroyKey(hKeySig);
  2317. }
  2318. #endif
  2319. return(hr);
  2320. }
  2321. HRESULT
  2322. epfEncodeCertAndSign(
  2323. IN HCRYPTPROV hProvSigner,
  2324. IN CERT_PUBLIC_KEY_INFO *pSubjectPublicKeyInfoSigner,
  2325. IN CERT_INFO *pCert,
  2326. IN char const *pszAlgId,
  2327. OUT BYTE **ppbSigned,
  2328. OUT DWORD *pcbSigned)
  2329. {
  2330. HRESULT hr;
  2331. BYTE *pbEncoded = NULL;
  2332. DWORD cbEncoded;
  2333. *ppbSigned = NULL;
  2334. if (!myEncodeToBeSigned(
  2335. X509_ASN_ENCODING,
  2336. pCert,
  2337. CERTLIB_USE_LOCALALLOC,
  2338. &pbEncoded,
  2339. &cbEncoded))
  2340. {
  2341. hr = myHLastError();
  2342. _JumpError(hr, error, "myEncodeToBeSigned");
  2343. }
  2344. // Try to use the new rsaenc.dll to generate a Nortel-compliant signature.
  2345. // The enrypted signature will not contain the algorithm OID or parameters.
  2346. hr = mySignMD5HashOnly(
  2347. hProvSigner,
  2348. pszAlgId,
  2349. pbEncoded,
  2350. cbEncoded,
  2351. ppbSigned,
  2352. pcbSigned);
  2353. _PrintIfError(hr, "mySignMD5HashOnly");
  2354. if (S_OK == hr)
  2355. {
  2356. if (CryptVerifyCertificateSignature(
  2357. NULL,
  2358. X509_ASN_ENCODING,
  2359. *ppbSigned,
  2360. *pcbSigned,
  2361. pSubjectPublicKeyInfoSigner))
  2362. {
  2363. wprintf(myLoadResourceString(IDS_CERT_SIG_OK)); // "Cert signature is valid"
  2364. wprintf(wszNewLine);
  2365. }
  2366. else
  2367. {
  2368. hr = myHLastError();
  2369. _PrintError(hr, "CryptVerifyCertificateSignature");
  2370. LocalFree(*ppbSigned);
  2371. *ppbSigned = NULL;
  2372. }
  2373. }
  2374. if (S_OK != hr && 1 < g_fForce)
  2375. {
  2376. // Must be running on an old rsaenh.dll that only supports PKCS1
  2377. // signatures. Just generate a standard PKCS1 signature.
  2378. hr = myEncodeSignedContent(
  2379. hProvSigner,
  2380. X509_ASN_ENCODING,
  2381. pszAlgId,
  2382. pbEncoded,
  2383. cbEncoded,
  2384. CERTLIB_USE_LOCALALLOC,
  2385. ppbSigned,
  2386. pcbSigned);
  2387. _JumpIfError(hr, error, "myEncodeSignedContent");
  2388. }
  2389. _JumpIfError(hr, error, "mySignMD5HashOnly");
  2390. error:
  2391. if (NULL != pbEncoded)
  2392. {
  2393. LocalFree(pbEncoded);
  2394. }
  2395. return(hr);
  2396. }
  2397. HRESULT
  2398. GenerateV1SerialNumber(
  2399. IN HCRYPTPROV hProv,
  2400. IN CRYPT_INTEGER_BLOB const *pSerialNumberOld,
  2401. OUT DWORD *pdwV1SerialNumber)
  2402. {
  2403. HRESULT hr;
  2404. BYTE *pb;
  2405. DWORD cb;
  2406. pb = (BYTE *) pdwV1SerialNumber;
  2407. cb = sizeof(*pdwV1SerialNumber);
  2408. if (!CryptGenRandom(hProv, cb, pb))
  2409. {
  2410. hr = myHLastError();
  2411. _JumpError(hr, error, "CryptGenRandom");
  2412. }
  2413. pb += sizeof(*pdwV1SerialNumber) - 1;
  2414. if (sizeof(*pdwV1SerialNumber) == pSerialNumberOld->cbData &&
  2415. NULL != pSerialNumberOld->pbData)
  2416. {
  2417. *pb = pSerialNumberOld->pbData[pSerialNumberOld->cbData - 1];
  2418. }
  2419. // make sure the last byte is never zero
  2420. if (0 == *pb)
  2421. {
  2422. *pb = 0x3a;
  2423. }
  2424. // Some clients can't handle negative serial numbers:
  2425. *pb &= 0x7f;
  2426. hr = S_OK;
  2427. error:
  2428. return(hr);
  2429. }
  2430. HRESULT
  2431. AddExtraByteToKey(
  2432. IN OUT BYTE **ppbKey,
  2433. IN OUT DWORD *pcbKey)
  2434. {
  2435. HRESULT hr;
  2436. BYTE *pbKey;
  2437. pbKey = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbKey + 1);
  2438. if (NULL == pbKey)
  2439. {
  2440. hr = E_OUTOFMEMORY;
  2441. _JumpError(hr, error, "LocalAlloc");
  2442. }
  2443. CopyMemory(pbKey, *ppbKey, *pcbKey);
  2444. pbKey[*pcbKey] = 0x01;
  2445. (*pcbKey)++;
  2446. LocalFree(*ppbKey);
  2447. *ppbKey = pbKey;
  2448. hr = S_OK;
  2449. error:
  2450. return(hr);
  2451. }
  2452. HRESULT
  2453. epfEncodeV1Cert(
  2454. OPTIONAL IN HCRYPTPROV hProvSigner,
  2455. OPTIONAL CERT_CONTEXT const *pccSigner,
  2456. IN CRYPT_INTEGER_BLOB const *pSerialNumberOld,
  2457. IN CERT_NAME_BLOB const *pIssuer,
  2458. IN CERT_NAME_BLOB const *pSubject,
  2459. OUT HCRYPTPROV *phProv,
  2460. OUT CERT_CONTEXT const **ppCert)
  2461. {
  2462. HRESULT hr;
  2463. HCRYPTPROV hProv = NULL;
  2464. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  2465. DWORD cbPubKey;
  2466. BYTE *pbPubKeyNew = NULL;
  2467. CERT_INFO Cert;
  2468. //char *pszAlgId = szOID_RSA_MD5RSA;
  2469. char *pszAlgId = szOID_OIWSEC_md5RSA;
  2470. DWORD dwV1SerialNumber;
  2471. BYTE *pbEncoded = NULL;
  2472. DWORD cbEncoded;
  2473. SYSTEMTIME st;
  2474. SYSTEMTIME st2;
  2475. *phProv = NULL;
  2476. *ppCert = NULL;
  2477. hr = GenerateV1Keys(NULL == hProvSigner, &hProv);
  2478. _JumpIfError(hr, error, "GenerateV1Keys");
  2479. if (!myCryptExportPublicKeyInfo(
  2480. hProv,
  2481. AT_SIGNATURE,
  2482. CERTLIB_USE_LOCALALLOC,
  2483. &pPubKey,
  2484. &cbPubKey))
  2485. {
  2486. hr = myHLastError();
  2487. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  2488. }
  2489. #if 0
  2490. wprintf(L"\nCERT_PUBLIC_KEY_INFO:\n");
  2491. DumpHex(
  2492. DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  2493. (BYTE const *) pPubKey,
  2494. cbPubKey);
  2495. wprintf(L"\nBefore mySqueezePublicKey:\n");
  2496. wprintf(L"cUnusedBits=%u\n", pPubKey->PublicKey.cUnusedBits);
  2497. DumpHex(
  2498. DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  2499. pPubKey->PublicKey.pbData,
  2500. pPubKey->PublicKey.cbData);
  2501. #endif
  2502. hr = mySqueezePublicKey(
  2503. pPubKey->PublicKey.pbData,
  2504. pPubKey->PublicKey.cbData,
  2505. &pbPubKeyNew,
  2506. &pPubKey->PublicKey.cbData);
  2507. _JumpIfError(hr, error, "mySqueezePublicKey");
  2508. hr = AddExtraByteToKey(&pbPubKeyNew, &pPubKey->PublicKey.cbData);
  2509. _JumpIfError(hr, error, "AddExtraByteToKey");
  2510. pPubKey->PublicKey.pbData = pbPubKeyNew;
  2511. #if 0
  2512. //wprintf(L"cUnusedBits=%u\n", pPubKey->PublicKey.cUnusedBits);
  2513. wprintf(L"\nAfter mySqueezePublicKey:\n");
  2514. DumpHex(
  2515. DH_NOTABPREFIX | DH_NOASCIIHEX | 4,
  2516. pPubKey->PublicKey.pbData,
  2517. pPubKey->PublicKey.cbData);
  2518. #endif
  2519. // CERT:
  2520. ZeroMemory(&Cert, sizeof(Cert));
  2521. Cert.dwVersion = CERT_V1;
  2522. // Use a DWORD for the V1 serial number
  2523. GenerateV1SerialNumber(hProv, pSerialNumberOld, &dwV1SerialNumber);
  2524. Cert.SerialNumber.pbData = (BYTE *) &dwV1SerialNumber;
  2525. Cert.SerialNumber.cbData = sizeof(dwV1SerialNumber);
  2526. Cert.SignatureAlgorithm.pszObjId = pszAlgId;
  2527. // ISSUER:
  2528. Cert.Issuer = *pIssuer; // Structure assignment
  2529. // Start with an arbitrary constant date in the past 12 months.
  2530. // Choose January 1st or June 1st: whichever will result in at least
  2531. // several months remaining until we hit the date again.
  2532. // From Feb 1st to June 30th, pick Jan 1st.
  2533. // From July 1st to Jan 31st, pick Jun 1st.
  2534. GetSystemTime(&st);
  2535. ZeroMemory(&st2, sizeof(st2));
  2536. st2.wYear = st.wYear;
  2537. st2.wDay = 1; // Jan or Jun 1st
  2538. st2.wHour = 12; // at Noon
  2539. if (2 <= st.wMonth && 6 >= st.wMonth)
  2540. {
  2541. st2.wMonth = 1; // January
  2542. }
  2543. else
  2544. {
  2545. st2.wMonth = 6; // June
  2546. }
  2547. CSASSERT(st2.wMonth != st.wMonth);
  2548. if (st2.wMonth > st.wMonth)
  2549. {
  2550. st2.wYear--;
  2551. }
  2552. if (!SystemTimeToFileTime(&st2, &Cert.NotBefore))
  2553. {
  2554. hr = myHLastError();
  2555. _JumpError(hr, error, "SystemTimeToFileTime");
  2556. }
  2557. Cert.NotAfter = Cert.NotBefore;
  2558. if (NULL == hProvSigner)
  2559. {
  2560. // Generate 20 year V1 root CA cert, centered over an arbitrary date
  2561. // in the past 12 months.
  2562. myMakeExprDateTime(&Cert.NotBefore, -10, ENUM_PERIOD_YEARS);
  2563. myMakeExprDateTime(&Cert.NotAfter, +10, ENUM_PERIOD_YEARS);
  2564. }
  2565. else
  2566. {
  2567. // Generate 1 year V1 user cert, that expired at least a year ago
  2568. myMakeExprDateTime(&Cert.NotBefore, -2, ENUM_PERIOD_YEARS);
  2569. myMakeExprDateTime(&Cert.NotAfter, -1, ENUM_PERIOD_YEARS);
  2570. }
  2571. // SUBJECT:
  2572. Cert.Subject = *pSubject; // Structure assignment
  2573. Cert.SubjectPublicKeyInfo = *pPubKey; // Structure assignment
  2574. hr = epfEncodeCertAndSign(
  2575. NULL != hProvSigner? hProvSigner : hProv,
  2576. NULL != pccSigner?
  2577. &pccSigner->pCertInfo->SubjectPublicKeyInfo :
  2578. &Cert.SubjectPublicKeyInfo,
  2579. &Cert,
  2580. pszAlgId,
  2581. &pbEncoded,
  2582. &cbEncoded);
  2583. _JumpIfError(hr, error, "EncodeCertAndSign");
  2584. CSASSERT(NULL != pbEncoded);
  2585. *ppCert = CertCreateCertificateContext(
  2586. X509_ASN_ENCODING,
  2587. pbEncoded,
  2588. cbEncoded);
  2589. if (NULL == *ppCert)
  2590. {
  2591. hr = myHLastError();
  2592. _JumpError(hr, error, "CertCreateCertificateContext");
  2593. }
  2594. *phProv = hProv;
  2595. hProv = NULL;
  2596. error:
  2597. if (NULL != hProv)
  2598. {
  2599. CryptReleaseContext(hProv, 0);
  2600. }
  2601. if (NULL != pbEncoded)
  2602. {
  2603. LocalFree(pbEncoded);
  2604. }
  2605. if (NULL != pPubKey)
  2606. {
  2607. LocalFree(pPubKey);
  2608. }
  2609. if (NULL != pbPubKeyNew)
  2610. {
  2611. LocalFree(pbPubKeyNew);
  2612. }
  2613. return(hr);
  2614. }
  2615. HRESULT
  2616. epfBuildV1Certs(
  2617. IN CERT_CONTEXT const *pccUserV1,
  2618. OUT CERT_CONTEXT const **ppccSigV1,
  2619. OUT HCRYPTPROV *phProvSigV1,
  2620. OUT CERT_CONTEXT const **ppccCAV1)
  2621. {
  2622. HRESULT hr;
  2623. CERT_CONTEXT const *pccCAV1 = NULL;
  2624. CERT_CONTEXT const *pccSigV1 = NULL;
  2625. HCRYPTPROV hProvCA = NULL;
  2626. HCRYPTPROV hProvSig = NULL;
  2627. *ppccSigV1 = NULL;
  2628. *phProvSigV1 = NULL;
  2629. *ppccCAV1 = NULL;
  2630. hr = epfEncodeV1Cert(
  2631. NULL, // hProvSigner
  2632. NULL, // pccSigner
  2633. &pccUserV1->pCertInfo->SerialNumber,
  2634. &pccUserV1->pCertInfo->Issuer,
  2635. &pccUserV1->pCertInfo->Issuer,
  2636. &hProvCA,
  2637. &pccCAV1);
  2638. _JumpIfError(hr, error, "epfEncodeV1Cert");
  2639. hr = epfEncodeV1Cert(
  2640. hProvCA,
  2641. pccCAV1, // pccSigner
  2642. &pccUserV1->pCertInfo->SerialNumber,
  2643. &pccUserV1->pCertInfo->Issuer,
  2644. &pccUserV1->pCertInfo->Subject,
  2645. &hProvSig,
  2646. &pccSigV1);
  2647. _JumpIfError(hr, error, "epfEncodeV1Cert");
  2648. CSASSERT(NULL != hProvSig);
  2649. CSASSERT(NULL != pccSigV1);
  2650. CSASSERT(NULL != pccCAV1);
  2651. *phProvSigV1 = hProvSig;
  2652. hProvSig = NULL;
  2653. *ppccSigV1 = pccSigV1;
  2654. pccSigV1 = NULL;
  2655. *ppccCAV1 = pccCAV1;
  2656. pccCAV1 = NULL;
  2657. error:
  2658. if (NULL != hProvCA)
  2659. {
  2660. CryptReleaseContext(hProvCA, 0);
  2661. }
  2662. if (NULL != hProvSig)
  2663. {
  2664. CryptReleaseContext(hProvSig, 0);
  2665. }
  2666. if (NULL != pccCAV1)
  2667. {
  2668. CertFreeCertificateContext(pccCAV1);
  2669. }
  2670. if (NULL != pccSigV1)
  2671. {
  2672. CertFreeCertificateContext(pccSigV1);
  2673. }
  2674. return(hr);
  2675. }
  2676. WCHAR const *
  2677. epfLoadResource(
  2678. IN UINT ids,
  2679. IN WCHAR const *pwszStatic)
  2680. {
  2681. WCHAR const *pwsz = myLoadResourceString(ids);
  2682. if (NULL == pwsz)
  2683. {
  2684. pwsz = pwszStatic;
  2685. }
  2686. return(pwsz);
  2687. }
  2688. HRESULT
  2689. cuInfDumpProtectedStoreValue(
  2690. IN HINF hInf,
  2691. IN WCHAR const *pwszSection,
  2692. IN WCHAR const *pwszKey,
  2693. IN WCHAR const *pwszSectionAndKey,
  2694. IN BOOL fDump,
  2695. OPTIONAL IN EPF_SYM_KEY_STRUCT const *psKey,
  2696. IN HRESULT hrQuiet)
  2697. {
  2698. HRESULT hr;
  2699. BYTE *pbStore = NULL;
  2700. DWORD cbStore;
  2701. if (NULL == psKey)
  2702. {
  2703. hr = cuInfDumpValue(
  2704. hInf,
  2705. pwszSection,
  2706. pwszKey,
  2707. 1, // Index
  2708. TRUE, // fLastValue
  2709. hrQuiet,
  2710. &pbStore,
  2711. &cbStore);
  2712. _PrintIfErrorStr(hr, "cuInfDumpValue", pwszSectionAndKey);
  2713. }
  2714. else
  2715. {
  2716. hr = cuInfDumpProtectedValue(
  2717. hInf,
  2718. pwszSection,
  2719. pwszKey,
  2720. psKey,
  2721. hrQuiet,
  2722. &pbStore,
  2723. &cbStore);
  2724. _PrintIfErrorStr(hr, "cuInfDumpProtectedValue", pwszSectionAndKey);
  2725. }
  2726. wprintf(wszNewLine);
  2727. if (fDump)
  2728. {
  2729. wprintf(s_wszHeader);
  2730. wprintf(L"[%ws] ", pwszSection);
  2731. }
  2732. wprintf(L"%ws:\n", pwszKey);
  2733. if (NULL != pbStore)
  2734. {
  2735. if (1 < g_fVerbose)
  2736. {
  2737. DumpHex(DH_NOTABPREFIX | 4, pbStore, cbStore);
  2738. }
  2739. DumpHex(
  2740. DH_NOTABPREFIX | 4,
  2741. pbStore,
  2742. cbStore);
  2743. hr = DumpSerializedCertStore(pbStore, cbStore);
  2744. _JumpIfError(hr, error, "DumpSerializedCertStore");
  2745. }
  2746. hr = S_OK;
  2747. error:
  2748. if (NULL != pbStore)
  2749. {
  2750. LocalFree(pbStore);
  2751. }
  2752. return(hr);
  2753. }
  2754. HRESULT
  2755. cuDumpAsnAlgorithm(
  2756. IN BYTE const *pbIn,
  2757. IN DWORD cbIn)
  2758. {
  2759. HRESULT hr;
  2760. CRYPT_SEQUENCE_OF_ANY *pSeqAlg = NULL;
  2761. char *pszObjId = NULL;
  2762. DWORD cb;
  2763. CRYPT_ALGORITHM_IDENTIFIER Alg;
  2764. hr = cuDecodeSequence(pbIn, cbIn, 2, &pSeqAlg);
  2765. _JumpIfError(hr, error, "cuDecodeSequence");
  2766. hr = cuDecodeObjId(
  2767. pSeqAlg->rgValue[0].pbData,
  2768. pSeqAlg->rgValue[0].cbData,
  2769. &pszObjId);
  2770. _JumpIfError(hr, error, "cuDecodeObjId");
  2771. Alg.pszObjId = pszObjId;
  2772. Alg.Parameters = pSeqAlg->rgValue[1];
  2773. cuDumpAlgorithm(IDS_SIGNATURE_ALGORITHM, &Alg);
  2774. error:
  2775. if (NULL != pszObjId)
  2776. {
  2777. LocalFree(pszObjId);
  2778. }
  2779. if (NULL != pSeqAlg)
  2780. {
  2781. LocalFree(pSeqAlg);
  2782. }
  2783. return(hr);
  2784. }
  2785. HRESULT
  2786. cuDumpAsnTime(
  2787. IN BYTE const *pbIn,
  2788. IN DWORD cbIn)
  2789. {
  2790. HRESULT hr;
  2791. FILETIME ft;
  2792. DWORD cb;
  2793. cb = sizeof(FILETIME);
  2794. if (!CryptDecodeObject(
  2795. X509_ASN_ENCODING,
  2796. X509_CHOICE_OF_TIME,
  2797. pbIn,
  2798. cbIn,
  2799. 0,
  2800. &ft,
  2801. &cb))
  2802. {
  2803. hr = myHLastError();
  2804. _JumpError(hr, error, "CryptDecodeObject");
  2805. }
  2806. hr = cuDumpFileTime(0, NULL, &ft);
  2807. _JumpIfError(hr, error, "cuDumpFileTime");
  2808. error:
  2809. return(hr);
  2810. }
  2811. HRESULT
  2812. epfDumpCRLValue(
  2813. IN BYTE const *pbIn,
  2814. IN DWORD cbIn)
  2815. {
  2816. HRESULT hr;
  2817. CRYPT_SEQUENCE_OF_ANY *pSeqOuter = NULL;
  2818. CRYPT_SEQUENCE_OF_ANY *pSeqInner = NULL;
  2819. CRYPT_SEQUENCE_OF_ANY *pSeq04 = NULL;
  2820. CRYPT_SEQUENCE_OF_ANY *pSeq040 = NULL;
  2821. CERT_SIGNED_CONTENT_INFO *pcsci = NULL;
  2822. DWORD cb;
  2823. DWORD dwVersion;
  2824. if (SZARRAYSIZE(szPROPASNTAG) < cbIn &&
  2825. 0 == _strnicmp(
  2826. (char const *) pbIn,
  2827. szPROPASNTAG,
  2828. SZARRAYSIZE(szPROPASNTAG)))
  2829. {
  2830. pbIn += SZARRAYSIZE(szPROPASNTAG);
  2831. cbIn -= SZARRAYSIZE(szPROPASNTAG);
  2832. }
  2833. if (1 < g_fVerbose)
  2834. {
  2835. DumpHex(DH_MULTIADDRESS | DH_NOTABPREFIX | 4, pbIn, cbIn);
  2836. }
  2837. // 3 SEQUENCES
  2838. hr = cuDecodeSequence(pbIn, cbIn, 3, &pSeqOuter);
  2839. _JumpIfError(hr, error, "cuDecodeSequence");
  2840. // Sequence 0:
  2841. // SEQUENCE { 5 SEQUENCES }
  2842. hr = cuDecodeSequence(
  2843. pSeqOuter->rgValue[0].pbData,
  2844. pSeqOuter->rgValue[0].cbData,
  2845. 5,
  2846. &pSeqInner);
  2847. _JumpIfError(hr, error, "cuDecodeSequence");
  2848. // Sequence 0.0:
  2849. // NAME
  2850. hr = cuDisplayCertName(
  2851. TRUE,
  2852. g_wszEmpty,
  2853. myLoadResourceString(IDS_ISSUER), // "Issuer"
  2854. g_wszPad4,
  2855. &pSeqInner->rgValue[0],
  2856. NULL);
  2857. _JumpIfError(hr, error, "cuDisplayCertName(Subject)");
  2858. // Sequence 0.1:
  2859. // DATE
  2860. cuDumpAsnTime(
  2861. pSeqInner->rgValue[1].pbData,
  2862. pSeqInner->rgValue[1].cbData);
  2863. // Sequence 0.2:
  2864. // DATE
  2865. cuDumpAsnTime(
  2866. pSeqInner->rgValue[2].pbData,
  2867. pSeqInner->rgValue[2].cbData);
  2868. // Sequence 0.3:
  2869. // SEQUENCE { OID, NULL }
  2870. cuDumpAsnAlgorithm(
  2871. pSeqInner->rgValue[3].pbData,
  2872. pSeqInner->rgValue[3].cbData);
  2873. // Sequence 0.4:
  2874. // SEQUENCE { SEQUENCE { INTEGER, DATE } }
  2875. hr = cuDecodeSequence(
  2876. pSeqInner->rgValue[4].pbData,
  2877. pSeqInner->rgValue[4].cbData,
  2878. 1,
  2879. &pSeq04);
  2880. _JumpIfError(hr, error, "cuDecodeSequence");
  2881. // Sequence 0.4.0:
  2882. // SEQUENCE { INTEGER, DATE }
  2883. hr = cuDecodeSequence(
  2884. pSeq04->rgValue[0].pbData,
  2885. pSeq04->rgValue[0].cbData,
  2886. 2,
  2887. &pSeq040);
  2888. _JumpIfError(hr, error, "cuDecodeSequence");
  2889. // Sequence 0.4.0.0.0:
  2890. // INTEGER
  2891. cb = sizeof(dwVersion);
  2892. if (!CryptDecodeObject(
  2893. X509_ASN_ENCODING,
  2894. X509_INTEGER,
  2895. pSeq040->rgValue[0].pbData,
  2896. pSeq040->rgValue[0].cbData,
  2897. 0,
  2898. &dwVersion,
  2899. &cb))
  2900. {
  2901. hr = myHLastError();
  2902. _JumpError(hr, error, "CryptDecodeObject");
  2903. }
  2904. cuDumpVersion(dwVersion + 1);
  2905. // Sequence 0.4.0.0.1:
  2906. // DATE
  2907. cuDumpAsnTime(
  2908. pSeqInner->rgValue[2].pbData,
  2909. pSeqInner->rgValue[2].cbData);
  2910. // Sequence 1:
  2911. // SEQUENCE { OID, NULL } (part of signature)
  2912. // cuDumpAsnAlgorithm(
  2913. // pSeqOuter->rgValue[1].pbData,
  2914. // pSeqOuter->rgValue[1].cbData);
  2915. // Sequence 2:
  2916. // BITSTRING (part of signature)
  2917. // pSeqOuter->rgValue[2].pbData
  2918. // pSeqOuter->rgValue[2].cbData
  2919. if (!myDecodeObject(
  2920. X509_ASN_ENCODING,
  2921. X509_CERT,
  2922. pbIn,
  2923. cbIn,
  2924. CERTLIB_USE_LOCALALLOC,
  2925. (VOID **) &pcsci,
  2926. &cb))
  2927. {
  2928. hr = myHLastError();
  2929. _JumpError(hr, error, "myDecodeObject");
  2930. }
  2931. cuDumpSignature(pcsci);
  2932. hr = S_OK;
  2933. error:
  2934. if (NULL != pcsci)
  2935. {
  2936. LocalFree(pcsci);
  2937. }
  2938. if (NULL != pSeq04)
  2939. {
  2940. LocalFree(pSeq04);
  2941. }
  2942. if (NULL != pSeq040)
  2943. {
  2944. LocalFree(pSeq040);
  2945. }
  2946. if (NULL != pSeqInner)
  2947. {
  2948. LocalFree(pSeqInner);
  2949. }
  2950. if (NULL != pSeqOuter)
  2951. {
  2952. LocalFree(pSeqOuter);
  2953. }
  2954. return(hr);
  2955. }
  2956. HRESULT
  2957. cuInfDumpCRLValue(
  2958. IN HINF hInf)
  2959. {
  2960. HRESULT hr;
  2961. BYTE *pbCRL0 = NULL;
  2962. DWORD cbCRL0;
  2963. BYTE *pbCRL1 = NULL;
  2964. DWORD cbCRL1;
  2965. BYTE *pbCRL = NULL;
  2966. wprintf(wszNewLine);
  2967. wprintf(
  2968. L"[%ws] %ws\n",
  2969. wszINFSECTION_REVOKATIONINFORMATION,
  2970. wszINFKEY_CRL);
  2971. hr = cuInfDumpValue(
  2972. hInf,
  2973. wszINFSECTION_REVOKATIONINFORMATION,
  2974. wszINFKEY_CRL,
  2975. 1,
  2976. TRUE,
  2977. S_OK,
  2978. &pbCRL0,
  2979. &cbCRL0);
  2980. _JumpIfErrorStr(hr, error, "cuInfDumpValue", wszINFKEY_CRL);
  2981. wprintf(
  2982. L"[%ws] %ws\n",
  2983. wszINFSECTION_REVOKATIONINFORMATION,
  2984. wszINFKEY_CRL1);
  2985. hr = cuInfDumpValue(
  2986. hInf,
  2987. wszINFSECTION_REVOKATIONINFORMATION,
  2988. wszINFKEY_CRL1,
  2989. 1,
  2990. TRUE,
  2991. S_OK,
  2992. &pbCRL1,
  2993. &cbCRL1);
  2994. _JumpIfErrorStr(hr, error, "cuInfDumpValue", wszINFKEY_CRL1);
  2995. pbCRL = (BYTE *) LocalAlloc(LMEM_FIXED, cbCRL0 + cbCRL1);
  2996. if (NULL == pbCRL)
  2997. {
  2998. hr = E_OUTOFMEMORY;
  2999. _JumpError(hr, error, "LocalAlloc");
  3000. }
  3001. CopyMemory(pbCRL, pbCRL0, cbCRL0);
  3002. CopyMemory(&pbCRL[cbCRL0], pbCRL1, cbCRL1);
  3003. hr = epfDumpCRLValue(pbCRL, cbCRL0 + cbCRL1);
  3004. _JumpIfError(hr, error, "epfDumpCRLValue");
  3005. error:
  3006. if (NULL != pbCRL0)
  3007. {
  3008. LocalFree(pbCRL0);
  3009. }
  3010. if (NULL != pbCRL1)
  3011. {
  3012. LocalFree(pbCRL1);
  3013. }
  3014. if (NULL != pbCRL)
  3015. {
  3016. LocalFree(pbCRL);
  3017. }
  3018. return(hr);
  3019. }
  3020. HRESULT
  3021. EPFFileDump(
  3022. IN WCHAR const *pwszFileName,
  3023. OPTIONAL IN WCHAR const *pwszPassword,
  3024. OPTIONAL IN OUT HCERTSTORE hStore)
  3025. {
  3026. HRESULT hr;
  3027. HRESULT hrQuiet;
  3028. WCHAR *pwszTempFile = NULL;
  3029. HINF hInf = INVALID_HANDLE_VALUE;
  3030. DWORD ErrorLine;
  3031. WCHAR wszPassword[MAX_PATH];
  3032. WCHAR *pwszSaltValue = NULL;
  3033. BYTE *pbToken = NULL;
  3034. DWORD cbToken;
  3035. DWORD dw;
  3036. DWORD dwVersion;
  3037. DWORD dwKeyCountV2;
  3038. DWORD dwKeyCount;
  3039. DWORD dwHashCount;
  3040. DWORD iKey;
  3041. BOOL fDump = g_fVerbose || NULL == hStore;
  3042. HCRYPTPROV hProv = NULL;
  3043. EPF_SYM_KEY_STRUCT sKey;
  3044. BYTE *pbCertV1Signing = NULL;
  3045. DWORD cbCertV1Signing;
  3046. BYTE *pbKeyV1Signing = NULL;
  3047. DWORD cbKeyV1Signing;
  3048. BYTE *pbKeyV1Exchange = NULL;
  3049. DWORD cbKeyV1Exchange;
  3050. BYTE *pbCertUser = NULL;
  3051. DWORD cbCertUser;
  3052. BYTE *pbCertCA = NULL;
  3053. DWORD cbCertCA;
  3054. BYTE *pbCertManager = NULL;
  3055. DWORD cbCertManager;
  3056. BYTE *pbCertV1Exchange = NULL;
  3057. DWORD cbCertV1Exchange;
  3058. BYTE *pbCertSigning = NULL;
  3059. DWORD cbCertSigning;
  3060. BYTE *pbKeySigning = NULL;
  3061. DWORD cbKeySigning;
  3062. BYTE *pbCertHistory = NULL;
  3063. DWORD cbCertHistory;
  3064. BYTE *pbrgKeyPrivate = NULL;
  3065. DWORD cbrgKeyPrivate;
  3066. BYTE *pbCertTrustList = NULL;
  3067. DWORD cbCertTrustList;
  3068. BYTE *pbSaltValue = NULL;
  3069. DWORD cbSaltValue;
  3070. DWORD dwEPFAlg;
  3071. DWORD dwSymKeyLen;
  3072. BOOL f40bit;
  3073. WCHAR *pwszFriendlyName = NULL;
  3074. BOOL fQuietOld = g_fQuiet;
  3075. ZeroMemory(&sKey, sizeof(sKey));
  3076. hrQuiet = S_OK;
  3077. hr = cuPatchEPFFile(pwszFileName, &pwszTempFile);
  3078. _JumpIfError2(hr, error, "cuPatchEPFFile", S_FALSE);
  3079. hr = cuGetPassword(
  3080. 0, // idsPrompt
  3081. NULL, // pwszfn
  3082. pwszPassword,
  3083. FALSE, // fVerify
  3084. wszPassword,
  3085. ARRAYSIZE(wszPassword),
  3086. &pwszPassword);
  3087. _JumpIfError(hr, error, "cuGetPassword");
  3088. hr = myInfOpenFile(pwszTempFile, &hInf, &ErrorLine);
  3089. _JumpIfError(hr, error, "myInfOpenFile");
  3090. if (!CryptAcquireContext(
  3091. &hProv,
  3092. NULL, // container name
  3093. MS_STRONG_PROV,
  3094. PROV_RSA_FULL,
  3095. CRYPT_VERIFYCONTEXT))
  3096. {
  3097. hr = myHLastError();
  3098. _JumpError(hr, error, "CryptAcquireContext");
  3099. }
  3100. //================================================================
  3101. // wszINFSECTION_USERX500NAME:
  3102. hr = cuInfDumpDNKeyValue(
  3103. hInf,
  3104. wszINFSECTION_USERX500NAME,
  3105. wszINFKEY_X500NAME,
  3106. fDump);
  3107. _JumpIfError(hr, error, "cuInfDumpDNKeyValue");
  3108. //================================================================
  3109. // wszINFSECTION_PASSWORDTOKEN:
  3110. hr = cuInfDumpNumericKeyValue(
  3111. hInf,
  3112. wszINFSECTION_PASSWORDTOKEN,
  3113. wszINFKEY_PROTECTION,
  3114. 1, // Index
  3115. TRUE, // fLastValue
  3116. fDump,
  3117. hrQuiet,
  3118. &dwSymKeyLen);
  3119. _JumpIfError(hr, error, "cuInfDumpNumericKeyValue");
  3120. hr = cuInfDumpNumericKeyValue(
  3121. hInf,
  3122. wszINFSECTION_PASSWORDTOKEN,
  3123. wszINFKEY_PROFILEVERSION,
  3124. 1, // Index
  3125. TRUE, // fLastValue
  3126. fDump,
  3127. hrQuiet,
  3128. &dwVersion);
  3129. _JumpIfError(hr, error, "cuInfDumpNumericKeyValue");
  3130. f40bit = FALSE;
  3131. switch (dwVersion)
  3132. {
  3133. case 2:
  3134. dwEPFAlg = EPFALG_CAST_MD5;
  3135. if (40 == dwSymKeyLen)
  3136. {
  3137. f40bit = TRUE;
  3138. }
  3139. else if (64 == dwSymKeyLen)
  3140. {
  3141. }
  3142. else
  3143. {
  3144. wprintf(
  3145. L"%ws %ws=40 | %ws=64!\n",
  3146. myLoadResourceString(IDS_EXPECTED), // "Expected"
  3147. wszINFKEY_PROTECTION,
  3148. wszINFKEY_PROTECTION);
  3149. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3150. _JumpError(hr, error, "cuInfDumpNumericKeyValue");
  3151. }
  3152. break;
  3153. case 3:
  3154. dwEPFAlg = EPFALG_RC2_SHA;
  3155. if (128 != dwSymKeyLen)
  3156. {
  3157. wprintf(
  3158. L"%ws %ws=128!\n",
  3159. myLoadResourceString(IDS_EXPECTED), // "Expected"
  3160. wszINFKEY_PROTECTION);
  3161. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3162. _JumpError(hr, error, "cuInfDumpNumericKeyValue");
  3163. }
  3164. hr = cuInfDumpNumericKeyValue(
  3165. hInf,
  3166. wszINFSECTION_PASSWORDTOKEN,
  3167. wszINFKEY_HASHCOUNT,
  3168. 1, // Index
  3169. TRUE, // fLastValue
  3170. fDump,
  3171. ERROR_LINE_NOT_FOUND, // hrQuiet
  3172. &dwHashCount);
  3173. _PrintIfError2(hr, "cuInfDumpNumericKeyValue", hr);
  3174. if (S_OK == hr)
  3175. {
  3176. dwEPFAlg = EPFALG_3DES;
  3177. }
  3178. break;
  3179. default:
  3180. wprintf(
  3181. L"%ws %ws=2 | %ws=3!\n",
  3182. myLoadResourceString(IDS_EXPECTED), // "Expected"
  3183. wszINFKEY_PROFILEVERSION,
  3184. wszINFKEY_PROFILEVERSION);
  3185. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3186. _JumpError(hr, error, "cuInfDumpNumericKeyValue");
  3187. }
  3188. if (EPFALG_CAST_MD5 == dwEPFAlg)
  3189. {
  3190. hr = cuInfDumpNumericKeyValue(
  3191. hInf,
  3192. wszINFSECTION_PASSWORDTOKEN,
  3193. wszINFKEY_CAST,
  3194. 1, // Index
  3195. TRUE, // fLastValue
  3196. fDump,
  3197. hrQuiet,
  3198. &dw);
  3199. _JumpIfError(hr, error, "cuInfDumpNumericKeyValue");
  3200. if (3 != dw)
  3201. {
  3202. wprintf(
  3203. L"%ws CAST=3!\n",
  3204. myLoadResourceString(IDS_EXPECTED)); // "Expected"
  3205. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3206. _JumpError(hr, error, "cuInfDumpNumericKeyValue");
  3207. }
  3208. }
  3209. hr = cuInfDumpHexKeyValue(
  3210. hInf,
  3211. wszINFSECTION_PASSWORDTOKEN,
  3212. wszINFKEY_TOKEN,
  3213. fDump,
  3214. &pbToken,
  3215. &cbToken);
  3216. _JumpIfError(hr, error, "cuInfDumpHexKeyValue");
  3217. hr = cuInfDumpStringKeyValue(
  3218. hInf,
  3219. wszINFSECTION_PASSWORDTOKEN,
  3220. wszINFKEY_SALTVALUE,
  3221. fDump,
  3222. hrQuiet,
  3223. &pwszSaltValue);
  3224. _JumpIfError(hr, error, "cuInfDumpStringKeyValue");
  3225. hr = cuInfDumpNumericKeyValue(
  3226. hInf,
  3227. wszINFSECTION_PASSWORDTOKEN,
  3228. wszINFKEY_HASHSIZE,
  3229. 1, // Index
  3230. TRUE, // fLastValue
  3231. fDump,
  3232. hrQuiet,
  3233. &dw);
  3234. _PrintIfError(hr, "cuInfDumpNumericKeyValue");
  3235. //================================================================
  3236. // Now we have password, SALT & token -- derive & verify proper type key.
  3237. // In most cases, cbHashSize is ZERO. Should pull from inf above, though.
  3238. pbSaltValue = NULL;
  3239. cbSaltValue = 0;
  3240. hr = EPFDeriveKey(
  3241. dwEPFAlg,
  3242. dwSymKeyLen,
  3243. hProv,
  3244. pwszPassword,
  3245. pwszSaltValue,
  3246. pbSaltValue,
  3247. cbSaltValue,
  3248. 0, // cbHashSize
  3249. &sKey);
  3250. _JumpIfError(hr, error, "EPFDeriveKey");
  3251. // check pwd via token
  3252. hr = EPFVerifyKeyToken(&sKey, pbToken, cbToken);
  3253. if (S_OK != hr)
  3254. {
  3255. _PrintError(hr, "EPFVerifyKeyToken");
  3256. if (2 > g_fForce || EPFALG_3DES != dwEPFAlg)
  3257. {
  3258. goto error;
  3259. }
  3260. }
  3261. //================================================================
  3262. // password looks good. Decrypt the EPF file data.
  3263. if (!g_fVerbose && !fDump)
  3264. {
  3265. g_fQuiet = TRUE;
  3266. }
  3267. InitCrcTable();
  3268. if (2 == dwVersion || EPFALG_3DES == dwEPFAlg)
  3269. {
  3270. DWORD dwKeyAlgId;
  3271. WCHAR const *pwszCertSection;
  3272. //================================================================
  3273. // wszINFSECTION_DIGITALSIGNATURE:
  3274. hr = cuInfDumpProtectedValue(
  3275. hInf,
  3276. wszINFSECTION_DIGITALSIGNATURE,
  3277. wszINFKEY_CERTIFICATE,
  3278. &sKey,
  3279. ERROR_LINE_NOT_FOUND, // hrQuiet
  3280. &pbCertV1Signing,
  3281. &cbCertV1Signing);
  3282. _PrintIfErrorStr(
  3283. hr,
  3284. "cuInfDumpProtectedValue",
  3285. wszSECTION_KEY(
  3286. dwEPFAlg,
  3287. wszINFSECTION_DIGITALSIGNATURE,
  3288. wszINFKEY_CERTIFICATE));
  3289. wprintf(wszNewLine);
  3290. if (fDump)
  3291. {
  3292. wprintf(s_wszHeader);
  3293. wprintf(L"[%ws] ", wszINFSECTION_DIGITALSIGNATURE);
  3294. }
  3295. wprintf(L"%ws:\n", wszINFKEY_CERTIFICATE);
  3296. if (NULL != pbCertV1Signing)
  3297. {
  3298. ExtraAsnBytes(pbCertV1Signing, cbCertV1Signing);
  3299. hr = cuDumpAsnBinary(pbCertV1Signing, cbCertV1Signing, MAXDWORD);
  3300. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3301. wprintf(wszNewLine);
  3302. }
  3303. hr = cuInfDumpProtectedValue(
  3304. hInf,
  3305. wszINFSECTION_DIGITALSIGNATURE,
  3306. wszINFKEY_KEY,
  3307. &sKey,
  3308. NULL == pbCertV1Signing? ERROR_LINE_NOT_FOUND : S_OK,
  3309. &pbKeyV1Signing,
  3310. &cbKeyV1Signing);
  3311. _PrintIfErrorStr(
  3312. hr,
  3313. "cuInfDumpProtectedValue",
  3314. wszSECTION_KEY(
  3315. dwEPFAlg,
  3316. wszINFSECTION_DIGITALSIGNATURE,
  3317. wszINFKEY_KEY));
  3318. if (fDump)
  3319. {
  3320. wprintf(
  3321. L"[%ws] %ws:\n",
  3322. wszINFSECTION_DIGITALSIGNATURE,
  3323. wszINFKEY_KEY);
  3324. }
  3325. // DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 4, pbKeyV1Signing, cbKeyV1Signing);
  3326. if (NULL != pbCertV1Signing && NULL != pbKeyV1Signing)
  3327. {
  3328. hr = VerifyAndSaveOneCertAndKey(
  3329. hStore,
  3330. fDump,
  3331. epfLoadResource(IDS_SIGNING, wszSIGNING),
  3332. pbCertV1Signing,
  3333. cbCertV1Signing,
  3334. pbKeyV1Signing,
  3335. cbKeyV1Signing,
  3336. CALG_RSA_SIGN,
  3337. AT_SIGNATURE);
  3338. _JumpIfError(hr, error, "VerifyAndSaveOneCertAndKey");
  3339. }
  3340. //================================================================
  3341. // wszINFSECTION_PRIVATEKEYS:
  3342. hr = cuInfDumpNumericKeyValue(
  3343. hInf,
  3344. wszINFSECTION_PRIVATEKEYS,
  3345. wszINFKEY_KEYCOUNT,
  3346. 1, // Index
  3347. TRUE, // fLastValue
  3348. fDump,
  3349. hrQuiet,
  3350. &dwKeyCountV2);
  3351. _JumpIfError(hr, error, "cuInfDumpNumericKeyValue");
  3352. pwszCertSection = f40bit? wszINFSECTION_USERCERTIFICATE :
  3353. (2 == dwVersion?
  3354. wszINFSECTION_FULLCERTIFICATEHISTORY :
  3355. wszINFSECTION_CERTIFICATEHISTORY);
  3356. for (iKey = 0; iKey < dwKeyCountV2; iKey++)
  3357. {
  3358. WCHAR wszKey[cwcINFKEY_KEY_FORMATTED];
  3359. WCHAR wszName[cwcINFKEY_NAME_FORMATTED];
  3360. DWORD dwSerial;
  3361. WCHAR const *pwszCertKey;
  3362. pwszCertKey = f40bit? wszINFKEY_CERTIFICATE : wszName;
  3363. if (NULL != pbCertV1Exchange)
  3364. {
  3365. LocalFree(pbCertV1Exchange);
  3366. pbCertV1Exchange = NULL;
  3367. }
  3368. if (NULL != pbKeyV1Exchange)
  3369. {
  3370. LocalFree(pbKeyV1Exchange);
  3371. pbKeyV1Exchange = NULL;
  3372. }
  3373. // wszINFSECTION_FULLCERTIFICATEHISTORY (cast) or
  3374. // wszINFSECTION_CERTIFICATEHISTORY (3des)
  3375. wsprintf(wszName, wszINFKEY_NAME_FORMAT, iKey + 1);
  3376. hr = cuInfDumpProtectedValue(
  3377. hInf,
  3378. pwszCertSection,
  3379. pwszCertKey,
  3380. &sKey,
  3381. hrQuiet,
  3382. &pbCertV1Exchange,
  3383. &cbCertV1Exchange);
  3384. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3385. wprintf(wszNewLine);
  3386. if (fDump)
  3387. {
  3388. wprintf(s_wszHeader);
  3389. }
  3390. wprintf(
  3391. L"[%ws] %ws:\n",
  3392. pwszCertSection,
  3393. pwszCertKey);
  3394. ExtraAsnBytes(pbCertV1Exchange, cbCertV1Exchange);
  3395. hr = cuDumpAsnBinary(
  3396. pbCertV1Exchange,
  3397. cbCertV1Exchange,
  3398. MAXDWORD);
  3399. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3400. wsprintf(wszKey, wszINFKEY_KEY_FORMAT, iKey + 1);
  3401. hr = cuInfDumpProtectedValue(
  3402. hInf,
  3403. wszINFSECTION_PRIVATEKEYS,
  3404. wszKey,
  3405. &sKey,
  3406. hrQuiet,
  3407. &pbKeyV1Exchange,
  3408. &cbKeyV1Exchange);
  3409. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3410. wprintf(wszNewLine);
  3411. if (fDump)
  3412. {
  3413. wprintf(L"[%ws] %ws:\n", wszINFSECTION_PRIVATEKEYS, wszKey);
  3414. }
  3415. if (g_fVerbose)
  3416. {
  3417. DumpHex(DH_NOTABPREFIX | DH_PRIVATEDATA | 4, pbKeyV1Exchange, cbKeyV1Exchange);
  3418. }
  3419. hr = VerifyAndSaveOneCertAndKey(
  3420. hStore,
  3421. fDump,
  3422. epfLoadResource(IDS_EXCHANGE, wszEXCHANGE),
  3423. pbCertV1Exchange,
  3424. cbCertV1Exchange,
  3425. pbKeyV1Exchange,
  3426. cbKeyV1Exchange,
  3427. CALG_RSA_KEYX,
  3428. AT_KEYEXCHANGE);
  3429. _JumpIfError(hr, error, "VerifyAndSaveOneCertAndKey");
  3430. //================================================================
  3431. // wszINFSECTION_CERTIFICATEHISTORY:
  3432. wsprintf(wszName, wszINFKEY_NAME_FORMAT, iKey + 1);
  3433. hr = cuInfDumpBinaryNameKeyValue(
  3434. hInf,
  3435. wszINFSECTION_CERTIFICATEHISTORY,
  3436. wszName,
  3437. 1, // Index
  3438. FALSE, // fLastValue
  3439. fDump,
  3440. hrQuiet);
  3441. _JumpIfError(hr, error, "cuInfDumpBinaryNameKeyValue");
  3442. hr = cuInfDumpNumericKeyValue(
  3443. hInf,
  3444. wszINFSECTION_CERTIFICATEHISTORY,
  3445. wszName,
  3446. 2, // Index
  3447. TRUE, // fLastValue
  3448. fDump,
  3449. hrQuiet,
  3450. &dwSerial);
  3451. _JumpIfError(hr, error, "cuInfDumpNumericKeyValue");
  3452. }
  3453. //================================================================
  3454. // wszINFSECTION_USERCERTIFICATE:
  3455. if (!f40bit)
  3456. {
  3457. hr = cuInfDumpProtectedValue(
  3458. hInf,
  3459. wszINFSECTION_USERCERTIFICATE,
  3460. wszINFKEY_CERTIFICATE,
  3461. &sKey,
  3462. hrQuiet,
  3463. &pbCertUser,
  3464. &cbCertUser);
  3465. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3466. wprintf(wszNewLine);
  3467. if (fDump)
  3468. {
  3469. wprintf(s_wszHeader);
  3470. }
  3471. wprintf(
  3472. L"[%ws] %ws:\n",
  3473. wszINFSECTION_USERCERTIFICATE,
  3474. wszINFKEY_CERTIFICATE);
  3475. ExtraAsnBytes(pbCertUser, cbCertUser);
  3476. hr = cuDumpAsnBinary(pbCertUser, cbCertUser, MAXDWORD);
  3477. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3478. }
  3479. //================================================================
  3480. // wszINFSECTION_CA:
  3481. hr = cuInfDumpProtectedValue(
  3482. hInf,
  3483. wszINFSECTION_CA,
  3484. wszINFKEY_CERTIFICATE,
  3485. &sKey,
  3486. hrQuiet,
  3487. &pbCertCA,
  3488. &cbCertCA);
  3489. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3490. wprintf(wszNewLine);
  3491. if (fDump)
  3492. {
  3493. wprintf(s_wszHeader);
  3494. }
  3495. wprintf(
  3496. L"[%ws] %ws:\n",
  3497. wszINFSECTION_CA,
  3498. wszINFKEY_CERTIFICATE);
  3499. ExtraAsnBytes(pbCertCA, cbCertCA);
  3500. hr = cuDumpAsnBinary(pbCertCA, cbCertCA, MAXDWORD);
  3501. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3502. hr = AddCACertToStore(pbCertCA, cbCertCA);
  3503. _PrintIfError(hr, "AddCACertToStore");
  3504. //================================================================
  3505. // wszINFSECTION_MANAGER:
  3506. if (f40bit)
  3507. {
  3508. hr = cuInfDumpProtectedValue(
  3509. hInf,
  3510. wszINFSECTION_MANAGER,
  3511. wszINFKEY_CERTIFICATE,
  3512. &sKey,
  3513. hrQuiet,
  3514. &pbCertManager,
  3515. &cbCertManager);
  3516. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3517. wprintf(wszNewLine);
  3518. if (fDump)
  3519. {
  3520. wprintf(s_wszHeader);
  3521. }
  3522. wprintf(
  3523. L"[%ws] %ws:\n",
  3524. wszINFSECTION_MANAGER,
  3525. wszINFKEY_CERTIFICATE);
  3526. ExtraAsnBytes(pbCertManager, cbCertManager);
  3527. hr = cuDumpAsnBinary(pbCertManager, cbCertManager, MAXDWORD);
  3528. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3529. hr = AddCACertToStore(pbCertManager, cbCertManager);
  3530. _PrintIfError(hr, "AddCACertToStore");
  3531. }
  3532. //================================================================
  3533. // wszINFSECTION_MICROSOFTEXCHANGE:
  3534. hr = cuInfDumpProtectedStringValue(
  3535. hInf,
  3536. wszINFSECTION_MICROSOFTEXCHANGE,
  3537. wszINFKEY_FRIENDLYNAME,
  3538. &sKey,
  3539. fDump,
  3540. hrQuiet,
  3541. &pwszFriendlyName);
  3542. _JumpIfError(hr, error, "cuInfDumpProtectedStringValue");
  3543. wprintf(
  3544. L"[%ws] %ws = %ws\n",
  3545. wszINFSECTION_MICROSOFTEXCHANGE,
  3546. wszINFKEY_FRIENDLYNAME,
  3547. pwszFriendlyName);
  3548. hr = cuInfDumpProtectedDwordValue(
  3549. hInf,
  3550. wszINFSECTION_MICROSOFTEXCHANGE,
  3551. wszINFKEY_KEYALGID,
  3552. &sKey,
  3553. fDump,
  3554. hrQuiet,
  3555. &dwKeyAlgId);
  3556. _JumpIfError(hr, error, "cuInfDumpProtectedDwordValue");
  3557. wprintf(
  3558. L"[%ws] %ws = 0x%x\n",
  3559. wszINFSECTION_MICROSOFTEXCHANGE,
  3560. wszINFKEY_KEYALGID,
  3561. dwKeyAlgId);
  3562. }
  3563. if (f40bit)
  3564. {
  3565. if (fDump)
  3566. {
  3567. hr = cuInfDumpCRLValue(hInf);
  3568. _PrintIfError(hr, "cuInfDumpCRLValue");
  3569. }
  3570. }
  3571. else
  3572. {
  3573. //================================================================
  3574. // wszINFSECTION_SMIME:
  3575. hr = cuInfDumpNumericKeyValue(
  3576. hInf,
  3577. wszINFSECTION_SMIME,
  3578. wszINFKEY_KEYCOUNT,
  3579. 1, // Index
  3580. TRUE, // fLastValue
  3581. fDump,
  3582. ERROR_LINE_NOT_FOUND, // hrQuiet
  3583. &dwKeyCount);
  3584. if (S_OK != hr)
  3585. {
  3586. dwKeyCount = 0;
  3587. hrQuiet = ERROR_LINE_NOT_FOUND;
  3588. _PrintErrorStr(
  3589. hr,
  3590. "cuInfDumpProtectedValue",
  3591. wszSECTION_KEY(
  3592. dwEPFAlg,
  3593. wszINFSECTION_SMIME,
  3594. wszINFKEY_KEYCOUNT));
  3595. }
  3596. hr = cuInfDumpProtectedValue(
  3597. hInf,
  3598. wszINFSECTION_SMIME,
  3599. wszINFKEY_SIGNINGCERTIFICATE,
  3600. &sKey,
  3601. ERROR_LINE_NOT_FOUND, // hrQuiet
  3602. &pbCertSigning,
  3603. &cbCertSigning);
  3604. _PrintIfErrorStr(
  3605. hr,
  3606. "cuInfDumpProtectedValue",
  3607. wszSECTION_KEY(
  3608. dwEPFAlg,
  3609. wszINFSECTION_SMIME,
  3610. wszINFKEY_SIGNINGCERTIFICATE));
  3611. wprintf(wszNewLine);
  3612. if (fDump)
  3613. {
  3614. wprintf(s_wszHeader);
  3615. wprintf(L"[%ws] ", wszINFSECTION_SMIME);
  3616. }
  3617. wprintf(L"%ws:\n", wszINFKEY_SIGNINGCERTIFICATE);
  3618. if (NULL != pbCertSigning)
  3619. {
  3620. ExtraAsnBytes(pbCertSigning, cbCertSigning);
  3621. hr = cuDumpAsnBinary(pbCertSigning, cbCertSigning, MAXDWORD);
  3622. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3623. hr = cuInfDumpProtectedValue(
  3624. hInf,
  3625. wszINFSECTION_SMIME,
  3626. wszINFKEY_SIGNINGKEY,
  3627. &sKey,
  3628. hrQuiet,
  3629. &pbKeySigning,
  3630. &cbKeySigning);
  3631. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3632. if (fDump)
  3633. {
  3634. wprintf(L"[%ws] %ws:\n", wszINFSECTION_SMIME, wszINFKEY_SIGNINGKEY);
  3635. }
  3636. hr = VerifyAndSaveCertAndKey(
  3637. hStore,
  3638. fDump,
  3639. epfLoadResource(IDS_SIGNING, wszSIGNING),
  3640. pbCertSigning,
  3641. cbCertSigning,
  3642. pbKeySigning,
  3643. cbKeySigning,
  3644. 1, // cKey
  3645. CALG_RSA_SIGN,
  3646. AT_SIGNATURE);
  3647. if (S_OK != hr)
  3648. {
  3649. _PrintErrorStr(
  3650. hr,
  3651. "VerifyAndSaveCertAndKey",
  3652. wszSECTION_KEY(
  3653. dwEPFAlg,
  3654. wszINFSECTION_SMIME,
  3655. wszINFKEY_SIGNINGKEY));
  3656. if (NULL != hStore)
  3657. {
  3658. goto error;
  3659. }
  3660. }
  3661. }
  3662. if (fDump)
  3663. {
  3664. wprintf(L"[%ws] %ws:\n", wszINFSECTION_SMIME, wszINFKEY_PRIVATEKEYS);
  3665. }
  3666. hr = cuInfDumpProtectedValue(
  3667. hInf,
  3668. wszINFSECTION_SMIME,
  3669. wszINFKEY_PRIVATEKEYS,
  3670. &sKey,
  3671. hrQuiet,
  3672. &pbrgKeyPrivate,
  3673. &cbrgKeyPrivate);
  3674. if (0 != dwKeyCount)
  3675. {
  3676. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3677. }
  3678. //================================================================
  3679. // wszINFSECTION_FULLCERTIFICATEHISTORY:
  3680. for (iKey = 0; iKey < dwKeyCount; iKey++)
  3681. {
  3682. WCHAR wszSMIME[cwcINFKEY_SMIME_FORMATTED];
  3683. wsprintf(wszSMIME, wszINFKEY_SMIME_FORMAT, iKey + 1);
  3684. hr = cuInfDumpProtectedValue(
  3685. hInf,
  3686. wszINFSECTION_FULLCERTIFICATEHISTORY,
  3687. wszSMIME,
  3688. &sKey,
  3689. hrQuiet,
  3690. &pbCertHistory,
  3691. &cbCertHistory);
  3692. _JumpIfError(hr, error, "cuInfDumpProtectedValue");
  3693. wprintf(wszNewLine);
  3694. if (fDump)
  3695. {
  3696. wprintf(s_wszHeader);
  3697. }
  3698. wprintf(
  3699. L"[%ws] %ws:\n",
  3700. wszINFSECTION_FULLCERTIFICATEHISTORY,
  3701. wszSMIME);
  3702. ExtraAsnBytes(pbCertHistory, cbCertHistory);
  3703. hr = cuDumpAsnBinary(pbCertHistory, cbCertHistory, MAXDWORD);
  3704. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3705. hr = VerifyAndSaveCertAndKey(
  3706. hStore,
  3707. fDump,
  3708. epfLoadResource(IDS_EXCHANGE, wszEXCHANGE),
  3709. pbCertHistory,
  3710. cbCertHistory,
  3711. pbrgKeyPrivate,
  3712. cbrgKeyPrivate,
  3713. dwKeyCount,
  3714. CALG_RSA_KEYX,
  3715. AT_KEYEXCHANGE);
  3716. if (S_OK != hr)
  3717. {
  3718. _PrintErrorStr(
  3719. hr,
  3720. "VerifyAndSaveCertAndKey",
  3721. wszSECTION_KEY(
  3722. dwEPFAlg,
  3723. wszINFSECTION_SMIME,
  3724. wszINFKEY_PRIVATEKEYS));
  3725. if (NULL != hStore)
  3726. {
  3727. goto error;
  3728. }
  3729. }
  3730. LocalFree(pbCertHistory);
  3731. pbCertHistory = NULL;
  3732. }
  3733. hr = cuInfDumpProtectedStoreValue(
  3734. hInf,
  3735. wszINFSECTION_SMIME,
  3736. wszINFKEY_ISSUINGCERTIFICATES,
  3737. wszSECTION_KEY(
  3738. dwEPFAlg,
  3739. wszINFSECTION_SMIME,
  3740. wszINFKEY_ISSUINGCERTIFICATES),
  3741. fDump,
  3742. &sKey,
  3743. hrQuiet);
  3744. _PrintIfErrorStr(
  3745. hr,
  3746. "cuInfDumpProtectedStoreValue",
  3747. wszSECTION_KEY(
  3748. dwEPFAlg,
  3749. wszINFSECTION_SMIME,
  3750. wszINFKEY_ISSUINGCERTIFICATES));
  3751. hr = cuInfDumpProtectedValue(
  3752. hInf,
  3753. wszINFSECTION_SMIME,
  3754. wszINFKEY_TRUSTLISTCERTIFICATE,
  3755. &sKey,
  3756. hrQuiet,
  3757. &pbCertTrustList,
  3758. &cbCertTrustList);
  3759. _PrintIfErrorStr(
  3760. hr,
  3761. "cuInfDumpProtectedValue",
  3762. wszSECTION_KEY(
  3763. dwEPFAlg,
  3764. wszINFSECTION_SMIME,
  3765. wszINFKEY_TRUSTLISTCERTIFICATE));
  3766. wprintf(wszNewLine);
  3767. if (fDump)
  3768. {
  3769. wprintf(s_wszHeader);
  3770. wprintf(L"[%ws] ", wszINFSECTION_SMIME);
  3771. }
  3772. wprintf(L"%ws:\n", wszINFKEY_TRUSTLISTCERTIFICATE);
  3773. if (NULL != pbCertTrustList)
  3774. {
  3775. ExtraAsnBytes(pbCertTrustList, cbCertTrustList);
  3776. hr = cuDumpAsnBinary(pbCertTrustList, cbCertTrustList, MAXDWORD);
  3777. _JumpIfError(hr, error, "cuDumpAsnBinary");
  3778. hr = AddCACertToStore(pbCertTrustList, cbCertTrustList);
  3779. _PrintIfError(hr, "AddCACertToStore");
  3780. }
  3781. }
  3782. wprintf(wszNewLine);
  3783. hr = S_OK;
  3784. error:
  3785. SecureZeroMemory(wszPassword, sizeof(wszPassword)); // password data
  3786. if (NULL != pwszSaltValue)
  3787. {
  3788. LocalFree(pwszSaltValue);
  3789. }
  3790. if (NULL != pbCertV1Signing)
  3791. {
  3792. LocalFree(pbCertV1Signing);
  3793. }
  3794. if (NULL != pbKeyV1Exchange)
  3795. {
  3796. SecureZeroMemory(pbKeyV1Exchange, cbKeyV1Exchange); // Key material
  3797. LocalFree(pbKeyV1Exchange);
  3798. }
  3799. if (NULL != pbKeyV1Signing)
  3800. {
  3801. SecureZeroMemory(pbKeyV1Signing, cbKeyV1Signing); // Key material
  3802. LocalFree(pbKeyV1Signing);
  3803. }
  3804. if (NULL != pbCertUser)
  3805. {
  3806. LocalFree(pbCertUser);
  3807. }
  3808. if (NULL != pbCertCA)
  3809. {
  3810. LocalFree(pbCertCA);
  3811. }
  3812. if (NULL != pbCertManager)
  3813. {
  3814. LocalFree(pbCertManager);
  3815. }
  3816. if (NULL != pbCertV1Exchange)
  3817. {
  3818. LocalFree(pbCertV1Exchange);
  3819. }
  3820. if (NULL != pbCertSigning)
  3821. {
  3822. LocalFree(pbCertSigning);
  3823. }
  3824. if (NULL != pbKeySigning)
  3825. {
  3826. SecureZeroMemory(pbKeySigning, cbKeySigning); // Key material
  3827. LocalFree(pbKeySigning);
  3828. }
  3829. if (NULL != pbCertHistory)
  3830. {
  3831. LocalFree(pbCertHistory);
  3832. }
  3833. if (NULL != pbrgKeyPrivate)
  3834. {
  3835. SecureZeroMemory(pbrgKeyPrivate, cbrgKeyPrivate); // Key material
  3836. LocalFree(pbrgKeyPrivate);
  3837. }
  3838. if (NULL != pbCertTrustList)
  3839. {
  3840. LocalFree(pbCertTrustList);
  3841. }
  3842. if (NULL != pwszFriendlyName)
  3843. {
  3844. LocalFree(pwszFriendlyName);
  3845. }
  3846. if (NULL != pbToken)
  3847. {
  3848. LocalFree(pbToken);
  3849. }
  3850. if (NULL != pbSaltValue)
  3851. {
  3852. LocalFree(pbSaltValue);
  3853. }
  3854. if (NULL != sKey.hKey)
  3855. {
  3856. CryptDestroyKey(sKey.hKey);
  3857. }
  3858. CAST3Cleanup(&sKey.sCastContext);
  3859. if (NULL != hProv)
  3860. {
  3861. CryptReleaseContext(hProv, 0);
  3862. }
  3863. if (INVALID_HANDLE_VALUE != hInf)
  3864. {
  3865. myInfCloseFile(hInf);
  3866. }
  3867. if (NULL != pwszTempFile)
  3868. {
  3869. if (!g_fSplitASN)
  3870. {
  3871. DeleteFile(pwszTempFile);
  3872. }
  3873. LocalFree(pwszTempFile);
  3874. }
  3875. g_fQuiet = fQuietOld;
  3876. return(hr);
  3877. }
  3878. VOID
  3879. FreeCertList(
  3880. IN CERT_CONTEXT const **ppcc,
  3881. IN DWORD ccc)
  3882. {
  3883. DWORD i;
  3884. if (NULL != ppcc)
  3885. {
  3886. for (i = 0; i < ccc; i++)
  3887. {
  3888. if (NULL != ppcc[i])
  3889. {
  3890. CertFreeCertificateContext(ppcc[i]);
  3891. }
  3892. }
  3893. LocalFree(ppcc);
  3894. }
  3895. }
  3896. int _cdecl
  3897. fnEPFCertSort(
  3898. IN VOID const *pvpcc1,
  3899. IN VOID const *pvpcc2)
  3900. {
  3901. CERT_CONTEXT const *pcc1 = *(CERT_CONTEXT const **) pvpcc1;
  3902. CERT_CONTEXT const *pcc2 = *(CERT_CONTEXT const **) pvpcc2;
  3903. BYTE abHash1[CBMAX_CRYPT_HASH_LEN];
  3904. DWORD cbHash1;
  3905. BYTE abHash2[CBMAX_CRYPT_HASH_LEN];
  3906. DWORD cbHash2;
  3907. int r = 0;
  3908. #define IHASH 5
  3909. cbHash1 = sizeof(abHash1);
  3910. if (CertGetCertificateContextProperty(
  3911. pcc1,
  3912. CERT_SHA1_HASH_PROP_ID,
  3913. abHash1,
  3914. &cbHash1) &&
  3915. CertGetCertificateContextProperty(
  3916. pcc2,
  3917. CERT_SHA1_HASH_PROP_ID,
  3918. abHash2,
  3919. &cbHash2))
  3920. {
  3921. r = abHash1[5] - abHash2[5];
  3922. }
  3923. if (0 == r)
  3924. {
  3925. r = CompareFileTime(
  3926. &pcc1->pCertInfo->NotBefore,
  3927. &pcc2->pCertInfo->NotBefore);
  3928. }
  3929. return(r);
  3930. }
  3931. #define ICC_V1SIGNING 0
  3932. #define ICC_V1ENCRYPTION 1
  3933. #define ICC_V3SIGNING 2
  3934. #define ICC_V3ENCRYPTION 3
  3935. #define ICC_MAX 4
  3936. HRESULT
  3937. GetCertListFromStore(
  3938. IN HCERTSTORE hStore,
  3939. IN DWORD icc,
  3940. OUT CERT_CONTEXT const ***pppcc,
  3941. OUT DWORD *pccc)
  3942. {
  3943. HRESULT hr;
  3944. CERT_CONTEXT const *pcc = NULL;
  3945. CRYPT_KEY_PROV_INFO *pkpi = NULL;
  3946. DWORD ccc;
  3947. DWORD i;
  3948. CERT_CONTEXT const **ppcc = NULL;
  3949. DWORD dwKeySpec = (ICC_V1SIGNING == icc || ICC_V3SIGNING == icc)?
  3950. AT_SIGNATURE : AT_KEYEXCHANGE;
  3951. BOOL fV1 = ICC_V1SIGNING == icc || ICC_V1ENCRYPTION == icc;
  3952. *pppcc = NULL;
  3953. ccc = 0;
  3954. while (TRUE)
  3955. {
  3956. if (NULL != pkpi)
  3957. {
  3958. LocalFree(pkpi);
  3959. pkpi = NULL;
  3960. }
  3961. pcc = CertEnumCertificatesInStore(hStore, pcc);
  3962. if (NULL == pcc)
  3963. {
  3964. break;
  3965. }
  3966. if ((CERT_V1 == pcc->pCertInfo->dwVersion) ^ !fV1)
  3967. {
  3968. hr = myCertGetKeyProviderInfo(pcc, &pkpi);
  3969. _PrintIfError2(hr, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
  3970. if (S_OK == hr && pkpi->dwKeySpec == dwKeySpec)
  3971. {
  3972. ccc++;
  3973. }
  3974. }
  3975. }
  3976. if (0 == ccc)
  3977. {
  3978. hr = CRYPT_E_NOT_FOUND;
  3979. _JumpError2(hr, error, "no certs", hr);
  3980. }
  3981. ppcc = (CERT_CONTEXT const **) LocalAlloc(
  3982. LMEM_FIXED | LMEM_ZEROINIT,
  3983. ccc * sizeof(*ppcc));
  3984. if (NULL == ppcc)
  3985. {
  3986. hr = E_OUTOFMEMORY;
  3987. _JumpError(hr, error, "LocalAlloc");
  3988. }
  3989. i = 0;
  3990. while (TRUE)
  3991. {
  3992. if (NULL != pkpi)
  3993. {
  3994. LocalFree(pkpi);
  3995. pkpi = NULL;
  3996. }
  3997. pcc = CertEnumCertificatesInStore(hStore, pcc);
  3998. if (NULL == pcc)
  3999. {
  4000. break;
  4001. }
  4002. if ((CERT_V1 == pcc->pCertInfo->dwVersion) ^ !fV1)
  4003. {
  4004. hr = myCertGetKeyProviderInfo(pcc, &pkpi);
  4005. _PrintIfError2(hr, "myCertGetKeyProviderInfo", CRYPT_E_NOT_FOUND);
  4006. if (S_OK == hr && pkpi->dwKeySpec == dwKeySpec)
  4007. {
  4008. ppcc[i] = CertDuplicateCertificateContext(pcc);
  4009. if (NULL == ppcc[i])
  4010. {
  4011. hr = myHLastError();
  4012. _JumpError(hr, error, "CertDuplicateCertificateContext");
  4013. }
  4014. i++;
  4015. }
  4016. }
  4017. }
  4018. CSASSERT(i == ccc);
  4019. qsort(ppcc, ccc, sizeof(ppcc[0]), fnEPFCertSort);
  4020. *pppcc = ppcc;
  4021. ppcc = NULL;
  4022. *pccc = ccc;
  4023. error:
  4024. FreeCertList(ppcc, ccc);
  4025. if (NULL != pkpi)
  4026. {
  4027. LocalFree(pkpi);
  4028. }
  4029. return(hr);
  4030. }
  4031. HRESULT
  4032. GetLowerCaseDNAndCN(
  4033. IN CERT_CONTEXT const *pcc,
  4034. OUT CHAR **ppszDN,
  4035. OUT WCHAR **ppwszCN)
  4036. {
  4037. HRESULT hr;
  4038. WCHAR *pwszDN = NULL;
  4039. char *pszDN = NULL;
  4040. DWORD Flags = CERT_X500_NAME_STR;
  4041. *ppszDN = NULL;
  4042. *ppwszCN = NULL;
  4043. if (CERT_V1 == pcc->pCertInfo->dwVersion)
  4044. {
  4045. Flags |= CERT_NAME_STR_REVERSE_FLAG;
  4046. }
  4047. hr = myCertNameToStr(
  4048. X509_ASN_ENCODING,
  4049. &pcc->pCertInfo->Subject,
  4050. Flags,
  4051. &pwszDN);
  4052. _JumpIfError(hr, error, "myCertNameToStr");
  4053. if (!myConvertWszToSz(&pszDN, pwszDN, -1))
  4054. {
  4055. hr = E_OUTOFMEMORY;
  4056. _JumpError(hr, error, "myConvertWszToSz");
  4057. }
  4058. _strlwr(pszDN);
  4059. hr = myCertGetNameString(pcc, CERT_NAME_SIMPLE_DISPLAY_TYPE, ppwszCN);
  4060. _JumpIfError(hr, error, "myCertGetNameString");
  4061. *ppszDN = pszDN;
  4062. pszDN = NULL;
  4063. error:
  4064. if (NULL != pwszDN)
  4065. {
  4066. LocalFree(pwszDN);
  4067. }
  4068. if (NULL != pszDN)
  4069. {
  4070. LocalFree(pszDN);
  4071. }
  4072. return(hr);
  4073. }
  4074. HRESULT
  4075. EPFCryptBinaryToBase64(
  4076. IN BYTE const *pbData,
  4077. IN DWORD cbData,
  4078. OUT WCHAR **ppwszBase64)
  4079. {
  4080. HRESULT hr;
  4081. WCHAR *pwszSrc;
  4082. WCHAR *pwszDst;
  4083. *ppwszBase64 = NULL;
  4084. hr = myCryptBinaryToString(
  4085. pbData,
  4086. cbData,
  4087. CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR,
  4088. ppwszBase64);
  4089. _JumpIfError(hr, error, "myCryptBinaryToString");
  4090. for (pwszSrc = pwszDst = *ppwszBase64; L'\0' != *pwszSrc; pwszSrc++)
  4091. {
  4092. switch (*pwszSrc)
  4093. {
  4094. case L'\r':
  4095. case L'\n':
  4096. case L'\t':
  4097. case L' ':
  4098. break; // skip all whitespace
  4099. default:
  4100. *pwszDst++ = *pwszSrc; // copy the rest
  4101. break;
  4102. }
  4103. }
  4104. *pwszDst = L'\0';
  4105. hr = S_OK;
  4106. error:
  4107. return(hr);
  4108. }
  4109. HRESULT
  4110. WriteBase64Value(
  4111. IN FILE *pf,
  4112. IN WCHAR const *pwszKey,
  4113. IN WCHAR const *pwszBase64Value,
  4114. OPTIONAL IN WCHAR const *pwsz2ndValue)
  4115. {
  4116. HRESULT hr;
  4117. WCHAR const *pwszRemain = pwszBase64Value;
  4118. DWORD cwcRemain = wcslen(pwszBase64Value);
  4119. CSASSERT(0 != cwcRemain);
  4120. while (0 != cwcRemain)
  4121. {
  4122. DWORD cwcLine;
  4123. DWORD cwc;
  4124. WCHAR const *pwsz1 = g_wszEmpty;
  4125. WCHAR const *pwsz2 = g_wszEmpty;
  4126. fprintf(pf, "%ws=", pwszKey);
  4127. cwcLine = 256 - (wcslen(pwszKey) + 1);
  4128. cwc = min(cwcLine, cwcRemain);
  4129. if (cwc == cwcRemain && NULL != pwsz2ndValue)
  4130. {
  4131. pwsz1 = L",";
  4132. pwsz2 = pwsz2ndValue;
  4133. }
  4134. fprintf(
  4135. pf,
  4136. "%.*ws%ws%ws\n",
  4137. cwc,
  4138. pwszRemain,
  4139. pwsz1,
  4140. pwsz2);
  4141. cwcRemain -= cwc;
  4142. pwszRemain += cwc;
  4143. pwszKey = L"_continue_";
  4144. }
  4145. hr = S_OK;
  4146. return(hr);
  4147. }
  4148. HRESULT
  4149. WriteIssuerNameAndSerialValue(
  4150. IN FILE *pf,
  4151. IN WCHAR const *pwszKey,
  4152. OPTIONAL IN CERT_CONTEXT const *pccCA,
  4153. IN CERT_CONTEXT const *pccUser)
  4154. {
  4155. HRESULT hr;
  4156. CERT_NAME_BLOB const *pName;
  4157. WCHAR *pwszBase64 = NULL;
  4158. DWORD dwSerial;
  4159. WCHAR wszSerial[cwcDWORDSPRINTF];
  4160. DWORD cb;
  4161. DWORD cwc;
  4162. if (NULL != pccCA)
  4163. {
  4164. pName = &pccCA->pCertInfo->Subject;
  4165. }
  4166. else
  4167. {
  4168. pName = &pccUser->pCertInfo->Issuer;
  4169. }
  4170. hr = EPFCryptBinaryToBase64(pName->pbData, pName->cbData, &pwszBase64);
  4171. _JumpIfError(hr, error, "EPFCryptBinaryToBase64");
  4172. dwSerial = 0;
  4173. cb = pccUser->pCertInfo->SerialNumber.cbData;
  4174. if (cb > sizeof(dwSerial))
  4175. {
  4176. cb = sizeof(dwSerial);
  4177. }
  4178. CopyMemory(&dwSerial, pccUser->pCertInfo->SerialNumber.pbData, cb);
  4179. wsprintf(wszSerial, L"%u", dwSerial);
  4180. hr = WriteBase64Value(pf, pwszKey, pwszBase64, wszSerial);
  4181. _JumpIfError(hr, error, "WriteBase64Value");
  4182. error:
  4183. if (NULL != pwszBase64)
  4184. {
  4185. LocalFree(pwszBase64);
  4186. }
  4187. return(hr);
  4188. }
  4189. HRESULT
  4190. WriteProtectedValue(
  4191. IN FILE *pf,
  4192. IN WCHAR const *pwszSection,
  4193. IN WCHAR const *pwszKey,
  4194. IN EPF_SYM_KEY_STRUCT const *psKey,
  4195. IN BYTE const *pbData,
  4196. IN DWORD cbData)
  4197. {
  4198. HRESULT hr;
  4199. DWORD i;
  4200. CRC16 Crc;
  4201. WCHAR *pwszProtectedKey = NULL;
  4202. BYTE *pbHeader = NULL;
  4203. DWORD cbHeader;
  4204. BYTE *pbValue = NULL;
  4205. DWORD cbValue;
  4206. BYTE *pbEncrypted = NULL;
  4207. DWORD cbEncrypted;
  4208. WCHAR *pwszBase64 = NULL;
  4209. hr = BuildProtectedKey(pwszKey, psKey->dwAlgId, &pwszProtectedKey);
  4210. _JumpIfError(hr, error, "BuildProtectedKey");
  4211. hr = BuildProtectedHeader(pwszSection, pwszKey, &pbHeader, &cbHeader);
  4212. _JumpIfError(hr, error, "BuildProtectedHeader");
  4213. cbValue = sizeof(Crc) + cbHeader + cbData;
  4214. pbValue = (BYTE *) LocalAlloc(LMEM_FIXED, cbValue);
  4215. if (NULL == pbValue)
  4216. {
  4217. hr = E_OUTOFMEMORY;
  4218. _JumpError(hr, error, "myConvertWszToSz");
  4219. }
  4220. CopyMemory(&pbValue[sizeof(Crc)], pbHeader, cbHeader);
  4221. CopyMemory(&pbValue[sizeof(Crc) + cbHeader], pbData, cbData);
  4222. // Calculate the CRC
  4223. Crc = 0xffff;
  4224. F_CRC16(g_CrcTable, &Crc, &pbValue[sizeof(Crc)], cbHeader + cbData);
  4225. _swab((char *) &Crc, (char *) pbValue, sizeof(Crc));
  4226. hr = EPFEncryptSection(
  4227. psKey,
  4228. pbValue,
  4229. cbValue,
  4230. &pbEncrypted,
  4231. &cbEncrypted);
  4232. _JumpIfError(hr, error, "EPFEncryptSection");
  4233. hr = EPFCryptBinaryToBase64(pbEncrypted, cbEncrypted, &pwszBase64);
  4234. _JumpIfError(hr, error, "EPFCryptBinaryToBase64");
  4235. hr = WriteBase64Value(pf, pwszProtectedKey, pwszBase64, NULL);
  4236. _JumpIfError(hr, error, "WriteBase64Value");
  4237. error:
  4238. if (NULL != pwszProtectedKey)
  4239. {
  4240. LocalFree(pwszProtectedKey);
  4241. }
  4242. if (NULL != pbHeader)
  4243. {
  4244. SecureZeroMemory(pbValue, cbValue); // possible private key material
  4245. LocalFree(pbHeader);
  4246. }
  4247. if (NULL != pbValue)
  4248. {
  4249. LocalFree(pbValue);
  4250. }
  4251. if (NULL != pbEncrypted)
  4252. {
  4253. LocalFree(pbEncrypted);
  4254. }
  4255. if (NULL != pwszBase64)
  4256. {
  4257. LocalFree(pwszBase64);
  4258. }
  4259. return(hr);
  4260. }
  4261. HRESULT
  4262. WriteProtectedStringValue(
  4263. IN FILE *pf,
  4264. IN WCHAR const *pwszSection,
  4265. IN WCHAR const *pwszKey,
  4266. IN EPF_SYM_KEY_STRUCT const *psKey,
  4267. IN WCHAR const *pwszValue)
  4268. {
  4269. HRESULT hr;
  4270. char *pszValue = NULL;
  4271. if (!myConvertWszToSz(&pszValue, pwszValue, -1))
  4272. {
  4273. hr = E_OUTOFMEMORY;
  4274. _JumpError(hr, error, "myConvertWszToSz");
  4275. }
  4276. hr = WriteProtectedValue(
  4277. pf,
  4278. pwszSection,
  4279. pwszKey,
  4280. psKey,
  4281. (BYTE const *) pszValue,
  4282. strlen(pszValue));
  4283. _JumpIfError(hr, error, "WriteProtectedValue");
  4284. error:
  4285. if (NULL != pszValue)
  4286. {
  4287. LocalFree(pszValue);
  4288. }
  4289. return(hr);
  4290. }
  4291. HRESULT
  4292. WriteProtectedDwordValue(
  4293. IN FILE *pf,
  4294. IN WCHAR const *pwszSection,
  4295. IN WCHAR const *pwszKey,
  4296. IN EPF_SYM_KEY_STRUCT const *psKey,
  4297. IN DWORD dwValue)
  4298. {
  4299. HRESULT hr;
  4300. hr = WriteProtectedValue(
  4301. pf,
  4302. pwszSection,
  4303. pwszKey,
  4304. psKey,
  4305. (BYTE const *) &dwValue,
  4306. sizeof(dwValue));
  4307. _JumpIfError(hr, error, "WriteProtectedValue");
  4308. error:
  4309. return(hr);
  4310. }
  4311. HRESULT
  4312. LoadKMSRSAKeyFromCert(
  4313. IN CERT_CONTEXT const *pcc,
  4314. OPTIONAL IN HCRYPTPROV hProv,
  4315. IN DWORD dwKeySpec,
  4316. OUT BYTE **ppbKey,
  4317. OUT DWORD *pcbKey,
  4318. OPTIONAL OUT CERT_PUBLIC_KEY_INFO **ppPublicKeyInfo)
  4319. {
  4320. HRESULT hr;
  4321. HCRYPTPROV hProvT = NULL;
  4322. HCRYPTKEY hKeyPrivate = NULL;
  4323. CRYPT_BIT_BLOB PrivateKey;
  4324. CERT_PUBLIC_KEY_INFO *pPublicKeyInfo = NULL;
  4325. DWORD cb;
  4326. ZeroMemory(&PrivateKey, sizeof(PrivateKey));
  4327. *ppbKey = NULL;
  4328. if (NULL != ppPublicKeyInfo)
  4329. {
  4330. *ppPublicKeyInfo = NULL;
  4331. }
  4332. if (NULL == hProv)
  4333. {
  4334. DWORD dwKeySpecT;
  4335. if (!CryptAcquireCertificatePrivateKey(
  4336. pcc,
  4337. 0, // dwFlags
  4338. NULL, // pvReserved
  4339. &hProvT,
  4340. &dwKeySpecT,
  4341. NULL)) // pfCallerFreeProv
  4342. {
  4343. hr = myHLastError();
  4344. _JumpError(hr, error, "CryptAcquireCertificatePrivateKey");
  4345. }
  4346. if (dwKeySpec != dwKeySpecT)
  4347. {
  4348. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4349. _JumpError(hr, error, "dwKeySpec mismatch");
  4350. }
  4351. hProv = hProvT;
  4352. }
  4353. if (!CryptGetUserKey(hProv, dwKeySpec, &hKeyPrivate))
  4354. {
  4355. hr = myHLastError();
  4356. _JumpError(hr, error, "CryptGetUserKey");
  4357. }
  4358. hr = myCryptExportPrivateKey(
  4359. hKeyPrivate,
  4360. &PrivateKey.pbData,
  4361. &PrivateKey.cbData);
  4362. _JumpIfError(hr, error, "myCryptExportPrivateKey");
  4363. if (!myCryptExportPublicKeyInfo(
  4364. hProv,
  4365. dwKeySpec,
  4366. CERTLIB_USE_LOCALALLOC,
  4367. &pPublicKeyInfo,
  4368. &cb))
  4369. {
  4370. hr = myHLastError();
  4371. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  4372. }
  4373. if (!myCertComparePublicKeyInfo(
  4374. X509_ASN_ENCODING,
  4375. CERT_V1 == pcc->pCertInfo->dwVersion,
  4376. pPublicKeyInfo,
  4377. &pcc->pCertInfo->SubjectPublicKeyInfo))
  4378. {
  4379. // by design, (my)CertComparePublicKeyInfo doesn't set last error!
  4380. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4381. _JumpError(hr, error, "public key mismatch");
  4382. }
  4383. hr = myEncodeKMSRSAKey(
  4384. PrivateKey.pbData,
  4385. PrivateKey.cbData,
  4386. ppbKey,
  4387. pcbKey);
  4388. _JumpIfError(hr, error, "myEncodeKMSRSAKey");
  4389. if (NULL != ppPublicKeyInfo)
  4390. {
  4391. *ppPublicKeyInfo = pPublicKeyInfo;
  4392. pPublicKeyInfo = NULL;
  4393. }
  4394. error:
  4395. if (NULL != PrivateKey.pbData)
  4396. {
  4397. SecureZeroMemory(PrivateKey.pbData, PrivateKey.cbData); // Key material
  4398. LocalFree(PrivateKey.pbData);
  4399. }
  4400. if (NULL != pPublicKeyInfo)
  4401. {
  4402. LocalFree(pPublicKeyInfo);
  4403. }
  4404. if (NULL != hKeyPrivate)
  4405. {
  4406. CryptDestroyKey(hKeyPrivate);
  4407. }
  4408. if (NULL != hProvT)
  4409. {
  4410. CryptReleaseContext(hProvT, 0);
  4411. }
  4412. return(hr);
  4413. }
  4414. HRESULT
  4415. WriteSingleEPFKeyValue(
  4416. IN FILE *pf,
  4417. IN WCHAR const *pwszSection,
  4418. IN WCHAR const *pwszKey,
  4419. IN EPF_SYM_KEY_STRUCT const *psKey,
  4420. IN CERT_CONTEXT const *pcc,
  4421. IN ALG_ID aiKeyAlg,
  4422. IN DWORD dwKeySpec,
  4423. IN DWORD dwKMSKeySpec)
  4424. {
  4425. HRESULT hr;
  4426. CERT_PUBLIC_KEY_INFO *pPublicKeyInfo = NULL;
  4427. BYTE *pbKMSRSAKey = NULL;
  4428. DWORD cbKMSRSAKey;
  4429. BYTE *pbPubKey = NULL;
  4430. DWORD cbPubKey;
  4431. BYTE *pbEPFKey = NULL;
  4432. DWORD cbEPFKey;
  4433. ExchangeKeyBlobEx ekb;
  4434. OneKeyBlob okb;
  4435. hr = LoadKMSRSAKeyFromCert(
  4436. pcc,
  4437. NULL, // hProv
  4438. dwKeySpec,
  4439. &pbKMSRSAKey,
  4440. &cbKMSRSAKey,
  4441. &pPublicKeyInfo);
  4442. _JumpIfError(hr, error, "LoadKMSRSAKeyFromCert");
  4443. ekb.dwSize = CBEKB;
  4444. ekb.cKeys = 1;
  4445. ekb.dwKeyAlg = aiKeyAlg;
  4446. ZeroMemory(&okb, sizeof(okb));
  4447. okb.dwKeySpec = dwKMSKeySpec;
  4448. okb.cbPrivKey = cbKMSRSAKey;
  4449. okb.obPrivKey = CBEKB + sizeof(okb);
  4450. if (AT_SIGNATURE == dwKeySpec)
  4451. {
  4452. // If this is a valid public key with a proper leading zero byte before
  4453. // the sign bit set in the next public key byte, remove the zero byte
  4454. // and decrement the lengths. This conforms with the old incorrect V1
  4455. // public key encoding used in EPF files.
  4456. hr = mySqueezePublicKey(
  4457. pPublicKeyInfo->PublicKey.pbData,
  4458. pPublicKeyInfo->PublicKey.cbData,
  4459. &pbPubKey,
  4460. &cbPubKey);
  4461. _JumpIfError(hr, error, "mySqueezePublicKey");
  4462. okb.cbPubKey = cbPubKey;
  4463. okb.obPubKey = okb.obPrivKey + cbKMSRSAKey;
  4464. }
  4465. cbEPFKey = okb.obPrivKey + okb.cbPrivKey + okb.cbPubKey;
  4466. pbEPFKey = (BYTE *) LocalAlloc(LMEM_FIXED, cbEPFKey);
  4467. if (NULL == pbEPFKey)
  4468. {
  4469. hr = E_OUTOFMEMORY;
  4470. _JumpError(hr, error, "LocalAlloc");
  4471. }
  4472. CopyMemory(pbEPFKey, &ekb, CBEKB);
  4473. CopyMemory(&pbEPFKey[CBEKB], &okb, sizeof(okb));
  4474. CopyMemory(&pbEPFKey[okb.obPrivKey], pbKMSRSAKey, cbKMSRSAKey);
  4475. if (0 != okb.cbPubKey)
  4476. {
  4477. CopyMemory(&pbEPFKey[okb.obPubKey], pbPubKey, okb.cbPubKey);
  4478. if (g_fVerbose)
  4479. {
  4480. wprintf(myLoadResourceString(IDS_CERT_PUBLIC_KEY_COLON)); // "Cert Public key:"
  4481. wprintf(wszNewLine);
  4482. DumpHex(
  4483. DH_NOTABPREFIX | 4,
  4484. pcc->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
  4485. pcc->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData);
  4486. wprintf(myLoadResourceString(IDS_PUBLIC_KEY_COLON)); // "Public key:"
  4487. wprintf(wszNewLine);
  4488. DumpHex(
  4489. DH_NOTABPREFIX | 4,
  4490. &pbEPFKey[okb.obPubKey],
  4491. okb.cbPubKey);
  4492. }
  4493. }
  4494. hr = WriteProtectedValue(
  4495. pf,
  4496. pwszSection,
  4497. pwszKey,
  4498. psKey,
  4499. pbEPFKey,
  4500. cbEPFKey);
  4501. _JumpIfError(hr, error, "WriteProtectedValue");
  4502. error:
  4503. if (NULL != pbEPFKey)
  4504. {
  4505. SecureZeroMemory(pbEPFKey, cbEPFKey); // Key material
  4506. LocalFree(pbEPFKey);
  4507. }
  4508. if (NULL != pbPubKey)
  4509. {
  4510. LocalFree(pbPubKey);
  4511. }
  4512. if (NULL != pbKMSRSAKey)
  4513. {
  4514. SecureZeroMemory(pbKMSRSAKey, cbKMSRSAKey); // Key material
  4515. LocalFree(pbKMSRSAKey);
  4516. }
  4517. if (NULL != pPublicKeyInfo)
  4518. {
  4519. LocalFree(pPublicKeyInfo);
  4520. }
  4521. return(hr);
  4522. }
  4523. HRESULT
  4524. WriteSingleKMSRSAKeyValue(
  4525. IN FILE *pf,
  4526. IN WCHAR const *pwszSection,
  4527. IN WCHAR const *pwszKey,
  4528. IN EPF_SYM_KEY_STRUCT const *psKey,
  4529. IN CERT_CONTEXT const *pcc,
  4530. OPTIONAL IN HCRYPTPROV hProv,
  4531. IN ALG_ID aiKeyAlg,
  4532. IN DWORD dwKeySpec,
  4533. IN DWORD dwKMSKeySpec)
  4534. {
  4535. HRESULT hr;
  4536. CERT_PUBLIC_KEY_INFO *pPublicKeyInfo = NULL;
  4537. BYTE *pbKMSRSAKey = NULL;
  4538. DWORD cbKMSRSAKey;
  4539. hr = LoadKMSRSAKeyFromCert(
  4540. pcc,
  4541. hProv,
  4542. dwKeySpec,
  4543. &pbKMSRSAKey,
  4544. &cbKMSRSAKey,
  4545. &pPublicKeyInfo);
  4546. _JumpIfError(hr, error, "LoadKMSRSAKeyFromCert");
  4547. hr = WriteProtectedValue(
  4548. pf,
  4549. pwszSection,
  4550. pwszKey,
  4551. psKey,
  4552. pbKMSRSAKey,
  4553. cbKMSRSAKey);
  4554. _JumpIfError(hr, error, "WriteProtectedValue");
  4555. error:
  4556. if (NULL != pbKMSRSAKey)
  4557. {
  4558. SecureZeroMemory(pbKMSRSAKey, cbKMSRSAKey); // Key material
  4559. LocalFree(pbKMSRSAKey);
  4560. }
  4561. if (NULL != pPublicKeyInfo)
  4562. {
  4563. LocalFree(pPublicKeyInfo);
  4564. }
  4565. return(hr);
  4566. }
  4567. HRESULT
  4568. WriteEncryptionKeysValue(
  4569. IN FILE *pf,
  4570. IN WCHAR const *pwszSection,
  4571. IN WCHAR const *pwszKey,
  4572. IN EPF_SYM_KEY_STRUCT const *psKey,
  4573. IN DWORD cccV1,
  4574. IN CERT_CONTEXT const **rgpccV1,
  4575. IN DWORD cccV3,
  4576. IN CERT_CONTEXT const **rgpccV3)
  4577. {
  4578. HRESULT hr;
  4579. DWORD i;
  4580. DWORD iKey;
  4581. ExchangeKeyBlobEx ekb;
  4582. BYTE *pbKeyData = NULL;
  4583. DWORD cbKeyData;
  4584. BYTE *pb;
  4585. OneKeyBlob okb;
  4586. CRYPT_DATA_BLOB *prgBlob = NULL;
  4587. ekb.dwSize = CBEKB;
  4588. ekb.cKeys = cccV1 + cccV3;
  4589. ekb.dwKeyAlg = CALG_RSA_KEYX;
  4590. if (0 != ekb.cKeys)
  4591. {
  4592. prgBlob = (CRYPT_DATA_BLOB *) LocalAlloc(
  4593. LMEM_FIXED | LMEM_ZEROINIT,
  4594. ekb.cKeys * sizeof(*prgBlob));
  4595. if (NULL == prgBlob)
  4596. {
  4597. hr = E_OUTOFMEMORY;
  4598. _JumpError(hr, error, "LocalAlloc");
  4599. }
  4600. iKey = 0;
  4601. for (i = 0; i < cccV1; i++)
  4602. {
  4603. hr = LoadKMSRSAKeyFromCert(
  4604. rgpccV1[i],
  4605. NULL, // hProv
  4606. AT_KEYEXCHANGE,
  4607. &prgBlob[iKey].pbData,
  4608. &prgBlob[iKey].cbData,
  4609. NULL);
  4610. _JumpIfError(hr, error, "LoadKMSRSAKeyFromCert");
  4611. iKey++;
  4612. }
  4613. for (i = 0; i < cccV3; i++)
  4614. {
  4615. hr = LoadKMSRSAKeyFromCert(
  4616. rgpccV3[i],
  4617. NULL, // hProv
  4618. AT_KEYEXCHANGE,
  4619. &prgBlob[iKey].pbData,
  4620. &prgBlob[iKey].cbData,
  4621. NULL);
  4622. _JumpIfError(hr, error, "LoadKMSRSAKeyFromCert");
  4623. iKey++;
  4624. }
  4625. cbKeyData = CBEKB + ekb.cKeys * sizeof(okb);
  4626. for (iKey = 0; iKey < ekb.cKeys; iKey++)
  4627. {
  4628. cbKeyData += prgBlob[iKey].cbData;
  4629. }
  4630. pbKeyData = (BYTE *) LocalAlloc(LMEM_FIXED, cbKeyData);
  4631. if (NULL == pbKeyData)
  4632. {
  4633. hr = E_OUTOFMEMORY;
  4634. _JumpError(hr, error, "LocalAlloc");
  4635. }
  4636. pb = pbKeyData;
  4637. CopyMemory(pb, &ekb, CBEKB);
  4638. pb += CBEKB;
  4639. ZeroMemory(&okb, sizeof(okb));
  4640. okb.dwKeySpec = dwKEYSPEC_V1ENCRYPTION_BASE;
  4641. okb.obPrivKey = CBEKB + ekb.cKeys * sizeof(okb);
  4642. for (iKey = 0; iKey < ekb.cKeys; iKey++)
  4643. {
  4644. if (iKey == cccV1)
  4645. {
  4646. okb.dwKeySpec = dwKEYSPEC_V3ENCRYPTION_BASE;
  4647. }
  4648. okb.cbPrivKey = prgBlob[iKey].cbData;
  4649. CopyMemory(pb, &okb, sizeof(okb));
  4650. CopyMemory(
  4651. &pbKeyData[okb.obPrivKey],
  4652. prgBlob[iKey].pbData,
  4653. okb.cbPrivKey);
  4654. pb += sizeof(okb);
  4655. okb.dwKeySpec++;
  4656. okb.obPrivKey += okb.cbPrivKey;
  4657. }
  4658. CSASSERT(pb == &pbKeyData[CBEKB + ekb.cKeys * sizeof(okb)]);
  4659. CSASSERT(okb.obPrivKey == cbKeyData);
  4660. hr = WriteProtectedValue(
  4661. pf,
  4662. pwszSection,
  4663. pwszKey,
  4664. psKey,
  4665. pbKeyData,
  4666. cbKeyData);
  4667. _JumpIfError(hr, error, "WriteProtectedValue");
  4668. }
  4669. hr = S_OK;
  4670. error:
  4671. if (NULL != prgBlob)
  4672. {
  4673. for (iKey = 0; iKey < ekb.cKeys; iKey++)
  4674. {
  4675. if (NULL != prgBlob[iKey].pbData)
  4676. {
  4677. SecureZeroMemory(prgBlob[iKey].pbData, prgBlob[iKey].cbData); // Key material
  4678. LocalFree(prgBlob[iKey].pbData);
  4679. }
  4680. }
  4681. LocalFree(prgBlob);
  4682. }
  4683. if (NULL != pbKeyData)
  4684. {
  4685. SecureZeroMemory(pbKeyData, cbKeyData); // Key material
  4686. LocalFree(pbKeyData);
  4687. }
  4688. return(hr);
  4689. }
  4690. #define wszDSKCCSTATUSATTRIBUTE L"kCCStatus"
  4691. WCHAR *s_apwszAttrs[] =
  4692. {
  4693. wszDSDNATTRIBUTE, // full DS DN
  4694. wszDSOBJECTCLASSATTRIBUTE, // object Class
  4695. CERTTYPE_PROP_CN, // DS CN
  4696. wszDSBASECRLATTRIBUTE, // rearranged CRL
  4697. wszDSCROSSCERTPAIRATTRIBUTE, // CTL certs?
  4698. L"teletexTerminalIdentifier", // proper CRL
  4699. wszDSKCCSTATUSATTRIBUTE, // CTL?
  4700. NULL
  4701. };
  4702. BOOL s_afString[] =
  4703. {
  4704. TRUE,
  4705. TRUE,
  4706. TRUE,
  4707. FALSE,
  4708. FALSE,
  4709. FALSE,
  4710. FALSE,
  4711. FALSE,
  4712. };
  4713. #define ISEMPTYATTR(pberval) \
  4714. (0 == (pberval)->bv_len || \
  4715. (1 == (pberval)->bv_len && 0 == *(BYTE const *) (pberval)->bv_val))
  4716. HRESULT
  4717. epfParseCTL(
  4718. IN BYTE const *pbCTL,
  4719. IN DWORD cbCTL,
  4720. IN BYTE const *pbHash,
  4721. IN DWORD cbHash,
  4722. OUT CTL_CONTEXT const **ppCTL)
  4723. {
  4724. HRESULT hr;
  4725. CTL_CONTEXT const *pCTL = NULL;
  4726. DWORD i;
  4727. *ppCTL = NULL;
  4728. if (g_fSplitASN)
  4729. {
  4730. hr = cuDumpAsnBinary(pbCTL, cbCTL, MAXDWORD);
  4731. _JumpIfError(hr, error, "cuDumpAsnBinary");
  4732. }
  4733. pCTL = CertCreateCTLContext(X509_ASN_ENCODING, pbCTL, cbCTL);
  4734. if (NULL == pCTL)
  4735. {
  4736. hr = myHLastError();
  4737. _JumpError(hr, error, "CertCreateCTLContext");
  4738. }
  4739. hr = CRYPT_E_NOT_FOUND;
  4740. for (i = 0; i < pCTL->pCtlInfo->cCTLEntry; i++)
  4741. {
  4742. CTL_ENTRY const *pCTLEntry = &pCTL->pCtlInfo->rgCTLEntry[i];
  4743. if (cbHash == pCTLEntry->SubjectIdentifier.cbData &&
  4744. 0 == memcmp(
  4745. pbHash,
  4746. pCTLEntry->SubjectIdentifier.pbData,
  4747. cbHash))
  4748. {
  4749. hr = S_OK;
  4750. *ppCTL = pCTL;
  4751. pCTL = NULL;
  4752. break;
  4753. }
  4754. }
  4755. _JumpIfError(hr, error, "memcmp");
  4756. error:
  4757. if (NULL != pCTL)
  4758. {
  4759. CertFreeCTLContext(pCTL);
  4760. }
  4761. return(hr);
  4762. }
  4763. HRESULT
  4764. epfGetOneKMSDSCTL(
  4765. IN WCHAR const *pwszDN,
  4766. IN BYTE const *pbHash,
  4767. IN DWORD cbHash,
  4768. OUT CTL_CONTEXT const **ppCTL);
  4769. HRESULT
  4770. epfGetCTLFromSearchResult(
  4771. IN LDAP *pld,
  4772. IN LDAPMessage *pSearchResult,
  4773. IN BOOL fGC,
  4774. IN BYTE const *pbHash,
  4775. IN DWORD cbHash,
  4776. OUT CTL_CONTEXT const **ppCTL)
  4777. {
  4778. HRESULT hr;
  4779. DWORD cres;
  4780. LDAPMessage *pres;
  4781. WCHAR **ppwszValues = NULL;
  4782. DWORD ires;
  4783. BOOL fIssuerFound = FALSE;
  4784. *ppCTL = NULL;
  4785. cres = ldap_count_entries(pld, pSearchResult);
  4786. if (0 == cres)
  4787. {
  4788. hr = HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT);
  4789. _JumpError(hr, error, "ldap_count_entries");
  4790. }
  4791. for (ires = 0, pres = ldap_first_entry(pld, pSearchResult);
  4792. NULL != pres;
  4793. ires++, pres = ldap_next_entry(pld, pres))
  4794. {
  4795. DWORD iAttr;
  4796. wprintf(s_wszHeader);
  4797. //wprintf(L"Result[%u]:\n", ires);
  4798. for (iAttr = 0; NULL != s_apwszAttrs[iAttr]; iAttr++)
  4799. {
  4800. DWORD iVal;
  4801. if (s_afString[iAttr])
  4802. {
  4803. WCHAR **rgpwszval = NULL;
  4804. rgpwszval = ldap_get_values(pld, pres, s_apwszAttrs[iAttr]);
  4805. if (NULL != rgpwszval)
  4806. {
  4807. //wprintf(L"%ws:\n", s_apwszAttrs[iAttr]);
  4808. for (iVal = 0; NULL != rgpwszval[iVal]; iVal++)
  4809. {
  4810. if (0 == LSTRCMPIS(
  4811. s_apwszAttrs[iAttr],
  4812. wszDSDNATTRIBUTE))
  4813. {
  4814. wprintf(L" %ws\n", rgpwszval[iVal]);
  4815. if (fGC)
  4816. {
  4817. hr = epfGetOneKMSDSCTL(
  4818. rgpwszval[iVal],
  4819. pbHash,
  4820. cbHash,
  4821. ppCTL);
  4822. _PrintIfError(hr, "epfGetOneKMSDSCTL");
  4823. }
  4824. }
  4825. }
  4826. if (NULL != rgpwszval)
  4827. {
  4828. ldap_value_free(rgpwszval);
  4829. }
  4830. //wprintf(wszNewLine);
  4831. }
  4832. else
  4833. {
  4834. //wprintf(L"%ws: EMPTY string value\n", s_apwszAttrs[iAttr]);
  4835. }
  4836. }
  4837. else
  4838. {
  4839. berval **rgpberval;
  4840. rgpberval = ldap_get_values_len(pld, pres, s_apwszAttrs[iAttr]);
  4841. if (NULL != rgpberval)
  4842. {
  4843. if (g_fVerbose)
  4844. {
  4845. wprintf(L"%ws:\n", s_apwszAttrs[iAttr]);
  4846. }
  4847. for (iVal = 0; NULL != rgpberval[iVal]; iVal++)
  4848. {
  4849. BOOL fEmpty = ISEMPTYATTR(rgpberval[iVal]);
  4850. BYTE const *pb = (BYTE const *) rgpberval[iVal]->bv_val;
  4851. DWORD cb = rgpberval[iVal]->bv_len;
  4852. #if 0
  4853. wprintf(
  4854. L" %ws[%u]: pb=%x cb=%x\n",
  4855. s_apwszAttrs[iAttr],
  4856. iVal,
  4857. pb,
  4858. cb);
  4859. #endif
  4860. if (g_fVerbose)
  4861. {
  4862. hr = cuDumpAsnBinary(pb, cb, iVal);
  4863. _PrintIfError(hr, "cuDumpAsnBinary");
  4864. }
  4865. //DumpHex(DH_NOTABPREFIX | 4, pb, cb);
  4866. if (!fIssuerFound &&
  4867. 0 == LSTRCMPIS(
  4868. s_apwszAttrs[iAttr],
  4869. wszDSKCCSTATUSATTRIBUTE))
  4870. {
  4871. //wprintf(L"epfParseCTL(%ws)\n", s_apwszAttrs[iAttr]);
  4872. //DumpHex(DH_NOTABPREFIX | 4, pb, cb);
  4873. hr = epfParseCTL(
  4874. pb,
  4875. cb,
  4876. pbHash,
  4877. cbHash,
  4878. ppCTL);
  4879. _PrintIfError(hr, "epfAddAsnBlobToStore");
  4880. fIssuerFound = S_OK == hr;
  4881. }
  4882. }
  4883. if (NULL != rgpberval)
  4884. {
  4885. ldap_value_free_len(rgpberval);
  4886. }
  4887. //wprintf(wszNewLine);
  4888. }
  4889. else
  4890. {
  4891. //wprintf(L"%ws: EMPTY binary value\n", s_apwszAttrs[iAttr]);
  4892. }
  4893. }
  4894. }
  4895. }
  4896. hr = fIssuerFound? S_OK : S_FALSE;
  4897. error:
  4898. return(hr);
  4899. }
  4900. HRESULT
  4901. epfGetOneKMSDSCTL(
  4902. IN WCHAR const *pwszDN,
  4903. IN BYTE const *pbHash,
  4904. IN DWORD cbHash,
  4905. OUT CTL_CONTEXT const **ppCTL)
  4906. {
  4907. HRESULT hr;
  4908. ULONG ldaperr;
  4909. LDAP *pld = NULL;
  4910. struct l_timeval timeout;
  4911. BSTR strConfigDN = NULL;
  4912. LDAPMessage *pSearchResult = NULL;
  4913. *ppCTL = NULL;
  4914. timeout.tv_sec = csecLDAPTIMEOUT;
  4915. timeout.tv_usec = 0;
  4916. hr = myLdapOpen(
  4917. g_pwszDC, // pwszDomainName
  4918. 0, // dwFlags
  4919. &pld,
  4920. NULL, // pstrDomainDN
  4921. &strConfigDN);
  4922. _JumpIfError(hr, error, "myLdapOpen");
  4923. wprintf(L"==> %ws\n", strConfigDN);
  4924. ldaperr = ldap_search_ext_s(
  4925. pld,
  4926. const_cast<WCHAR *>(pwszDN),
  4927. LDAP_SCOPE_BASE,
  4928. L"(objectCategory=msExchKeyManagementServer)",
  4929. s_apwszAttrs,
  4930. 0,
  4931. NULL,
  4932. NULL,
  4933. &timeout,
  4934. 10000, // size limit (number of entries)
  4935. &pSearchResult);
  4936. if (LDAP_SUCCESS != ldaperr)
  4937. {
  4938. hr = myHLdapError(pld, ldaperr, NULL);
  4939. _JumpError(hr, error, "ldap_search_ext_s");
  4940. }
  4941. hr = epfGetCTLFromSearchResult(
  4942. pld,
  4943. pSearchResult,
  4944. FALSE,
  4945. pbHash,
  4946. cbHash,
  4947. ppCTL);
  4948. _JumpIfError(hr, error, "epfGetCTLFromSearchResult");
  4949. error:
  4950. if (NULL != pSearchResult)
  4951. {
  4952. ldap_msgfree(pSearchResult);
  4953. }
  4954. myLdapClose(pld, NULL, strConfigDN);
  4955. return(hr);
  4956. }
  4957. HRESULT
  4958. epfGetV3CACTLFromHash(
  4959. IN BYTE const *pbHash,
  4960. IN DWORD cbHash,
  4961. OUT CTL_CONTEXT const **ppCTL)
  4962. {
  4963. HRESULT hr;
  4964. ULONG ldaperr;
  4965. struct l_timeval timeout;
  4966. LDAP *pldGC = NULL;
  4967. LDAPMessage *pSearchResult = NULL;
  4968. BSTR strConfigDN = NULL;
  4969. BOOL fGCFirst = FALSE;
  4970. *ppCTL = NULL;
  4971. timeout.tv_sec = csecLDAPTIMEOUT;
  4972. timeout.tv_usec = 0;
  4973. hr = myLdapOpen(
  4974. g_pwszDC, // pwszDomainName
  4975. fGCFirst? RLBF_REQUIRE_GC : 0, // dwFlags
  4976. &pldGC,
  4977. NULL, // pstrDomainDN
  4978. &strConfigDN);
  4979. _JumpIfError(hr, error, "myLdapOpen");
  4980. wprintf(L"%ws\n", strConfigDN);
  4981. ldaperr = ldap_search_ext_s(
  4982. pldGC,
  4983. strConfigDN,
  4984. LDAP_SCOPE_SUBTREE,
  4985. L"(objectCategory=msExchKeyManagementServer)",
  4986. s_apwszAttrs,
  4987. 0,
  4988. NULL,
  4989. NULL,
  4990. &timeout,
  4991. 10000, // size limit (number of entries)
  4992. &pSearchResult);
  4993. if (LDAP_SUCCESS != ldaperr)
  4994. {
  4995. hr = myHLdapError(pldGC, ldaperr, NULL);
  4996. _JumpError(hr, error, "ldap_search_ext_s");
  4997. }
  4998. hr = epfGetCTLFromSearchResult(
  4999. pldGC,
  5000. pSearchResult,
  5001. fGCFirst,
  5002. pbHash,
  5003. cbHash,
  5004. ppCTL);
  5005. _JumpIfError(hr, error, "epfGetCTLFromSearchResult");
  5006. error:
  5007. if (NULL != pSearchResult)
  5008. {
  5009. ldap_msgfree(pSearchResult);
  5010. }
  5011. myLdapClose(pldGC, NULL, strConfigDN);
  5012. return(hr);
  5013. }
  5014. HRESULT
  5015. epfGetMSCARootHash(
  5016. IN CERT_CONTEXT const *pccUser,
  5017. OUT BYTE *pbHash,
  5018. IN OUT DWORD *pcbHash)
  5019. {
  5020. HRESULT hr;
  5021. CERT_CHAIN_PARA ChainParams;
  5022. CERT_CHAIN_CONTEXT const *pChainContext = NULL;
  5023. CERT_CHAIN_ELEMENT const *pElement;
  5024. ZeroMemory(&ChainParams, sizeof(ChainParams));
  5025. ChainParams.cbSize = sizeof(ChainParams);
  5026. DBGPRINT((DBG_SS_CERTUTIL, "Calling CertGetCertificateChain...\n"));
  5027. // Get the chain and verify the cert:
  5028. if (!CertGetCertificateChain(
  5029. g_fUserRegistry? HCCE_CURRENT_USER : HCCE_LOCAL_MACHINE,
  5030. pccUser, // pCertContext
  5031. NULL, // pTime
  5032. NULL, // hAdditionalStore
  5033. &ChainParams, // pChainPara
  5034. 0, // dwFlags
  5035. NULL, // pvReserved
  5036. &pChainContext)) // ppChainContext
  5037. {
  5038. hr = myHLastError();
  5039. _JumpError(hr, error, "CertGetCertificateChain");
  5040. }
  5041. DBGPRINT((DBG_SS_CERTUTIL, "CertGetCertificateChain done\n"));
  5042. myDumpChain(
  5043. S_OK,
  5044. CA_VERIFY_FLAGS_DUMP_CHAIN |
  5045. (g_fSplitASN? CA_VERIFY_FLAGS_SAVE_CHAIN : 0),
  5046. pccUser,
  5047. NULL, // pfnCallback
  5048. NULL, // pwszMissingIssuer
  5049. pChainContext);
  5050. hr = CRYPT_E_NOT_FOUND;
  5051. if (1 > pChainContext->cChain ||
  5052. 2 > pChainContext->rgpChain[0]->cElement)
  5053. {
  5054. _JumpError(hr, error, "no chain");
  5055. }
  5056. pElement = pChainContext->rgpChain[0]->rgpElement[
  5057. pChainContext->rgpChain[0]->cElement - 1];
  5058. if (0 == (CERT_TRUST_IS_SELF_SIGNED & pElement->TrustStatus.dwInfoStatus))
  5059. {
  5060. _JumpError(hr, error, "incomplete chain");
  5061. }
  5062. if (!CertGetCertificateContextProperty(
  5063. pElement->pCertContext,
  5064. CERT_SHA1_HASH_PROP_ID,
  5065. pbHash,
  5066. pcbHash))
  5067. {
  5068. hr = myHLastError();
  5069. _JumpError(hr, error, "CertGetCertificateContextProperty");
  5070. }
  5071. hr = S_OK;
  5072. error:
  5073. if (NULL != pChainContext)
  5074. {
  5075. CertFreeCertificateChain(pChainContext);
  5076. }
  5077. return(hr);
  5078. }
  5079. HRESULT
  5080. epfGetV3CACTLFromChain(
  5081. IN CERT_CONTEXT const *pccUserV3,
  5082. OUT CTL_CONTEXT const **ppCTL)
  5083. {
  5084. HRESULT hr;
  5085. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  5086. DWORD cbHash;
  5087. *ppCTL = NULL;
  5088. cbHash = sizeof(abHash);
  5089. hr = epfGetMSCARootHash(pccUserV3, abHash, &cbHash);
  5090. if (S_OK != hr)
  5091. {
  5092. _PrintError(hr, "epfGetMSCARootHash");
  5093. if (1 >= g_fForce)
  5094. {
  5095. goto error;
  5096. }
  5097. cbHash = sizeof(abHash);
  5098. ZeroMemory(abHash, sizeof(abHash));
  5099. }
  5100. hr = epfGetV3CACTLFromHash(abHash, cbHash, ppCTL);
  5101. _JumpIfError(hr, error, "epfGetV3CACTLFromHash");
  5102. error:
  5103. return(hr);
  5104. }
  5105. HRESULT
  5106. GetCACertFromStore(
  5107. IN CERT_NAME_BLOB const *pIssuer,
  5108. OPTIONAL IN CRYPT_INTEGER_BLOB const *pSerialNumber,
  5109. OPTIONAL IN CERT_CONTEXT const *pccUserV1,
  5110. IN BOOL fV1CA,
  5111. IN WCHAR const *pwszStore,
  5112. IN BOOL fUserStore,
  5113. OUT CERT_CONTEXT const **ppccCA)
  5114. {
  5115. HRESULT hr;
  5116. HCERTSTORE hStore = NULL;
  5117. CERT_CONTEXT const *pcc = NULL;
  5118. WCHAR *pwszIssuer = NULL;
  5119. *ppccCA = NULL;
  5120. hr = myCertNameToStr(
  5121. X509_ASN_ENCODING,
  5122. pIssuer,
  5123. CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
  5124. &pwszIssuer);
  5125. _JumpIfError(hr, error, "myCertNameToStr");
  5126. DBGPRINT((
  5127. DBG_SS_CERTUTILI,
  5128. "fV1=%x, fUser=%u, %ws '%ws'\n",
  5129. fV1CA,
  5130. fUserStore,
  5131. pwszStore,
  5132. pwszIssuer));
  5133. hStore = CertOpenStore(
  5134. CERT_STORE_PROV_SYSTEM_W,
  5135. X509_ASN_ENCODING,
  5136. NULL, // hProv
  5137. CERT_STORE_OPEN_EXISTING_FLAG |
  5138. CERT_STORE_ENUM_ARCHIVED_FLAG |
  5139. CERT_STORE_READONLY_FLAG |
  5140. (fUserStore? 0 : CERT_SYSTEM_STORE_LOCAL_MACHINE),
  5141. pwszStore);
  5142. if (NULL == hStore)
  5143. {
  5144. hr = myHLastError();
  5145. _JumpErrorStr(hr, error, "CertOpenStore", pwszStore);
  5146. }
  5147. while (TRUE)
  5148. {
  5149. pcc = CertFindCertificateInStore(
  5150. hStore,
  5151. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  5152. 0, // dwFindFlags
  5153. CERT_FIND_SUBJECT_NAME,
  5154. pIssuer,
  5155. pcc);
  5156. if (NULL == pcc)
  5157. {
  5158. hr = myHLastError();
  5159. DBGPRINT((
  5160. DBG_SS_ERROR,
  5161. "fV1=%x, fUser=%u, %ws\n",
  5162. fV1CA,
  5163. fUserStore,
  5164. pwszStore));
  5165. _JumpErrorStr(hr, error, "CertFindCertificateInStore", pwszIssuer);
  5166. }
  5167. if (fV1CA ^ (CERT_V1 != pcc->pCertInfo->dwVersion))
  5168. {
  5169. // The V1 CA should have been used to sign the V1 user cert.
  5170. if (fV1CA &&
  5171. NULL != pccUserV1 &&
  5172. !CryptVerifyCertificateSignature(
  5173. NULL,
  5174. X509_ASN_ENCODING,
  5175. pccUserV1->pbCertEncoded,
  5176. pccUserV1->cbCertEncoded,
  5177. &pcc->pCertInfo->SubjectPublicKeyInfo))
  5178. {
  5179. hr = myHLastError();
  5180. _PrintError(hr, "CryptVerifyCertificateSignature");
  5181. }
  5182. // The V1 signature check fails, so ignore the error and use the
  5183. // cert anyway. The binary Issuer name match will have to suffice.
  5184. //else
  5185. {
  5186. *ppccCA = pcc;
  5187. pcc = NULL;
  5188. break;
  5189. }
  5190. }
  5191. }
  5192. hr = S_OK;
  5193. error:
  5194. if (NULL != pwszIssuer)
  5195. {
  5196. LocalFree(pwszIssuer);
  5197. }
  5198. if (NULL != pcc)
  5199. {
  5200. CertFreeCertificateContext(pcc);
  5201. }
  5202. if (NULL != hStore)
  5203. {
  5204. CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
  5205. }
  5206. return(hr);
  5207. }
  5208. typedef struct _STORELIST
  5209. {
  5210. WCHAR const *pwszStoreName;
  5211. BOOL fUserStore;
  5212. } STORELIST;
  5213. STORELIST g_aCAStoreList[] =
  5214. {
  5215. { wszCA_CERTSTORE, FALSE },
  5216. { wszCA_CERTSTORE, TRUE },
  5217. { wszROOT_CERTSTORE, FALSE },
  5218. { wszROOT_CERTSTORE, TRUE },
  5219. { wszMY_CERTSTORE, FALSE },
  5220. { wszMY_CERTSTORE, TRUE },
  5221. };
  5222. HRESULT
  5223. GetCACert(
  5224. OPTIONAL IN CERT_CONTEXT const *pccUserV1,
  5225. OPTIONAL IN CERT_CONTEXT const *pccUserV3,
  5226. IN BOOL fV1CA,
  5227. OPTIONAL IN WCHAR const *pwszCACertId,
  5228. OUT CERT_CONTEXT const **ppccCA)
  5229. {
  5230. HRESULT hr;
  5231. WCHAR *pwszSimpleName = NULL;
  5232. CTL_CONTEXT const *pCTL = NULL;
  5233. CMSG_CMS_SIGNER_INFO *pcsi = NULL;
  5234. BSTR strSerialNumber = NULL;
  5235. CERT_NAME_BLOB const *pIssuer = NULL;
  5236. CRYPT_INTEGER_BLOB const *pSerialNumber = NULL;
  5237. *ppccCA = NULL;
  5238. hr = CRYPT_E_NOT_FOUND;
  5239. if (NULL == pwszCACertId && NULL != pccUserV3)
  5240. {
  5241. hr = epfGetV3CACTLFromChain(pccUserV3, &pCTL);
  5242. _PrintIfError(hr, "epfGetV3CACTLFromChain");
  5243. if (S_OK == hr && NULL != pCTL)
  5244. {
  5245. DWORD cb;
  5246. hr = myCryptMsgGetParam(
  5247. pCTL->hCryptMsg,
  5248. CMSG_CMS_SIGNER_INFO_PARAM,
  5249. 0,
  5250. CERTLIB_USE_LOCALALLOC,
  5251. (VOID **) &pcsi,
  5252. &cb);
  5253. _JumpIfError(hr, error, "myCryptMsgGetParam");
  5254. if (CERT_ID_ISSUER_SERIAL_NUMBER == pcsi->SignerId.dwIdChoice)
  5255. {
  5256. hr = MultiByteIntegerToBstr(
  5257. FALSE,
  5258. pcsi->SignerId.IssuerSerialNumber.SerialNumber.cbData,
  5259. pcsi->SignerId.IssuerSerialNumber.SerialNumber.pbData,
  5260. &strSerialNumber);
  5261. _JumpIfError(hr, error, "MultiByteIntegerToBstr");
  5262. pwszCACertId = strSerialNumber;
  5263. pSerialNumber = &pcsi->SignerId.IssuerSerialNumber.SerialNumber;
  5264. pIssuer = &pcsi->SignerId.IssuerSerialNumber.Issuer;
  5265. }
  5266. }
  5267. }
  5268. if (NULL != pccUserV1 || NULL != pIssuer)
  5269. {
  5270. DWORD i;
  5271. if (NULL == pIssuer)
  5272. {
  5273. pIssuer = &pccUserV1->pCertInfo->Issuer;
  5274. }
  5275. for (i = 0; i < ARRAYSIZE(g_aCAStoreList); i++)
  5276. {
  5277. hr = GetCACertFromStore(
  5278. pIssuer,
  5279. pSerialNumber,
  5280. pccUserV1,
  5281. fV1CA,
  5282. g_aCAStoreList[i].pwszStoreName,
  5283. g_aCAStoreList[i].fUserStore,
  5284. ppccCA);
  5285. if (S_OK == hr)
  5286. {
  5287. break;
  5288. }
  5289. _PrintErrorStr(
  5290. hr,
  5291. fV1CA? "GetCACertFromStore:V1" : "GetCACertFromStore:V3",
  5292. g_aCAStoreList[i].pwszStoreName);
  5293. }
  5294. }
  5295. if (NULL == *ppccCA)
  5296. {
  5297. hr = myGetCertificateFromPicker(
  5298. g_hInstance,
  5299. NULL, // hwndParent
  5300. fV1CA?
  5301. IDS_GETKMSV1CACERT_TITLE :
  5302. IDS_GETKMSCACERT_TITLE,
  5303. fV1CA?
  5304. IDS_GETKMSV1CACERT_SUBTITLE :
  5305. IDS_GETKMSCACERT_SUBTITLE,
  5306. // dwFlags: HKLM+HKCU My store
  5307. CUCS_MYSTORE |
  5308. CUCS_CASTORE |
  5309. CUCS_ROOTSTORE |
  5310. CUCS_MACHINESTORE |
  5311. CUCS_USERSTORE |
  5312. (g_fCryptSilent? CUCS_SILENT : 0) |
  5313. (fV1CA? CUCS_V1ONLY : CUCS_V3ONLY),
  5314. NULL != pwszCACertId? pwszCACertId : g_wszCACertCN,
  5315. 0, // cStore
  5316. NULL, // rghStore
  5317. 0, // cpszObjId
  5318. NULL, // apszObjId
  5319. ppccCA);
  5320. _JumpIfError(hr, error, "myGetCertificateFromPicker");
  5321. }
  5322. if (NULL != *ppccCA)
  5323. {
  5324. hr = myCertGetNameString(
  5325. *ppccCA,
  5326. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  5327. &pwszSimpleName);
  5328. if (S_OK != hr || 0 != lstrcmp(g_wszCACertCN, pwszSimpleName))
  5329. {
  5330. _PrintIfError(hr, "myCertGetNameString");
  5331. CertFreeCertificateContext(*ppccCA);
  5332. *ppccCA = NULL;
  5333. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5334. _JumpErrorStr(
  5335. hr,
  5336. error,
  5337. "bad CA CommonName",
  5338. pwszSimpleName);
  5339. }
  5340. if (NULL != pCTL)
  5341. {
  5342. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA cvse;
  5343. ZeroMemory(&cvse, sizeof(cvse));
  5344. cvse.cbSize = sizeof(cvse);
  5345. cvse.dwSignerType = CMSG_VERIFY_SIGNER_PUBKEY;
  5346. cvse.pvSigner = &(*ppccCA)->pCertInfo->SubjectPublicKeyInfo;
  5347. if (!CryptMsgControl(
  5348. pCTL->hCryptMsg,
  5349. 0, // dwFlags
  5350. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  5351. &cvse))
  5352. {
  5353. hr = myHLastError();
  5354. _JumpError(hr, error, "CryptMsgControl(VerifySig)");
  5355. }
  5356. }
  5357. hr = S_OK;
  5358. }
  5359. error:
  5360. // myGetCertificateFromPicker cancel returns S_OK & NULL
  5361. if (S_OK != hr || NULL == *ppccCA)
  5362. {
  5363. wprintf(
  5364. L"%ws\n",
  5365. myLoadResourceString(IDS_CANNOT_FIND_EPF_CA_CERT));
  5366. }
  5367. if (NULL != pCTL)
  5368. {
  5369. CertFreeCTLContext(pCTL);
  5370. }
  5371. if (NULL != pcsi)
  5372. {
  5373. LocalFree(pcsi);
  5374. }
  5375. if (NULL != strSerialNumber)
  5376. {
  5377. SysFreeString(strSerialNumber);
  5378. }
  5379. if (NULL != pwszSimpleName)
  5380. {
  5381. LocalFree(pwszSimpleName);
  5382. }
  5383. return(hr);
  5384. }
  5385. // [Password Token]
  5386. // Protection=128
  5387. // Profile Version=3
  5388. // Token=4BA715FC963A9B50
  5389. // SaltValue=J0+bHju332R+5Ia4dP52HvLav04=
  5390. // HashSize=0
  5391. //
  5392. // [User X.500 Name]
  5393. // X500Name=o=pki-kms-test, ou=dcross, cn=recipients, cn=user1
  5394. //
  5395. // [S/MIME]
  5396. // @Signing Certificate=FQLn5nUsYfhZZnmb5Zid8NIzJeXpKatACMsiXHsLzx...
  5397. // _continue_=...
  5398. // ...
  5399. // @Signing Key=ot7snTvKNUM2BSFwKXxyrLnDK5qmAcnpreL9MD84wXY4pW2...
  5400. // _continue_=...
  5401. // ...
  5402. // @Private Keys=E6oly3MbeMk6VCJuZ6UgUhX3npQCUFBmbEvw9L+...
  5403. // _continue_=...
  5404. // ...
  5405. // KeyCount=1
  5406. // @Issuing Certificates=bWQQmVuPjFkWSL...
  5407. // @Trust List Certificate=25irS5M5LL...
  5408. // _continue_=...
  5409. // ...
  5410. //
  5411. // [Full Certificate History]
  5412. // @SMIME_1=y3OPoks2yR6EAag5IiBsx+MzWeF3a3xy9Zj...
  5413. // _continue_=...
  5414. // @SMIME_2=NB5HNJNXp4IVu5cvNyZFS+MzWeF3a3xy9Zj...
  5415. // _continue_=...
  5416. // ...
  5417. //
  5418. // EPF file cert and key contents:
  5419. // [S/MIME] @Signing Certificate: Single signing cert.
  5420. // [S/MIME] @Signing Key: Single signing key.
  5421. //
  5422. // [S/MIME] KeyCount: count of encryption certs and keys
  5423. // [S/MIME] @Private Keys: encryption keys
  5424. // [Full Certificate History] SMIME_1: encryption cert
  5425. // [Full Certificate History] SMIME_2: encryption cert
  5426. //
  5427. // [S/MIME] @Trust List Certificate: Single root cert; not issuing CA cert!
  5428. //
  5429. // [S/MIME] @Issuing Certificates: serialized CAPI cert store
  5430. // 0000 00 00 00 00 43 45 52 54 00 00 00 00 00 00 00 00 ....CERT........
  5431. // 0010 00 00 00 00 ....
  5432. //
  5433. HRESULT
  5434. EPFSaveCertStoreToFile(
  5435. IN HCERTSTORE hStore,
  5436. IN WCHAR const *pwszPassword,
  5437. IN WCHAR const *pwszfnOut,
  5438. OPTIONAL IN WCHAR const *pwszV3CACertId,
  5439. IN DWORD dwEPFAlg,
  5440. OPTIONAL IN WCHAR const *pwszSalt)
  5441. {
  5442. HRESULT hr;
  5443. FILE *pf = NULL;
  5444. char *pszfnOut = NULL;
  5445. WCHAR *pwszSaltValue = NULL;
  5446. char *pszDN = NULL;
  5447. char *pszDNT = NULL;
  5448. WCHAR *pwszCN = NULL;
  5449. WCHAR *pwszCNT = NULL;
  5450. DWORD i;
  5451. DWORD iCertHistory;
  5452. CERT_CONTEXT const **appcc[ICC_MAX];
  5453. DWORD accc[ICC_MAX];
  5454. HCRYPTPROV hProvV1Signing = NULL;
  5455. DWORD ccert;
  5456. HCERTSTORE hStoreMem = NULL;
  5457. CRYPT_DATA_BLOB BlobStore;
  5458. HCRYPTPROV hProv = NULL;
  5459. EPF_SYM_KEY_STRUCT sKey;
  5460. BYTE abSaltValue[CBMAX_CRYPT_HASH_LEN];
  5461. BYTE abToken[CBTOKEN];
  5462. BYTE *pbSalt = NULL;
  5463. DWORD cbSalt;
  5464. CERT_CONTEXT const *pccCAV1 = NULL;
  5465. CERT_CONTEXT const *pccCAV3 = NULL;
  5466. WCHAR wszSMIME[cwcINFKEY_SMIME_FORMATTED];
  5467. CERT_CONTEXT const *pccUserV1;
  5468. CERT_CONTEXT const *pccUserV3;
  5469. CERT_CONTEXT const *pccT;
  5470. BOOL fQuietOld = g_fQuiet;
  5471. ZeroMemory(&sKey, sizeof(sKey));
  5472. ZeroMemory(appcc, sizeof(appcc));
  5473. ZeroMemory(accc, sizeof(accc));
  5474. BlobStore.pbData = NULL;
  5475. ccert = 0;
  5476. for (i = 0; i < ARRAYSIZE(appcc); i++)
  5477. {
  5478. hr = GetCertListFromStore(hStore, i, &appcc[i], &accc[i]);
  5479. _PrintIfError2(hr, "GetCertListFromStore", CRYPT_E_NOT_FOUND);
  5480. ccert += accc[i];
  5481. if (0 != accc[i])
  5482. {
  5483. wprintf(
  5484. L"V%u %ws %ws: %u\n",
  5485. (ICC_V1SIGNING == i || ICC_V1ENCRYPTION == i)? 1 : 3,
  5486. (ICC_V1SIGNING == i || ICC_V3SIGNING == i)?
  5487. epfLoadResource(IDS_SIGNING, wszSIGNING) :
  5488. epfLoadResource(IDS_EXCHANGE, wszEXCHANGE),
  5489. myLoadResourceString(IDS_CERTS), // "certs"
  5490. accc[i]);
  5491. }
  5492. }
  5493. if (0 == ccert)
  5494. {
  5495. hr = CRYPT_E_NOT_FOUND;
  5496. _JumpError(hr, error, "no certs");
  5497. }
  5498. for (i = 0; i < ARRAYSIZE(appcc); i++)
  5499. {
  5500. if (0 != accc[i])
  5501. {
  5502. DWORD j;
  5503. for (j = 0; j < accc[i]; j++)
  5504. {
  5505. int r;
  5506. if (NULL != pszDNT)
  5507. {
  5508. LocalFree(pszDNT);
  5509. pszDNT = NULL;
  5510. }
  5511. if (NULL != pwszCNT)
  5512. {
  5513. LocalFree(pwszCNT);
  5514. pwszCNT = NULL;
  5515. }
  5516. hr = GetLowerCaseDNAndCN(appcc[i][j], &pszDNT, &pwszCNT);
  5517. _JumpIfError(hr, error, "GetLowerCaseDNAndCN");
  5518. if (g_fVerbose)
  5519. {
  5520. wprintf(L"DN[%u][%u] = %hs\n", i, j, pszDNT);
  5521. wprintf(L"CN[%u][%u] = %ws\n", i, j, pwszCNT);
  5522. }
  5523. if (NULL == pszDN)
  5524. {
  5525. pszDN = pszDNT;
  5526. pszDNT = NULL;
  5527. }
  5528. if (NULL == pwszCN)
  5529. {
  5530. pwszCN = pwszCNT;
  5531. pwszCNT = NULL;
  5532. continue;
  5533. }
  5534. r = lstrcmp(pwszCN, pwszCNT);
  5535. if (0 != r)
  5536. {
  5537. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  5538. _PrintErrorStr(hr, "bad subject CN", pwszCNT);
  5539. _JumpErrorStr(hr, error, "expected subject CN", pwszCN);
  5540. }
  5541. }
  5542. }
  5543. }
  5544. if (!myConvertWszToSz(&pszfnOut, pwszfnOut, -1))
  5545. {
  5546. hr = E_OUTOFMEMORY;
  5547. _JumpError(hr, error, "myConvertWszToSz");
  5548. }
  5549. if (!CryptAcquireContext(
  5550. &hProv,
  5551. NULL, // container name
  5552. MS_STRONG_PROV,
  5553. PROV_RSA_FULL,
  5554. CRYPT_VERIFYCONTEXT))
  5555. {
  5556. hr = myHLastError();
  5557. _JumpError(hr, error, "CryptAcquireContext");
  5558. }
  5559. if (NULL != pwszSalt)
  5560. {
  5561. hr = myCryptStringToBinary(
  5562. pwszSalt,
  5563. 0,
  5564. CRYPT_STRING_BASE64,
  5565. &pbSalt,
  5566. &cbSalt,
  5567. NULL,
  5568. NULL);
  5569. _JumpIfError(hr, error, "myCryptStringToBinary");
  5570. if (sizeof(abSaltValue) != cbSalt)
  5571. {
  5572. hr = E_INVALIDARG;
  5573. _JumpError(hr, error, "cbSalt");
  5574. }
  5575. }
  5576. else
  5577. {
  5578. if (!CryptGenRandom(hProv, sizeof(abSaltValue), abSaltValue))
  5579. {
  5580. hr = myHLastError();
  5581. _JumpError(hr, error, "CryptGenRandom");
  5582. }
  5583. hr = EPFCryptBinaryToBase64(
  5584. abSaltValue,
  5585. sizeof(abSaltValue),
  5586. &pwszSaltValue);
  5587. _JumpIfError(hr, error, "EPFCryptBinaryToBase64");
  5588. pwszSalt = pwszSaltValue;
  5589. }
  5590. pccUserV1 = NULL;
  5591. if (0 != accc[ICC_V1SIGNING])
  5592. {
  5593. pccUserV1 = appcc[ICC_V1SIGNING][accc[ICC_V1SIGNING] - 1];
  5594. }
  5595. else if (0 != accc[ICC_V1ENCRYPTION])
  5596. {
  5597. pccUserV1 = appcc[ICC_V1ENCRYPTION][accc[ICC_V1ENCRYPTION] - 1];
  5598. }
  5599. if (NULL != pccUserV1 && EPFALG_DEFAULT == dwEPFAlg)
  5600. {
  5601. dwEPFAlg = EPFALG_CAST;
  5602. }
  5603. hr = EPFDeriveKey(
  5604. EPFALG_DEFAULT == dwEPFAlg? EPFALG_RC2_SHA : EPFALG_CAST_MD5,
  5605. EPFALG_DEFAULT == dwEPFAlg? 128 : 64,
  5606. hProv,
  5607. pwszPassword,
  5608. pwszSalt,
  5609. pbSalt,
  5610. cbSalt,
  5611. 0, // cbHashSize
  5612. &sKey);
  5613. _JumpIfError(hr, error, "EPFDeriveKey");
  5614. hr = EPFGenerateKeyToken(&sKey, abToken, sizeof(abToken));
  5615. _JumpIfError(hr, error, "EPFGenerateKeyToken");
  5616. if (!g_fForce)
  5617. {
  5618. pf = fopen(pszfnOut, "r");
  5619. if (NULL != pf)
  5620. {
  5621. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  5622. _JumpError(hr, error, "fopen");
  5623. }
  5624. }
  5625. pf = fopen(pszfnOut, "w");
  5626. if (NULL == pf)
  5627. {
  5628. hr = CO_E_FAILEDTOCREATEFILE;
  5629. _JumpError(hr, error, "fopen");
  5630. }
  5631. fprintf(pf, "[" szINFSECTION_PASSWORDTOKEN "]\n");
  5632. fprintf(pf, szINFKEY_PROTECTION "=%u\n", EPFALG_DEFAULT == dwEPFAlg? 128 : 64);
  5633. fprintf(pf, szINFKEY_PROFILEVERSION "=%u\n", EPFALG_DEFAULT == dwEPFAlg? 3 : 2);
  5634. if (EPFALG_DEFAULT != dwEPFAlg)
  5635. {
  5636. fprintf(pf, szINFKEY_CAST "=3\n");
  5637. }
  5638. fprintf(pf, szINFKEY_TOKEN "=");
  5639. for (i = 0; i < sizeof(abToken); i++)
  5640. {
  5641. fprintf(pf, "%02X", abToken[i]);
  5642. }
  5643. fprintf(pf, "\n");
  5644. fprintf(pf, szINFKEY_SALTVALUE "=%ws\n", pwszSalt);
  5645. fprintf(pf, szINFKEY_HASHSIZE "=0\n");
  5646. fprintf(pf, "\n[" szINFSECTION_USERX500NAME "]\n");
  5647. fprintf(pf, szINFKEY_X500NAME "=%hs\n", pszDN);
  5648. InitCrcTable();
  5649. if (!g_fVerbose)
  5650. {
  5651. g_fQuiet = TRUE;
  5652. }
  5653. if (EPFALG_DEFAULT != dwEPFAlg)
  5654. {
  5655. if (0 == accc[ICC_V1SIGNING] && NULL != pccUserV1)
  5656. {
  5657. appcc[ICC_V1SIGNING] = (CERT_CONTEXT const **) LocalAlloc(
  5658. LMEM_FIXED | LMEM_ZEROINIT,
  5659. sizeof(appcc[ICC_V1SIGNING][0]));
  5660. if (NULL == appcc[ICC_V1SIGNING])
  5661. {
  5662. hr = E_OUTOFMEMORY;
  5663. _JumpError(hr, error, "LocalAlloc");
  5664. }
  5665. hr = epfBuildV1Certs(
  5666. pccUserV1,
  5667. &appcc[ICC_V1SIGNING][0],
  5668. &hProvV1Signing,
  5669. &pccCAV1);
  5670. _JumpIfError(hr, error, "epfBuildV1Certs");
  5671. accc[ICC_V1SIGNING] = 1;
  5672. }
  5673. if (0 != accc[ICC_V1SIGNING])
  5674. {
  5675. pccT = appcc[ICC_V1SIGNING][accc[ICC_V1SIGNING] - 1];
  5676. fprintf(pf, "\n[" szINFSECTION_DIGITALSIGNATURE "]\n");
  5677. hr = WriteProtectedValue(
  5678. pf,
  5679. wszINFSECTION_DIGITALSIGNATURE,
  5680. wszINFKEY_CERTIFICATE,
  5681. &sKey,
  5682. pccT->pbCertEncoded,
  5683. pccT->cbCertEncoded);
  5684. _JumpIfError(hr, error, "WriteProtectedValue");
  5685. hr = cuDumpAsnBinary(pccT->pbCertEncoded, pccT->cbCertEncoded, MAXDWORD);
  5686. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5687. // szINFKEY_KEY
  5688. hr = WriteSingleKMSRSAKeyValue(
  5689. pf,
  5690. wszINFSECTION_DIGITALSIGNATURE,
  5691. wszINFKEY_KEY,
  5692. &sKey,
  5693. pccT,
  5694. hProvV1Signing,
  5695. CALG_RSA_SIGN,
  5696. AT_SIGNATURE,
  5697. dwKEYSPEC_V1SIGNATURE);
  5698. _JumpIfError(hr, error, "WriteSingleKMSRSAKeyValue");
  5699. }
  5700. if (NULL == pccCAV1)
  5701. {
  5702. hr = GetCACert(pccUserV1, NULL, TRUE, NULL, &pccCAV1);
  5703. _JumpIfError(hr, error, "GetCACert");
  5704. }
  5705. if (0 != accc[ICC_V1ENCRYPTION])
  5706. {
  5707. WCHAR wszName[cwcINFKEY_NAME_FORMATTED];
  5708. fprintf(pf, "\n[" szINFSECTION_PRIVATEKEYS "]\n");
  5709. for (i = 0; i < accc[ICC_V1ENCRYPTION]; i++)
  5710. {
  5711. WCHAR wszKey[cwcINFKEY_KEY_FORMATTED];
  5712. pccT = appcc[ICC_V1ENCRYPTION][i];
  5713. wsprintf(wszKey, wszINFKEY_KEY_FORMAT, i + 1);
  5714. hr = WriteSingleKMSRSAKeyValue(
  5715. pf,
  5716. wszINFSECTION_PRIVATEKEYS,
  5717. wszKey,
  5718. &sKey,
  5719. pccT,
  5720. NULL, // hProv
  5721. CALG_RSA_KEYX,
  5722. AT_KEYEXCHANGE,
  5723. dwKEYSPEC_V1ENCRYPTION_BASE + i);
  5724. _JumpIfError(hr, error, "WriteSingleKMSRSAKeyValue");
  5725. }
  5726. fprintf(pf, szINFKEY_KEYCOUNT "=%u\n", accc[ICC_V1ENCRYPTION]);
  5727. fprintf(pf, "\n[" szINFSECTION_CERTIFICATEHISTORY "]\n");
  5728. for (i = 0; i < accc[ICC_V1ENCRYPTION]; i++)
  5729. {
  5730. pccT = appcc[ICC_V1ENCRYPTION][i];
  5731. wsprintf(wszName, wszINFKEY_NAME_FORMAT, i + 1);
  5732. hr = WriteIssuerNameAndSerialValue(pf, wszName, pccCAV1, pccT);
  5733. _JumpIfError(hr, error, "WriteIssuerNameAndSerialValue");
  5734. }
  5735. fprintf(pf, "\n[" szINFSECTION_FULLCERTIFICATEHISTORY "]\n");
  5736. // szINFKEY_NAME_FORMAT: Name%u -- V1 Encryption certs
  5737. for (i = 0; i < accc[ICC_V1ENCRYPTION]; i++)
  5738. {
  5739. pccT = appcc[ICC_V1ENCRYPTION][i];
  5740. wsprintf(wszName, wszINFKEY_NAME_FORMAT, i + 1);
  5741. hr = WriteProtectedValue(
  5742. pf,
  5743. wszINFSECTION_FULLCERTIFICATEHISTORY,
  5744. wszName,
  5745. &sKey,
  5746. pccT->pbCertEncoded,
  5747. pccT->cbCertEncoded);
  5748. _JumpIfError(hr, error, "WriteProtectedValue");
  5749. hr = cuDumpAsnBinary(pccT->pbCertEncoded, pccT->cbCertEncoded, MAXDWORD);
  5750. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5751. }
  5752. // szINFKEY_SMIME_FORMAT: SMIME_%u -- V3 Encryption certs
  5753. for (i = 0; i < accc[ICC_V3ENCRYPTION]; i++)
  5754. {
  5755. pccT = appcc[ICC_V3ENCRYPTION][i];
  5756. wsprintf(wszSMIME, wszINFKEY_SMIME_FORMAT, i + 1);
  5757. hr = WriteProtectedValue(
  5758. pf,
  5759. wszINFSECTION_FULLCERTIFICATEHISTORY,
  5760. wszSMIME,
  5761. &sKey,
  5762. pccT->pbCertEncoded,
  5763. pccT->cbCertEncoded);
  5764. _JumpIfError(hr, error, "WriteProtectedValue");
  5765. hr = cuDumpAsnBinary(pccT->pbCertEncoded, pccT->cbCertEncoded, MAXDWORD);
  5766. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5767. }
  5768. fprintf(pf, "\n[" szINFSECTION_USERCERTIFICATE "]\n");
  5769. pccT = appcc[ICC_V1ENCRYPTION][accc[ICC_V1ENCRYPTION] - 1];
  5770. hr = WriteProtectedValue(
  5771. pf,
  5772. wszINFSECTION_USERCERTIFICATE,
  5773. wszINFKEY_CERTIFICATE,
  5774. &sKey,
  5775. pccT->pbCertEncoded,
  5776. pccT->cbCertEncoded);
  5777. _JumpIfError(hr, error, "WriteProtectedValue");
  5778. hr = cuDumpAsnBinary(pccT->pbCertEncoded, pccT->cbCertEncoded, MAXDWORD);
  5779. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5780. }
  5781. fprintf(pf, "\n[" szINFSECTION_CA "]\n");
  5782. hr = WriteProtectedValue(
  5783. pf,
  5784. wszINFSECTION_CA,
  5785. wszINFKEY_CERTIFICATE,
  5786. &sKey,
  5787. NULL != pccCAV1? pccCAV1->pbCertEncoded : NULL,
  5788. NULL != pccCAV1? pccCAV1->cbCertEncoded : 0);
  5789. _JumpIfError(hr, error, "WriteProtectedValue");
  5790. hr = cuDumpAsnBinary(pccT->pbCertEncoded, pccT->cbCertEncoded, MAXDWORD);
  5791. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5792. fprintf(pf, "\n[" szINFSECTION_MICROSOFTEXCHANGE "]\n");
  5793. hr = WriteProtectedStringValue(
  5794. pf,
  5795. wszINFSECTION_MICROSOFTEXCHANGE,
  5796. wszINFKEY_FRIENDLYNAME,
  5797. &sKey,
  5798. L"SzNull");
  5799. _JumpIfError(hr, error, "WriteProtectedStringValue");
  5800. hr = WriteProtectedDwordValue(
  5801. pf,
  5802. wszINFSECTION_MICROSOFTEXCHANGE,
  5803. wszINFKEY_KEYALGID,
  5804. &sKey,
  5805. EPFALG_CASTEXPORT == dwEPFAlg?
  5806. EPFALG_EXPORT :
  5807. EPFALG_DOMESTIC);
  5808. _JumpIfError(hr, error, "WriteProtectedDwordValue");
  5809. }
  5810. if (0 != accc[ICC_V3SIGNING] || 0 != accc[ICC_V3ENCRYPTION])
  5811. {
  5812. fprintf(pf, "\n[" szINFSECTION_SMIME "]\n");
  5813. // szINFKEY_SIGNINGCERTIFICATE
  5814. if (0 != accc[ICC_V3SIGNING])
  5815. {
  5816. pccT = appcc[ICC_V3SIGNING][accc[ICC_V3SIGNING] - 1];
  5817. hr = WriteProtectedValue(
  5818. pf,
  5819. wszINFSECTION_SMIME,
  5820. wszINFKEY_SIGNINGCERTIFICATE,
  5821. &sKey,
  5822. pccT->pbCertEncoded,
  5823. pccT->cbCertEncoded);
  5824. _JumpIfError(hr, error, "WriteProtectedValue");
  5825. hr = cuDumpAsnBinary(pccT->pbCertEncoded, pccT->cbCertEncoded, MAXDWORD);
  5826. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5827. // szINFKEY_SIGNINGKEY
  5828. hr = WriteSingleEPFKeyValue(
  5829. pf,
  5830. wszINFSECTION_SMIME,
  5831. wszINFKEY_SIGNINGKEY,
  5832. &sKey,
  5833. pccT,
  5834. CALG_RSA_SIGN,
  5835. AT_SIGNATURE,
  5836. dwKEYSPEC_V3SIGNATURE);
  5837. _JumpIfError(hr, error, "WriteSingleEPFKeyValue");
  5838. }
  5839. // szINFKEY_PRIVATEKEYS
  5840. if (0 != accc[ICC_V3ENCRYPTION])
  5841. {
  5842. hr = WriteEncryptionKeysValue(
  5843. pf,
  5844. wszINFSECTION_SMIME,
  5845. wszINFKEY_PRIVATEKEYS,
  5846. &sKey,
  5847. 0, // V3 keys only? accc[ICC_V1ENCRYPTION],
  5848. appcc[ICC_V1ENCRYPTION],
  5849. accc[ICC_V3ENCRYPTION],
  5850. appcc[ICC_V3ENCRYPTION]);
  5851. _JumpIfError(hr, error, "WriteEncryptionKeys");
  5852. }
  5853. fprintf(pf, szINFKEY_KEYCOUNT "=%u\n", accc[ICC_V3ENCRYPTION]);
  5854. // szINFKEY_ISSUINGCERTIFICATES -- empty serialized cert store
  5855. hStoreMem = CertOpenStore(
  5856. CERT_STORE_PROV_MEMORY,
  5857. X509_ASN_ENCODING,
  5858. NULL,
  5859. CERT_STORE_NO_CRYPT_RELEASE_FLAG |
  5860. CERT_STORE_ENUM_ARCHIVED_FLAG,
  5861. NULL);
  5862. if (NULL == hStoreMem)
  5863. {
  5864. hr = myHLastError();
  5865. _JumpError(hr, error, "CertOpenStore");
  5866. }
  5867. while (TRUE)
  5868. {
  5869. if (!CertSaveStore(
  5870. hStoreMem,
  5871. X509_ASN_ENCODING,
  5872. CERT_STORE_SAVE_AS_STORE,
  5873. CERT_STORE_SAVE_TO_MEMORY,
  5874. &BlobStore,
  5875. 0))
  5876. {
  5877. hr = myHLastError();
  5878. _JumpError(hr, error, "CertSaveStore");
  5879. }
  5880. if (NULL != BlobStore.pbData)
  5881. {
  5882. break;
  5883. }
  5884. BlobStore.pbData = (BYTE *) LocalAlloc(LMEM_FIXED, BlobStore.cbData);
  5885. if (NULL == BlobStore.pbData)
  5886. {
  5887. hr = E_OUTOFMEMORY;
  5888. _JumpError(hr, error, "LocalAlloc");
  5889. }
  5890. }
  5891. hr = WriteProtectedValue(
  5892. pf,
  5893. wszINFSECTION_SMIME,
  5894. wszINFKEY_ISSUINGCERTIFICATES,
  5895. &sKey,
  5896. BlobStore.pbData,
  5897. BlobStore.cbData);
  5898. _JumpIfError(hr, error, "WriteProtectedValue");
  5899. // szINFKEY_TRUSTLISTCERTIFICATE -- root cert
  5900. pccUserV3 = NULL;
  5901. if (0 != accc[ICC_V3SIGNING])
  5902. {
  5903. pccUserV3 = appcc[ICC_V3SIGNING][accc[ICC_V3SIGNING] - 1];
  5904. }
  5905. else if (0 != accc[ICC_V3ENCRYPTION])
  5906. {
  5907. pccUserV3 = appcc[ICC_V3ENCRYPTION][accc[ICC_V3ENCRYPTION] - 1];
  5908. }
  5909. hr = GetCACert(pccUserV1, pccUserV3, FALSE, pwszV3CACertId, &pccCAV3);
  5910. _JumpIfError(hr, error, "GetCACert");
  5911. hr = WriteProtectedValue(
  5912. pf,
  5913. wszINFSECTION_SMIME,
  5914. wszINFKEY_TRUSTLISTCERTIFICATE,
  5915. &sKey,
  5916. NULL != pccCAV3? pccCAV3->pbCertEncoded : NULL,
  5917. NULL != pccCAV3? pccCAV3->cbCertEncoded : 0);
  5918. _JumpIfError(hr, error, "WriteProtectedValue");
  5919. }
  5920. if (EPFALG_DEFAULT == dwEPFAlg)
  5921. {
  5922. fprintf(pf, "\n[" szINFSECTION_FULLCERTIFICATEHISTORY "]\n");
  5923. // szINFKEY_SMIME_FORMAT: SMIME_%u -- V3 Encryption certs
  5924. for (i = 0; i < accc[ICC_V3ENCRYPTION]; i++)
  5925. {
  5926. pccT = appcc[ICC_V3ENCRYPTION][i];
  5927. wsprintf(wszSMIME, wszINFKEY_SMIME_FORMAT, i + 1);
  5928. hr = WriteProtectedValue(
  5929. pf,
  5930. wszINFSECTION_FULLCERTIFICATEHISTORY,
  5931. wszSMIME,
  5932. &sKey,
  5933. pccT->pbCertEncoded,
  5934. pccT->cbCertEncoded);
  5935. _JumpIfError(hr, error, "WriteProtectedValue");
  5936. hr = cuDumpAsnBinary(
  5937. pccT->pbCertEncoded,
  5938. pccT->cbCertEncoded,
  5939. MAXDWORD);
  5940. _JumpIfError(hr, error, "cuDumpAsnBinary");
  5941. }
  5942. }
  5943. fprintf(pf, "\n");
  5944. fflush(pf);
  5945. if (ferror(pf))
  5946. {
  5947. hr = HRESULT_FROM_WIN32(ERROR_DISK_FULL);
  5948. _JumpError(hr, error, "write error");
  5949. }
  5950. hr = S_OK;
  5951. error:
  5952. if (NULL != hStoreMem)
  5953. {
  5954. CertCloseStore(hStoreMem, CERT_CLOSE_STORE_CHECK_FLAG);
  5955. }
  5956. for (i = 0; i < ARRAYSIZE(appcc); i++)
  5957. {
  5958. FreeCertList(appcc[i], accc[i]);
  5959. }
  5960. if (NULL != pccCAV1)
  5961. {
  5962. CertFreeCertificateContext(pccCAV1);
  5963. }
  5964. if (NULL != pccCAV3)
  5965. {
  5966. CertFreeCertificateContext(pccCAV3);
  5967. }
  5968. if (NULL != pf)
  5969. {
  5970. fclose(pf);
  5971. }
  5972. if (NULL != pszDNT)
  5973. {
  5974. LocalFree(pszDNT);
  5975. }
  5976. if (NULL != pszDN)
  5977. {
  5978. LocalFree(pszDN);
  5979. }
  5980. if (NULL != pwszCNT)
  5981. {
  5982. LocalFree(pwszCNT);
  5983. }
  5984. if (NULL != pwszCN)
  5985. {
  5986. LocalFree(pwszCN);
  5987. }
  5988. if (NULL != pbSalt)
  5989. {
  5990. LocalFree(pbSalt);
  5991. }
  5992. if (NULL != pwszSaltValue)
  5993. {
  5994. LocalFree(pwszSaltValue);
  5995. }
  5996. if (NULL != pszfnOut)
  5997. {
  5998. LocalFree(pszfnOut);
  5999. }
  6000. if (NULL != BlobStore.pbData)
  6001. {
  6002. LocalFree(BlobStore.pbData);
  6003. }
  6004. if (NULL != sKey.hKey)
  6005. {
  6006. CryptDestroyKey(sKey.hKey);
  6007. }
  6008. if (NULL != hProvV1Signing)
  6009. {
  6010. CryptReleaseContext(hProvV1Signing, 0);
  6011. }
  6012. if (NULL != hProv)
  6013. {
  6014. CryptReleaseContext(hProv, 0);
  6015. }
  6016. g_fQuiet = fQuietOld;
  6017. return(hr);
  6018. }