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.

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