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.

3336 lines
105 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1996
  6. //
  7. // File: tsca.cpp
  8. //
  9. // Contents: Simplified Cryptographic API (SCA) Tests
  10. //
  11. // See Usage() for list of test options.
  12. //
  13. //
  14. // Functions: main
  15. //
  16. // History: 08-Mar-96 philh created
  17. // 20-Aug-96 jeffspel name changes
  18. //
  19. //--------------------------------------------------------------------------
  20. #define CMS_PKCS7 1
  21. #ifdef CMS_PKCS7
  22. #define CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS 1
  23. #endif // CMS_PKCS7
  24. #define CRYPT_DECRYPT_MESSAGE_PARA_HAS_EXTRA_FIELDS 1
  25. #include <windows.h>
  26. #include <assert.h>
  27. #include "wincrypt.h"
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <stddef.h>
  32. #include <memory.h>
  33. #include <time.h>
  34. #include <malloc.h>
  35. #include <dbgdef.h>
  36. // #define ENABLE_SCA_STREAM_TEST 1
  37. #define SCA_STREAM_ENABLE_FLAG 0x80000000
  38. #define SCA_INDEFINITE_STREAM_FLAG 0x40000000
  39. //+-------------------------------------------------------------------------
  40. // Parameters, data used to encode the messages.
  41. //--------------------------------------------------------------------------
  42. static DWORD dwCryptProvType = PROV_RSA_FULL;
  43. static DWORD dwPubKeyBitLen = 0;
  44. static LPCSTR pszHashName = "md5";
  45. static LPCSTR pszEncryptName = "rc2";
  46. static DWORD dwEncryptBitLen = 0;
  47. static BOOL fEncryptIV = FALSE;
  48. static BOOL fVerbose = FALSE;
  49. static HCERTSTORE hCertStore = 0;
  50. static LPSTR pszMsgCertFilename = NULL;
  51. static LPSTR pszMsgEncodedFilename = NULL;
  52. static LPSTR pszReadEncodedFilename = NULL;
  53. static BOOL fDetached = FALSE;
  54. static DWORD dwMsgEncodingType = PKCS_7_ASN_ENCODING;
  55. static DWORD dwCertEncodingType = X509_ASN_ENCODING;
  56. static DWORD dwSignKeySpec = AT_SIGNATURE;
  57. static BOOL fInnerSigned = FALSE;
  58. static LPSTR pszCertNameFindStr = NULL;
  59. #ifdef ENABLE_SCA_STREAM_TEST
  60. static BOOL fStream = FALSE;
  61. static BOOL fIndefiniteStream = FALSE;
  62. #endif
  63. BOOL fNoRecipients = FALSE;
  64. BOOL fAllRecipients = FALSE;
  65. BOOL fDhRecipient = FALSE;
  66. BOOL fEncapsulatedContent = FALSE;
  67. #ifdef CMS_PKCS7
  68. BOOL fSP3Encrypt = FALSE;
  69. BOOL fDefaultGetSigner = FALSE;
  70. BOOL fRecipientKeyId = FALSE;
  71. BOOL fSignerKeyId = FALSE;
  72. BOOL fHashEncryptionAlgorithm = FALSE;
  73. BOOL fNoSalt = FALSE;
  74. #define MAX_SALT_LEN 11
  75. BYTE rgbSalt[MAX_SALT_LEN];
  76. CMSG_RC4_AUX_INFO RC4AuxInfo;
  77. BOOL fSilentKey = FALSE;
  78. #endif
  79. #define MAX_MSG_CERT 30
  80. #define MAX_MSG_CRL 30
  81. #define MAX_RECIPIENT_CERT 50
  82. #define MAX_HASH_LEN 20
  83. static LPCSTR pszMsgContent = "Message Content Message Content";
  84. static LPCSTR pszMsgContent2 = "Second Message Content";
  85. static LPCSTR pszMsgContent3 = "Third Message Content";
  86. static const BYTE *pbToBeEncoded = (const BYTE *) pszMsgContent;
  87. static DWORD cbToBeEncoded = strlen(pszMsgContent) + 1;
  88. #define DETACHED_CONTENT_CNT 3
  89. static const BYTE *rgpbDetachedToBeEncoded[DETACHED_CONTENT_CNT] = {
  90. (const BYTE *) pszMsgContent,
  91. (const BYTE *) pszMsgContent2,
  92. (const BYTE *) pszMsgContent3
  93. };
  94. static DWORD rgcbDetachedToBeEncoded[DETACHED_CONTENT_CNT] = {
  95. strlen(pszMsgContent) + 1,
  96. strlen(pszMsgContent2) + 1,
  97. strlen(pszMsgContent3) + 1
  98. };
  99. #define DELTA_LESS_LENGTH 8
  100. #define DELTA_MORE_LENGTH 32
  101. static CMSG_RC2_AUX_INFO RC2AuxInfo;
  102. BOOL fAuthAttr = FALSE;
  103. #define AUTH_ATTR_COUNT 2
  104. BYTE attr1[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','1',0};
  105. BYTE attr2[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','2',0};
  106. BYTE attr3[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','3',0};
  107. CRYPT_ATTR_BLOB rgatrblob1[] = {
  108. { sizeof( attr1), attr1}
  109. };
  110. CRYPT_ATTR_BLOB rgatrblob2[] = {
  111. { sizeof( attr2), attr2},
  112. { sizeof( attr3), attr3}
  113. };
  114. CRYPT_ATTRIBUTE rgAuthAttr[AUTH_ATTR_COUNT] = {
  115. {"1.2.3.5.7", 1, rgatrblob1},
  116. {"1.2.3.5.11", 2, rgatrblob2}
  117. };
  118. static inline IsDSSProv(
  119. IN DWORD dwProvType
  120. )
  121. {
  122. return (PROV_DSS == dwProvType || PROV_DSS_DH == dwProvType);
  123. }
  124. //+-------------------------------------------------------------------------
  125. // Error output routines
  126. //--------------------------------------------------------------------------
  127. static void PrintError(LPCSTR pszMsg)
  128. {
  129. printf("%s\n", pszMsg);
  130. }
  131. static void PrintLastError(LPCSTR pszMsg)
  132. {
  133. DWORD dwErr = GetLastError();
  134. printf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
  135. }
  136. static void CheckLessLength(
  137. LPCSTR pszMsg,
  138. BOOL fResult,
  139. DWORD cbActual,
  140. DWORD cbExpected
  141. )
  142. {
  143. if (fResult)
  144. printf("%s failed => expected ERROR_MORE_DATA\n", pszMsg);
  145. else {
  146. DWORD dwErr = GetLastError();
  147. if (fVerbose)
  148. printf("%s with less length got expected error => 0x%x (%d)\n",
  149. pszMsg, dwErr, dwErr);
  150. if (ERROR_MORE_DATA != dwErr)
  151. printf("%s failed => LastError = %d, expected = %d\n",
  152. pszMsg, dwErr, ERROR_MORE_DATA);
  153. }
  154. if (cbActual != cbExpected)
  155. printf("%s failed => ", pszMsg);
  156. if (fVerbose || cbActual != cbExpected)
  157. printf("cbData = %d, expected = %d\n", cbActual, cbExpected);
  158. }
  159. static void CheckMoreLength(
  160. LPCSTR pszMsg,
  161. DWORD cbActual,
  162. DWORD cbExpected
  163. )
  164. {
  165. if (cbActual != cbExpected) {
  166. printf("%s failed => ", pszMsg);
  167. printf("cbData = %d, expected = %d\n", cbActual, cbExpected);
  168. }
  169. }
  170. //+-------------------------------------------------------------------------
  171. // Test allocation and free routines
  172. //--------------------------------------------------------------------------
  173. static void *TestAlloc(
  174. IN size_t cbBytes
  175. )
  176. {
  177. void *pv;
  178. pv = malloc(cbBytes);
  179. if (pv == NULL) {
  180. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  181. PrintLastError("TestAlloc");
  182. }
  183. return pv;
  184. }
  185. static void TestFree(
  186. IN void *pv
  187. )
  188. {
  189. if (pv)
  190. free(pv);
  191. }
  192. static BOOL AllocAndEncodeObject(
  193. IN LPCSTR lpszStructType,
  194. IN const void *pvStructInfo,
  195. OUT BYTE **ppbEncoded,
  196. OUT DWORD *pcbEncoded
  197. )
  198. {
  199. BOOL fResult;
  200. BYTE *pbEncoded = NULL;
  201. DWORD cbEncoded;
  202. fResult = CryptEncodeObject(
  203. dwCertEncodingType,
  204. lpszStructType,
  205. pvStructInfo,
  206. NULL, // pbEncoded
  207. &cbEncoded);
  208. if (!fResult || cbEncoded == 0) {
  209. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  210. printf("CryptEncodeObject(StructType: %d, cbEncoded == 0)",
  211. (DWORD)(DWORD_PTR) lpszStructType);
  212. else
  213. printf("CryptEncodeObject(StructType: %s, cbEncoded == 0)",
  214. lpszStructType);
  215. PrintLastError("");
  216. goto ErrorReturn;
  217. }
  218. if (NULL == (pbEncoded = (BYTE *) TestAlloc(cbEncoded)))
  219. goto ErrorReturn;
  220. if (!CryptEncodeObject(
  221. dwCertEncodingType,
  222. lpszStructType,
  223. pvStructInfo,
  224. pbEncoded,
  225. &cbEncoded
  226. )) {
  227. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  228. printf("CryptEncodeObject(StructType: %d)",
  229. (DWORD)(DWORD_PTR) lpszStructType);
  230. else
  231. printf("CryptEncodeObject(StructType: %s)",
  232. lpszStructType);
  233. PrintLastError("");
  234. goto ErrorReturn;
  235. }
  236. fResult = TRUE;
  237. CommonReturn:
  238. *ppbEncoded = pbEncoded;
  239. *pcbEncoded = cbEncoded;
  240. return fResult;
  241. ErrorReturn:
  242. if (pbEncoded) {
  243. TestFree(pbEncoded);
  244. pbEncoded = NULL;
  245. }
  246. cbEncoded = 0;
  247. fResult = FALSE;
  248. goto CommonReturn;
  249. }
  250. static PCCRYPT_OID_INFO GetOIDInfo(LPCSTR pszName, DWORD dwGroupId = 0)
  251. {
  252. WCHAR wszName[256];
  253. PCCRYPT_OID_INFO pInfo;
  254. MultiByteToWideChar(
  255. CP_ACP,
  256. 0, // dwFlags
  257. pszName,
  258. -1, // null terminated
  259. wszName,
  260. sizeof(wszName) / sizeof(wszName[0]));
  261. return CryptFindOIDInfo(
  262. CRYPT_OID_INFO_NAME_KEY,
  263. (void *) wszName,
  264. dwGroupId
  265. );
  266. }
  267. static LPCSTR GetOID(LPCSTR pszName, DWORD dwGroupId = 0)
  268. {
  269. PCCRYPT_OID_INFO pInfo;
  270. if (pInfo = GetOIDInfo(pszName, dwGroupId))
  271. return pInfo->pszOID;
  272. else
  273. return NULL;
  274. }
  275. static ALG_ID GetAlgid(LPCSTR pszName, DWORD dwGroupId = 0)
  276. {
  277. PCCRYPT_OID_INFO pInfo;
  278. if (pInfo = GetOIDInfo(pszName, dwGroupId))
  279. return pInfo->Algid;
  280. else
  281. return 0;
  282. }
  283. #define CROW 16
  284. static void PrintBytes(LPCSTR pszHdr, BYTE *pb, DWORD cbSize)
  285. {
  286. ULONG cb, i;
  287. while (cbSize > 0)
  288. {
  289. printf("%s", pszHdr);
  290. cb = min(CROW, cbSize);
  291. cbSize -= cb;
  292. for (i = 0; i<cb; i++)
  293. printf(" %02X", pb[i]);
  294. for (i = cb; i<CROW; i++)
  295. printf(" ");
  296. printf(" '");
  297. for (i = 0; i<cb; i++)
  298. if (pb[i] >= 0x20 && pb[i] <= 0x7f)
  299. printf("%c", pb[i]);
  300. else
  301. printf(".");
  302. pb += cb;
  303. printf("'\n");
  304. }
  305. }
  306. //+-------------------------------------------------------------------------
  307. // Allocate and read an encoded DER blob from a file
  308. //--------------------------------------------------------------------------
  309. static BOOL ReadDERFromFile(
  310. LPCSTR pszFileName,
  311. PBYTE *ppbDER,
  312. PDWORD pcbDER
  313. )
  314. {
  315. BOOL fRet;
  316. HANDLE hFile = 0;
  317. PBYTE pbDER = NULL;
  318. DWORD cbDER;
  319. DWORD cbRead;
  320. if( INVALID_HANDLE_VALUE == (hFile = CreateFile( pszFileName, GENERIC_READ,
  321. FILE_SHARE_READ | FILE_SHARE_WRITE,
  322. NULL, OPEN_EXISTING, 0, NULL))) {
  323. printf( "can't open %s\n", pszFileName);
  324. goto ErrorReturn;
  325. }
  326. cbDER = GetFileSize( hFile, NULL);
  327. if (cbDER == 0) {
  328. printf( "empty file %s\n", pszFileName);
  329. goto ErrorReturn;
  330. }
  331. if (NULL == (pbDER = (PBYTE)TestAlloc(cbDER))) {
  332. printf( "can't alloc %d bytes\n", cbDER);
  333. goto ErrorReturn;
  334. }
  335. if (!ReadFile( hFile, pbDER, cbDER, &cbRead, NULL) ||
  336. (cbRead != cbDER)) {
  337. printf( "can't read %s\n", pszFileName);
  338. goto ErrorReturn;
  339. }
  340. *ppbDER = pbDER;
  341. *pcbDER = cbDER;
  342. fRet = TRUE;
  343. CommonReturn:
  344. if (hFile)
  345. CloseHandle(hFile);
  346. return fRet;
  347. ErrorReturn:
  348. if (pbDER)
  349. TestFree(pbDER);
  350. *ppbDER = NULL;
  351. *pcbDER = 0;
  352. fRet = FALSE;
  353. goto CommonReturn;
  354. }
  355. //+-------------------------------------------------------------------------
  356. // Write an encoded DER blob to a file
  357. //--------------------------------------------------------------------------
  358. static BOOL WriteDERToFile(
  359. LPCSTR pszFileName,
  360. PBYTE pbDER,
  361. DWORD cbDER
  362. )
  363. {
  364. BOOL fResult;
  365. // Write the Encoded Blob to the file
  366. HANDLE hFile;
  367. hFile = CreateFile(pszFileName,
  368. GENERIC_WRITE,
  369. 0, // fdwShareMode
  370. NULL, // lpsa
  371. CREATE_ALWAYS,
  372. 0, // fdwAttrsAndFlags
  373. 0); // TemplateFile
  374. if (INVALID_HANDLE_VALUE == hFile) {
  375. fResult = FALSE;
  376. PrintLastError("WriteDERToFile::CreateFile");
  377. } else {
  378. DWORD dwBytesWritten;
  379. if (!(fResult = WriteFile(
  380. hFile,
  381. pbDER,
  382. cbDER,
  383. &dwBytesWritten,
  384. NULL // lpOverlapped
  385. )))
  386. PrintLastError("WriteDERToFile::WriteFile");
  387. CloseHandle(hFile);
  388. }
  389. return fResult;
  390. }
  391. static HCERTSTORE OpenStore(LPCSTR pszStoreFilename)
  392. {
  393. HCERTSTORE hStore;
  394. HANDLE hFile = 0;
  395. if( INVALID_HANDLE_VALUE == (hFile = CreateFile(pszStoreFilename,
  396. GENERIC_READ,
  397. FILE_SHARE_READ | FILE_SHARE_WRITE,
  398. NULL, OPEN_EXISTING, 0, NULL))) {
  399. printf( "can't open %s\n", pszStoreFilename);
  400. hStore = CertOpenStore(
  401. CERT_STORE_PROV_MEMORY,
  402. dwCertEncodingType,
  403. 0, // hProv
  404. 0, // dwFlags
  405. NULL // pvPara
  406. );
  407. } else {
  408. hStore = CertOpenStore(
  409. CERT_STORE_PROV_FILE,
  410. dwCertEncodingType,
  411. 0, // hProv
  412. 0, // dwFlags
  413. hFile
  414. );
  415. CloseHandle(hFile);
  416. }
  417. if (hStore == NULL)
  418. PrintLastError("CertOpenStore");
  419. return hStore;
  420. }
  421. static void SaveStore(HCERTSTORE hStore, LPCSTR pszSaveFilename)
  422. {
  423. HANDLE hFile;
  424. hFile = CreateFile(pszSaveFilename,
  425. GENERIC_WRITE,
  426. 0, // fdwShareMode
  427. NULL, // lpsa
  428. CREATE_ALWAYS,
  429. 0, // fdwAttrsAndFlags
  430. 0); // TemplateFile
  431. if (INVALID_HANDLE_VALUE == hFile) {
  432. printf( "can't open %s\n", pszSaveFilename);
  433. PrintLastError("CloseStore::CreateFile");
  434. } else {
  435. if (!CertSaveStore(
  436. hStore,
  437. 0, // dwEncodingType,
  438. CERT_STORE_SAVE_AS_STORE,
  439. CERT_STORE_SAVE_TO_FILE,
  440. (void *) hFile,
  441. 0 // dwFlags
  442. ))
  443. PrintLastError("CertSaveStore");
  444. CloseHandle(hFile);
  445. }
  446. }
  447. static void DisplayCert(PCCERT_CONTEXT pCert);
  448. static void DisplayCrl(PCCRL_CONTEXT pCrl);
  449. //+-------------------------------------------------------------------------
  450. // Functions for initializing and freeing SCA parameters
  451. //--------------------------------------------------------------------------
  452. static BOOL InitSignPara(OUT PCRYPT_SIGN_MESSAGE_PARA pPara);
  453. static void FreeSignPara(IN PCRYPT_SIGN_MESSAGE_PARA pPara);
  454. static BOOL InitVerifyPara(OUT PCRYPT_VERIFY_MESSAGE_PARA pPara);
  455. static void FreeVerifyPara(IN PCRYPT_VERIFY_MESSAGE_PARA pPara);
  456. static BOOL InitEncryptPara(
  457. OUT PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
  458. OUT DWORD *pcRecipientCert,
  459. OUT PCCERT_CONTEXT **pppRecipientCert
  460. );
  461. static void FreeEncryptPara(
  462. IN PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
  463. IN DWORD cRecipientCert,
  464. IN PCCERT_CONTEXT *ppRecipientCert
  465. );
  466. static BOOL InitDecryptPara(OUT PCRYPT_DECRYPT_MESSAGE_PARA pPara);
  467. static void FreeDecryptPara(IN PCRYPT_DECRYPT_MESSAGE_PARA pPara);
  468. static BOOL InitHashPara(OUT PCRYPT_HASH_MESSAGE_PARA pPara);
  469. static void FreeHashPara(IN PCRYPT_HASH_MESSAGE_PARA pPara);
  470. //+-------------------------------------------------------------------------
  471. // Top Level Test Functions
  472. //--------------------------------------------------------------------------
  473. static BOOL TestSign()
  474. {
  475. BOOL fResult;
  476. CRYPT_SIGN_MESSAGE_PARA SignPara;
  477. CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
  478. BYTE *pbSignedBlob = NULL;
  479. DWORD cbSignedBlob;
  480. BYTE *pbDecoded = NULL;
  481. DWORD cbDecoded;
  482. DWORD *pcbDecoded;
  483. PCCERT_CONTEXT pSignerCert = NULL;
  484. PCCERT_CONTEXT pSignerCert2 = NULL;
  485. LONG lSignerCount;
  486. BYTE *pbDecoded2 = NULL;
  487. DWORD cbDecoded2;
  488. DWORD dwMsgType;
  489. DWORD cbData;
  490. DWORD dwInnerContentType = 0x1233467;
  491. DWORD cToBeSigned;
  492. const BYTE **ppbToBeSigned;
  493. DWORD *pcbToBeSigned;
  494. ppbToBeSigned = rgpbDetachedToBeEncoded;
  495. pcbToBeSigned = rgcbDetachedToBeEncoded;
  496. if (fDetached)
  497. cToBeSigned = DETACHED_CONTENT_CNT;
  498. else if (0 == cbToBeEncoded) {
  499. cToBeSigned = 0;
  500. ppbToBeSigned = NULL;
  501. pcbToBeSigned = NULL;
  502. } else
  503. cToBeSigned = 1;
  504. if (pszReadEncodedFilename)
  505. fResult = TRUE;
  506. else
  507. fResult = InitSignPara(&SignPara);
  508. fResult &= InitVerifyPara(&VerifyPara);
  509. if (!fResult) goto ErrorReturn;
  510. if (pszReadEncodedFilename) {
  511. if (!ReadDERFromFile(
  512. pszReadEncodedFilename,
  513. &pbSignedBlob,
  514. &cbSignedBlob
  515. ))
  516. goto ErrorReturn;
  517. } else {
  518. cbSignedBlob = 1; // bad length should be ignored
  519. fResult = CryptSignMessage(
  520. &SignPara,
  521. fDetached,
  522. cToBeSigned,
  523. ppbToBeSigned,
  524. pcbToBeSigned,
  525. NULL, // pbSignedBlob
  526. &cbSignedBlob
  527. );
  528. if (!fResult || cbSignedBlob == 0) {
  529. PrintLastError("CryptSignMessage(cb == 0)");
  530. goto ErrorReturn;
  531. }
  532. if (NULL == (pbSignedBlob = (BYTE *) TestAlloc(
  533. cbSignedBlob + DELTA_MORE_LENGTH)))
  534. goto ErrorReturn;
  535. if (!CryptSignMessage(
  536. &SignPara,
  537. fDetached,
  538. cToBeSigned,
  539. ppbToBeSigned,
  540. pcbToBeSigned,
  541. pbSignedBlob,
  542. &cbSignedBlob
  543. )) {
  544. PrintLastError("CryptSignMessage");
  545. goto ErrorReturn;
  546. }
  547. cbData = cbSignedBlob - DELTA_LESS_LENGTH;
  548. fResult = CryptSignMessage(
  549. &SignPara,
  550. fDetached,
  551. cToBeSigned,
  552. ppbToBeSigned,
  553. pcbToBeSigned,
  554. pbSignedBlob,
  555. &cbData
  556. );
  557. // Note, length varies for DSS
  558. if (!IsDSSProv(dwCryptProvType))
  559. CheckLessLength("CryptSignMessage", fResult, cbData, cbSignedBlob);
  560. cbData = cbSignedBlob + DELTA_MORE_LENGTH;
  561. if (!CryptSignMessage(
  562. &SignPara,
  563. fDetached,
  564. cToBeSigned,
  565. ppbToBeSigned,
  566. pcbToBeSigned,
  567. pbSignedBlob,
  568. &cbData
  569. )) {
  570. PrintLastError("CryptSignMessage");
  571. goto ErrorReturn;
  572. }
  573. // Note, length varies for DSS
  574. if (!IsDSSProv(dwCryptProvType))
  575. CheckMoreLength("CryptSignMessage", cbData, cbSignedBlob);
  576. cbSignedBlob = cbData;
  577. }
  578. if (NULL == pszReadEncodedFilename && pszMsgEncodedFilename)
  579. WriteDERToFile(pszMsgEncodedFilename, pbSignedBlob, cbSignedBlob);
  580. if (pszMsgCertFilename) {
  581. HCERTSTORE hMsgCertStore;
  582. if (hMsgCertStore = CryptGetMessageCertificates(
  583. dwMsgEncodingType | dwCertEncodingType,
  584. 0, // hCryptProv,
  585. 0, // dwFlags
  586. pbSignedBlob,
  587. cbSignedBlob
  588. )) {
  589. SaveStore(hMsgCertStore, pszMsgCertFilename);
  590. CertCloseStore(hMsgCertStore, 0);
  591. } else
  592. PrintLastError("CryptGetMessageCertificates");
  593. }
  594. lSignerCount = CryptGetMessageSignerCount(dwMsgEncodingType,
  595. pbSignedBlob, cbSignedBlob);
  596. if (lSignerCount < 0)
  597. PrintLastError("CryptGetMessageSignerCount");
  598. else if (fVerbose)
  599. printf("Signer Count: %d\n", lSignerCount);
  600. if (fDetached) {
  601. if (!CryptVerifyDetachedMessageSignature(
  602. &VerifyPara,
  603. 0, // dwSignerIndex
  604. pbSignedBlob,
  605. cbSignedBlob,
  606. DETACHED_CONTENT_CNT,
  607. rgpbDetachedToBeEncoded,
  608. rgcbDetachedToBeEncoded,
  609. &pSignerCert
  610. )) {
  611. PrintLastError("CryptVerifyDetachedMessageSignature");
  612. goto ErrorReturn;
  613. }
  614. } else {
  615. cbDecoded = 3; // bad length should be ignored
  616. if (!CryptVerifyMessageSignature(
  617. &VerifyPara,
  618. 0, // dwSignerIndex
  619. pbSignedBlob,
  620. cbSignedBlob,
  621. NULL, // pbDecoded
  622. &cbDecoded,
  623. NULL // ppSignerCert
  624. )) {
  625. PrintLastError("CryptVerifyMessageSignature");
  626. goto ErrorReturn;
  627. }
  628. if (cbDecoded == 0)
  629. // Message doesn't contain any content, only certs and CRLs
  630. pcbDecoded = NULL;
  631. else {
  632. pcbDecoded = &cbDecoded;
  633. if (NULL == (pbDecoded = (BYTE *) TestAlloc(
  634. cbDecoded + DELTA_MORE_LENGTH)))
  635. goto ErrorReturn;
  636. }
  637. if (!CryptVerifyMessageSignature(
  638. &VerifyPara,
  639. 0, // dwSignerIndex
  640. pbSignedBlob,
  641. cbSignedBlob,
  642. pbDecoded,
  643. pcbDecoded,
  644. &pSignerCert
  645. )) {
  646. if (GetLastError() == CRYPT_E_NO_SIGNER) {
  647. printf("message has no signers\n");
  648. // Try again with all out parameters set to NULL.
  649. // GetSignerCertificate should still be called
  650. fResult = CryptVerifyMessageSignature(
  651. &VerifyPara,
  652. 0, // dwSignerIndex
  653. pbSignedBlob,
  654. cbSignedBlob,
  655. NULL, // pbDecoded
  656. NULL, // pcbDecoded
  657. NULL // ppSignerCert
  658. );
  659. if (fResult) {
  660. printf("CryptVerifyMessageSignature(no signer, NULL outs)");
  661. printf(" failed => returned SUCCESS\n");
  662. } else if (GetLastError() != CRYPT_E_NO_SIGNER)
  663. PrintLastError("CryptVerifyMessageSignature(no signer, NULL outs)");
  664. } else {
  665. PrintLastError("CryptVerifyMessageSignature");
  666. goto ErrorReturn;
  667. }
  668. }
  669. if (cbDecoded > DELTA_LESS_LENGTH) {
  670. cbData = cbDecoded - DELTA_LESS_LENGTH;
  671. fResult = CryptVerifyMessageSignature(
  672. &VerifyPara,
  673. 0, // dwSignerIndex
  674. pbSignedBlob,
  675. cbSignedBlob,
  676. pbDecoded,
  677. &cbData,
  678. NULL // ppSignerCert
  679. );
  680. CheckLessLength("CryptVerifyMessageSignature", fResult, cbData,
  681. cbDecoded);
  682. cbData = cbDecoded + DELTA_MORE_LENGTH;
  683. if (!CryptVerifyMessageSignature(
  684. &VerifyPara,
  685. 0, // dwSignerIndex
  686. pbSignedBlob,
  687. cbSignedBlob,
  688. pbDecoded,
  689. &cbData,
  690. NULL // ppSignerCert
  691. )) {
  692. if (GetLastError() == CRYPT_E_NO_SIGNER)
  693. printf("message has no signers\n");
  694. else {
  695. PrintLastError("CryptVerifyMessageSignature");
  696. goto ErrorReturn;
  697. }
  698. }
  699. CheckMoreLength("CryptVerifyMessageSignature", cbData, cbDecoded);
  700. }
  701. }
  702. if (pSignerCert) {
  703. if (fVerbose) {
  704. printf("----- Verifier -----\n");
  705. DisplayCert(pSignerCert);
  706. }
  707. } else
  708. printf("no verifier cert\n");
  709. if (!fDetached) {
  710. if (!pszReadEncodedFilename) {
  711. if (cbDecoded == cbToBeEncoded &&
  712. memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
  713. if (fVerbose)
  714. printf("SUCCESS:: Decoded == ToBeEncoded\n");
  715. } else
  716. printf("***** ERROR:: Decoded != ToBeEncoded\n");
  717. }
  718. if (fVerbose) {
  719. printf("Decoded bytes::\n");
  720. PrintBytes(" ", pbDecoded, cbDecoded);
  721. }
  722. if (pszReadEncodedFilename && pszMsgEncodedFilename)
  723. WriteDERToFile(pszMsgEncodedFilename, pbDecoded, cbDecoded);
  724. cbDecoded2 = cbDecoded;
  725. if (cbDecoded2 ) {
  726. if (NULL == (pbDecoded2 = (BYTE *) TestAlloc(
  727. cbDecoded2 + DELTA_MORE_LENGTH)))
  728. goto ErrorReturn;
  729. }
  730. if (!CryptDecodeMessage(
  731. CMSG_ALL_FLAGS,
  732. NULL, // pDecryptPara
  733. &VerifyPara,
  734. 0, // dwSignerIndex
  735. pbSignedBlob,
  736. cbSignedBlob,
  737. 0, // dwPrevInnerContentType
  738. &dwMsgType,
  739. &dwInnerContentType,
  740. pbDecoded2,
  741. &cbDecoded2,
  742. NULL, // ppXchgCert
  743. &pSignerCert2
  744. )) {
  745. if (GetLastError() == CRYPT_E_NO_SIGNER)
  746. printf("message has no signers\n");
  747. else {
  748. PrintLastError("CryptDecodeMessage(CMSG_SIGNED)");
  749. goto ErrorReturn;
  750. }
  751. }
  752. if (cbDecoded2 > DELTA_LESS_LENGTH) {
  753. cbData = cbDecoded2 - DELTA_LESS_LENGTH;
  754. fResult = CryptDecodeMessage(
  755. CMSG_ALL_FLAGS,
  756. NULL, // pDecryptPara
  757. &VerifyPara,
  758. 0, // dwSignerIndex
  759. pbSignedBlob,
  760. cbSignedBlob,
  761. 0, // dwPrevInnerContentType
  762. &dwMsgType,
  763. NULL, // pdwInnerContentType
  764. pbDecoded2,
  765. &cbData,
  766. NULL, // ppXchgCert
  767. NULL // ppSignerCert
  768. );
  769. CheckLessLength("CryptDecodeMessage(SIGN)", fResult, cbData,
  770. cbDecoded2);
  771. cbData = cbDecoded2 + DELTA_MORE_LENGTH;
  772. if (!CryptDecodeMessage(
  773. CMSG_ALL_FLAGS,
  774. NULL, // pDecryptPara
  775. &VerifyPara,
  776. 0, // dwSignerIndex
  777. pbSignedBlob,
  778. cbSignedBlob,
  779. 0, // dwPrevInnerContentType
  780. &dwMsgType,
  781. &dwInnerContentType,
  782. pbDecoded2,
  783. &cbData,
  784. NULL, // ppXchgCert
  785. NULL // ppSignerCert
  786. )) {
  787. if (GetLastError() == CRYPT_E_NO_SIGNER)
  788. printf("message has no signers\n");
  789. else {
  790. PrintLastError("CryptDecodeMessage(CMSG_SIGNED)");
  791. goto ErrorReturn;
  792. }
  793. }
  794. CheckMoreLength("CryptDecodeMessage", cbData, cbDecoded2);
  795. }
  796. if (dwMsgType != CMSG_SIGNED)
  797. printf("failed :: dwMsgType(%d) != CMSG_SIGNED\n", dwMsgType);
  798. else if (fVerbose)
  799. printf("SUCCESS:: CryptDecodeMessage(CMSG_SIGNED)\n");
  800. #ifdef CMS_PKCS7
  801. if ((fEncapsulatedContent && dwInnerContentType != CMSG_HASHED) ||
  802. (!fEncapsulatedContent && dwInnerContentType != CMSG_DATA)) {
  803. #else
  804. if (dwInnerContentType != CMSG_DATA) {
  805. #endif // CMS_PKCS7
  806. if (pszReadEncodedFilename)
  807. printf("SIGNED InnerContentType = %d\n", dwInnerContentType);
  808. else {
  809. #ifdef CMS_PKCS7
  810. if (fEncapsulatedContent)
  811. printf("SIGNED failed :: dwInnerContentType(%d) != CMSG_HASHED\n",
  812. dwInnerContentType);
  813. else
  814. #endif // CMS_PKCS7
  815. printf("SIGNED failed :: dwInnerContentType(%d) != CMSG_DATA\n",
  816. dwInnerContentType);
  817. }
  818. }
  819. if (cbDecoded2 != cbDecoded ||
  820. (cbDecoded > 0 &&
  821. memcmp(pbDecoded, pbDecoded2, cbDecoded) != 0))
  822. printf("failed :: bad decoded content for CryptDecodeMessage(CMSG_SIGNED)\n");
  823. if (pSignerCert && (pSignerCert2 == NULL ||
  824. !CertCompareCertificate(dwCertEncodingType,
  825. pSignerCert->pCertInfo, pSignerCert2->pCertInfo)))
  826. printf("failed :: bad signer cert for CryptDecodeMessage(CMSG_SIGNED)\n");
  827. }
  828. fResult = TRUE;
  829. goto CommonReturn;
  830. ErrorReturn:
  831. fResult = FALSE;
  832. CommonReturn:
  833. if (!pszReadEncodedFilename)
  834. FreeSignPara(&SignPara);
  835. FreeVerifyPara(&VerifyPara);
  836. if (pbSignedBlob)
  837. TestFree(pbSignedBlob);
  838. if (pbDecoded)
  839. TestFree(pbDecoded);
  840. if (pbDecoded2)
  841. TestFree(pbDecoded2);
  842. if (pSignerCert)
  843. CertFreeCertificateContext(pSignerCert);
  844. if (pSignerCert2)
  845. CertFreeCertificateContext(pSignerCert2);
  846. return fResult;
  847. }
  848. static BOOL TestEnvelope()
  849. {
  850. BOOL fResult;
  851. CRYPT_ENCRYPT_MESSAGE_PARA EncryptPara;
  852. DWORD cRecipientCert;
  853. PCCERT_CONTEXT *ppRecipientCert;
  854. CRYPT_DECRYPT_MESSAGE_PARA DecryptPara;
  855. BYTE *pbEncryptedBlob = NULL;
  856. DWORD cbEncryptedBlob;
  857. BYTE *pbDecoded = NULL;
  858. DWORD cbDecoded;
  859. PCCERT_CONTEXT pXchgCert = NULL;
  860. BYTE *pbDecoded2 = NULL;
  861. DWORD cbDecoded2;
  862. DWORD dwMsgType;
  863. PCCERT_CONTEXT pXchgCert2 = NULL;
  864. DWORD cbData;
  865. DWORD dwInnerContentType = 0x1233467;
  866. if (pszReadEncodedFilename)
  867. fResult = TRUE;
  868. else
  869. fResult = InitEncryptPara(&EncryptPara, &cRecipientCert,
  870. &ppRecipientCert);
  871. fResult &= InitDecryptPara(&DecryptPara);
  872. if (!fResult) goto ErrorReturn;
  873. if (pszReadEncodedFilename) {
  874. if (!ReadDERFromFile(
  875. pszReadEncodedFilename,
  876. &pbEncryptedBlob,
  877. &cbEncryptedBlob
  878. ))
  879. goto ErrorReturn;
  880. } else {
  881. fResult = CryptEncryptMessage(
  882. &EncryptPara,
  883. cRecipientCert,
  884. ppRecipientCert,
  885. pbToBeEncoded,
  886. cbToBeEncoded,
  887. NULL, // pbEncryptedBlob
  888. &cbEncryptedBlob
  889. );
  890. if (!fResult || cbEncryptedBlob == 0) {
  891. PrintLastError("CryptEncryptMessage(cb == 0)");
  892. goto ErrorReturn;
  893. }
  894. if (NULL == (pbEncryptedBlob = (BYTE *) TestAlloc(
  895. cbEncryptedBlob + DELTA_MORE_LENGTH)))
  896. goto ErrorReturn;
  897. fResult = CryptEncryptMessage(
  898. &EncryptPara,
  899. cRecipientCert,
  900. ppRecipientCert,
  901. pbToBeEncoded,
  902. cbToBeEncoded,
  903. pbEncryptedBlob,
  904. &cbEncryptedBlob
  905. );
  906. if (!fResult) {
  907. PrintLastError("CryptEncryptMessage");
  908. goto ErrorReturn;
  909. }
  910. cbData = cbEncryptedBlob - DELTA_LESS_LENGTH;
  911. fResult = CryptEncryptMessage(
  912. &EncryptPara,
  913. cRecipientCert,
  914. ppRecipientCert,
  915. pbToBeEncoded,
  916. cbToBeEncoded,
  917. pbEncryptedBlob,
  918. &cbData
  919. );
  920. // Note, length varies for DH
  921. if (!fDhRecipient)
  922. CheckLessLength("CryptEncryptMessage", fResult, cbData,
  923. cbEncryptedBlob);
  924. cbData = cbEncryptedBlob + DELTA_MORE_LENGTH;
  925. fResult = CryptEncryptMessage(
  926. &EncryptPara,
  927. cRecipientCert,
  928. ppRecipientCert,
  929. pbToBeEncoded,
  930. cbToBeEncoded,
  931. pbEncryptedBlob,
  932. &cbData
  933. );
  934. if (!fResult) {
  935. PrintLastError("CryptEncryptMessage");
  936. goto ErrorReturn;
  937. }
  938. // Note, length varies for DH
  939. if (!fDhRecipient)
  940. CheckMoreLength("CryptEncryptMessage", cbData, cbEncryptedBlob);
  941. cbEncryptedBlob = cbData;
  942. }
  943. if (NULL == pszReadEncodedFilename && pszMsgEncodedFilename)
  944. WriteDERToFile(pszMsgEncodedFilename, pbEncryptedBlob, cbEncryptedBlob);
  945. cbDecoded = 0;
  946. fResult = CryptDecryptMessage(
  947. &DecryptPara,
  948. pbEncryptedBlob,
  949. cbEncryptedBlob,
  950. NULL, // pbDecoded
  951. &cbDecoded,
  952. NULL // ppXchgCert
  953. );
  954. if (!fResult && GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
  955. printf("message has no recipients\n");
  956. else if (!fResult || (cbToBeEncoded > 0 && cbDecoded == 0 &&
  957. NULL == pszReadEncodedFilename)) {
  958. PrintLastError("CryptDecryptMessage(cb == 0)");
  959. goto ErrorReturn;
  960. }
  961. if (NULL == (pbDecoded = (BYTE *) TestAlloc(cbDecoded + DELTA_MORE_LENGTH)))
  962. goto ErrorReturn;
  963. if (!CryptDecryptMessage(
  964. &DecryptPara,
  965. pbEncryptedBlob,
  966. cbEncryptedBlob,
  967. pbDecoded,
  968. &cbDecoded,
  969. &pXchgCert
  970. )) {
  971. if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
  972. printf("message has no recipients\n");
  973. else {
  974. PrintLastError("CryptDecryptMessage");
  975. goto ErrorReturn;
  976. }
  977. }
  978. if (pszReadEncodedFilename && pszMsgEncodedFilename)
  979. WriteDERToFile(pszMsgEncodedFilename, pbDecoded, cbDecoded);
  980. if (cbDecoded > DELTA_LESS_LENGTH) {
  981. cbData = cbDecoded - DELTA_LESS_LENGTH;
  982. fResult = CryptDecryptMessage(
  983. &DecryptPara,
  984. pbEncryptedBlob,
  985. cbEncryptedBlob,
  986. pbDecoded,
  987. &cbData,
  988. NULL // ppXchgCert
  989. );
  990. CheckLessLength("CryptDecryptMessage", fResult, cbData, cbDecoded);
  991. }
  992. cbData = cbDecoded + DELTA_MORE_LENGTH;
  993. if (!CryptDecryptMessage(
  994. &DecryptPara,
  995. pbEncryptedBlob,
  996. cbEncryptedBlob,
  997. pbDecoded,
  998. &cbData,
  999. NULL // ppXchgCert
  1000. )) {
  1001. if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
  1002. printf("message has no recipients\n");
  1003. else {
  1004. PrintLastError("CryptDecryptMessage");
  1005. goto ErrorReturn;
  1006. }
  1007. }
  1008. CheckMoreLength("CryptDecryptMessage", cbData, cbDecoded);
  1009. if (pXchgCert) {
  1010. if (fVerbose) {
  1011. printf("----- XchgCert -----\n");
  1012. DisplayCert(pXchgCert);
  1013. }
  1014. } else
  1015. printf("no xchg cert\n");
  1016. if (!pszReadEncodedFilename && !fNoRecipients) {
  1017. if (cbDecoded == cbToBeEncoded &&
  1018. memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
  1019. if (fVerbose)
  1020. printf("SUCCESS:: Decoded == ToBeEncoded\n");
  1021. } else
  1022. printf("***** ERROR:: Decoded != ToBeEncoded\n");
  1023. }
  1024. if (fVerbose) {
  1025. printf("Decoded bytes::\n");
  1026. PrintBytes(" ", pbDecoded, cbDecoded);
  1027. }
  1028. cbDecoded2 = cbDecoded;
  1029. if (NULL == (pbDecoded2 = (BYTE *) TestAlloc(
  1030. cbDecoded2 + DELTA_MORE_LENGTH)))
  1031. goto ErrorReturn;
  1032. if (!CryptDecodeMessage(
  1033. CMSG_ALL_FLAGS,
  1034. &DecryptPara,
  1035. NULL, // pVerifyPara
  1036. 0, // dwSignerIndex
  1037. pbEncryptedBlob,
  1038. cbEncryptedBlob,
  1039. 0, // dwPrevInnerContentType
  1040. &dwMsgType,
  1041. &dwInnerContentType,
  1042. pbDecoded2,
  1043. &cbDecoded2,
  1044. &pXchgCert2,
  1045. NULL // pSignerCert
  1046. )) {
  1047. if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
  1048. printf("message has no recipients\n");
  1049. else {
  1050. PrintLastError("CryptDecodeMessage(CMSG_ENVELOPED)");
  1051. goto ErrorReturn;
  1052. }
  1053. }
  1054. if (cbDecoded2 > DELTA_LESS_LENGTH) {
  1055. cbData = cbDecoded2 - DELTA_LESS_LENGTH;
  1056. fResult = CryptDecodeMessage(
  1057. CMSG_ALL_FLAGS,
  1058. &DecryptPara,
  1059. NULL, // pVerifyPara
  1060. 0, // dwSignerIndex
  1061. pbEncryptedBlob,
  1062. cbEncryptedBlob,
  1063. 0, // dwPrevInnerContentType
  1064. &dwMsgType,
  1065. NULL, // pdwInnerContentType
  1066. pbDecoded2,
  1067. &cbData,
  1068. NULL, // ppXchgCert
  1069. NULL // ppSignerCert
  1070. );
  1071. CheckLessLength("CryptDecodeMessage(ENVELOPE)", fResult, cbData,
  1072. cbDecoded2);
  1073. }
  1074. cbData = cbDecoded2 + DELTA_MORE_LENGTH;
  1075. if (!CryptDecodeMessage(
  1076. CMSG_ALL_FLAGS,
  1077. &DecryptPara,
  1078. NULL, // pVerifyPara
  1079. 0, // dwSignerIndex
  1080. pbEncryptedBlob,
  1081. cbEncryptedBlob,
  1082. 0, // dwPrevInnerContentType
  1083. &dwMsgType,
  1084. &dwInnerContentType,
  1085. pbDecoded2,
  1086. &cbData,
  1087. NULL, // ppXchgCert
  1088. NULL // ppSignerCert
  1089. )) {
  1090. if (GetLastError() == CRYPT_E_RECIPIENT_NOT_FOUND)
  1091. printf("message has no recipients\n");
  1092. else {
  1093. PrintLastError("CryptDecodeMessage(CMSG_ENVELOPED)");
  1094. goto ErrorReturn;
  1095. }
  1096. }
  1097. CheckMoreLength("CryptDecodeMessage(ENVELOPE)", cbData, cbDecoded2);
  1098. if (dwMsgType != CMSG_ENVELOPED)
  1099. printf("failed :: dwMsgType(%d) != CMSG_ENVELOPED\n", dwMsgType);
  1100. else if (fVerbose)
  1101. printf("SUCCESS:: CryptDecodeMessage(CMSG_ENVELOPED)\n");
  1102. if (!pszReadEncodedFilename) {
  1103. #ifdef CMS_PKCS7
  1104. if ((fEncapsulatedContent && dwInnerContentType != CMSG_HASHED) ||
  1105. (!fEncapsulatedContent && dwInnerContentType != CMSG_DATA)) {
  1106. #else
  1107. if (dwInnerContentType != CMSG_DATA) {
  1108. #endif // CMS_PKCS7
  1109. #ifdef CMS_PKCS7
  1110. if (fEncapsulatedContent)
  1111. printf("ENVELOPE failed :: dwInnerContentType(%d) != CMSG_HASHED\n",
  1112. dwInnerContentType);
  1113. else
  1114. #endif // CMS_PKCS7
  1115. printf("ENVELOPE failed :: dwInnerContentType(%d) != CMSG_DATA\n",
  1116. dwInnerContentType);
  1117. }
  1118. }
  1119. if (cbDecoded2 != cbDecoded ||
  1120. (cbDecoded > 0 &&
  1121. memcmp(pbDecoded, pbDecoded2, cbDecoded) != 0))
  1122. printf("failed :: bad decoded content for CryptDecodeMessage(CMSG_ENVELOPED)\n");
  1123. if (pXchgCert && (pXchgCert2 == NULL ||
  1124. !CertCompareCertificate(dwCertEncodingType,
  1125. pXchgCert->pCertInfo, pXchgCert2->pCertInfo)))
  1126. printf("failed :: bad xchg cert for CryptDecodeMessage(CMSG_ENVELOPED)\n");
  1127. fResult = TRUE;
  1128. goto CommonReturn;
  1129. ErrorReturn:
  1130. fResult = FALSE;
  1131. CommonReturn:
  1132. if (!pszReadEncodedFilename)
  1133. FreeEncryptPara(&EncryptPara, cRecipientCert, ppRecipientCert);
  1134. FreeDecryptPara(&DecryptPara);
  1135. if (pbEncryptedBlob)
  1136. TestFree(pbEncryptedBlob);
  1137. if (pbDecoded)
  1138. TestFree(pbDecoded);
  1139. if (pbDecoded2)
  1140. TestFree(pbDecoded2);
  1141. if (pXchgCert)
  1142. CertFreeCertificateContext(pXchgCert);
  1143. if (pXchgCert2)
  1144. CertFreeCertificateContext(pXchgCert2);
  1145. return fResult;
  1146. }
  1147. static BOOL TestSignAndEnvelope()
  1148. {
  1149. BOOL fResult;
  1150. CRYPT_SIGN_MESSAGE_PARA SignPara;
  1151. CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
  1152. CRYPT_ENCRYPT_MESSAGE_PARA EncryptPara;
  1153. DWORD cRecipientCert;
  1154. PCCERT_CONTEXT *ppRecipientCert;
  1155. CRYPT_DECRYPT_MESSAGE_PARA DecryptPara;
  1156. BYTE *pbEncodedBlob = NULL;
  1157. DWORD cbEncodedBlob;
  1158. BYTE *pbDecoded = NULL;
  1159. DWORD cbDecoded;
  1160. PCCERT_CONTEXT pSignerCert = NULL;
  1161. PCCERT_CONTEXT pXchgCert = NULL;
  1162. DWORD cbData;
  1163. fResult = InitSignPara(&SignPara);
  1164. fResult &= InitVerifyPara(&VerifyPara);
  1165. fResult &= InitEncryptPara(&EncryptPara, &cRecipientCert, &ppRecipientCert);
  1166. fResult &= InitDecryptPara(&DecryptPara);
  1167. if (!fResult) goto ErrorReturn;
  1168. if (fInnerSigned || fEncapsulatedContent) {
  1169. SignPara.dwFlags |= CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG;
  1170. EncryptPara.dwInnerContentType = CMSG_SIGNED;
  1171. }
  1172. fResult = CryptSignAndEncryptMessage(
  1173. &SignPara,
  1174. &EncryptPara,
  1175. cRecipientCert,
  1176. ppRecipientCert,
  1177. pbToBeEncoded,
  1178. cbToBeEncoded,
  1179. NULL, // pbEncodedBlob
  1180. &cbEncodedBlob
  1181. );
  1182. if (!fResult || cbEncodedBlob == 0) {
  1183. PrintLastError("CryptSignAndEncryptMessage(cb == 0)");
  1184. goto ErrorReturn;
  1185. }
  1186. if (NULL == (pbEncodedBlob = (BYTE *) TestAlloc(
  1187. cbEncodedBlob + DELTA_MORE_LENGTH)))
  1188. goto ErrorReturn;
  1189. fResult = CryptSignAndEncryptMessage(
  1190. &SignPara,
  1191. &EncryptPara,
  1192. cRecipientCert,
  1193. ppRecipientCert,
  1194. pbToBeEncoded,
  1195. cbToBeEncoded,
  1196. pbEncodedBlob,
  1197. &cbEncodedBlob
  1198. );
  1199. if (!fResult){
  1200. PrintLastError("CryptSignAndEncryptMessage");
  1201. goto ErrorReturn;
  1202. }
  1203. cbData = cbEncodedBlob - DELTA_LESS_LENGTH;
  1204. fResult = CryptSignAndEncryptMessage(
  1205. &SignPara,
  1206. &EncryptPara,
  1207. cRecipientCert,
  1208. ppRecipientCert,
  1209. pbToBeEncoded,
  1210. cbToBeEncoded,
  1211. pbEncodedBlob,
  1212. &cbData
  1213. );
  1214. // Note, length varies for DSS or DH
  1215. if (!IsDSSProv(dwCryptProvType) && !fDhRecipient)
  1216. CheckLessLength("CryptSignAndEncryptMessage", fResult, cbData,
  1217. cbEncodedBlob);
  1218. cbData = cbEncodedBlob + DELTA_MORE_LENGTH;
  1219. fResult = CryptSignAndEncryptMessage(
  1220. &SignPara,
  1221. &EncryptPara,
  1222. cRecipientCert,
  1223. ppRecipientCert,
  1224. pbToBeEncoded,
  1225. cbToBeEncoded,
  1226. pbEncodedBlob,
  1227. &cbData
  1228. );
  1229. if (!fResult){
  1230. PrintLastError("CryptSignAndEncryptMessage");
  1231. goto ErrorReturn;
  1232. }
  1233. // Note, length varies for DSS or DH
  1234. if (!IsDSSProv(dwCryptProvType) && !fDhRecipient)
  1235. CheckMoreLength("CryptSignAndEncryptMessage", cbData, cbEncodedBlob);
  1236. cbEncodedBlob = cbData;
  1237. if (pszMsgEncodedFilename)
  1238. WriteDERToFile(pszMsgEncodedFilename, pbEncodedBlob, cbEncodedBlob);
  1239. fResult = CryptDecryptAndVerifyMessageSignature(
  1240. &DecryptPara,
  1241. &VerifyPara,
  1242. 0, // dwSignerIndex
  1243. pbEncodedBlob,
  1244. cbEncodedBlob,
  1245. NULL, // pbDecoded
  1246. &cbDecoded,
  1247. NULL, // ppXchgCert
  1248. NULL // ppSignerCert
  1249. );
  1250. if (!fResult || cbDecoded == 0) {
  1251. PrintLastError("CryptDecryptAndVerifyMessageSignature(cb == 0)");
  1252. goto ErrorReturn;
  1253. }
  1254. if (NULL == (pbDecoded = (BYTE *) TestAlloc(
  1255. cbDecoded + DELTA_MORE_LENGTH)))
  1256. goto ErrorReturn;
  1257. if (!CryptDecryptAndVerifyMessageSignature(
  1258. &DecryptPara,
  1259. &VerifyPara,
  1260. 0, // dwSignerIndex
  1261. pbEncodedBlob,
  1262. cbEncodedBlob,
  1263. pbDecoded,
  1264. &cbDecoded,
  1265. &pXchgCert,
  1266. &pSignerCert
  1267. )) {
  1268. PrintLastError("CryptDecryptAndVerifyMessageSignature");
  1269. goto ErrorReturn;
  1270. }
  1271. cbData = cbDecoded - DELTA_LESS_LENGTH;
  1272. fResult = CryptDecryptAndVerifyMessageSignature(
  1273. &DecryptPara,
  1274. &VerifyPara,
  1275. 0, // dwSignerIndex
  1276. pbEncodedBlob,
  1277. cbEncodedBlob,
  1278. pbDecoded,
  1279. &cbData,
  1280. NULL, // ppXchgCert
  1281. NULL // ppSignerCert
  1282. );
  1283. CheckLessLength("CryptDecryptAndVerifyMessageSignature", fResult, cbData,
  1284. cbDecoded);
  1285. cbData = cbDecoded + DELTA_MORE_LENGTH;
  1286. if (!CryptDecryptAndVerifyMessageSignature(
  1287. &DecryptPara,
  1288. &VerifyPara,
  1289. 0, // dwSignerIndex
  1290. pbEncodedBlob,
  1291. cbEncodedBlob,
  1292. pbDecoded,
  1293. &cbData,
  1294. NULL, // ppXchgCert
  1295. NULL // ppSignerCert
  1296. )) {
  1297. PrintLastError("CryptDecryptAndVerifyMessageSignature");
  1298. goto ErrorReturn;
  1299. }
  1300. CheckMoreLength("CryptDecryptAndVerifyMessageSignature", cbData,
  1301. cbDecoded);
  1302. if (pXchgCert) {
  1303. if (fVerbose) {
  1304. printf("----- XchgCert -----\n");
  1305. DisplayCert(pXchgCert);
  1306. }
  1307. } else
  1308. printf("no xchg cert\n");
  1309. if (pSignerCert) {
  1310. if (fVerbose) {
  1311. printf("----- Verifier -----\n");
  1312. DisplayCert(pSignerCert);
  1313. }
  1314. } else
  1315. printf("no verifier cert\n");
  1316. if (cbDecoded == cbToBeEncoded &&
  1317. memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
  1318. if (fVerbose)
  1319. printf("SUCCESS:: Decoded == ToBeEncoded\n");
  1320. } else
  1321. printf("***** ERROR:: Decoded != ToBeEncoded\n");
  1322. if (fVerbose) {
  1323. printf("Decoded bytes::\n");
  1324. PrintBytes(" ", pbDecoded, cbDecoded);
  1325. }
  1326. fResult = TRUE;
  1327. goto CommonReturn;
  1328. ErrorReturn:
  1329. fResult = FALSE;
  1330. CommonReturn:
  1331. FreeSignPara(&SignPara);
  1332. FreeVerifyPara(&VerifyPara);
  1333. FreeEncryptPara(&EncryptPara, cRecipientCert, ppRecipientCert);
  1334. FreeDecryptPara(&DecryptPara);
  1335. if (pbEncodedBlob)
  1336. TestFree(pbEncodedBlob);
  1337. if (pbDecoded)
  1338. TestFree(pbDecoded);
  1339. if (pSignerCert)
  1340. CertFreeCertificateContext(pSignerCert);
  1341. if (pXchgCert)
  1342. CertFreeCertificateContext(pXchgCert);
  1343. return fResult;
  1344. }
  1345. static BOOL TestHash()
  1346. {
  1347. BOOL fResult;
  1348. CRYPT_HASH_MESSAGE_PARA HashPara;
  1349. CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
  1350. BYTE *pbHashedBlob = NULL;
  1351. DWORD cbHashedBlob;
  1352. BYTE *pbDecoded = NULL;
  1353. DWORD cbDecoded;
  1354. BYTE *pbDecoded2 = NULL;
  1355. DWORD cbDecoded2;
  1356. DWORD dwMsgType;
  1357. DWORD cbData;
  1358. DWORD dwInnerContentType = 0x1233467;
  1359. fResult = InitHashPara(&HashPara);
  1360. if (!fResult) goto ErrorReturn;
  1361. cbHashedBlob = 0;
  1362. fResult = CryptHashMessage(
  1363. &HashPara,
  1364. fDetached,
  1365. fDetached ? DETACHED_CONTENT_CNT : 1,
  1366. rgpbDetachedToBeEncoded,
  1367. rgcbDetachedToBeEncoded,
  1368. NULL, // pbHashedBlob
  1369. &cbHashedBlob,
  1370. NULL, // pbComputedHash
  1371. NULL // pcbComputedHash
  1372. );
  1373. if (!fResult || cbHashedBlob == 0) {
  1374. PrintLastError("CryptHashMessage(cb == 0)");
  1375. goto ErrorReturn;
  1376. }
  1377. if (NULL == (pbHashedBlob = (BYTE *) TestAlloc(
  1378. cbHashedBlob + DELTA_MORE_LENGTH)))
  1379. goto ErrorReturn;
  1380. if (!CryptHashMessage(
  1381. &HashPara,
  1382. fDetached,
  1383. fDetached ? DETACHED_CONTENT_CNT : 1,
  1384. rgpbDetachedToBeEncoded,
  1385. rgcbDetachedToBeEncoded,
  1386. pbHashedBlob,
  1387. &cbHashedBlob,
  1388. NULL, // pbComputedHash
  1389. NULL // pcbComputedHash
  1390. )) {
  1391. PrintLastError("CryptHashMessage");
  1392. goto ErrorReturn;
  1393. }
  1394. cbData = cbHashedBlob - DELTA_LESS_LENGTH;
  1395. fResult = CryptHashMessage(
  1396. &HashPara,
  1397. fDetached,
  1398. fDetached ? DETACHED_CONTENT_CNT : 1,
  1399. rgpbDetachedToBeEncoded,
  1400. rgcbDetachedToBeEncoded,
  1401. pbHashedBlob,
  1402. &cbData,
  1403. NULL, // pbComputedHash
  1404. NULL // pcbComputedHash
  1405. );
  1406. CheckLessLength("CryptHashMessage", fResult, cbData, cbHashedBlob);
  1407. cbData = cbHashedBlob + DELTA_MORE_LENGTH;
  1408. if (!CryptHashMessage(
  1409. &HashPara,
  1410. fDetached,
  1411. fDetached ? DETACHED_CONTENT_CNT : 1,
  1412. rgpbDetachedToBeEncoded,
  1413. rgcbDetachedToBeEncoded,
  1414. pbHashedBlob,
  1415. &cbData,
  1416. NULL, // pbComputedHash
  1417. NULL // pcbComputedHash
  1418. )) {
  1419. PrintLastError("CryptHashMessage");
  1420. goto ErrorReturn;
  1421. }
  1422. CheckMoreLength("CryptHashMessage", cbData, cbHashedBlob);
  1423. if (pszMsgEncodedFilename)
  1424. WriteDERToFile(pszMsgEncodedFilename, pbHashedBlob, cbHashedBlob);
  1425. if (fDetached) {
  1426. if (!CryptVerifyDetachedMessageHash(
  1427. &HashPara,
  1428. pbHashedBlob,
  1429. cbHashedBlob,
  1430. DETACHED_CONTENT_CNT,
  1431. rgpbDetachedToBeEncoded,
  1432. rgcbDetachedToBeEncoded,
  1433. NULL, // pbComputedHash
  1434. NULL // pcbComputedHash
  1435. )) {
  1436. PrintLastError("CryptVerifyDetachedMessageHash");
  1437. goto ErrorReturn;
  1438. }
  1439. } else {
  1440. fResult = CryptVerifyMessageHash(
  1441. &HashPara,
  1442. pbHashedBlob,
  1443. cbHashedBlob,
  1444. NULL, // pbDecoded
  1445. &cbDecoded,
  1446. NULL, // pbComputedHash
  1447. NULL // pcbComputedHash
  1448. );
  1449. if (!fResult || cbDecoded == 0) {
  1450. PrintLastError("CryptVerifyMessageHash(cb == 0)");
  1451. goto ErrorReturn;
  1452. }
  1453. if (NULL == (pbDecoded = (BYTE *) TestAlloc(
  1454. cbDecoded + DELTA_MORE_LENGTH)))
  1455. goto ErrorReturn;
  1456. if (!CryptVerifyMessageHash(
  1457. &HashPara,
  1458. pbHashedBlob,
  1459. cbHashedBlob,
  1460. pbDecoded,
  1461. &cbDecoded,
  1462. NULL, // pbComputedHash
  1463. NULL // pcbComputedHash
  1464. )) {
  1465. PrintLastError("CryptVerifyMessageHash");
  1466. goto ErrorReturn;
  1467. }
  1468. cbData = cbDecoded - DELTA_LESS_LENGTH;
  1469. fResult = CryptVerifyMessageHash(
  1470. &HashPara,
  1471. pbHashedBlob,
  1472. cbHashedBlob,
  1473. pbDecoded,
  1474. &cbData,
  1475. NULL, // pbComputedHash
  1476. NULL // pcbComputedHash
  1477. );
  1478. CheckLessLength("CryptVerifyMessageHash", fResult, cbData, cbDecoded);
  1479. cbData = cbDecoded + DELTA_MORE_LENGTH;
  1480. if (!CryptVerifyMessageHash(
  1481. &HashPara,
  1482. pbHashedBlob,
  1483. cbHashedBlob,
  1484. pbDecoded,
  1485. &cbData,
  1486. NULL, // pbComputedHash
  1487. NULL // pcbComputedHash
  1488. )) {
  1489. PrintLastError("CryptVerifyMessageHash");
  1490. goto ErrorReturn;
  1491. }
  1492. CheckMoreLength("CryptVerifyMessageHash", cbData, cbDecoded);
  1493. }
  1494. if (!fDetached) {
  1495. if (cbDecoded == cbToBeEncoded &&
  1496. memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
  1497. if (fVerbose)
  1498. printf("SUCCESS:: Decoded == ToBeEncoded\n");
  1499. } else
  1500. printf("***** ERROR:: Decoded != ToBeEncoded\n");
  1501. if (fVerbose) {
  1502. printf("Decoded bytes::\n");
  1503. PrintBytes(" ", pbDecoded, cbDecoded);
  1504. }
  1505. cbDecoded2 = cbDecoded;
  1506. if (cbDecoded2 ) {
  1507. if (NULL == (pbDecoded2 = (BYTE *) TestAlloc(cbDecoded2)))
  1508. goto ErrorReturn;
  1509. }
  1510. InitVerifyPara(&VerifyPara);
  1511. if (!CryptDecodeMessage(
  1512. CMSG_ALL_FLAGS,
  1513. NULL, // pDecryptPara
  1514. &VerifyPara,
  1515. 0, // dwSignerIndex
  1516. pbHashedBlob,
  1517. cbHashedBlob,
  1518. 0, // dwPrevInnerContentType
  1519. &dwMsgType,
  1520. &dwInnerContentType,
  1521. pbDecoded2,
  1522. &cbDecoded2,
  1523. NULL, // ppXchgCert
  1524. NULL // ppSignCert
  1525. )) {
  1526. PrintLastError("CryptDecodeMessage(CMSG_HASHED)");
  1527. goto ErrorReturn;
  1528. }
  1529. if (dwMsgType != CMSG_HASHED)
  1530. printf("failed :: dwMsgType(%d) != CMSG_HASHED\n", dwMsgType);
  1531. else if (fVerbose)
  1532. printf("SUCCESS:: CryptDecodeMessage(CMSG_HASHED)\n");
  1533. if (dwInnerContentType != CMSG_DATA) {
  1534. printf("HASHED failed :: dwInnerContentType(%d) != CMSG_DATA\n",
  1535. dwInnerContentType);
  1536. }
  1537. if (cbDecoded2 != cbDecoded ||
  1538. (cbDecoded > 0 &&
  1539. memcmp(pbDecoded, pbDecoded2, cbDecoded) != 0))
  1540. printf("failed :: bad decoded content for CryptDecodeMessage(CMSG_HASHED)\n");
  1541. }
  1542. fResult = TRUE;
  1543. goto CommonReturn;
  1544. ErrorReturn:
  1545. fResult = FALSE;
  1546. CommonReturn:
  1547. FreeHashPara(&HashPara);
  1548. if (pbHashedBlob)
  1549. TestFree(pbHashedBlob);
  1550. if (pbDecoded)
  1551. TestFree(pbDecoded);
  1552. if (pbDecoded2)
  1553. TestFree(pbDecoded2);
  1554. return fResult;
  1555. }
  1556. static BOOL TestComputedHash()
  1557. {
  1558. BOOL fResult;
  1559. CRYPT_HASH_MESSAGE_PARA HashPara;
  1560. BYTE *pbHashedBlob = NULL;
  1561. DWORD cbHashedBlob;
  1562. BYTE *pbDecoded = NULL;
  1563. DWORD cbDecoded;
  1564. BYTE rgbEncodedComputedHash[MAX_HASH_LEN];
  1565. BYTE rgbDecodedComputedHash[MAX_HASH_LEN];
  1566. DWORD cbEncodedComputedHash;
  1567. DWORD cbDecodedComputedHash;
  1568. fResult = InitHashPara(&HashPara);
  1569. if (!fResult) goto ErrorReturn;
  1570. cbHashedBlob = 0;
  1571. cbEncodedComputedHash = 0;
  1572. fResult = CryptHashMessage(
  1573. &HashPara,
  1574. fDetached,
  1575. fDetached ? DETACHED_CONTENT_CNT : 1,
  1576. rgpbDetachedToBeEncoded,
  1577. rgcbDetachedToBeEncoded,
  1578. NULL, // pbHashedBlob
  1579. &cbHashedBlob,
  1580. NULL, // pbComputedHash
  1581. &cbEncodedComputedHash
  1582. );
  1583. if (!fResult || cbHashedBlob == 0) {
  1584. PrintLastError("CryptHashMessage(cb == 0)");
  1585. goto ErrorReturn;
  1586. }
  1587. if (cbEncodedComputedHash == 0) {
  1588. PrintLastError("CryptHashMessage(cbComputedHash == 0)");
  1589. goto ErrorReturn;
  1590. }
  1591. if (cbEncodedComputedHash > MAX_HASH_LEN) {
  1592. PrintLastError("CryptHashMessage(cbComputedHash > MAX_HASH_LEN)");
  1593. goto ErrorReturn;
  1594. }
  1595. if (NULL == (pbHashedBlob = (BYTE *) TestAlloc(cbHashedBlob)))
  1596. goto ErrorReturn;
  1597. if (!CryptHashMessage(
  1598. &HashPara,
  1599. fDetached,
  1600. fDetached ? DETACHED_CONTENT_CNT : 1,
  1601. rgpbDetachedToBeEncoded,
  1602. rgcbDetachedToBeEncoded,
  1603. pbHashedBlob,
  1604. &cbHashedBlob,
  1605. rgbEncodedComputedHash,
  1606. &cbEncodedComputedHash
  1607. )) {
  1608. PrintLastError("CryptHashMessage");
  1609. goto ErrorReturn;
  1610. }
  1611. if (fVerbose) {
  1612. printf("Encoded Computed Hash::\n");
  1613. PrintBytes(" ", rgbEncodedComputedHash, cbEncodedComputedHash);
  1614. }
  1615. if (pszMsgEncodedFilename)
  1616. WriteDERToFile(pszMsgEncodedFilename, pbHashedBlob, cbHashedBlob);
  1617. if (fDetached) {
  1618. cbDecodedComputedHash = MAX_HASH_LEN;
  1619. if(!CryptVerifyDetachedMessageHash(
  1620. &HashPara,
  1621. pbHashedBlob,
  1622. cbHashedBlob,
  1623. DETACHED_CONTENT_CNT,
  1624. rgpbDetachedToBeEncoded,
  1625. rgcbDetachedToBeEncoded,
  1626. rgbDecodedComputedHash,
  1627. &cbDecodedComputedHash
  1628. )) {
  1629. PrintLastError("CryptVerifyDetachedMessageHash");
  1630. goto ErrorReturn;
  1631. }
  1632. if (cbDecodedComputedHash == 0) {
  1633. PrintLastError("CryptVerifyDetachedMessageHash(cbComputedHash == 0)");
  1634. goto ErrorReturn;
  1635. }
  1636. if (cbDecodedComputedHash > MAX_HASH_LEN) {
  1637. PrintLastError("CryptVerifyDetachedMessageHash(cbComputedHash > MAX_HASH_LEN)");
  1638. goto ErrorReturn;
  1639. }
  1640. } else {
  1641. cbDecoded = 0;
  1642. cbDecodedComputedHash = 0;
  1643. fResult = CryptVerifyMessageHash(
  1644. &HashPara,
  1645. pbHashedBlob,
  1646. cbHashedBlob,
  1647. NULL, // pbDecoded
  1648. &cbDecoded,
  1649. NULL, // pbComputedHash
  1650. &cbDecodedComputedHash
  1651. );
  1652. if (!fResult || cbDecoded == 0) {
  1653. PrintLastError("CryptVerifyMessageHash(cb == 0)");
  1654. goto ErrorReturn;
  1655. }
  1656. if (cbDecodedComputedHash == 0) {
  1657. PrintLastError("CryptVerifyMessageHash(cbComputedHash == 0)");
  1658. goto ErrorReturn;
  1659. }
  1660. if (cbDecodedComputedHash > MAX_HASH_LEN) {
  1661. PrintLastError("CryptVerifyMessageHash(cbComputedHash > MAX_HASH_LEN)");
  1662. goto ErrorReturn;
  1663. }
  1664. if (NULL == (pbDecoded = (BYTE *) TestAlloc(cbDecoded)))
  1665. goto ErrorReturn;
  1666. if(!CryptVerifyMessageHash(
  1667. &HashPara,
  1668. pbHashedBlob,
  1669. cbHashedBlob,
  1670. pbDecoded,
  1671. &cbDecoded,
  1672. rgbDecodedComputedHash,
  1673. &cbDecodedComputedHash
  1674. )) {
  1675. PrintLastError("CryptVerifyMessageHash");
  1676. goto ErrorReturn;
  1677. }
  1678. }
  1679. if (fVerbose) {
  1680. printf("Decoded Computed Hash::\n");
  1681. PrintBytes(" ", rgbDecodedComputedHash, cbDecodedComputedHash);
  1682. }
  1683. if (cbDecodedComputedHash == cbEncodedComputedHash &&
  1684. memcmp(rgbDecodedComputedHash, rgbEncodedComputedHash,
  1685. cbDecodedComputedHash) == 0) {
  1686. if (fVerbose)
  1687. printf("SUCCESS:: Computed Hash Decoded == ToBeEncoded\n");
  1688. } else
  1689. printf("***** ERROR:: Computed Hash Decoded != ToBeEncoded\n");
  1690. if (!fDetached) {
  1691. if (cbDecoded == cbToBeEncoded &&
  1692. memcmp(pbDecoded, pbToBeEncoded, cbDecoded) == 0) {
  1693. if (fVerbose)
  1694. printf("SUCCESS:: Decoded == ToBeEncoded\n");
  1695. } else
  1696. printf("***** ERROR:: Decoded != ToBeEncoded\n");
  1697. if (fVerbose) {
  1698. printf("Decoded bytes::\n");
  1699. PrintBytes(" ", pbDecoded, cbDecoded);
  1700. }
  1701. }
  1702. fResult = TRUE;
  1703. goto CommonReturn;
  1704. ErrorReturn:
  1705. fResult = FALSE;
  1706. CommonReturn:
  1707. FreeHashPara(&HashPara);
  1708. if (pbHashedBlob)
  1709. TestFree(pbHashedBlob);
  1710. if (pbDecoded)
  1711. TestFree(pbDecoded);
  1712. return fResult;
  1713. }
  1714. static BOOL TestNoCertSign()
  1715. {
  1716. BOOL fResult;
  1717. HCRYPTPROV hCryptProv = 0;
  1718. CRYPT_KEY_SIGN_MESSAGE_PARA SignPara;
  1719. CRYPT_KEY_VERIFY_MESSAGE_PARA VerifyPara;
  1720. BYTE *pbSignedBlob = NULL;
  1721. DWORD cbSignedBlob;
  1722. BYTE *pbDecoded = NULL;
  1723. DWORD cbDecoded;
  1724. PCERT_PUBLIC_KEY_INFO pPublicKeyInfo1 = NULL;
  1725. PCERT_PUBLIC_KEY_INFO pPublicKeyInfo2 = NULL;
  1726. DWORD cbInfo;
  1727. BYTE *pbEncodedKey = NULL;
  1728. DWORD cbEncodedKey;
  1729. fResult = CryptAcquireContext(
  1730. &hCryptProv,
  1731. NULL, // pszContainer
  1732. NULL, // pszProvider
  1733. dwCryptProvType,
  1734. 0 // dwFlags
  1735. );
  1736. if (!fResult) {
  1737. hCryptProv = 0;
  1738. PrintLastError("TestNoCertSign::CryptAcquireContext");
  1739. goto ErrorReturn;
  1740. }
  1741. cbInfo = 0;
  1742. fResult = CryptExportPublicKeyInfo(
  1743. hCryptProv,
  1744. dwSignKeySpec,
  1745. dwCertEncodingType,
  1746. NULL, // pPubKeyInfo
  1747. &cbInfo
  1748. );
  1749. if (!fResult || cbInfo == 0) {
  1750. PrintLastError("CryptExportPublicKeyInfo(cb == 0)");
  1751. goto ErrorReturn;
  1752. }
  1753. if (NULL == (pPublicKeyInfo1 = (PCERT_PUBLIC_KEY_INFO) TestAlloc(cbInfo)))
  1754. goto ErrorReturn;
  1755. if (!CryptExportPublicKeyInfo(
  1756. hCryptProv,
  1757. dwSignKeySpec,
  1758. dwCertEncodingType,
  1759. pPublicKeyInfo1,
  1760. &cbInfo
  1761. )) {
  1762. PrintLastError("CryptExportPublicKeyInfo");
  1763. goto ErrorReturn;
  1764. }
  1765. cbEncodedKey = 0;
  1766. fResult = CryptEncodeObject(
  1767. dwCertEncodingType,
  1768. X509_PUBLIC_KEY_INFO,
  1769. pPublicKeyInfo1,
  1770. NULL, // pbEncodedKey
  1771. &cbEncodedKey
  1772. );
  1773. if (!fResult || cbEncodedKey == 0) {
  1774. PrintLastError("CryptEncodeObject(cb == 0)");
  1775. goto ErrorReturn;
  1776. }
  1777. if (NULL == (pbEncodedKey = (BYTE *) TestAlloc(cbEncodedKey)))
  1778. goto ErrorReturn;
  1779. if (!CryptEncodeObject(
  1780. dwCertEncodingType,
  1781. X509_PUBLIC_KEY_INFO,
  1782. pPublicKeyInfo1,
  1783. pbEncodedKey,
  1784. &cbEncodedKey
  1785. )) {
  1786. PrintLastError("CryptEncodeObject");
  1787. goto ErrorReturn;
  1788. }
  1789. memset(&SignPara, 0, sizeof(SignPara));
  1790. SignPara.cbSize = sizeof(SignPara);
  1791. SignPara.dwMsgAndCertEncodingType =
  1792. dwMsgEncodingType | dwCertEncodingType;
  1793. SignPara.hCryptProv = hCryptProv;
  1794. SignPara.dwKeySpec = dwSignKeySpec;
  1795. if (NULL == (SignPara.HashAlgorithm.pszObjId = (LPSTR) GetOID(
  1796. pszHashName, CRYPT_HASH_ALG_OID_GROUP_ID))) {
  1797. printf("Failed => unknown hash name (%s)\n", pszHashName);
  1798. goto ErrorReturn;
  1799. }
  1800. if (IsDSSProv(dwCryptProvType)) {
  1801. SignPara.cbSize = sizeof(SignPara);
  1802. SignPara.PubKeyAlgorithm.pszObjId = (LPSTR) GetOID(
  1803. "Dss", CRYPT_PUBKEY_ALG_OID_GROUP_ID);
  1804. } else
  1805. SignPara.cbSize = offsetof(CRYPT_KEY_SIGN_MESSAGE_PARA,
  1806. PubKeyAlgorithm);
  1807. memset(&VerifyPara, 0, sizeof(VerifyPara));
  1808. VerifyPara.cbSize = sizeof(VerifyPara);
  1809. VerifyPara.dwMsgEncodingType = dwMsgEncodingType;
  1810. VerifyPara.hCryptProv = 0;
  1811. cbSignedBlob = 0;
  1812. fResult = CryptSignMessageWithKey(
  1813. &SignPara,
  1814. pbEncodedKey,
  1815. cbEncodedKey,
  1816. NULL, // pbSignedBlob
  1817. &cbSignedBlob
  1818. );
  1819. if (!fResult || cbSignedBlob == 0) {
  1820. PrintLastError("CryptSignMessageWithKey(cb == 0)");
  1821. goto ErrorReturn;
  1822. }
  1823. if (NULL == (pbSignedBlob = (BYTE *) TestAlloc(cbSignedBlob)))
  1824. goto ErrorReturn;
  1825. if (!CryptSignMessageWithKey(
  1826. &SignPara,
  1827. pbEncodedKey,
  1828. cbEncodedKey,
  1829. pbSignedBlob,
  1830. &cbSignedBlob
  1831. )) {
  1832. PrintLastError("CryptSignMessageWithKey");
  1833. goto ErrorReturn;
  1834. }
  1835. if (pszMsgEncodedFilename)
  1836. WriteDERToFile(pszMsgEncodedFilename, pbSignedBlob, cbSignedBlob);
  1837. // First get the encoded public key info (ie, don't verify the signature)
  1838. cbDecoded = 0;
  1839. fResult = CryptVerifyMessageSignatureWithKey(
  1840. &VerifyPara,
  1841. NULL, // pPublicKeyInfo
  1842. pbSignedBlob,
  1843. cbSignedBlob,
  1844. NULL, // pbDecoded
  1845. &cbDecoded
  1846. );
  1847. if (!fResult || cbDecoded == 0) {
  1848. PrintLastError("CryptVerifyMessageSignatureWithKey(cb == 0)");
  1849. goto ErrorReturn;
  1850. }
  1851. if (NULL == (pbDecoded = (BYTE *) TestAlloc(cbDecoded)))
  1852. goto ErrorReturn;
  1853. if(!CryptVerifyMessageSignatureWithKey(
  1854. &VerifyPara,
  1855. NULL, // pPublicKeyInfo
  1856. pbSignedBlob,
  1857. cbSignedBlob,
  1858. pbDecoded,
  1859. &cbDecoded
  1860. )) {
  1861. PrintLastError("CryptVerifyMessageSignatureWithKey");
  1862. goto ErrorReturn;
  1863. }
  1864. // Now decode the public key info stored in the signed message
  1865. cbInfo = 0;
  1866. fResult = CryptDecodeObject(
  1867. dwCertEncodingType,
  1868. X509_PUBLIC_KEY_INFO,
  1869. pbDecoded,
  1870. cbDecoded,
  1871. 0, // dwFlags
  1872. NULL, // pInfo
  1873. &cbInfo
  1874. );
  1875. if (!fResult || cbInfo == 0) {
  1876. PrintLastError("CryptDecodeObject(cb == 0)");
  1877. goto ErrorReturn;
  1878. }
  1879. if (NULL == (pPublicKeyInfo2 = (PCERT_PUBLIC_KEY_INFO) TestAlloc(cbInfo)))
  1880. goto ErrorReturn;
  1881. if (!CryptDecodeObject(
  1882. dwCertEncodingType,
  1883. X509_PUBLIC_KEY_INFO,
  1884. pbDecoded,
  1885. cbDecoded,
  1886. 0, // dwFlags
  1887. pPublicKeyInfo2,
  1888. &cbInfo
  1889. )) {
  1890. PrintLastError("CryptDecodeObject");
  1891. goto ErrorReturn;
  1892. }
  1893. if (fVerbose) {
  1894. printf("Decoded Algorithm Identifier:: %s\n",
  1895. pPublicKeyInfo2->Algorithm.pszObjId);
  1896. printf("Decoded public key bytes::\n");
  1897. PrintBytes(" ", pPublicKeyInfo2->PublicKey.pbData,
  1898. pPublicKeyInfo2->PublicKey.cbData);
  1899. }
  1900. if (strcmp(pPublicKeyInfo1->Algorithm.pszObjId,
  1901. pPublicKeyInfo2->Algorithm.pszObjId) == 0 &&
  1902. CertComparePublicKeyInfo(
  1903. dwCertEncodingType,
  1904. pPublicKeyInfo1,
  1905. pPublicKeyInfo2)) {
  1906. if (fVerbose)
  1907. printf("SUCCESS:: Decoded PublicKeyInfo == PublicKeyInfo\n");
  1908. } else {
  1909. printf("***** ERROR:: Decoded PublicKeyInfo != PublicKeyInfo\n");
  1910. if (fVerbose) {
  1911. printf("Expected Algorithm Identifier:: %s\n",
  1912. pPublicKeyInfo1->Algorithm.pszObjId);
  1913. printf("Expected public key bytes::\n");
  1914. PrintBytes(" ", pPublicKeyInfo1->PublicKey.pbData,
  1915. pPublicKeyInfo1->PublicKey.cbData);
  1916. }
  1917. goto ErrorReturn;
  1918. }
  1919. // Use the public key info to verify the signature
  1920. if (!CryptVerifyMessageSignatureWithKey(
  1921. &VerifyPara,
  1922. pPublicKeyInfo2,
  1923. pbSignedBlob,
  1924. cbSignedBlob,
  1925. NULL, // pbDecoded
  1926. NULL // pcbDecoded
  1927. )) {
  1928. PrintLastError("CryptVerifyMessageSignatureWithKey(pPublicKeyInfo verify)");
  1929. goto ErrorReturn;
  1930. }
  1931. fResult = TRUE;
  1932. goto CommonReturn;
  1933. ErrorReturn:
  1934. fResult = FALSE;
  1935. CommonReturn:
  1936. if (hCryptProv)
  1937. CryptReleaseContext(hCryptProv, 0);
  1938. if (pPublicKeyInfo1)
  1939. TestFree(pPublicKeyInfo1);
  1940. if (pPublicKeyInfo2)
  1941. TestFree(pPublicKeyInfo2);
  1942. if (pbSignedBlob)
  1943. TestFree(pbSignedBlob);
  1944. if (pbDecoded)
  1945. TestFree(pbDecoded);
  1946. if (pbEncodedKey)
  1947. TestFree(pbEncodedKey);
  1948. return fResult;
  1949. }
  1950. static BOOL TimeStampTest(PCRYPT_TIME_STAMP_REQUEST_INFO pTSInfo) {
  1951. BYTE * pbDer = NULL;
  1952. DWORD cbEncode = 0;
  1953. DWORD cbDecode = 0;
  1954. PCRYPT_TIME_STAMP_REQUEST_INFO pbTSInfo = NULL;
  1955. BOOL fOk = TRUE;
  1956. // encode it
  1957. if(
  1958. !CryptEncodeObject(
  1959. CRYPT_ASN_ENCODING,
  1960. PKCS_TIME_REQUEST,
  1961. pTSInfo,
  1962. NULL,
  1963. &cbEncode) ||
  1964. (pbDer = (PBYTE) _alloca(cbEncode)) == NULL ||
  1965. !CryptEncodeObject(
  1966. CRYPT_ASN_ENCODING,
  1967. PKCS_TIME_REQUEST,
  1968. pTSInfo,
  1969. pbDer,
  1970. &cbEncode) )
  1971. {
  1972. goto CryptEncodeTimeRequestError;
  1973. }
  1974. // decode it
  1975. if(
  1976. !CryptDecodeObject(
  1977. CRYPT_ASN_ENCODING,
  1978. PKCS_TIME_REQUEST,
  1979. pbDer,
  1980. cbEncode,
  1981. CRYPT_DECODE_NOCOPY_FLAG,
  1982. NULL,
  1983. &cbDecode) ||
  1984. (pbTSInfo = (PCRYPT_TIME_STAMP_REQUEST_INFO) _alloca(cbDecode)) == NULL ||
  1985. !CryptDecodeObject(
  1986. CRYPT_ASN_ENCODING,
  1987. PKCS_TIME_REQUEST,
  1988. pbDer,
  1989. cbEncode,
  1990. CRYPT_DECODE_NOCOPY_FLAG,
  1991. pbTSInfo,
  1992. &cbDecode) )
  1993. {
  1994. goto CryptDecodeTimeRequestError;
  1995. }
  1996. // compare encoded data with decoded data
  1997. if(
  1998. _stricmp(pTSInfo->pszTimeStampAlgorithm, pbTSInfo->pszTimeStampAlgorithm) ||
  1999. _stricmp(pTSInfo->pszContentType, pbTSInfo->pszContentType) ||
  2000. pTSInfo->Content.cbData != pbTSInfo->Content.cbData ||
  2001. pTSInfo->cAttribute != pbTSInfo->cAttribute )
  2002. {
  2003. goto CompareTimeRequestError;
  2004. }
  2005. if(pTSInfo->Content.cbData != 0 &&
  2006. memcmp(pTSInfo->Content.pbData, pbTSInfo->Content.pbData, pTSInfo->Content.cbData) )
  2007. {
  2008. goto CompareTimeRequestError;
  2009. }
  2010. CommonReturn:
  2011. return(fOk);
  2012. ErrorReturn:
  2013. fOk = FALSE;
  2014. goto CommonReturn;
  2015. // TRACE_ERROR(BuildTimeStampError);
  2016. TRACE_ERROR(CryptEncodeTimeRequestError);
  2017. TRACE_ERROR(CryptDecodeTimeRequestError);
  2018. TRACE_ERROR(CompareTimeRequestError);
  2019. }
  2020. static BOOL TestTimeStamp()
  2021. {
  2022. CRYPT_TIME_STAMP_REQUEST_INFO TSInfo;
  2023. BOOL fOk;
  2024. BYTE rgTestData[] = {
  2025. 0x1b, 0xf6, 0x92, 0xee, 0x6c, 0x44, 0xc5, 0xed, 0x51, 0xe4, 0x1a, 0xac, 0x21, 0x07, 0x2f, 0x63,
  2026. 0x6b, 0xc9, 0x27, 0x30, 0x90, 0xb8, 0x3c, 0xa6, 0x75, 0xf8, 0x17, 0x5a, 0x28, 0x2b, 0xe7, 0x3f,
  2027. 0xd7, 0x47, 0xad, 0x82, 0x1a, 0x34, 0x37, 0x27, 0x22, 0xd2, 0x64, 0x8b, 0x24, 0xe6, 0x42, 0x55,
  2028. 0x8a, 0xfe, 0xd1, 0xb4, 0xcf, 0x96, 0xa3, 0xea, 0x90, 0xf9, 0x2b, 0xeb, 0x16, 0x27, 0xaa, 0x5b
  2029. };
  2030. // initialize the timestamp structure
  2031. TSInfo.pszTimeStampAlgorithm = szOID_RSA_signingTime;
  2032. TSInfo.pszContentType = szOID_RSA_data;
  2033. TSInfo.Content.cbData = sizeof(rgTestData);
  2034. TSInfo.Content.pbData = rgTestData;
  2035. TSInfo.cAttribute = 0;
  2036. TSInfo.rgAttribute = NULL;
  2037. if( (fOk = TimeStampTest(&TSInfo) ) == TRUE ) {
  2038. TSInfo.Content.cbData = 0;
  2039. TSInfo.Content.pbData = NULL;
  2040. fOk = TimeStampTest(&TSInfo);
  2041. }
  2042. return(fOk);
  2043. }
  2044. static BOOL TestPKCS10Attr() {
  2045. CRYPT_ENROLLMENT_NAME_VALUE_PAIR nameValuePair = {L"Name", L"Value"};
  2046. PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValuePair = NULL;
  2047. DWORD cb = 0;
  2048. CRYPT_DATA_BLOB blob;
  2049. BOOL fOk = TRUE;
  2050. BYTE signatureData[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA};
  2051. CRYPT_CSP_PROVIDER cspProvider = {32, L"My CSP", {sizeof(signatureData), signatureData, 0}};
  2052. PCRYPT_CSP_PROVIDER pCSPProvider = NULL;
  2053. memset(&blob, 0, sizeof(CRYPT_DATA_BLOB));
  2054. if(!CryptEncodeObjectEx(
  2055. CRYPT_ASN_ENCODING,
  2056. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  2057. &nameValuePair,
  2058. CRYPT_ENCODE_ALLOC_FLAG,
  2059. NULL,
  2060. &blob.pbData,
  2061. &blob.cbData
  2062. ))
  2063. goto ErrorCryptEncodeNameValuePair;
  2064. if(!CryptDecodeObjectEx(
  2065. CRYPT_ASN_ENCODING,
  2066. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  2067. blob.pbData,
  2068. blob.cbData,
  2069. CRYPT_ENCODE_ALLOC_FLAG,
  2070. NULL,
  2071. &pNameValuePair,
  2072. &cb
  2073. ))
  2074. goto ErrorCryptDecodeNameValuePair;
  2075. if(
  2076. wcscmp(nameValuePair.pwszName, pNameValuePair->pwszName) ||
  2077. wcscmp(nameValuePair.pwszValue, pNameValuePair->pwszValue) )
  2078. goto CompareNameValuePair;
  2079. // szOID_ENROLLMENT_CSP_PROVIDER
  2080. assert(blob.pbData != NULL);
  2081. LocalFree(blob.pbData);
  2082. memset(&blob, 0, sizeof(CRYPT_DATA_BLOB));
  2083. cb = 0;
  2084. if(!CryptEncodeObjectEx(
  2085. CRYPT_ASN_ENCODING,
  2086. szOID_ENROLLMENT_CSP_PROVIDER,
  2087. &cspProvider,
  2088. CRYPT_ENCODE_ALLOC_FLAG,
  2089. NULL,
  2090. &blob.pbData,
  2091. &blob.cbData
  2092. ))
  2093. goto ErrorCryptEncodeCSPProvider;
  2094. if(!CryptDecodeObjectEx(
  2095. CRYPT_ASN_ENCODING,
  2096. szOID_ENROLLMENT_CSP_PROVIDER,
  2097. blob.pbData,
  2098. blob.cbData,
  2099. CRYPT_ENCODE_ALLOC_FLAG,
  2100. NULL,
  2101. &pCSPProvider,
  2102. &cb
  2103. ))
  2104. goto ErrorCryptDecodeCSPProvider;
  2105. if(
  2106. wcscmp(cspProvider.pwszProviderName, pCSPProvider->pwszProviderName) ||
  2107. cspProvider.Signature.cbData != pCSPProvider->Signature.cbData ||
  2108. cspProvider.Signature.cUnusedBits != pCSPProvider->Signature.cUnusedBits ||
  2109. cspProvider.dwKeySpec != pCSPProvider->dwKeySpec ||
  2110. memcmp(cspProvider.Signature.pbData, pCSPProvider->Signature.pbData, cspProvider.Signature.cbData) )
  2111. goto CompareCSPProvider;
  2112. CommonReturn:
  2113. if(blob.pbData != NULL)
  2114. LocalFree(blob.pbData);
  2115. if(pNameValuePair != NULL)
  2116. LocalFree(pNameValuePair);
  2117. if(pCSPProvider != NULL)
  2118. LocalFree(pCSPProvider);
  2119. return(fOk);
  2120. ErrorReturn:
  2121. fOk = FALSE;
  2122. goto CommonReturn;
  2123. // TRACE_ERROR(BuildTimeStampError);
  2124. TRACE_ERROR(ErrorCryptEncodeNameValuePair);
  2125. TRACE_ERROR(ErrorCryptDecodeNameValuePair);
  2126. TRACE_ERROR(CompareNameValuePair);
  2127. TRACE_ERROR(ErrorCryptEncodeCSPProvider);
  2128. TRACE_ERROR(ErrorCryptDecodeCSPProvider);
  2129. TRACE_ERROR(CompareCSPProvider);
  2130. }
  2131. typedef BOOL (*PFN_TEST)(void);
  2132. static struct
  2133. {
  2134. LPCSTR pszName;
  2135. PFN_TEST pfn;
  2136. } Tests[] = {
  2137. "Sign", TestSign,
  2138. "Envelope", TestEnvelope,
  2139. "SignAndEnvelope", TestSignAndEnvelope,
  2140. "Hash", TestHash,
  2141. "ComputedHash", TestComputedHash,
  2142. "NoCertSign", TestNoCertSign,
  2143. "TimeStamp", TestTimeStamp,
  2144. "PKCS10Attr", TestPKCS10Attr
  2145. };
  2146. #define NTESTS (sizeof(Tests)/sizeof(Tests[0]))
  2147. static void Usage(void)
  2148. {
  2149. int i;
  2150. printf("Usage: tsca [options] <StoreFilename> [<TestName>] [<CertNameString>]\n");
  2151. printf("Options are:\n");
  2152. #ifdef CMS_PKCS7
  2153. printf(" -EncapsulatedContent - CMS encapsulated content\n");
  2154. printf(" -SP3Encrypt - SP3 compatible encrypt\n");
  2155. printf(" -DefaultGetSigner - Use default GetSignerCertificate\n");
  2156. printf(" -NoRecipients - No Envelope Recipients\n");
  2157. printf(" -AllRecipients - All Envelope Recipients in store\n");
  2158. printf(" -RecipientKeyId - Use KeyId for recipients\n");
  2159. printf(" -SignerKeyId - Use KeyId for signers\n");
  2160. printf(" -HashEncryptionAlgorithm - Use signature as hash encrypt algorithm\n");
  2161. printf(" -NoSalt - NoSalt for RC4\n");
  2162. printf(" -SilentKey - Silent private key usage\n");
  2163. #endif // CMS_PKCS7
  2164. printf(" -h - This message\n");
  2165. printf(" -A - Authenticated Attributes\n");
  2166. printf(" -D - Detached Hash or Signature\n");
  2167. printf(" -I - Inner Signed Content for SignAndEnvelope\n");
  2168. printf(" -X - Sign using keyeXchange\n");
  2169. printf(" -l - Print command line\n");
  2170. printf(" -v - Verbose\n");
  2171. printf(" -H<name> - Hash algorithm, default of \"md5\"\n");
  2172. printf(" -E<name> - Encrypt algorithm, default of \"rc2\"\n");
  2173. printf(" -e<EncryptBitLen> - Encrypt key bit length\n");
  2174. printf(" -i - Include IV in encrypt parameters\n");
  2175. printf(" -p<provider> - Specify crypto provider type number\n");
  2176. printf(" -P<PubKeyBitLen> - Public key bit length\n");
  2177. printf(" -r<filename> - Read encoded message from file\n");
  2178. printf(" -m<filename> - Write encoded message to file\n");
  2179. printf(" -c<filename> - Write message cert store to file\n");
  2180. printf(" -0 - Zero length content\n");
  2181. #ifdef ENABLE_SCA_STREAM_TEST
  2182. printf(" -s - Enable streaming\n");
  2183. printf(" -S - Enable indefinite length streaming\n");
  2184. #endif
  2185. printf("\n");
  2186. printf("Tests are (case insensitive name):\n");
  2187. for (i = 0; i < NTESTS; i++)
  2188. printf(" %s\n", Tests[i].pszName);
  2189. printf("\n");
  2190. printf("Default: ALL Tests\n");
  2191. }
  2192. int _cdecl main(int argc, char * argv[])
  2193. {
  2194. BOOL fResult;
  2195. LPSTR pszStoreFilename = NULL;
  2196. LPSTR pszTestName = NULL;
  2197. int TestIdx = 0;
  2198. while (--argc>0)
  2199. {
  2200. if (**++argv == '-')
  2201. {
  2202. #ifdef CMS_PKCS7
  2203. if (0 == _stricmp(argv[0]+1, "EncapsulatedContent")) {
  2204. fEncapsulatedContent = TRUE;
  2205. } else if (0 == _stricmp(argv[0]+1, "SP3Encrypt")) {
  2206. fSP3Encrypt = TRUE;
  2207. } else if (0 == _stricmp(argv[0]+1, "DefaultGetSigner")) {
  2208. fDefaultGetSigner = TRUE;
  2209. } else if (0 == _stricmp(argv[0]+1, "NoRecipients")) {
  2210. fNoRecipients = TRUE;
  2211. } else if (0 == _stricmp(argv[0]+1, "AllRecipients")) {
  2212. fAllRecipients = TRUE;
  2213. } else if (0 == _stricmp(argv[0]+1, "RecipientKeyId")) {
  2214. fRecipientKeyId = TRUE;
  2215. } else if (0 == _stricmp(argv[0]+1, "SignerKeyId")) {
  2216. fSignerKeyId = TRUE;
  2217. } else if (0 == _stricmp(argv[0]+1, "HashEncryptionAlgorithm")) {
  2218. fHashEncryptionAlgorithm = TRUE;
  2219. } else if (0 == _stricmp(argv[0]+1, "NoSalt")) {
  2220. fNoSalt = TRUE;
  2221. } else if (0 == _stricmp(argv[0]+1, "SilentKey")) {
  2222. fSilentKey = TRUE;
  2223. } else {
  2224. #endif // CMS_PKCS7
  2225. switch(argv[0][1])
  2226. {
  2227. case 'A':
  2228. fAuthAttr = TRUE;
  2229. break;
  2230. case 'D':
  2231. fDetached = TRUE;
  2232. break;
  2233. case 'I':
  2234. fInnerSigned = TRUE;
  2235. break;
  2236. case 'l':
  2237. printf("command line: %s\n", GetCommandLine());
  2238. break;
  2239. case 'p':
  2240. dwCryptProvType = strtoul( argv[0]+2, NULL, 0);
  2241. break;
  2242. case 'P':
  2243. dwPubKeyBitLen = strtoul( argv[0]+2, NULL, 0);
  2244. break;
  2245. case 'H':
  2246. pszHashName = argv[0]+2;
  2247. break;
  2248. case 'E':
  2249. pszEncryptName = argv[0]+2;
  2250. break;
  2251. case 'e':
  2252. dwEncryptBitLen = strtoul( argv[0]+2, NULL, 0);
  2253. break;
  2254. case 'i':
  2255. fEncryptIV = TRUE;
  2256. break;
  2257. case 'v':
  2258. fVerbose = TRUE;
  2259. break;
  2260. case 'X':
  2261. dwSignKeySpec = AT_KEYEXCHANGE;
  2262. break;
  2263. case 'm':
  2264. pszMsgEncodedFilename = argv[0]+2;
  2265. if (*pszMsgEncodedFilename == '\0') {
  2266. printf("Need to specify filename\n");
  2267. Usage();
  2268. return -1;
  2269. }
  2270. break;
  2271. case 'c':
  2272. pszMsgCertFilename = argv[0]+2;
  2273. if (*pszMsgCertFilename == '\0') {
  2274. printf("Need to specify filename\n");
  2275. Usage();
  2276. return -1;
  2277. }
  2278. break;
  2279. case 'r':
  2280. pszReadEncodedFilename = argv[0]+2;
  2281. if (*pszReadEncodedFilename == '\0') {
  2282. printf("Need to specify filename\n");
  2283. Usage();
  2284. return -1;
  2285. }
  2286. break;
  2287. case '0':
  2288. cbToBeEncoded = 0;
  2289. rgcbDetachedToBeEncoded[0] = 0;
  2290. break;
  2291. #ifdef ENABLE_SCA_STREAM_TEST
  2292. case 'S':
  2293. fIndefiniteStream = TRUE;
  2294. case 's':
  2295. fStream = TRUE;
  2296. break;
  2297. #endif
  2298. case 'h':
  2299. default:
  2300. Usage();
  2301. return -1;
  2302. }
  2303. #ifdef CMS_PKCS7
  2304. }
  2305. #endif // CMS_PKCS7
  2306. } else {
  2307. if (pszStoreFilename == NULL)
  2308. pszStoreFilename = argv[0];
  2309. else if(pszTestName == NULL)
  2310. pszTestName = argv[0];
  2311. else if (pszCertNameFindStr == NULL)
  2312. pszCertNameFindStr = argv[0];
  2313. else {
  2314. printf("Too many arguments\n");
  2315. Usage();
  2316. return -1;
  2317. }
  2318. }
  2319. }
  2320. if (pszStoreFilename == NULL) {
  2321. printf("missing store filename\n");
  2322. Usage();
  2323. return -1;
  2324. }
  2325. if (pszTestName) {
  2326. for (TestIdx = 0; TestIdx < NTESTS; TestIdx++) {
  2327. if (_stricmp(pszTestName, Tests[TestIdx].pszName) == 0)
  2328. break;
  2329. }
  2330. if (TestIdx >= NTESTS) {
  2331. printf("Bad TestName: %s\n", pszTestName);
  2332. Usage();
  2333. return -1;
  2334. }
  2335. } else
  2336. TestIdx = 0;
  2337. if (fDetached) printf("Detached Enabled ");
  2338. if (pszReadEncodedFilename)
  2339. printf("Reading encoded msg from file: %s ", pszReadEncodedFilename);
  2340. if (pszMsgEncodedFilename)
  2341. printf("Writing encoded msg to file: %s ", pszMsgEncodedFilename);
  2342. if (pszMsgCertFilename)
  2343. printf("Writing msg cert store to file: %s ", pszMsgCertFilename);
  2344. printf("\n");
  2345. // Attempt to open the store
  2346. hCertStore = OpenStore(pszStoreFilename);
  2347. if (hCertStore == NULL)
  2348. goto ErrorReturn;
  2349. for ( ; TestIdx < NTESTS; TestIdx++) {
  2350. printf("Starting %s Test\n", Tests[TestIdx].pszName);
  2351. fResult = Tests[TestIdx].pfn();
  2352. if (fResult)
  2353. printf("Passed\n");
  2354. else
  2355. printf("Failed\n");
  2356. printf("\n");
  2357. if (pszTestName)
  2358. break;
  2359. }
  2360. ErrorReturn:
  2361. if (hCertStore) {
  2362. if (!CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG))
  2363. PrintLastError("CertCloseStore");
  2364. }
  2365. return 0;
  2366. }
  2367. static BOOL NameAttributeValueCompare(
  2368. IN const BYTE *pbValue,
  2369. IN DWORD cbValue,
  2370. IN PCERT_NAME_BLOB pName
  2371. )
  2372. {
  2373. BOOL fResult;
  2374. PCERT_NAME_INFO pInfo = NULL;
  2375. DWORD cbInfo;
  2376. DWORD cRDN, cAttr;
  2377. PCERT_RDN pRDN;
  2378. PCERT_RDN_ATTR pAttr;
  2379. cbInfo = 0;
  2380. fResult = CryptDecodeObject(
  2381. dwCertEncodingType,
  2382. X509_NAME,
  2383. pName->pbData,
  2384. pName->cbData,
  2385. 0, // dwFlags
  2386. NULL, // pInfo
  2387. &cbInfo
  2388. );
  2389. if (!fResult || cbInfo == 0) {
  2390. PrintLastError(
  2391. "NameAttributeValueCompare::CryptDecodeObject(cbInfo == 0)");
  2392. goto ErrorReturn;
  2393. }
  2394. pInfo = (PCERT_NAME_INFO) TestAlloc(cbInfo);
  2395. if (pInfo == NULL) goto ErrorReturn;
  2396. if (!CryptDecodeObject(
  2397. dwCertEncodingType,
  2398. X509_NAME,
  2399. pName->pbData,
  2400. pName->cbData,
  2401. 0, // dwFlags
  2402. pInfo,
  2403. &cbInfo
  2404. )) {
  2405. PrintLastError("NameAttributeValueCompare::CryptDecodeObject");
  2406. goto ErrorReturn;
  2407. }
  2408. for (cRDN = pInfo->cRDN, pRDN = pInfo->rgRDN; cRDN > 0; cRDN--, pRDN++) {
  2409. for (cAttr = pRDN->cRDNAttr, pAttr = pRDN->rgRDNAttr;
  2410. cAttr > 0; cAttr--, pAttr++) {
  2411. if (pAttr->Value.cbData == cbValue &&
  2412. memcmp(pAttr->Value.pbData, pbValue, cbValue) == 0) {
  2413. fResult = TRUE;
  2414. goto CommonReturn;
  2415. }
  2416. }
  2417. }
  2418. ErrorReturn:
  2419. fResult = FALSE;
  2420. CommonReturn:
  2421. if (pInfo)
  2422. TestFree(pInfo);
  2423. return fResult;
  2424. }
  2425. static PCCERT_CONTEXT FindCertWithKey(IN DWORD dwKeySpec)
  2426. {
  2427. PCCERT_CONTEXT pCert;
  2428. void *pvFindPara;
  2429. DWORD dwFindType;
  2430. if (pszCertNameFindStr) {
  2431. dwFindType = CERT_FIND_SUBJECT_STR_A;
  2432. pvFindPara = (void *) pszCertNameFindStr;
  2433. } else {
  2434. dwFindType = CERT_FIND_ANY;
  2435. pvFindPara = NULL;
  2436. }
  2437. // Find the first certificate in the store with a CRYPT_KEY_PROV_INFO
  2438. // property matching the specified dwSignKeySpec, dwCryptProvType and
  2439. // dwPubKeyBitLen
  2440. pCert = NULL;
  2441. while (TRUE) {
  2442. pCert = CertFindCertificateInStore(
  2443. hCertStore,
  2444. dwCertEncodingType,
  2445. 0, // dwFindFlags,
  2446. dwFindType,
  2447. pvFindPara,
  2448. pCert
  2449. );
  2450. if (pCert == NULL)
  2451. break;
  2452. PCRYPT_KEY_PROV_INFO pInfo = NULL;
  2453. DWORD cbInfo = 0;
  2454. CertGetCertificateContextProperty(
  2455. pCert,
  2456. CERT_KEY_PROV_INFO_PROP_ID,
  2457. NULL,
  2458. &cbInfo
  2459. );
  2460. if (cbInfo >= sizeof(CRYPT_KEY_PROV_INFO) &&
  2461. (pInfo = (PCRYPT_KEY_PROV_INFO) TestAlloc(cbInfo))) {
  2462. BOOL fMatch = FALSE;
  2463. if (CertGetCertificateContextProperty(
  2464. pCert,
  2465. CERT_KEY_PROV_INFO_PROP_ID,
  2466. pInfo,
  2467. &cbInfo) &&
  2468. dwKeySpec == pInfo->dwKeySpec &&
  2469. dwCryptProvType == pInfo->dwProvType) {
  2470. if (0 == dwPubKeyBitLen)
  2471. fMatch = TRUE;
  2472. else
  2473. fMatch = (dwPubKeyBitLen == CertGetPublicKeyLength(
  2474. pCert->dwCertEncodingType,
  2475. &pCert->pCertInfo->SubjectPublicKeyInfo));
  2476. }
  2477. TestFree(pInfo);
  2478. if (fMatch)
  2479. break;
  2480. }
  2481. }
  2482. return pCert;
  2483. }
  2484. static BOOL InitSignPara(OUT PCRYPT_SIGN_MESSAGE_PARA pPara)
  2485. {
  2486. BOOL fResult;
  2487. PCCERT_CONTEXT pCert;
  2488. PCCERT_CONTEXT pIssuer;
  2489. PCCRL_CONTEXT pCrl;
  2490. DWORD dwFlags;
  2491. BYTE bIntendedKeyUsage;
  2492. memset(pPara, 0, sizeof(*pPara));
  2493. pPara->cbSize = sizeof(*pPara);
  2494. pPara->dwMsgEncodingType = dwMsgEncodingType;
  2495. if (NULL == (pPara->HashAlgorithm.pszObjId = (LPSTR) GetOID(
  2496. pszHashName, CRYPT_HASH_ALG_OID_GROUP_ID))) {
  2497. printf("Failed => unknown hash name (%s) for signing\n",
  2498. pszHashName);
  2499. goto ErrorReturn;
  2500. }
  2501. #ifdef ENABLE_SCA_STREAM_TEST
  2502. if (fStream) {
  2503. pPara->dwFlags |= SCA_STREAM_ENABLE_FLAG;
  2504. if (fIndefiniteStream)
  2505. pPara->dwFlags |= SCA_INDEFINITE_STREAM_FLAG;
  2506. }
  2507. #endif
  2508. #ifdef CMS_PKCS7
  2509. if (fSignerKeyId)
  2510. pPara->dwFlags |= CRYPT_MESSAGE_KEYID_SIGNER_FLAG;
  2511. if (fEncapsulatedContent) {
  2512. pPara->dwFlags |= CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG;
  2513. pPara->dwInnerContentType = CMSG_HASHED;
  2514. }
  2515. if (fSilentKey)
  2516. pPara->dwFlags |= CRYPT_MESSAGE_SILENT_KEYSET_FLAG;
  2517. #endif // CMS_PKCS7
  2518. pPara->rgpMsgCert = (PCCERT_CONTEXT*) TestAlloc(
  2519. sizeof(PCCERT_CONTEXT) * MAX_MSG_CERT);
  2520. if (pPara->rgpMsgCert == NULL) goto ErrorReturn;
  2521. pPara->rgpMsgCrl = (PCCRL_CONTEXT*) TestAlloc(
  2522. sizeof(PCCRL_CONTEXT) * MAX_MSG_CRL);
  2523. if (pPara->rgpMsgCrl == NULL) goto ErrorReturn;
  2524. pCert = FindCertWithKey(dwSignKeySpec);
  2525. if (pCert == NULL) {
  2526. PrintError("Couldn't find a cert having a key provider");
  2527. goto ErrorReturn;
  2528. } else if (fVerbose) {
  2529. printf("----- Signer -----\n");
  2530. DisplayCert(pCert);
  2531. }
  2532. #ifdef CMS_PKCS7
  2533. if (fHashEncryptionAlgorithm) {
  2534. pPara->HashEncryptionAlgorithm = pCert->pCertInfo->SignatureAlgorithm;
  2535. }
  2536. #endif // CMS_PKCS7
  2537. pPara->pSigningCert = pCert;
  2538. pPara->cMsgCert = 1;
  2539. pPara->rgpMsgCert[0] = pCert;
  2540. // Add the cert's issuer certs to the message. Add the issuer CRLs to
  2541. // the message.
  2542. while (TRUE) {
  2543. dwFlags = 0;
  2544. pIssuer = CertGetIssuerCertificateFromStore(
  2545. hCertStore,
  2546. pCert,
  2547. NULL, // pPrevIssuerContext
  2548. &dwFlags
  2549. );
  2550. if (pIssuer == NULL) break;
  2551. if (pPara->cMsgCert == MAX_MSG_CERT) {
  2552. PrintError("cMsgCert == MAX_MSG_CERT");
  2553. CertFreeCertificateContext(pIssuer);
  2554. break;
  2555. }
  2556. pCert = pIssuer;
  2557. pPara->rgpMsgCert[pPara->cMsgCert++] = pCert;
  2558. pCrl = NULL;
  2559. while (TRUE) {
  2560. dwFlags = 0;
  2561. pCrl = CertGetCRLFromStore(
  2562. pIssuer->hCertStore,
  2563. pIssuer,
  2564. pCrl,
  2565. &dwFlags
  2566. );
  2567. if (pCrl == NULL) break;
  2568. if (pPara->cMsgCrl == MAX_MSG_CRL) {
  2569. PrintError("cMsgCrl == MAX_MSG_CRL");
  2570. CertFreeCRLContext(pCrl);
  2571. break;
  2572. }
  2573. pPara->rgpMsgCrl[pPara->cMsgCrl++] = CertDuplicateCRLContext(pCrl);
  2574. }
  2575. }
  2576. if (fAuthAttr) {
  2577. pPara->cAuthAttr = AUTH_ATTR_COUNT;
  2578. pPara->rgAuthAttr = rgAuthAttr;
  2579. }
  2580. if (fVerbose) {
  2581. DWORD i;
  2582. printf("Msg Certs: %d MsgCrls: %d\n", pPara->cMsgCert, pPara->cMsgCrl);
  2583. for (i = 0; i < pPara->cMsgCert; i++) {
  2584. printf("----- Msg Cert[%i] -----\n", i);
  2585. DisplayCert(pPara->rgpMsgCert[i]);
  2586. }
  2587. for (i = 0; i < pPara->cMsgCrl; i++) {
  2588. printf("----- Msg Crl[%i] -----\n", i);
  2589. DisplayCrl(pPara->rgpMsgCrl[i]);
  2590. }
  2591. }
  2592. fResult = TRUE;
  2593. goto CommonReturn;
  2594. ErrorReturn:
  2595. FreeSignPara(pPara);
  2596. fResult = FALSE;
  2597. CommonReturn:
  2598. return fResult;
  2599. }
  2600. static void FreeSignPara(IN PCRYPT_SIGN_MESSAGE_PARA pPara)
  2601. {
  2602. while (pPara->cMsgCert-- > 0)
  2603. CertFreeCertificateContext(pPara->rgpMsgCert[pPara->cMsgCert]);
  2604. while (pPara->cMsgCrl-- > 0)
  2605. CertFreeCRLContext(pPara->rgpMsgCrl[pPara->cMsgCrl]);
  2606. if (pPara->rgpMsgCert)
  2607. TestFree(pPara->rgpMsgCert);
  2608. if (pPara->rgpMsgCrl)
  2609. TestFree(pPara->rgpMsgCrl);
  2610. memset(pPara, 0, sizeof(*pPara));
  2611. }
  2612. static PCCERT_CONTEXT WINAPI GetSignerCertificate(
  2613. IN void *pvGetArg,
  2614. IN DWORD dwCertEncodingType,
  2615. IN PCERT_INFO pSignerId, // Only the Issuer and SerialNumber
  2616. // fields are used
  2617. IN HCERTSTORE hMsgCertStore
  2618. )
  2619. {
  2620. if (fVerbose)
  2621. printf("GetSignerCertificate pSignerId = 0x%p\n", pSignerId);
  2622. return CertGetSubjectCertificateFromStore(hMsgCertStore, dwCertEncodingType,
  2623. pSignerId);
  2624. }
  2625. static BOOL InitVerifyPara(OUT PCRYPT_VERIFY_MESSAGE_PARA pPara)
  2626. {
  2627. memset(pPara, 0, sizeof(*pPara));
  2628. pPara->cbSize = sizeof(*pPara);
  2629. pPara->dwMsgAndCertEncodingType =
  2630. dwMsgEncodingType | dwCertEncodingType;
  2631. #ifdef ENABLE_SCA_STREAM_TEST
  2632. if (fStream)
  2633. pPara->dwMsgAndCertEncodingType |= SCA_STREAM_ENABLE_FLAG;
  2634. #endif
  2635. pPara->hCryptProv = 0;
  2636. #ifdef CMS_PKCS7
  2637. if (!fDefaultGetSigner)
  2638. #endif
  2639. pPara->pfnGetSignerCertificate = GetSignerCertificate;
  2640. return TRUE;
  2641. }
  2642. static void FreeVerifyPara(IN PCRYPT_VERIFY_MESSAGE_PARA pPara)
  2643. {
  2644. }
  2645. #define IV_LENGTH 8
  2646. static BOOL GetIV(BYTE rgbIV[IV_LENGTH])
  2647. {
  2648. SYSTEMTIME st;
  2649. GetSystemTime(&st);
  2650. assert(IV_LENGTH == sizeof(FILETIME));
  2651. SystemTimeToFileTime(&st, (LPFILETIME) rgbIV);
  2652. return TRUE;
  2653. }
  2654. static BOOL InitEncryptPara(
  2655. OUT PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
  2656. OUT DWORD *pcRecipientCert,
  2657. OUT PCCERT_CONTEXT **pppRecipientCert
  2658. )
  2659. {
  2660. BOOL fResult;
  2661. PCCERT_CONTEXT pCert;
  2662. BYTE bIntendedKeyUsage;
  2663. PCRYPT_OBJID_BLOB pAlgPara;
  2664. *pppRecipientCert = NULL;
  2665. memset(pPara, 0, sizeof(*pPara));
  2666. pPara->cbSize = sizeof(*pPara);
  2667. pPara->dwMsgEncodingType = dwMsgEncodingType;
  2668. pPara->hCryptProv = 0;
  2669. #ifdef ENABLE_SCA_STREAM_TEST
  2670. if (fStream) {
  2671. pPara->dwFlags |= SCA_STREAM_ENABLE_FLAG;
  2672. if (fIndefiniteStream)
  2673. pPara->dwFlags |= SCA_INDEFINITE_STREAM_FLAG;
  2674. }
  2675. #endif
  2676. #ifdef CMS_PKCS7
  2677. if (fRecipientKeyId)
  2678. pPara->dwFlags |= CRYPT_MESSAGE_KEYID_RECIPIENT_FLAG;
  2679. if (fEncapsulatedContent) {
  2680. pPara->dwFlags |= CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG;
  2681. pPara->dwInnerContentType = CMSG_HASHED;
  2682. }
  2683. #endif // CMS_PKCS7
  2684. if (NULL == (pPara->ContentEncryptionAlgorithm.pszObjId = (LPSTR) GetOID(
  2685. pszEncryptName, CRYPT_ENCRYPT_ALG_OID_GROUP_ID))) {
  2686. printf("Failed => unknown encrypt name (%s)\n", pszEncryptName);
  2687. goto ErrorReturn;
  2688. }
  2689. pAlgPara = &pPara->ContentEncryptionAlgorithm.Parameters;
  2690. if (0 != dwEncryptBitLen && CALG_RC2 == GetAlgid(
  2691. pszEncryptName, CRYPT_ENCRYPT_ALG_OID_GROUP_ID)) {
  2692. if (fEncryptIV) {
  2693. CRYPT_RC2_CBC_PARAMETERS RC2Parameters;
  2694. switch (dwEncryptBitLen) {
  2695. case 40:
  2696. RC2Parameters.dwVersion = CRYPT_RC2_40BIT_VERSION;
  2697. break;
  2698. case 64:
  2699. RC2Parameters.dwVersion = CRYPT_RC2_64BIT_VERSION;
  2700. break;
  2701. case 128:
  2702. RC2Parameters.dwVersion = CRYPT_RC2_128BIT_VERSION;
  2703. break;
  2704. default:
  2705. printf("Failed => unknown RC2 length (%d)\n",
  2706. dwEncryptBitLen);
  2707. goto ErrorReturn;
  2708. }
  2709. RC2Parameters.fIV = fEncryptIV;
  2710. if (fEncryptIV) {
  2711. if (!GetIV(RC2Parameters.rgbIV))
  2712. goto ErrorReturn;
  2713. }
  2714. if (!AllocAndEncodeObject(
  2715. PKCS_RC2_CBC_PARAMETERS,
  2716. &RC2Parameters,
  2717. &pAlgPara->pbData,
  2718. &pAlgPara->cbData))
  2719. goto ErrorReturn;
  2720. } else {
  2721. RC2AuxInfo.cbSize = sizeof(RC2AuxInfo);
  2722. RC2AuxInfo.dwBitLen = dwEncryptBitLen;
  2723. pPara->pvEncryptionAuxInfo = &RC2AuxInfo;
  2724. #ifdef CMS_PKCS7
  2725. if (fSP3Encrypt)
  2726. RC2AuxInfo.dwBitLen |= CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  2727. #endif
  2728. }
  2729. } else if (CALG_RC4 == GetAlgid(pszEncryptName,
  2730. CRYPT_ENCRYPT_ALG_OID_GROUP_ID)) {
  2731. if (fEncryptIV) {
  2732. CRYPT_DATA_BLOB Salt;
  2733. DWORD i;
  2734. for (i = 0; i < MAX_SALT_LEN; i++)
  2735. rgbSalt[i] = (BYTE) i;
  2736. Salt.cbData = MAX_SALT_LEN;
  2737. Salt.pbData = rgbSalt;
  2738. if (!AllocAndEncodeObject(
  2739. X509_OCTET_STRING,
  2740. &Salt,
  2741. &pAlgPara->pbData,
  2742. &pAlgPara->cbData
  2743. ))
  2744. goto ErrorReturn;
  2745. } else if (0 != dwEncryptBitLen) {
  2746. memset(&RC4AuxInfo, 0, sizeof(RC4AuxInfo));
  2747. RC4AuxInfo.cbSize = sizeof(RC4AuxInfo);
  2748. RC4AuxInfo.dwBitLen = dwEncryptBitLen;
  2749. if (fNoSalt)
  2750. RC4AuxInfo.dwBitLen |= CMSG_RC4_NO_SALT_FLAG;
  2751. pPara->pvEncryptionAuxInfo = &RC4AuxInfo;
  2752. }
  2753. } else if (fEncryptIV) {
  2754. BYTE rgbIV[IV_LENGTH];
  2755. CRYPT_DATA_BLOB Data;
  2756. Data.pbData = rgbIV;
  2757. Data.cbData = sizeof(rgbIV);
  2758. if (!GetIV(rgbIV))
  2759. goto ErrorReturn;
  2760. if (!AllocAndEncodeObject(
  2761. X509_OCTET_STRING,
  2762. &Data,
  2763. &pAlgPara->pbData,
  2764. &pAlgPara->cbData))
  2765. goto ErrorReturn;
  2766. }
  2767. #ifdef CMS_PKCS7
  2768. else if (fSP3Encrypt) {
  2769. RC2AuxInfo.cbSize = sizeof(RC2AuxInfo);
  2770. RC2AuxInfo.dwBitLen = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
  2771. pPara->pvEncryptionAuxInfo = &RC2AuxInfo;
  2772. }
  2773. #endif
  2774. *pcRecipientCert = 0;
  2775. *pppRecipientCert = (PCCERT_CONTEXT*) TestAlloc(
  2776. sizeof(PCCERT_CONTEXT) * MAX_RECIPIENT_CERT);
  2777. if (*pppRecipientCert == NULL) goto ErrorReturn;
  2778. #ifdef CMS_PKCS7
  2779. if (fNoRecipients)
  2780. ;
  2781. else if (fAllRecipients) {
  2782. pCert = NULL;
  2783. while (pCert = CertEnumCertificatesInStore(hCertStore, pCert)) {
  2784. if (*pcRecipientCert == MAX_RECIPIENT_CERT) {
  2785. PrintError("cRecipientCert == MAX_RECIPIENT_CERT");
  2786. CertFreeCertificateContext(pCert);
  2787. break;
  2788. }
  2789. (*pppRecipientCert)[*pcRecipientCert] =
  2790. CertDuplicateCertificateContext(pCert);
  2791. *pcRecipientCert += 1;
  2792. }
  2793. } else
  2794. #endif // CMS_PKCS7
  2795. if (0 != dwPubKeyBitLen && !IsDSSProv(dwCryptProvType)) {
  2796. // Get exchange cert of the specified key length
  2797. pCert = FindCertWithKey(AT_KEYEXCHANGE);
  2798. if (pCert == NULL) {
  2799. printf(
  2800. "Failed => couldn't find an exchange cert with key length (%d)\n",
  2801. dwPubKeyBitLen);
  2802. goto ErrorReturn;
  2803. } else {
  2804. (*pppRecipientCert)[*pcRecipientCert] = pCert;
  2805. *pcRecipientCert += 1;
  2806. }
  2807. } else {
  2808. // Find certificates in the store with xchg key usage
  2809. pCert = NULL;
  2810. while (TRUE) {
  2811. pCert = CertEnumCertificatesInStore(
  2812. hCertStore,
  2813. pCert);
  2814. if (pCert == NULL)
  2815. break;
  2816. CertGetIntendedKeyUsage(
  2817. dwCertEncodingType,
  2818. pCert->pCertInfo,
  2819. &bIntendedKeyUsage,
  2820. 1 // cbKeyUsage
  2821. );
  2822. if (bIntendedKeyUsage &
  2823. (CERT_KEY_ENCIPHERMENT_KEY_USAGE |
  2824. CERT_DATA_ENCIPHERMENT_KEY_USAGE |
  2825. CERT_KEY_AGREEMENT_KEY_USAGE)) {
  2826. if (*pcRecipientCert == MAX_RECIPIENT_CERT) {
  2827. PrintError("cRecipientCert == MAX_RECIPIENT_CERT");
  2828. CertFreeCertificateContext(pCert);
  2829. break;
  2830. }
  2831. (*pppRecipientCert)[*pcRecipientCert] =
  2832. CertDuplicateCertificateContext(pCert);
  2833. *pcRecipientCert += 1;
  2834. }
  2835. }
  2836. }
  2837. #ifdef CMS_PKCS7
  2838. if (fNoRecipients)
  2839. ;
  2840. else
  2841. #endif // CMS_PKCS7
  2842. if (*pcRecipientCert == 0) {
  2843. PrintError("Couldn't find a recipient xchg cert");
  2844. goto ErrorReturn;
  2845. } else {
  2846. DWORD i;
  2847. if (fVerbose)
  2848. printf("Recipient Certs: %d\n", *pcRecipientCert);
  2849. for (i = 0; i < *pcRecipientCert; i++) {
  2850. if (fVerbose) {
  2851. printf("----- Recipient Cert[%i] -----\n", i);
  2852. DisplayCert((*pppRecipientCert)[i]);
  2853. }
  2854. if (!fDhRecipient) {
  2855. PCERT_INFO pCertInfo = (*pppRecipientCert)[i]->pCertInfo;
  2856. PCERT_PUBLIC_KEY_INFO pPublicKeyInfo =
  2857. &pCertInfo->SubjectPublicKeyInfo;
  2858. PCCRYPT_OID_INFO pOIDInfo;
  2859. ALG_ID aiPubKey;
  2860. if (pOIDInfo = CryptFindOIDInfo(
  2861. CRYPT_OID_INFO_OID_KEY,
  2862. pPublicKeyInfo->Algorithm.pszObjId,
  2863. CRYPT_PUBKEY_ALG_OID_GROUP_ID))
  2864. aiPubKey = pOIDInfo->Algid;
  2865. else
  2866. aiPubKey = 0;
  2867. if (aiPubKey == CALG_DH_SF || aiPubKey == CALG_DH_EPHEM) {
  2868. printf("Has Diffie Hellman recipients\n");
  2869. fDhRecipient = TRUE;
  2870. }
  2871. }
  2872. }
  2873. }
  2874. fResult = TRUE;
  2875. goto CommonReturn;
  2876. ErrorReturn:
  2877. FreeEncryptPara(pPara, *pcRecipientCert, *pppRecipientCert);
  2878. *pcRecipientCert = 0;
  2879. *pppRecipientCert = NULL;
  2880. fResult = FALSE;
  2881. CommonReturn:
  2882. return fResult;
  2883. }
  2884. static void FreeEncryptPara(
  2885. IN PCRYPT_ENCRYPT_MESSAGE_PARA pPara,
  2886. IN DWORD cRecipientCert,
  2887. IN PCCERT_CONTEXT *ppRecipientCert
  2888. )
  2889. {
  2890. TestFree(pPara->ContentEncryptionAlgorithm.Parameters.pbData);
  2891. pPara->ContentEncryptionAlgorithm.Parameters.pbData = NULL;
  2892. if (ppRecipientCert) {
  2893. while (cRecipientCert-- > 0) {
  2894. CertFreeCertificateContext(ppRecipientCert[cRecipientCert]);
  2895. }
  2896. TestFree(ppRecipientCert);
  2897. }
  2898. }
  2899. static BOOL InitDecryptPara(OUT PCRYPT_DECRYPT_MESSAGE_PARA pPara)
  2900. {
  2901. memset(pPara, 0, sizeof(*pPara));
  2902. pPara->cbSize = sizeof(*pPara);
  2903. pPara->dwMsgAndCertEncodingType =
  2904. dwMsgEncodingType | dwCertEncodingType;
  2905. #ifdef ENABLE_SCA_STREAM_TEST
  2906. if (fStream)
  2907. pPara->dwMsgAndCertEncodingType |= SCA_STREAM_ENABLE_FLAG;
  2908. #endif
  2909. pPara->rghCertStore = (HCERTSTORE*) TestAlloc(sizeof(HCERTSTORE));
  2910. if (fSilentKey)
  2911. pPara->dwFlags |= CRYPT_MESSAGE_SILENT_KEYSET_FLAG;
  2912. if (pPara->rghCertStore) {
  2913. pPara->rghCertStore[0] = hCertStore;
  2914. pPara->cCertStore = 1;
  2915. return TRUE;
  2916. } else
  2917. return FALSE;
  2918. }
  2919. static void FreeDecryptPara(IN PCRYPT_DECRYPT_MESSAGE_PARA pPara)
  2920. {
  2921. if (pPara->rghCertStore) {
  2922. TestFree(pPara->rghCertStore);
  2923. pPara->rghCertStore = 0;
  2924. }
  2925. }
  2926. static BOOL InitHashPara(OUT PCRYPT_HASH_MESSAGE_PARA pPara)
  2927. {
  2928. memset(pPara, 0, sizeof(*pPara));
  2929. pPara->cbSize = sizeof(*pPara);
  2930. pPara->dwMsgEncodingType = dwMsgEncodingType;
  2931. pPara->hCryptProv = 0;
  2932. if (NULL == (pPara->HashAlgorithm.pszObjId = (LPSTR) GetOID(
  2933. pszHashName, CRYPT_HASH_ALG_OID_GROUP_ID))) {
  2934. printf("Failed => unknown hash name (%s)\n", pszHashName);
  2935. return FALSE;
  2936. }
  2937. return TRUE;
  2938. }
  2939. static void FreeHashPara(IN PCRYPT_HASH_MESSAGE_PARA pPara)
  2940. {
  2941. }
  2942. static BOOL DecodeName(BYTE *pbEncoded, DWORD cbEncoded)
  2943. {
  2944. BOOL fResult;
  2945. PCERT_NAME_INFO pInfo = NULL;
  2946. DWORD cbInfo;
  2947. DWORD i,j;
  2948. PCERT_RDN pRDN;
  2949. PCERT_RDN_ATTR pAttr;
  2950. cbInfo = 0;
  2951. fResult = CryptDecodeObject(
  2952. dwCertEncodingType,
  2953. X509_NAME,
  2954. pbEncoded,
  2955. cbEncoded,
  2956. 0, // dwFlags
  2957. NULL, // pInfo
  2958. &cbInfo
  2959. );
  2960. if (!fResult || cbInfo == 0) {
  2961. PrintLastError("DecodeName::CryptDecodeObject(cbInfo == 0)");
  2962. goto ErrorReturn;
  2963. }
  2964. pInfo = (PCERT_NAME_INFO) TestAlloc(cbInfo);
  2965. if (pInfo == NULL) goto ErrorReturn;
  2966. if (!CryptDecodeObject(
  2967. dwCertEncodingType,
  2968. X509_NAME,
  2969. pbEncoded,
  2970. cbEncoded,
  2971. 0, // dwFlags
  2972. pInfo,
  2973. &cbInfo
  2974. )) {
  2975. PrintLastError("DecodeName::CryptDecodeObject");
  2976. goto ErrorReturn;
  2977. }
  2978. for (i = 0, pRDN = pInfo->rgRDN; i < pInfo->cRDN; i++, pRDN++) {
  2979. for (j = 0, pAttr = pRDN->rgRDNAttr; j < pRDN->cRDNAttr; j++, pAttr++) {
  2980. LPSTR pszObjId = pAttr->pszObjId;
  2981. if (pszObjId == NULL)
  2982. pszObjId = "<NULL OBJID>";
  2983. if ((pAttr->dwValueType == CERT_RDN_ENCODED_BLOB) ||
  2984. (pAttr->dwValueType == CERT_RDN_OCTET_STRING)) {
  2985. printf(" [%d,%d] %s ValueType: %d\n",
  2986. i, j, pszObjId, pAttr->dwValueType);
  2987. } else
  2988. printf(" [%d,%d] %s %s\n",
  2989. i, j, pszObjId, pAttr->Value.pbData);
  2990. }
  2991. }
  2992. fResult = TRUE;
  2993. goto CommonReturn;
  2994. ErrorReturn:
  2995. fResult = FALSE;
  2996. CommonReturn:
  2997. if (pInfo)
  2998. TestFree(pInfo);
  2999. return fResult;
  3000. }
  3001. static void DisplayCert(PCCERT_CONTEXT pCert)
  3002. {
  3003. printf("Subject::\n");
  3004. DecodeName(pCert->pCertInfo->Subject.pbData,
  3005. pCert->pCertInfo->Subject.cbData);
  3006. printf("Issuer::\n");
  3007. DecodeName(pCert->pCertInfo->Issuer.pbData,
  3008. pCert->pCertInfo->Issuer.cbData);
  3009. {
  3010. DWORD cb;
  3011. BYTE *pb;
  3012. printf("SerialNumber::");
  3013. for (cb = pCert->pCertInfo->SerialNumber.cbData,
  3014. pb = pCert->pCertInfo->SerialNumber.pbData + (cb - 1);
  3015. cb > 0; cb--, pb--) {
  3016. printf(" %02X", *pb);
  3017. }
  3018. printf("\n");
  3019. }
  3020. }
  3021. static void PrintCrlEntries(DWORD cEntry, PCRL_ENTRY pEntry)
  3022. {
  3023. DWORD i;
  3024. for (i = 0; i < cEntry; i++, pEntry++) {
  3025. DWORD cb;
  3026. BYTE *pb;
  3027. printf(" [%d] SerialNumber::", i);
  3028. for (cb = pEntry->SerialNumber.cbData,
  3029. pb = pEntry->SerialNumber.pbData + (cb - 1); cb > 0; cb--, pb++) {
  3030. printf(" %02X", *pb);
  3031. }
  3032. printf("\n");
  3033. }
  3034. }
  3035. static void DisplayCrl(PCCRL_CONTEXT pCrl)
  3036. {
  3037. printf("Issuer::\n");
  3038. DecodeName(pCrl->pCrlInfo->Issuer.pbData,
  3039. pCrl->pCrlInfo->Issuer.cbData);
  3040. if (pCrl->pCrlInfo->cCRLEntry == 0)
  3041. printf("Entries:: NONE\n");
  3042. else {
  3043. printf("Entries::\n");
  3044. PrintCrlEntries(pCrl->pCrlInfo->cCRLEntry,
  3045. pCrl->pCrlInfo->rgCRLEntry);
  3046. }
  3047. }