Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

928 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: cscsp.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include <tchar.h>
  13. #include "initcert.h"
  14. #include "cscsp.h"
  15. #include "csdisp.h"
  16. TCHAR const g_wszRegKeyCSP[] = wszREGKEYCSP;
  17. TCHAR const g_wszRegKeyEncryptionCSP[] = wszREGKEYENCRYPTIONCSP;
  18. TCHAR const g_wszRegProviderType[] = wszREGPROVIDERTYPE;
  19. TCHAR const g_wszRegProvider[] = wszREGPROVIDER;
  20. TCHAR const g_wszRegHashAlgorithm[] = wszHASHALGORITHM;
  21. TCHAR const g_wszRegEncryptionAlgorithm[] = wszENCRYPTIONALGORITHM;
  22. TCHAR const g_wszRegMachineKeyset[] = wszMACHINEKEYSET;
  23. TCHAR const g_wszRegKeySize[] = wszREGKEYSIZE;
  24. BOOL
  25. myCertSrvCryptAcquireContext(
  26. OUT HCRYPTPROV *phProv,
  27. IN WCHAR const *pwszContainer,
  28. IN WCHAR const *pwszProvider,
  29. IN DWORD dwProvType,
  30. IN DWORD dwFlags,
  31. IN BOOL fMachineKeyset)
  32. {
  33. HRESULT hr;
  34. if (fMachineKeyset)
  35. {
  36. dwFlags |= CRYPT_MACHINE_KEYSET;
  37. }
  38. if (!CryptAcquireContext(
  39. phProv,
  40. pwszContainer,
  41. pwszProvider,
  42. dwProvType,
  43. dwFlags))
  44. {
  45. hr = myHLastError();
  46. _JumpErrorStr2(
  47. hr,
  48. error,
  49. (CRYPT_MACHINE_KEYSET & dwFlags)?
  50. "CryptAcquireContext(Machine)" : "CryptAcquireContext(User)",
  51. pwszContainer,
  52. (CRYPT_DELETEKEYSET & dwFlags)? hr : S_OK);
  53. }
  54. hr = S_OK;
  55. error:
  56. if (S_OK != hr)
  57. {
  58. SetLastError(hr);
  59. }
  60. return(S_OK == hr);
  61. }
  62. HRESULT
  63. myGetCertSrvCSP(
  64. IN BOOL fEncryptionCSP,
  65. IN WCHAR const *pwszSanitizedCAName,
  66. OUT DWORD *pdwProvType,
  67. OUT WCHAR **ppwszProvName,
  68. OUT ALG_ID *pidAlg,
  69. OUT BOOL *pfMachineKeyset,
  70. OPTIONAL OUT DWORD *pdwKeySize)
  71. {
  72. HRESULT hr;
  73. HKEY hCertSrvCSPKey = NULL;
  74. DWORD dwValueType;
  75. DWORD dwValueSize;
  76. WCHAR *pwszPath = NULL;
  77. WCHAR *pwszProvName = NULL;
  78. WCHAR const *pwszRegKeyCSP;
  79. DWORD cwc;
  80. if (NULL != ppwszProvName)
  81. {
  82. *ppwszProvName = NULL;
  83. }
  84. if (NULL != pdwKeySize)
  85. {
  86. *pdwKeySize = 0;
  87. }
  88. if (NULL == pwszSanitizedCAName ||
  89. NULL == pdwProvType ||
  90. NULL == ppwszProvName ||
  91. NULL == pidAlg ||
  92. NULL == pfMachineKeyset)
  93. {
  94. hr = E_POINTER;
  95. _JumpError(hr, error, "NULL parm");
  96. }
  97. pwszRegKeyCSP = fEncryptionCSP? g_wszRegKeyEncryptionCSP : g_wszRegKeyCSP;
  98. cwc = WSZARRAYSIZE(wszREGKEYCONFIGPATH_BS) +
  99. wcslen(pwszSanitizedCAName) +
  100. 1 +
  101. wcslen(pwszRegKeyCSP);
  102. pwszPath = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  103. if (NULL == pwszPath)
  104. {
  105. hr = E_OUTOFMEMORY;
  106. _JumpError(hr, error, "LocalAlloc");
  107. }
  108. wcscpy(pwszPath, wszREGKEYCONFIGPATH_BS);
  109. wcscat(pwszPath, pwszSanitizedCAName);
  110. wcscat(pwszPath, L"\\");
  111. wcscat(pwszPath, pwszRegKeyCSP);
  112. CSASSERT(cwc == wcslen(pwszPath));
  113. hr = RegOpenKeyEx(
  114. HKEY_LOCAL_MACHINE,
  115. pwszPath,
  116. 0,
  117. KEY_ALL_ACCESS,
  118. &hCertSrvCSPKey);
  119. _JumpIfErrorStr2(hr, error, "RegOpenKeyEx", pwszPath, ERROR_FILE_NOT_FOUND);
  120. dwValueSize = 0;
  121. hr = RegQueryValueEx(
  122. hCertSrvCSPKey,
  123. g_wszRegProvider,
  124. 0,
  125. &dwValueType,
  126. NULL,
  127. &dwValueSize);
  128. _JumpIfError(hr, error, "RegQueryValueEx");
  129. if (REG_SZ != dwValueType)
  130. {
  131. hr = E_INVALIDARG;
  132. _JumpError(hr, error, "Invalid reg type");
  133. }
  134. pwszProvName = (WCHAR *) LocalAlloc(
  135. LMEM_FIXED,
  136. dwValueSize + sizeof(WCHAR));
  137. if (NULL == pwszProvName)
  138. {
  139. hr = E_OUTOFMEMORY;
  140. _JumpError(hr, error, "LocalAlloc");
  141. }
  142. hr = RegQueryValueEx(
  143. hCertSrvCSPKey,
  144. g_wszRegProvider,
  145. 0,
  146. &dwValueType,
  147. (BYTE *) pwszProvName,
  148. &dwValueSize);
  149. _JumpIfError(hr, error, "RegQueryValueEx");
  150. pwszProvName[dwValueSize / sizeof(WCHAR)] = L'\0';
  151. dwValueSize = sizeof(*pdwProvType);
  152. hr = RegQueryValueEx(hCertSrvCSPKey,
  153. g_wszRegProviderType,
  154. 0,
  155. &dwValueType,
  156. (BYTE *) pdwProvType,
  157. &dwValueSize);
  158. _JumpIfError(hr, error, "RegQueryValueEx");
  159. if (REG_DWORD != dwValueType)
  160. {
  161. hr = E_INVALIDARG;
  162. _JumpError(hr, error, "Invalid reg type");
  163. }
  164. dwValueSize = sizeof(*pidAlg);
  165. hr = RegQueryValueEx(
  166. hCertSrvCSPKey,
  167. fEncryptionCSP?
  168. g_wszRegEncryptionAlgorithm :
  169. g_wszRegHashAlgorithm,
  170. 0,
  171. &dwValueType,
  172. (BYTE *) pidAlg,
  173. &dwValueSize);
  174. if (S_OK != hr && fEncryptionCSP)
  175. {
  176. _PrintErrorStr2(
  177. hr,
  178. "RegQueryValueEx",
  179. g_wszRegEncryptionAlgorithm,
  180. ERROR_FILE_NOT_FOUND);
  181. dwValueSize = sizeof(*pidAlg);
  182. hr = RegQueryValueEx(
  183. hCertSrvCSPKey,
  184. g_wszRegHashAlgorithm,
  185. 0,
  186. &dwValueType,
  187. (BYTE *) pidAlg,
  188. &dwValueSize);
  189. }
  190. _JumpIfError(hr, error, "RegQueryValueEx");
  191. if (REG_DWORD != dwValueType)
  192. {
  193. hr = E_INVALIDARG;
  194. _JumpError(hr, error, "Invalid reg type");
  195. }
  196. dwValueSize = sizeof(*pfMachineKeyset);
  197. hr = RegQueryValueEx(hCertSrvCSPKey,
  198. g_wszRegMachineKeyset,
  199. 0,
  200. &dwValueType,
  201. (BYTE *) pfMachineKeyset,
  202. &dwValueSize);
  203. _JumpIfError(hr, error, "RegQueryValueEx");
  204. if (REG_DWORD != dwValueType)
  205. {
  206. hr = E_INVALIDARG;
  207. _JumpError(hr, error, "Invalid reg type");
  208. }
  209. if (NULL != pdwKeySize)
  210. {
  211. dwValueSize = sizeof(*pdwKeySize);
  212. hr = RegQueryValueEx(hCertSrvCSPKey,
  213. g_wszRegKeySize,
  214. 0,
  215. &dwValueType,
  216. (BYTE *) pdwKeySize,
  217. &dwValueSize);
  218. _JumpIfError(hr, error, "RegQueryValueEx");
  219. if (REG_DWORD != dwValueType)
  220. {
  221. hr = E_INVALIDARG;
  222. _JumpError(hr, error, "Invalid reg type");
  223. }
  224. }
  225. *ppwszProvName = pwszProvName;
  226. pwszProvName = NULL;
  227. hr = S_OK;
  228. error:
  229. if (NULL != pwszProvName)
  230. {
  231. LocalFree(pwszProvName);
  232. }
  233. if (NULL != pwszPath)
  234. {
  235. LocalFree(pwszPath);
  236. }
  237. if (NULL != hCertSrvCSPKey)
  238. {
  239. RegCloseKey(hCertSrvCSPKey);
  240. }
  241. return(myHError(hr));
  242. }
  243. //+------------------------------------------------------------------------
  244. //
  245. // Function: myGetSigningOID( . . . . )
  246. //
  247. // Synopsis: Determine algorithm identifer for cert creation
  248. // Arguments: csp_provider_type, hash_algorithm_id.
  249. // Returns: object identifier
  250. //
  251. //-------------------------------------------------------------------------
  252. HRESULT
  253. myGetSigningOID(
  254. OPTIONAL IN HCRYPTPROV hProv, // hProv OR pwszProvName & dwProvType
  255. OPTIONAL IN WCHAR const *pwszProvName,
  256. OPTIONAL IN DWORD dwProvType,
  257. IN ALG_ID idHashAlg,
  258. OUT CHAR **ppszAlgId)
  259. {
  260. HRESULT hr;
  261. PCCRYPT_OID_INFO pcOIDInfo; //don't free it
  262. ALG_ID aidAlgKey[] = {idHashAlg, 0};
  263. HCRYPTPROV hProvT = NULL;
  264. int i;
  265. DWORD dwFlags;
  266. DWORD cbData;
  267. PROV_ENUMALGS enumalgs;
  268. BOOL fFoundSignID = FALSE;
  269. *ppszAlgId = NULL;
  270. if (NULL == hProv)
  271. {
  272. CSASSERT(NULL != pwszProvName);
  273. if (!myCertSrvCryptAcquireContext(
  274. &hProvT,
  275. NULL,
  276. pwszProvName,
  277. dwProvType,
  278. CRYPT_VERIFYCONTEXT,
  279. FALSE))
  280. {
  281. hr = myHLastError();
  282. _JumpErrorStr(hr, error, "myCertSrvCryptAcquireContext", pwszProvName);
  283. }
  284. hProv = hProvT;
  285. }
  286. // find public key id
  287. dwFlags = CRYPT_FIRST;
  288. for (i = 0; ; i++)
  289. {
  290. cbData = sizeof(enumalgs);
  291. if (!CryptGetProvParam(
  292. hProv,
  293. PP_ENUMALGS,
  294. (BYTE *) &enumalgs,
  295. &cbData,
  296. dwFlags))
  297. {
  298. hr = myHLastError();
  299. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  300. {
  301. // out of for loop
  302. break;
  303. }
  304. _JumpError(hr, error, "CryptGetProvParam");
  305. }
  306. if (ALG_CLASS_SIGNATURE == GET_ALG_CLASS(enumalgs.aiAlgid))
  307. {
  308. fFoundSignID = TRUE;
  309. aidAlgKey[1] = enumalgs.aiAlgid;
  310. break;
  311. }
  312. dwFlags = 0;
  313. }
  314. if (fFoundSignID)
  315. {
  316. pcOIDInfo = CryptFindOIDInfo(
  317. CRYPT_OID_INFO_SIGN_KEY,
  318. aidAlgKey,
  319. CRYPT_SIGN_ALG_OID_GROUP_ID); // only signing
  320. if (NULL == pcOIDInfo)
  321. {
  322. hr = E_INVALIDARG;
  323. _JumpError(hr, error, "unsupported signing algorithm");
  324. }
  325. hr = myDupStringA(pcOIDInfo->pszOID, ppszAlgId);
  326. _JumpIfError(hr, error, "myDupStringA");
  327. }
  328. hr = S_OK;
  329. error:
  330. if (NULL != hProvT)
  331. {
  332. CryptReleaseContext(hProvT, 0);
  333. }
  334. CSASSERT(S_OK == hr || FAILED(hr));
  335. return(hr);
  336. }
  337. HRESULT
  338. myValidateKeyForSigning(
  339. IN HCRYPTPROV hProv,
  340. OPTIONAL IN CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo,
  341. IN ALG_ID algId)
  342. {
  343. HRESULT hr;
  344. BYTE abRandom[64];
  345. HCRYPTKEY hKey = NULL;
  346. HCRYPTHASH hHash = NULL;
  347. BYTE *pbSignature = NULL;
  348. DWORD cbSignature;
  349. // create a supported hash
  350. if (!CryptCreateHash(hProv, algId, 0, 0, &hHash))
  351. {
  352. hr = myHLastError();
  353. DBGPRINT((DBG_SS_ERROR, "algId = %x\n", algId));
  354. _JumpError(hr, error, "CryptCreateHash");
  355. }
  356. // create some random data
  357. if (!CryptGenRandom(hProv, ARRAYSIZE(abRandom), abRandom))
  358. {
  359. hr = myHLastError();
  360. _JumpError(hr, error, "CryptGenRandom");
  361. }
  362. if (!CryptHashData(hHash, abRandom, ARRAYSIZE(abRandom), 0))
  363. {
  364. hr = myHLastError();
  365. _JumpError(hr, error, "CryptHashData");
  366. }
  367. // sign the hash, get size first
  368. if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &cbSignature))
  369. {
  370. hr = myHLastError();
  371. _JumpError(hr, error, "CryptSignHash");
  372. }
  373. pbSignature = (BYTE *) LocalAlloc(LMEM_FIXED, cbSignature);
  374. if (NULL == pbSignature)
  375. {
  376. hr = E_OUTOFMEMORY;
  377. _JumpError(hr, error, "LocalAlloc");
  378. }
  379. if (!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &cbSignature))
  380. {
  381. hr = myHLastError();
  382. _JumpError(hr, error, "CryptSignHash");
  383. }
  384. if (NULL != pPublicKeyInfo)
  385. {
  386. // import public key into provider
  387. if (!CryptImportPublicKeyInfo(
  388. hProv,
  389. X509_ASN_ENCODING,
  390. const_cast<CERT_PUBLIC_KEY_INFO *>(pPublicKeyInfo),
  391. &hKey))
  392. {
  393. hr = myHLastError();
  394. _JumpError(hr, error, "CryptImportPublicKeyInfo");
  395. }
  396. }
  397. else
  398. {
  399. // get public key from container
  400. if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
  401. {
  402. hr = myHLastError();
  403. _JumpError(hr, error, "CryptGetUserKey");
  404. }
  405. }
  406. if (!CryptVerifySignature(hHash, pbSignature, cbSignature, hKey, NULL, 0))
  407. {
  408. hr = myHLastError();
  409. _JumpError(hr, error, "CryptVerifySignature");
  410. }
  411. hr = S_OK;
  412. error:
  413. if (NULL != hHash)
  414. {
  415. CryptDestroyHash(hHash);
  416. }
  417. if (NULL != hKey)
  418. {
  419. CryptDestroyKey(hKey);
  420. }
  421. if (NULL != pbSignature)
  422. {
  423. LocalFree(pbSignature);
  424. }
  425. CSASSERT(S_OK == hr || FAILED(hr));
  426. return(hr);
  427. }
  428. HRESULT
  429. myValidateKeyForEncrypting(
  430. IN HCRYPTPROV hProv,
  431. IN CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo,
  432. IN ALG_ID algId)
  433. {
  434. HRESULT hr;
  435. HCRYPTKEY hKeyPub = NULL;
  436. HCRYPTKEY hKeySym = NULL;
  437. HCRYPTKEY hKeyPri = NULL;
  438. BYTE *pbKeySym = NULL;
  439. DWORD cbKeySym;
  440. BYTE abRandom[64];
  441. BYTE *pbEncrypted = NULL;
  442. BYTE *pbDecrypted = NULL;
  443. DWORD cbEncrypted;
  444. DWORD cbDecrypted;
  445. // import public key into provider
  446. if (!CryptImportPublicKeyInfo(
  447. hProv,
  448. X509_ASN_ENCODING,
  449. const_cast<CERT_PUBLIC_KEY_INFO *>(pPublicKeyInfo),
  450. &hKeyPub))
  451. {
  452. hr = myHLastError();
  453. _JumpError(hr, error, "CryptImportPublicKeyInfo");
  454. }
  455. // Generate a default sized symmetric session key
  456. if (!CryptGenKey(hProv, algId, CRYPT_EXPORTABLE, &hKeySym))
  457. {
  458. hr = myHLastError();
  459. _JumpError(hr, error, "CryptGenKey");
  460. }
  461. // create some random data
  462. if (!CryptGenRandom(hProv, ARRAYSIZE(abRandom), abRandom))
  463. {
  464. hr = myHLastError();
  465. _JumpError(hr, error, "CryptGenRandom");
  466. }
  467. #if 1
  468. DBGPRINT((DBG_SS_CERTLIBI, "Plain text size = %d\n", ARRAYSIZE(abRandom)));
  469. DBGDUMPHEX((
  470. DBG_SS_CERTLIBI,
  471. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  472. abRandom,
  473. ARRAYSIZE(abRandom)));
  474. #endif
  475. hr = myCryptEncrypt(
  476. hKeySym,
  477. abRandom,
  478. ARRAYSIZE(abRandom),
  479. &pbEncrypted,
  480. &cbEncrypted);
  481. _JumpIfError(hr, error, "myCryptEncrypt");
  482. #if 1
  483. DBGPRINT((DBG_SS_CERTLIBI, "Encrypted size = %d\n", cbEncrypted));
  484. DBGDUMPHEX((
  485. DBG_SS_CERTLIBI,
  486. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  487. pbEncrypted,
  488. cbEncrypted));
  489. #endif
  490. hr = myCryptExportKey(hKeySym, hKeyPub, SIMPLEBLOB, 0, &pbKeySym, &cbKeySym);
  491. _JumpIfError(hr, error, "myCryptExportKey");
  492. CryptDestroyKey(hKeySym);
  493. hKeySym = NULL;
  494. #if 1
  495. DBGPRINT((DBG_SS_CERTLIBI, "SIMPLEBLOB:\n"));
  496. DBGDUMPHEX((
  497. DBG_SS_CERTLIBI,
  498. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  499. pbKeySym,
  500. cbKeySym));
  501. #endif
  502. // get private key from container and import session key blob
  503. if (!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKeyPri))
  504. {
  505. hr = myHLastError();
  506. _JumpError(hr, error, "CryptGetUserKey");
  507. }
  508. if (!CryptImportKey(
  509. hProv,
  510. pbKeySym,
  511. cbKeySym,
  512. hKeyPri,
  513. CRYPT_EXPORTABLE,
  514. &hKeySym))
  515. {
  516. hr = myHLastError();
  517. _JumpError(hr, error, "CryptImportKey");
  518. }
  519. hr = myCryptDecrypt(
  520. hKeySym,
  521. pbEncrypted,
  522. cbEncrypted,
  523. &pbDecrypted,
  524. &cbDecrypted);
  525. _JumpIfError(hr, error, "myCryptDecrypt");
  526. #if 1
  527. DBGPRINT((DBG_SS_CERTLIBI, "Decrypted size = %d\n", cbDecrypted));
  528. DBGDUMPHEX((
  529. DBG_SS_CERTLIBI,
  530. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  531. pbDecrypted,
  532. cbDecrypted));
  533. #endif
  534. if (ARRAYSIZE(abRandom) != cbDecrypted ||
  535. 0 != memcmp(abRandom, pbDecrypted, ARRAYSIZE(abRandom)))
  536. {
  537. hr = NTE_BAD_KEY;
  538. _JumpIfError(hr, error, "Decrypted data mismatch");
  539. }
  540. hr = S_OK;
  541. error:
  542. if (NULL != hKeyPub)
  543. {
  544. CryptDestroyKey(hKeyPub);
  545. }
  546. if (NULL != hKeySym)
  547. {
  548. CryptDestroyKey(hKeySym);
  549. }
  550. if (NULL != hKeyPri)
  551. {
  552. CryptDestroyKey(hKeyPri);
  553. }
  554. if (NULL != pbEncrypted)
  555. {
  556. LocalFree(pbEncrypted);
  557. }
  558. if (NULL != pbDecrypted)
  559. {
  560. LocalFree(pbDecrypted);
  561. }
  562. if (NULL != pbKeySym)
  563. {
  564. LocalFree(pbKeySym);
  565. }
  566. CSASSERT(S_OK == hr || FAILED(hr));
  567. return(hr);
  568. }
  569. HRESULT
  570. myValidateHashForSigning(
  571. IN WCHAR const *pwszContainer,
  572. IN WCHAR const *pwszProvName,
  573. IN DWORD dwProvType,
  574. IN BOOL fMachineKeyset,
  575. IN OPTIONAL CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo,
  576. IN ALG_ID algId)
  577. {
  578. HRESULT hr;
  579. HCRYPTPROV hProv = NULL;
  580. // get private key handler
  581. if (!myCertSrvCryptAcquireContext(
  582. &hProv,
  583. pwszContainer,
  584. pwszProvName,
  585. dwProvType,
  586. 0,
  587. fMachineKeyset))
  588. {
  589. hr = myHLastError();
  590. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  591. }
  592. hr = myValidateKeyForSigning(hProv, pPublicKeyInfo, algId);
  593. _JumpIfError(hr, error, "myValidateKeyForSigning");
  594. error:
  595. if (NULL != hProv)
  596. {
  597. CryptReleaseContext(hProv, 0);
  598. }
  599. CSASSERT(S_OK == hr || FAILED(hr));
  600. return(hr);
  601. }
  602. HRESULT
  603. GenerateTemporaryContainerName(
  604. OUT WCHAR **ppwszKeyContainerName)
  605. {
  606. HRESULT hr;
  607. GUID guid;
  608. WCHAR awcbuf[MAX_PATH];
  609. DWORD cb;
  610. DWORD cwc;
  611. myGenerateGuidSerialNumber(&guid);
  612. wcscpy(awcbuf, L"KeyVerification--");
  613. cwc = wcslen(awcbuf);
  614. cb = sizeof(awcbuf) - cwc * sizeof(WCHAR);
  615. hr = MultiByteIntegerToWszBuf(
  616. FALSE,
  617. sizeof(guid),
  618. (BYTE const *) &guid,
  619. &cb,
  620. &awcbuf[cwc]);
  621. _JumpIfError(hr, error, "MultiByteIntegerToWszBuf");
  622. hr = myDupString(awcbuf, ppwszKeyContainerName);
  623. _JumpIfError(hr, error, "myDupString");
  624. error:
  625. return(hr);
  626. }
  627. VOID
  628. DeleteRSAKeyContainer(
  629. IN WCHAR const *pwszKeyContainerName,
  630. IN BOOL fMachineKeyset)
  631. {
  632. HCRYPTPROV hProv;
  633. DWORD dwFlags = CRYPT_DELETEKEYSET;
  634. if (fMachineKeyset)
  635. {
  636. dwFlags = CRYPT_MACHINE_KEYSET;
  637. }
  638. CryptAcquireContext(
  639. &hProv,
  640. pwszKeyContainerName,
  641. NULL, // pwszProvName
  642. PROV_RSA_FULL,
  643. dwFlags);
  644. }
  645. HRESULT
  646. myValidateKeyBlob(
  647. IN BYTE const *pbKey,
  648. IN DWORD cbKey,
  649. IN CERT_PUBLIC_KEY_INFO const *pPublicKeyInfo,
  650. IN BOOL fV1Cert,
  651. OPTIONAL OUT CRYPT_KEY_PROV_INFO *pkpi)
  652. {
  653. HRESULT hr;
  654. WCHAR *pwszKeyContainerName = NULL;
  655. HCRYPTPROV hProv = NULL;
  656. HCRYPTKEY hKey = NULL;
  657. CRYPT_KEY_PROV_INFO kpi;
  658. BOOL fMatchingKey;
  659. WCHAR wszPassword[MAX_PATH];
  660. hr = GenerateTemporaryContainerName(&pwszKeyContainerName);
  661. _JumpIfError(hr, error, "GenerateTemporaryContainerName");
  662. DeleteRSAKeyContainer(pwszKeyContainerName, FALSE);
  663. DBGPRINT((DBG_SS_CERTLIBI, "Key Container: %ws\n", pwszKeyContainerName));
  664. if (!CryptAcquireContext(
  665. &hProv,
  666. pwszKeyContainerName,
  667. NULL,
  668. PROV_RSA_FULL,
  669. CRYPT_NEWKEYSET))
  670. {
  671. hr = myHLastError();
  672. _JumpError(hr, error, "CryptAcquireContext");
  673. }
  674. if (!CryptImportKey(
  675. hProv,
  676. pbKey,
  677. cbKey,
  678. NULL, // hPubKey
  679. CRYPT_EXPORTABLE,
  680. &hKey))
  681. {
  682. hr = myHLastError();
  683. _JumpError(hr, error, "CryptImportKey");
  684. }
  685. CryptDestroyKey(hKey);
  686. hKey = NULL;
  687. ZeroMemory(&kpi, sizeof(kpi));
  688. kpi.pwszContainerName = pwszKeyContainerName;
  689. kpi.dwProvType = PROV_RSA_FULL;
  690. kpi.dwKeySpec = AT_KEYEXCHANGE;
  691. if (!CryptGetUserKey(hProv, kpi.dwKeySpec, &hKey))
  692. {
  693. hr = myHLastError();
  694. _PrintIfError2(hr, "CryptGetUserKey", hr);
  695. kpi.dwKeySpec = AT_SIGNATURE;
  696. if (!CryptGetUserKey(hProv, kpi.dwKeySpec, &hKey))
  697. {
  698. hr = myHLastError();
  699. _JumpIfError(hr, error, "CryptGetUserKey");
  700. }
  701. }
  702. CryptDestroyKey(hKey);
  703. hKey = NULL;
  704. CryptReleaseContext(hProv, 0);
  705. hProv = NULL;
  706. if (!CryptAcquireContext(
  707. &hProv,
  708. pwszKeyContainerName,
  709. NULL,
  710. PROV_RSA_FULL,
  711. 0))
  712. {
  713. hr = myHLastError();
  714. _JumpError(hr, error, "CryptAcquireContext");
  715. }
  716. if (AT_SIGNATURE == kpi.dwKeySpec)
  717. {
  718. hr = myValidateKeyForSigning(hProv, pPublicKeyInfo, CALG_SHA1);
  719. _PrintIfError(hr, "myValidateKeyForSigning");
  720. }
  721. else
  722. {
  723. hr = myValidateKeyForEncrypting(hProv, pPublicKeyInfo, CALG_RC4);
  724. _PrintIfError(hr, "myValidateKeyForEncrypting");
  725. }
  726. if (S_OK != hr)
  727. {
  728. _JumpError(hr, error, "Key Validation");
  729. }
  730. hr = myVerifyPublicKey(
  731. NULL, // pCert
  732. fV1Cert,
  733. &kpi, // pKeyProvInfo
  734. pPublicKeyInfo, // pPublicKeyInfo
  735. &fMatchingKey);
  736. if (S_OK != hr)
  737. {
  738. _JumpError(hr, error, "myVerifyPublicKey");
  739. }
  740. if (!fMatchingKey)
  741. {
  742. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  743. _JumpError(hr, error, "Key doesn't match cert");
  744. }
  745. if (NULL != pkpi)
  746. {
  747. *pkpi = kpi;
  748. pwszKeyContainerName = NULL;
  749. }
  750. error:
  751. if (NULL != hKey)
  752. {
  753. CryptDestroyKey(hKey);
  754. }
  755. if (NULL != hProv)
  756. {
  757. CryptReleaseContext(hProv, 0);
  758. }
  759. if (NULL != pwszKeyContainerName)
  760. {
  761. DeleteRSAKeyContainer(pwszKeyContainerName, FALSE);
  762. LocalFree(pwszKeyContainerName);
  763. }
  764. return(hr);
  765. }
  766. /*
  767. * myEnumProviders
  768. *
  769. * Purpose:
  770. * Enumerate the providers.
  771. *
  772. * Parameters:
  773. * IN dwIndex - Index to the providers to enumerate
  774. * IN pdwReserved - Reserved for future use
  775. * IN dwFlags - Flags parameter
  776. * OUT pdwProvType - The type of the provider
  777. * OUT ppwszProvName - Name of the enumerated provider
  778. */
  779. HRESULT
  780. myEnumProviders(
  781. IN DWORD dwIndex,
  782. IN DWORD *pdwReserved,
  783. IN DWORD dwFlags,
  784. OUT DWORD *pdwProvType,
  785. OUT WCHAR **ppwszProvName)
  786. {
  787. HRESULT hr;
  788. char *pszProvName = NULL;
  789. DWORD cbProvName;
  790. *ppwszProvName = NULL;
  791. while (TRUE)
  792. {
  793. if (!CryptEnumProvidersA(
  794. dwIndex,
  795. pdwReserved,
  796. dwFlags,
  797. pdwProvType,
  798. pszProvName,
  799. &cbProvName))
  800. {
  801. hr = myHLastError();
  802. _JumpError2(hr, error, "CryptEnumProvidersA", hr);
  803. }
  804. if (NULL != pszProvName)
  805. {
  806. break;
  807. }
  808. // allocate ansi string buffer
  809. pszProvName = (char *) LocalAlloc(LMEM_FIXED, cbProvName);
  810. if (NULL == pszProvName)
  811. {
  812. hr = E_OUTOFMEMORY;
  813. _JumpError(hr, error, "LocalAlloc");
  814. }
  815. }
  816. if (!myConvertSzToWsz(ppwszProvName, pszProvName, -1))
  817. {
  818. hr = E_OUTOFMEMORY;
  819. _JumpError(hr, error, "myConvertSzToWsz");
  820. }
  821. hr = S_OK;
  822. error:
  823. if (NULL != pszProvName)
  824. {
  825. LocalFree(pszProvName);
  826. }
  827. return(hr);
  828. }