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.

550 lines
13 KiB

  1. //
  2. // Utils.c
  3. //
  4. // 7/6/00 dangriff created
  5. //
  6. #include <windows.h>
  7. #include <wincrypt.h>
  8. #include <stdio.h>
  9. #include "utils.h"
  10. #include "cspstruc.h"
  11. #include "csptestsuite.h"
  12. #include "logging.h"
  13. //
  14. // Function: BuildAlgList
  15. //
  16. BOOL BuildAlgList(HCRYPTPROV hProv, PCSPINFO pCSPInfo)
  17. {
  18. DWORD cb = 0;
  19. DWORD dwFlags = 0;
  20. PALGNODE pAlgNode = NULL;
  21. PTESTCASE ptc = &(pCSPInfo->TestCase);
  22. PROV_ENUMALGS_EX ProvEnumalgsEx;
  23. // Enumerate all supported algs
  24. dwFlags = CRYPT_FIRST;
  25. cb = sizeof(ProvEnumalgsEx);
  26. memset(&ProvEnumalgsEx, 0, cb);
  27. LogTestCaseSeparator(FALSE); // Log a blank line first
  28. LogInfo(L"CryptGetProvParam PP_ENUMALGS_EX: enumerating supported algorithms");
  29. while (CryptGetProvParam(
  30. hProv,
  31. PP_ENUMALGS_EX,
  32. (PBYTE) &ProvEnumalgsEx,
  33. &cb,
  34. dwFlags))
  35. {
  36. // Increment the test case counter for every enumerated alg
  37. ++ptc->dwTestCaseID;
  38. if (NULL == pCSPInfo->pAlgList)
  39. {
  40. //
  41. // Allocate first node at user's pointer
  42. //
  43. LOG_TRY(TestAlloc(
  44. &((PBYTE) pCSPInfo->pAlgList),
  45. sizeof(ALGNODE),
  46. ptc));
  47. pAlgNode = pCSPInfo->pAlgList;
  48. }
  49. else
  50. {
  51. //
  52. // Add another node to the list
  53. //
  54. LOG_TRY(TestAlloc(
  55. &((PBYTE) pAlgNode->pAlgNodeNext),
  56. sizeof(ALGNODE),
  57. ptc));
  58. pAlgNode = pAlgNode->pAlgNodeNext;
  59. }
  60. // Zero out the ALGNODE struct
  61. memset(pAlgNode, 0, sizeof(ALGNODE));
  62. // Copy the ProvEnumalgsEx data into the ALGNODE struct
  63. memcpy(&(pAlgNode->ProvEnumalgsEx), &ProvEnumalgsEx, cb);
  64. //
  65. // We just need to know if the current algorithm is considered "known"
  66. // by the Test Suite. First, search through the list of REQUIRED algs,
  67. // and assume that all REQUIRED algs are also KNOWN.
  68. //
  69. if (TRUE == (pAlgNode->fIsRequiredAlg =
  70. IsRequiredAlg(
  71. ProvEnumalgsEx.aiAlgid,
  72. pCSPInfo->dwExternalProvType)))
  73. {
  74. pAlgNode->fIsKnownAlg = TRUE;
  75. }
  76. else
  77. {
  78. //
  79. // Now search through the remaining KNOWN, non-required, algorithms
  80. //
  81. pAlgNode->fIsKnownAlg =
  82. IsKnownAlg(
  83. ProvEnumalgsEx.aiAlgid,
  84. pCSPInfo->dwExternalProvType);
  85. }
  86. if (CRYPT_FIRST == dwFlags)
  87. {
  88. dwFlags = 0;
  89. }
  90. LogProvEnumalgsEx(&ProvEnumalgsEx);
  91. }
  92. if (ERROR_NO_MORE_ITEMS != GetLastError())
  93. {
  94. ptc->dwErrorCode = ERROR_NO_MORE_ITEMS;
  95. ptc->fExpectSuccess = FALSE;
  96. ptc->pwszErrorHelp = L"CryptGetProvParam PP_ENUMALGS_EX: Wrong error code returned at end of enumeration";
  97. //
  98. // Log a FAIL
  99. //
  100. return CheckAndLogStatus(
  101. API_CRYPTGETPROVPARAM,
  102. FALSE,
  103. ptc,
  104. NULL,
  105. 0);
  106. }
  107. //
  108. // Log a PASS
  109. //
  110. /*
  111. return CheckAndLogStatus(
  112. API_CRYPTGETPROVPARAM,
  113. TRUE,
  114. ptc,
  115. NULL,
  116. 0);
  117. */
  118. return TRUE;
  119. Cleanup:
  120. return FALSE;
  121. }
  122. //
  123. // Function: CreateNewInteropContext
  124. //
  125. BOOL CreateNewInteropContext(
  126. OUT HCRYPTPROV *phProv,
  127. IN LPWSTR pwszContainer,
  128. IN DWORD dwFlags,
  129. IN PTESTCASE ptc)
  130. {
  131. BOOL fSuccess = FALSE;
  132. //DWORD dwError = 0;
  133. DWORD dwProvType = LogGetInteropProvType();
  134. LPWSTR pwszProvName = LogGetInteropProvName();
  135. BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
  136. DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
  137. //
  138. // All calls to CreateNewInteropContext are considered critical, since
  139. // they are typically followed by additional dependent test code. Set a high
  140. // failure rate for this reason.
  141. //
  142. ptc->dwErrorLevel = CSP_ERROR_API;
  143. ptc->fExpectSuccess = TRUE;
  144. if (CRYPT_VERIFYCONTEXT != (dwFlags & CRYPT_VERIFYCONTEXT))
  145. {
  146. TAcquire(
  147. phProv,
  148. pwszContainer,
  149. pwszProvName,
  150. dwProvType,
  151. CRYPT_DELETEKEYSET,
  152. ptc);
  153. dwFlags &= CRYPT_NEWKEYSET;
  154. }
  155. fSuccess = TAcquire(
  156. phProv,
  157. pwszContainer,
  158. pwszProvName,
  159. dwProvType,
  160. dwFlags,
  161. ptc);
  162. ptc->dwErrorLevel = dwSavedErrorLevel;
  163. ptc->fExpectSuccess = fSavedExpectSuccess;
  164. return fSuccess;
  165. }
  166. //
  167. // Function: CreateNewContext
  168. //
  169. BOOL CreateNewContext(
  170. OUT HCRYPTPROV *phProv,
  171. IN LPWSTR pwszContainer,
  172. IN DWORD dwFlags,
  173. IN PTESTCASE ptc)
  174. {
  175. BOOL fSuccess = FALSE;
  176. //DWORD dwError = 0;
  177. DWORD dwProvType = LogGetProvType();
  178. LPWSTR pwszProvName = LogGetProvName();
  179. BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
  180. DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
  181. //
  182. // All calls to CreateNewContext are considered critical, since
  183. // they are typically followed by additional dependent test code. Set a high
  184. // failure rate for this reason.
  185. //
  186. ptc->dwErrorLevel = CSP_ERROR_API;
  187. ptc->fExpectSuccess = TRUE;
  188. if ( ! (dwFlags & CRYPT_VERIFYCONTEXT))
  189. {
  190. //
  191. // Call the CryptAcquireContext API directly (instead of
  192. // TAcquire) since this key container may not already exist.
  193. //
  194. if (dwFlags & CRYPT_MACHINE_KEYSET)
  195. {
  196. CryptAcquireContext(
  197. phProv,
  198. pwszContainer,
  199. pwszProvName,
  200. dwProvType,
  201. CRYPT_DELETEKEYSET | CRYPT_MACHINE_KEYSET);
  202. }
  203. else
  204. {
  205. CryptAcquireContext(
  206. phProv,
  207. pwszContainer,
  208. pwszProvName,
  209. dwProvType,
  210. CRYPT_DELETEKEYSET);
  211. }
  212. if (FALSE == ptc->fTestingUserProtected &&
  213. FALSE == ptc->fSmartCardCSP)
  214. {
  215. //
  216. // Unless the above flag is set, all non-VERIFYCONTEXT context handles
  217. // will be created with with the CRYPT_SILENT flag in order to
  218. // maximize the test exposure to this flag.
  219. //
  220. dwFlags |= CRYPT_SILENT;
  221. }
  222. }
  223. fSuccess = TAcquire(
  224. phProv,
  225. pwszContainer,
  226. pwszProvName,
  227. dwProvType,
  228. dwFlags,
  229. ptc);
  230. ptc->dwErrorLevel = dwSavedErrorLevel;
  231. ptc->fExpectSuccess = fSavedExpectSuccess;
  232. return fSuccess;
  233. }
  234. //
  235. // Function: CreateNewKey
  236. //
  237. BOOL CreateNewKey(
  238. IN HCRYPTPROV hProv,
  239. IN ALG_ID Algid,
  240. IN DWORD dwFlags,
  241. OUT HCRYPTKEY *phKey,
  242. IN PTESTCASE ptc)
  243. {
  244. BOOL fSuccess = FALSE;
  245. //DWORD dwError = 0;
  246. BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
  247. DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
  248. //
  249. // All calls to CreateNewKey are considered critical, since
  250. // they are typically followed by additional dependent test code. Set a high
  251. // failure rate for the next CSP call for this reason.
  252. //
  253. ptc->dwErrorLevel = CSP_ERROR_API;
  254. ptc->fExpectSuccess = TRUE;
  255. fSuccess = TGenKey(
  256. hProv,
  257. Algid,
  258. dwFlags,
  259. phKey,
  260. ptc);
  261. ptc->dwErrorLevel = dwSavedErrorLevel;
  262. ptc->fExpectSuccess = fSavedExpectSuccess;
  263. return fSuccess;
  264. }
  265. //
  266. // Function: CreateNewHash
  267. //
  268. BOOL CreateNewHash(
  269. IN HCRYPTPROV hProv,
  270. IN ALG_ID Algid,
  271. OUT HCRYPTHASH *phHash,
  272. IN PTESTCASE ptc)
  273. {
  274. BOOL fSuccess = FALSE;
  275. //DWORD dwError = 0;
  276. BOOL fSavedExpectSuccess = ptc->fExpectSuccess;
  277. DWORD dwSavedErrorLevel = ptc->dwErrorLevel;
  278. //
  279. // All calls to CreateNewHash are considered critical, since
  280. // they are typically followed by additional dependent test code. Set a high
  281. // failure rate for the next CSP call for this reason.
  282. //
  283. ptc->dwErrorLevel = CSP_ERROR_API;
  284. ptc->fExpectSuccess = TRUE;
  285. fSuccess = TCreateHash(
  286. hProv,
  287. Algid,
  288. 0, // hKey
  289. 0, // dwFlags
  290. phHash,
  291. ptc);
  292. ptc->dwErrorLevel = dwSavedErrorLevel;
  293. ptc->fExpectSuccess = fSavedExpectSuccess;
  294. return fSuccess;
  295. }
  296. //
  297. // Function: TestAlloc
  298. //
  299. BOOL TestAlloc(OUT PBYTE *ppb, IN DWORD cb, PTESTCASE ptc)
  300. {
  301. if (NULL == (*ppb = (PBYTE) malloc(cb)))
  302. {
  303. LogApiFailure(
  304. API_MEMORY,
  305. ERROR_API_FAILED,
  306. ptc);
  307. return FALSE;
  308. }
  309. memset(*ppb, 0, cb);
  310. return TRUE;
  311. }
  312. //
  313. // Function: AlgListIterate
  314. //
  315. BOOL AlgListIterate(
  316. IN PALGNODE pAlgList,
  317. IN PFN_ALGNODE_FILTER pfnFilter,
  318. IN PFN_ALGNODE_PROC pfnProc,
  319. IN PVOID pvProcData,
  320. IN PTESTCASE ptc)
  321. {
  322. BOOL fErrorOccurred = FALSE;
  323. PALGNODE pAlgNode = NULL;
  324. for (pAlgNode = pAlgList; pAlgNode != NULL; pAlgNode = pAlgNode->pAlgNodeNext)
  325. {
  326. if ( ((*pfnFilter)(pAlgNode)) )
  327. {
  328. if (! ((*pfnProc)(pAlgNode, ptc, pvProcData)) )
  329. {
  330. fErrorOccurred = TRUE;
  331. }
  332. }
  333. }
  334. if (fErrorOccurred)
  335. {
  336. return FALSE;
  337. }
  338. else
  339. {
  340. return TRUE;
  341. }
  342. }
  343. //
  344. // Function: HashAlgFilter
  345. //
  346. BOOL HashAlgFilter(PALGNODE pAlgNode)
  347. {
  348. if ( (ALG_CLASS_HASH == GET_ALG_CLASS(pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
  349. pAlgNode->fIsKnownAlg)
  350. {
  351. return ! MacAlgFilter(pAlgNode);
  352. }
  353. return FALSE;
  354. }
  355. //
  356. // Function: MacAlgFilter
  357. //
  358. BOOL MacAlgFilter(PALGNODE pAlgNode)
  359. {
  360. if ( ((CALG_MAC == pAlgNode->ProvEnumalgsEx.aiAlgid) ||
  361. (CALG_HMAC == pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
  362. pAlgNode->fIsKnownAlg)
  363. {
  364. return TRUE;
  365. }
  366. else
  367. {
  368. return FALSE;
  369. }
  370. }
  371. //
  372. // Function: BlockCipherFilter
  373. //
  374. BOOL BlockCipherFilter(PALGNODE pAlgNode)
  375. {
  376. if ( (ALG_TYPE_BLOCK == GET_ALG_TYPE(pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
  377. pAlgNode->fIsKnownAlg)
  378. {
  379. return TRUE;
  380. }
  381. else
  382. {
  383. return FALSE;
  384. }
  385. }
  386. //
  387. // Function: DataEncryptFilter
  388. //
  389. BOOL DataEncryptFilter(PALGNODE pAlgNode)
  390. {
  391. if ( (ALG_CLASS_DATA_ENCRYPT == GET_ALG_CLASS(pAlgNode->ProvEnumalgsEx.aiAlgid)) &&
  392. pAlgNode->fIsKnownAlg)
  393. {
  394. return TRUE;
  395. }
  396. else
  397. {
  398. return FALSE;
  399. }
  400. }
  401. //
  402. // Function: AllEncryptionAlgsFilter
  403. // Purpose: Same algorithm set as DataEncryptFilter above,
  404. // with the addition of the RSA key-exchange alg.
  405. //
  406. BOOL AllEncryptionAlgsFilter(PALGNODE pAlgNode)
  407. {
  408. return (CALG_RSA_KEYX == pAlgNode->ProvEnumalgsEx.aiAlgid) ||
  409. DataEncryptFilter(pAlgNode);
  410. }
  411. //
  412. // Function: RSAAlgFilter
  413. //
  414. BOOL RSAAlgFilter(PALGNODE pAlgNode)
  415. {
  416. return (CALG_RSA_KEYX == pAlgNode->ProvEnumalgsEx.aiAlgid) ||
  417. (CALG_RSA_SIGN == pAlgNode->ProvEnumalgsEx.aiAlgid);
  418. }
  419. //
  420. // Function: PrintBytes
  421. //
  422. #define CROW 8
  423. void PrintBytes(LPWSTR pwszHdr, BYTE *pb, DWORD cbSize)
  424. {
  425. ULONG cb, i;
  426. WCHAR rgwsz[1024];
  427. wsprintf(rgwsz, L" %s, %d bytes ::", pwszHdr, cbSize);
  428. LogInfo(rgwsz);
  429. while (cbSize > 0)
  430. {
  431. // Start every row with an extra space
  432. wsprintf(rgwsz, L" ");
  433. cb = min(CROW, cbSize);
  434. cbSize -= cb;
  435. for (i = 0; i < cb; i++)
  436. wsprintf(rgwsz + wcslen(rgwsz), L" %02x", pb[i]);
  437. for (i = cb; i < CROW; i++)
  438. wsprintf(rgwsz + wcslen(rgwsz), L" ");
  439. wsprintf(rgwsz + wcslen(rgwsz), L" '");
  440. for (i = 0; i < cb; i++)
  441. {
  442. if (pb[i] >= 0x20 && pb[i] <= 0x7f)
  443. wsprintf(rgwsz + wcslen(rgwsz), L"%c", pb[i]);
  444. else
  445. wsprintf(rgwsz + wcslen(rgwsz), L".");
  446. }
  447. LogInfo(rgwsz);
  448. pb += cb;
  449. }
  450. }
  451. //
  452. // Function: MkWStr
  453. //
  454. LPWSTR MkWStr(LPSTR psz)
  455. {
  456. int cWChars = 0;
  457. LPWSTR pwsz = NULL;
  458. if (psz == NULL)
  459. {
  460. return NULL;
  461. }
  462. cWChars = MultiByteToWideChar(
  463. 0,
  464. 0,
  465. psz,
  466. -1,
  467. NULL,
  468. 0);
  469. if (NULL == (pwsz = (LPWSTR) malloc(cWChars * sizeof(WCHAR))))
  470. {
  471. return NULL;
  472. }
  473. MultiByteToWideChar(
  474. 0,
  475. 0,
  476. psz,
  477. -1,
  478. pwsz,
  479. cWChars);
  480. return(pwsz);
  481. }