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.

6638 lines
219 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1997
  6. //
  7. // File: tcrmsg.cpp
  8. //
  9. // Contents: Cryptographic Message API Tests
  10. //
  11. // See Usage() for list of test options.
  12. //
  13. //
  14. // Functions: main
  15. //
  16. // History: 26-Feb-96 philh created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "global.hxx"
  20. #define SAVE_STREAM_FILES 1
  21. #define MAX_HASH_LEN 20
  22. #define ZEROSTRUCT(arg) (memset( &arg, 0, sizeof(arg)))
  23. //+-------------------------------------------------------------------------
  24. // Parameters, data used to encode the messages.
  25. //--------------------------------------------------------------------------
  26. HCRYPTPROV hCryptProv = 0;
  27. DWORD dwProvType = PROV_RSA_FULL;
  28. #ifdef CMS_PKCS7
  29. HCRYPTPROV hMultiSignerCryptProv = 0;
  30. DWORD dwMultiSignerProvType = PROV_RSA_FULL;
  31. BOOL fMultiSigner = FALSE;
  32. BOOL fHashEncryptionAlgorithm = FALSE;
  33. BOOL fAlgorithmParameters = FALSE;
  34. BOOL fNoSignature = FALSE;
  35. BYTE rgbOctets[] = {4, 8, 1,2,3,4,5,6,7,8};
  36. BYTE rgbInvalidAsn[] = {0xFF, 0xFF};
  37. #endif // CMS_PKCS7
  38. LPSTR pszCertNameFindStr = NULL;
  39. HCERTSTORE hSignerStore = NULL;
  40. PCCERT_CONTEXT pNamedSigner = NULL;
  41. HCRYPTPROV hNamedSignerCryptProv = 0;
  42. LPSTR pszFilename = NULL;
  43. BOOL fVerbose = FALSE;
  44. BOOL fNoSigners = FALSE;
  45. BOOL fAddSigner = FALSE;
  46. BOOL fDetached = FALSE;
  47. BOOL fAuthAttr = FALSE;
  48. BOOL fInnerContent = FALSE;
  49. BOOL fCountersign = FALSE;
  50. BOOL fStream = FALSE;
  51. BOOL fIndefinite = FALSE;
  52. BOOL fBare = FALSE;
  53. BOOL fMD5 = FALSE;
  54. BOOL fNoRecipients = FALSE;
  55. DWORD dwMsgEncodingType = PKCS_7_ASN_ENCODING;
  56. DWORD dwCertEncodingType = X509_ASN_ENCODING;
  57. LPCSTR pszContainer = NULL;
  58. LPCSTR pszProvider = NULL;
  59. BOOL fDefaultVerifyProv = FALSE;
  60. HCRYPTPROV hDefaultVerifyProv = 0;
  61. BOOL fEnhanced = FALSE;
  62. LPCSTR pszEncryptName = "rc2";
  63. LPCSTR pszEncryptOID = NULL;
  64. DWORD dwEncryptBitLen = 0;
  65. BOOL fEncryptIV = FALSE;
  66. #ifdef CMS_PKCS7
  67. BOOL fOriginatorInfo = FALSE;
  68. #endif // CMS_PKCS7
  69. typedef struct _PUBLIC_KEY_DATA {
  70. BYTE Data[1024];
  71. } PUBLIC_KEY_DATA;
  72. #define DEFAULT_MSG_CONTENT_SIZE 49
  73. DWORD cbMsgContent = DEFAULT_MSG_CONTENT_SIZE;
  74. BYTE rgbMsgContentFill[7] = {'C','o','n','t','e','n','t'};
  75. #define cbMsgContentFill sizeof(rgbMsgContentFill)
  76. DWORD iMsgContentOffset = 0;
  77. PBYTE pbInnerContent = NULL;
  78. DWORD cbInnerContent;
  79. // rsaEncryption
  80. CRYPT_ALGORITHM_IDENTIFIER PublicKeyAlgorithm =
  81. {szOID_RSA_RSA, {0,0}};
  82. // DES or RC4
  83. CRYPT_ALGORITHM_IDENTIFIER ContentEncryptionAlgorithm[] = {
  84. {szOID_OIWSEC_desCBC, {0,0}},
  85. {szOID_RSA_RC4, {0,0}},
  86. {szOID_RSA_RC2CBC, {0,0}},
  87. };
  88. #define CONTENT_ALG_DES 0
  89. #define CONTENT_ALG_RC4 1
  90. #define CONTENT_ALG_RC2 2
  91. // MD5 or SHA1
  92. CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithms[] = {
  93. {szOID_RSA_MD5, {0,0}},
  94. {szOID_OIWSEC_sha1, {0,0}},
  95. };
  96. #define DIGEST_ALG_MD5 0
  97. #define DIGEST_ALG_SHA 1
  98. // MD5 or SHA
  99. CRYPT_ALGORITHM_IDENTIFIER SignDigestAlgorithms[] = {
  100. {szOID_RSA_MD5, {0,0}},
  101. {szOID_OIWSEC_sha1, {0,0}},
  102. };
  103. #define SIGNDIGEST_ALG_MD5 0
  104. #define SIGNDIGEST_ALG_SHA 1
  105. LPSTR pszSignerSerialNumberFileName = "name.der";
  106. DWORD dwSignerSerialNumber = 0x01010101;
  107. DWORD dwSignerSerialNumber1 = 0x02020202;
  108. DWORD dwSignerSerialNumber2 = 0x03030303;
  109. PUBLIC_KEY_DATA SignerPublicKeyData;
  110. #define SIGNED_CERT_COUNT 3
  111. DWORD cSignedCert = 1;
  112. LPCSTR rgpszSignedCertFileName[SIGNED_CERT_COUNT] = {
  113. "cert1.der",
  114. "cert2.der",
  115. "cert3.der"
  116. };
  117. CERT_BLOB rgSignedCertBlob[3];
  118. #ifdef CMS_PKCS7
  119. #define ATTR_CERT_COUNT 2
  120. DWORD cAttrCert = 0;
  121. BOOL fEncapsulatedContent = FALSE;
  122. LPCSTR rgpszAttrCertFileName[ATTR_CERT_COUNT] = {
  123. "cert2.der",
  124. "cert3.der"
  125. };
  126. CERT_BLOB rgAttrCertBlob[ATTR_CERT_COUNT];
  127. #endif // CMS_PKCS7
  128. #ifdef CMS_PKCS7
  129. #define SIGNED_CRL_COUNT 1
  130. DWORD cSignedCrl = 0;
  131. LPCSTR rgpszSignedCrlFileName[SIGNED_CRL_COUNT] = {
  132. "crl1.der"
  133. };
  134. CRL_BLOB rgSignedCrlBlob[SIGNED_CRL_COUNT];
  135. #else
  136. #define SIGNED_CRL_COUNT 0
  137. #endif
  138. #define RECIPIENT_COUNT 2
  139. DWORD PkcsRecipientCount = RECIPIENT_COUNT;
  140. LPCSTR rgpszRecipientIssuerFileName[RECIPIENT_COUNT] = {
  141. "recip1.der",
  142. "recip2.der"
  143. };
  144. DWORD rgdwRecipientSerialNumber[RECIPIENT_COUNT] = {
  145. 0x02020202,
  146. 0x03030303
  147. };
  148. PUBLIC_KEY_DATA RecipientPublicKeyData;
  149. CERT_INFO rgRecipientCertInfo[RECIPIENT_COUNT];
  150. PCERT_INFO rgpRecipientCertInfo[RECIPIENT_COUNT];
  151. #ifdef CMS_PKCS7
  152. BOOL fRecipientProv = FALSE;
  153. BOOL fKeyTrans = FALSE;
  154. BOOL fKeyAgree = FALSE;
  155. BOOL fMailList = FALSE;
  156. BOOL fCmsRecipient = FALSE;
  157. BOOL fRecipientKeyId = FALSE;
  158. BOOL fCertInfoKeyId = FALSE;
  159. BOOL fSignerId = FALSE;
  160. BOOL fNoSalt = FALSE;
  161. #define MAX_SALT_LEN 11
  162. BYTE rgbSalt[MAX_SALT_LEN];
  163. CMSG_RC4_AUX_INFO RC4AuxInfo;
  164. CMSG_RECIPIENT_ENCODE_INFO rgCmsRecipient[RECIPIENT_COUNT * 4];
  165. CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO rgKeyTrans[RECIPIENT_COUNT * 4];
  166. HCRYPTPROV hKeyAgreeProv = 0;
  167. PUBLIC_KEY_DATA KeyAgreePublicKeyData;
  168. CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO rgKeyAgree[RECIPIENT_COUNT * 4];
  169. CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO rgEncryptedKey[RECIPIENT_COUNT];
  170. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO rgpEncryptedKey[RECIPIENT_COUNT];
  171. CMSG_RC2_AUX_INFO KeyAgreeRC2AuxInfo;
  172. BYTE rgbKeyAgreeOtherAttr[] = {0x04, 3, 3, 2, 1};
  173. CRYPT_ATTRIBUTE_TYPE_VALUE KeyAgreeOtherAttr = {
  174. "1.2.10.11.12",
  175. sizeof(rgbKeyAgreeOtherAttr), rgbKeyAgreeOtherAttr
  176. };
  177. LPCSTR pszUserKeyingMaterial = "UserKeyingMaterial";
  178. CMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO rgMailList[RECIPIENT_COUNT * 4];
  179. CMSG_RC2_AUX_INFO MailListRC2AuxInfo;
  180. BYTE rgbMailListOtherAttr[] = {0x04, 2, 1, 2};
  181. CRYPT_ATTRIBUTE_TYPE_VALUE MailListOtherAttr = {
  182. "1.2.3.4.5.6.7.8.9",
  183. sizeof(rgbMailListOtherAttr), rgbMailListOtherAttr
  184. };
  185. DWORD cCmsRecipients = 0;
  186. #endif // CMS_PKCS7
  187. #define AUTH_ATTR_COUNT 2
  188. BYTE attr1[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','1',0};
  189. BYTE attr2[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','2',0};
  190. BYTE attr3[] = {0x04, 0x0c, 'A','t','t','r','i','b','u','t','e',' ','3',0};
  191. CRYPT_ATTR_BLOB rgatrblob1[] = {
  192. { sizeof( attr1), attr1}
  193. };
  194. CRYPT_ATTR_BLOB rgatrblob2[] = {
  195. { sizeof( attr2), attr2},
  196. { sizeof( attr3), attr3}
  197. };
  198. CRYPT_ATTRIBUTE rgAuthAttr[AUTH_ATTR_COUNT] = {
  199. {"1.2.3.5.7", 1, rgatrblob1},
  200. {"1.2.3.5.11", 2, rgatrblob2}
  201. };
  202. #define UNAUTH_ATTR_COUNT 1
  203. BYTE unattr1[] = {0x04, 0x0c, 'A','T','T','R','I','B','U','T','E',' ','1',0};
  204. CRYPT_ATTR_BLOB rgunatrblob1[] = {
  205. { sizeof( unattr1), unattr1}
  206. };
  207. CRYPT_ATTRIBUTE rgUnauthAttr[UNAUTH_ATTR_COUNT] = {
  208. {"1.2.3.5.13.23", 1, rgunatrblob1},
  209. };
  210. LPSTR pszInnerContentObjId = szOID_RSA_digestedData;
  211. LPCSTR pszInnerContentFileName = "content.der";
  212. //CRYPT_DER_BLOB derInnerContent = {NULL,0};
  213. CERT_INFO rgSignerCertInfo[2];
  214. #ifdef CMS_PKCS7
  215. CERT_ID rgSignerId[2];
  216. #endif // CMS_PKCS7
  217. CMSG_SIGNER_ENCODE_INFO rgSignerEncodeInfo[2];
  218. CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
  219. CMSG_ENVELOPED_ENCODE_INFO EnvelopedMsgEncodeInfo;
  220. CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO SignedAndEnvelopedMsgEncodeInfo;
  221. CMSG_HASHED_ENCODE_INFO HashedMsgEncodeInfo;
  222. #ifdef CMS_PKCS7
  223. PUBLIC_KEY_DATA MultiSignerPublicKeyData;
  224. BYTE rgbEncodedSignerHash[2][MAX_HASH_LEN];
  225. DWORD rgcbEncodedSignerHash[2];
  226. #endif // CMS_PKCS7
  227. static inline IsDSSProv(
  228. IN DWORD dwProvType
  229. )
  230. {
  231. return (PROV_DSS == dwProvType || PROV_DSS_DH == dwProvType);
  232. }
  233. //+-------------------------------------------------------------------------
  234. // Error output routines
  235. //--------------------------------------------------------------------------
  236. #define PRINT_ERROR(function,label) \
  237. label##: \
  238. PrintError( #function "::" #label); \
  239. goto ErrorReturn;
  240. void PrintError(LPCSTR pszMsg)
  241. {
  242. printf("failed => %s\n", pszMsg);
  243. }
  244. void PrintLastError(LPCSTR pszMsg)
  245. {
  246. DWORD dwErr = GetLastError();
  247. printf("%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
  248. }
  249. //+-------------------------------------------------------------------------
  250. // Test allocation and free routines
  251. //--------------------------------------------------------------------------
  252. void *TestAlloc(
  253. IN size_t cb
  254. )
  255. {
  256. void *pv;
  257. // pv = LocalAlloc(LMEM_FIXED, cb);
  258. pv = malloc(cb);
  259. if (pv == NULL) {
  260. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  261. PrintLastError("TestAlloc");
  262. }
  263. return pv;
  264. }
  265. void *TestAllocZero(
  266. IN size_t cb
  267. )
  268. {
  269. void *pv;
  270. // pv = LocalAlloc(LMEM_FIXED, cb);
  271. pv = malloc(cb);
  272. if (pv == NULL) {
  273. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  274. PrintLastError("TestAlloc");
  275. } else {
  276. memset( pv, 0, cb);
  277. }
  278. return pv;
  279. }
  280. void TestFree(
  281. IN void *pv
  282. )
  283. {
  284. // LocalFree((HLOCAL) pv);
  285. if (pv)
  286. free(pv);
  287. }
  288. static BOOL AllocAndEncodeObject(
  289. IN LPCSTR lpszStructType,
  290. IN const void *pvStructInfo,
  291. OUT BYTE **ppbEncoded,
  292. OUT DWORD *pcbEncoded
  293. )
  294. {
  295. BOOL fResult;
  296. BYTE *pbEncoded = NULL;
  297. DWORD cbEncoded;
  298. fResult = CryptEncodeObject(
  299. PKCS_7_ASN_ENCODING,
  300. lpszStructType,
  301. pvStructInfo,
  302. NULL, // pbEncoded
  303. &cbEncoded);
  304. if (!fResult || cbEncoded == 0) {
  305. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  306. printf("CryptEncodeObject(StructType: %d, cbEncoded == 0)",
  307. (DWORD)(DWORD_PTR) lpszStructType);
  308. else
  309. printf("CryptEncodeObject(StructType: %s, cbEncoded == 0)",
  310. lpszStructType);
  311. PrintLastError("");
  312. goto ErrorReturn;
  313. }
  314. if (NULL == (pbEncoded = (BYTE *) TestAlloc(cbEncoded)))
  315. goto ErrorReturn;
  316. if (!CryptEncodeObject(
  317. PKCS_7_ASN_ENCODING,
  318. lpszStructType,
  319. pvStructInfo,
  320. pbEncoded,
  321. &cbEncoded
  322. )) {
  323. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  324. printf("CryptEncodeObject(StructType: %d)",
  325. (DWORD)(DWORD_PTR) lpszStructType);
  326. else
  327. printf("CryptEncodeObject(StructType: %s)",
  328. lpszStructType);
  329. PrintLastError("");
  330. goto ErrorReturn;
  331. }
  332. fResult = TRUE;
  333. CommonReturn:
  334. *ppbEncoded = pbEncoded;
  335. *pcbEncoded = cbEncoded;
  336. return fResult;
  337. ErrorReturn:
  338. if (pbEncoded) {
  339. TestFree(pbEncoded);
  340. pbEncoded = NULL;
  341. }
  342. cbEncoded = 0;
  343. fResult = FALSE;
  344. goto CommonReturn;
  345. }
  346. static BOOL AllocAndDecodeObject(
  347. IN LPCSTR lpszStructType,
  348. IN const BYTE *pbEncoded,
  349. IN DWORD cbEncoded,
  350. OUT void **ppvStructInfo,
  351. IN OUT DWORD *pcbStructInfo
  352. )
  353. {
  354. BOOL fResult;
  355. void *pvStructInfo = NULL;
  356. DWORD cbStructInfo = 0;
  357. if (!CryptDecodeObject(
  358. X509_ASN_ENCODING,
  359. lpszStructType,
  360. pbEncoded,
  361. cbEncoded,
  362. 0, // dwFlags
  363. NULL,
  364. &cbStructInfo
  365. )) {
  366. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  367. printf("CryptDecodeObject(StructType: %d, cbStructInfo == 0)",
  368. (DWORD)(DWORD_PTR) lpszStructType);
  369. else
  370. printf("CryptDecodeObject(StructType: %s, cbStructInfo == 0)",
  371. lpszStructType);
  372. PrintLastError("");
  373. goto ErrorReturn;
  374. }
  375. if (NULL == (pvStructInfo = TestAlloc(cbStructInfo)))
  376. goto ErrorReturn;
  377. if (!CryptDecodeObject(
  378. X509_ASN_ENCODING,
  379. lpszStructType,
  380. pbEncoded,
  381. cbEncoded,
  382. 0, // dwFlags
  383. pvStructInfo,
  384. &cbStructInfo
  385. )) {
  386. if ((DWORD_PTR) lpszStructType <= 0xFFFF)
  387. printf("CryptDecodeObject(StructType: %d)",
  388. (DWORD)(DWORD_PTR) lpszStructType);
  389. else
  390. printf("CryptDecodeObject(StructType: %s)",
  391. lpszStructType);
  392. PrintLastError("");
  393. goto ErrorReturn;
  394. }
  395. fResult = TRUE;
  396. CommonReturn:
  397. *ppvStructInfo = pvStructInfo;
  398. *pcbStructInfo = cbStructInfo;
  399. return fResult;
  400. ErrorReturn:
  401. fResult = FALSE;
  402. TestFree(pvStructInfo);
  403. pvStructInfo = NULL;
  404. goto CommonReturn;
  405. }
  406. //+-------------------------------------------------------------------------
  407. // Stream support
  408. //--------------------------------------------------------------------------
  409. typedef struct _TEST_STREAM_DATA {
  410. DWORD dwEncodingType;
  411. DWORD dwEncodeFlags;
  412. DWORD dwDecodeFlags;
  413. DWORD dwMsgTypeEncoding;
  414. DWORD dwMsgTypeDecoding;
  415. PVOID pvMsgEncodeInfo;
  416. LPSTR pszInnerContentType;
  417. PCMSG_STREAM_INFO pStreamInfo;
  418. HCRYPTMSG hMsg;
  419. BOOL fEncoding;
  420. BOOL fReady;
  421. #ifdef CMS_PKCS7
  422. DWORD rgcbComputedHash[2];
  423. BYTE rgbComputedHash[2][MAX_HASH_LEN];
  424. #endif // CMS_PKCS7
  425. } TEST_STREAM_DATA, *PTEST_STREAM_DATA;
  426. DEFINE_LIST_AND_NODE_CLASS( CStreamList, CStreamNode, TEST_STREAM_DATA);
  427. CStreamNode::~CStreamNode()
  428. {
  429. TestFree( m_data.pStreamInfo);
  430. };
  431. CStreamList *plistStream = NULL;
  432. DEFINE_LIST_AND_NODE_CLASS( CBlobList, CBlobNode, CRYPT_DATA_BLOB);
  433. CBlobNode::~CBlobNode()
  434. {
  435. TestFree( m_data.pbData);
  436. };
  437. LPSTR pszStreamMsgTypes = "S";
  438. #define pszStreamFileName "stream.msg"
  439. #define pszFilenameDecode "decode.dat"
  440. HANDLE hFileStream = INVALID_HANDLE_VALUE;
  441. HANDLE hFileStreamDecode = INVALID_HANDLE_VALUE;
  442. DWORD cbFileDecode;
  443. #if DBG
  444. #define cbStreamDataDeltaEncode 17
  445. #else
  446. #define cbStreamDataDeltaEncode 1024
  447. #endif
  448. BYTE abStreamDataDeltaEncode[cbStreamDataDeltaEncode];
  449. #if DBG
  450. DWORD cbStreamDataDeltaDecode = 1;
  451. //DWORD cbStreamDataDeltaDecode = 19;
  452. #else
  453. DWORD cbStreamDataDeltaDecode = 1024;
  454. #endif
  455. //+-------------------------------------------------------------------------
  456. // Check that a CryptMsgGetParam to a buffer fails with the right error
  457. // because the buffer is too small.
  458. //--------------------------------------------------------------------------
  459. BOOL
  460. WINAPI
  461. TCM_CheckGetParam(
  462. IN HCRYPTMSG hCryptMsg,
  463. IN DWORD dwParamType,
  464. IN DWORD dwIndex,
  465. IN PVOID pv,
  466. IN DWORD cbData)
  467. {
  468. BOOL fRet;
  469. DWORD cbSmall;
  470. if (cbData < 1)
  471. goto SuccessReturn;
  472. cbSmall = cbData - 1;
  473. if (CryptMsgGetParam(
  474. hCryptMsg,
  475. dwParamType,
  476. dwIndex,
  477. pv,
  478. &cbSmall))
  479. goto GetSmallBufferRetError;
  480. if (ERROR_MORE_DATA != GetLastError())
  481. goto GetSmallBufferLastErrorError;
  482. SuccessReturn:
  483. fRet = TRUE;
  484. CommonReturn:
  485. return fRet;
  486. ErrorReturn:
  487. fRet = FALSE;
  488. goto CommonReturn;
  489. PRINT_ERROR(TCM_CheckGetParam,GetSmallBufferRetError)
  490. PRINT_ERROR(TCM_CheckGetParam,GetSmallBufferLastErrorError)
  491. }
  492. //+-------------------------------------------------------------------------
  493. // Do a CryptMsgGetParam to a buffer alloc'd by TestAlloc
  494. //--------------------------------------------------------------------------
  495. BOOL
  496. WINAPI
  497. TCM_AllocGetParam(
  498. IN HCRYPTMSG hCryptMsg,
  499. IN DWORD dwParamType,
  500. IN DWORD dwIndex,
  501. OUT PBYTE *ppbData,
  502. OUT DWORD *pcbData)
  503. {
  504. DWORD dwError = ERROR_SUCCESS;
  505. BOOL fRet;
  506. DWORD cb;
  507. PBYTE pb = NULL;
  508. cb = 0;
  509. CryptMsgGetParam(
  510. hCryptMsg,
  511. dwParamType,
  512. dwIndex,
  513. NULL,
  514. &cb);
  515. if (cb == 0)
  516. goto GetEncodedSizeError;
  517. if (NULL == (pb = (PBYTE)TestAlloc(cb)))
  518. goto AllocEncodedError;
  519. if (!TCM_CheckGetParam(
  520. hCryptMsg,
  521. dwParamType,
  522. dwIndex,
  523. pb,
  524. cb))
  525. goto CheckGetEncodedError;
  526. if (!CryptMsgGetParam(
  527. hCryptMsg,
  528. dwParamType,
  529. dwIndex,
  530. pb,
  531. &cb))
  532. goto GetEncodedError;
  533. fRet = TRUE;
  534. CommonReturn:
  535. *ppbData = pb;
  536. *pcbData = cb;
  537. if (dwError != ERROR_SUCCESS)
  538. SetLastError(dwError);
  539. return fRet;
  540. ErrorReturn:
  541. dwError = GetLastError();
  542. TestFree(pb);
  543. pb = NULL;
  544. cb = 0;
  545. fRet = FALSE;
  546. goto CommonReturn;
  547. PRINT_ERROR(TCM_AllocGetParam,GetEncodedSizeError)
  548. PRINT_ERROR(TCM_AllocGetParam,AllocEncodedError)
  549. PRINT_ERROR(TCM_AllocGetParam,CheckGetEncodedError)
  550. PRINT_ERROR(TCM_AllocGetParam,GetEncodedError)
  551. }
  552. //+-------------------------------------------------------------------------
  553. // Compare 2 CRYPT_ALGORITHM_IDENTIFIER structs.
  554. //
  555. // Returns: FALSE iff differ
  556. //--------------------------------------------------------------------------
  557. BOOL
  558. WINAPI
  559. EqualAlgorithm(
  560. IN PCRYPT_ALGORITHM_IDENTIFIER pai1,
  561. IN PCRYPT_ALGORITHM_IDENTIFIER pai2)
  562. {
  563. BOOL fRet;
  564. fRet = (0 == strcmp( pai1->pszObjId, pai2->pszObjId));
  565. fRet &= (pai1->Parameters.cbData == pai2->Parameters.cbData);
  566. if (fRet) {
  567. fRet &= (0 == memcmp( pai1->Parameters.pbData,
  568. pai2->Parameters.pbData,
  569. pai1->Parameters.cbData));
  570. }
  571. return fRet;
  572. }
  573. //+-------------------------------------------------------------------------
  574. // Compare 2 CRYPT_ATTRIBUTE structs.
  575. //
  576. // Returns: FALSE iff differ
  577. //--------------------------------------------------------------------------
  578. BOOL
  579. WINAPI
  580. EqualAttribute(
  581. IN PCRYPT_ATTRIBUTE patr1,
  582. IN PCRYPT_ATTRIBUTE patr2)
  583. {
  584. BOOL fRet;
  585. DWORD i;
  586. PCRYPT_ATTR_BLOB pabl1;
  587. PCRYPT_ATTR_BLOB pabl2;
  588. fRet = (0 == strcmp( patr1->pszObjId, patr2->pszObjId));
  589. fRet &= (patr1->cValue == patr2->cValue);
  590. if (fRet) {
  591. for (i=patr1->cValue, pabl1=patr1->rgValue, pabl2=patr2->rgValue;
  592. i>0;
  593. i--, pabl1++, pabl2++) {
  594. fRet &= (pabl1->cbData == pabl2->cbData);
  595. if (fRet) {
  596. fRet &= (0 == memcmp( pabl1->pbData,
  597. pabl2->pbData,
  598. pabl1->cbData));
  599. }
  600. }
  601. }
  602. return fRet;
  603. }
  604. void XORAttributeBytes()
  605. {
  606. DWORD cb;
  607. BYTE *pb;
  608. cb = sizeof(attr1) / sizeof(attr1[0]);
  609. pb = attr1;
  610. while(cb--)
  611. *pb++ ^= 0xFF;
  612. cb = sizeof(attr2) / sizeof(attr2[0]);
  613. pb = attr2;
  614. while(cb--)
  615. *pb++ ^= 0xFF;
  616. cb = sizeof(attr3) / sizeof(attr3[0]);
  617. pb = attr3;
  618. while(cb--)
  619. *pb++ ^= 0xFF;
  620. cb = sizeof(unattr1) / sizeof(unattr1[0]);
  621. pb = unattr1;
  622. while(cb--)
  623. *pb++ ^= 0xFF;
  624. }
  625. void XORBlob(
  626. IN PCRYPT_DATA_BLOB pBlob
  627. )
  628. {
  629. DWORD cb;
  630. BYTE *pb;
  631. cb = pBlob->cbData;
  632. pb = pBlob->pbData;
  633. while(cb--)
  634. *pb++ ^= 0xFF;
  635. }
  636. void XORBitBlob(
  637. IN PCRYPT_BIT_BLOB pBlob
  638. )
  639. {
  640. CRYPT_DATA_BLOB Blob;
  641. Blob.pbData = pBlob->pbData;
  642. Blob.cbData = pBlob->cbData;
  643. XORBlob(&Blob);
  644. }
  645. //+-------------------------------------------------------------------------
  646. // Read an encoded DER blob from a file
  647. //--------------------------------------------------------------------------
  648. BOOL
  649. GetDERFromFile(
  650. LPCSTR pszFileName,
  651. PBYTE *ppbDER,
  652. PDWORD pcbDER
  653. )
  654. {
  655. BOOL fRet;
  656. HANDLE hFile;
  657. PBYTE pbDER;
  658. DWORD cbDER;
  659. DWORD cbRead;
  660. if( INVALID_HANDLE_VALUE == (hFile = CreateFile( pszFileName, GENERIC_READ,
  661. FILE_SHARE_READ | FILE_SHARE_WRITE,
  662. NULL, OPEN_EXISTING, 0, NULL))) {
  663. printf( "can't open %s\n", pszFileName);
  664. goto ErrorReturn;
  665. }
  666. cbDER = GetFileSize( hFile, NULL);
  667. if (NULL == (pbDER = (PBYTE)TestAlloc( cbDER))) {
  668. printf( "can't alloc %d bytes\n", cbDER);
  669. goto ErrorReturn;
  670. }
  671. if (!ReadFile( hFile, pbDER, cbDER, &cbRead, NULL) ||
  672. (cbRead != cbDER)) {
  673. printf( "can't read %s\n", pszFileName);
  674. goto ErrorReturn;
  675. }
  676. CloseHandle( hFile);
  677. *ppbDER = pbDER;
  678. *pcbDER = cbDER;
  679. fRet = TRUE;
  680. CommonReturn:
  681. return fRet;
  682. ErrorReturn:
  683. fRet = FALSE;
  684. goto CommonReturn;
  685. }
  686. //+-------------------------------------------------------------------------
  687. // Write a buffer to a file
  688. //--------------------------------------------------------------------------
  689. BOOL
  690. WINAPI
  691. TCM_WriteBufToFile(
  692. LPCSTR pszFile,
  693. PBYTE pbData,
  694. DWORD cbData)
  695. {
  696. BOOL fRet;
  697. HANDLE hFile;
  698. DWORD cbWritten;
  699. if( INVALID_HANDLE_VALUE == (hFile = CreateFile( pszFile, GENERIC_WRITE,
  700. 0, NULL, CREATE_ALWAYS, 0, NULL)))
  701. goto CreateFileError;
  702. if (!WriteFile( hFile, pbData, cbData, &cbWritten, NULL) ||
  703. (cbWritten != cbData))
  704. goto WriteFileError;
  705. CloseHandle( hFile);
  706. fRet = TRUE;
  707. CommonReturn:
  708. return fRet;
  709. ErrorReturn:
  710. fRet = FALSE;
  711. goto CommonReturn;
  712. PRINT_ERROR(TCM_WriteBufToFile,CreateFileError)
  713. PRINT_ERROR(TCM_WriteBufToFile,WriteFileError)
  714. }
  715. //+-------------------------------------------------------------------------
  716. // Get the number of contents octets in a DER encoding.
  717. //
  718. // Parameters:
  719. // pcbContent - receives the number of contents octets
  720. // pbLength - points to the first length octet
  721. // cbDER - number of bytes remaining in the DER encoding
  722. //
  723. // Returns:
  724. // success - the number of bytes in the length field, >=0
  725. // failure - <0
  726. //--------------------------------------------------------------------------
  727. LONG
  728. WINAPI
  729. TCM_DecodeLength(
  730. OUT DWORD *pcbContent,
  731. IN PBYTE pbLength,
  732. IN DWORD cbDER)
  733. {
  734. long i;
  735. BYTE cbLength;
  736. PBYTE pb;
  737. if (cbDER < 1)
  738. goto EncodeOverflowError;
  739. if (0x80 == *pbLength)
  740. goto IsBERError;
  741. // determine the number of length octets and contents octets
  742. if ((cbLength = *pbLength) & 0x80) {
  743. cbLength &= ~0x80; // low 7 bits have number of bytes
  744. if (cbLength > 4)
  745. goto LengthTooLargeError;
  746. if (cbLength >= cbDER)
  747. goto EncodeOverflowError2;
  748. *pcbContent = 0;
  749. for (i=cbLength, pb=pbLength+1; i>0; i--, pb++)
  750. *pcbContent = (*pcbContent << 8) + (DWORD)*pb;
  751. i = cbLength + 1;
  752. } else {
  753. *pcbContent = (DWORD)cbLength;
  754. i = 1;
  755. }
  756. CommonReturn:
  757. return i; // how many bytes there were in the length field
  758. EncodeOverflowError:
  759. IsBERError:
  760. LengthTooLargeError:
  761. EncodeOverflowError2:
  762. i = -1;
  763. goto CommonReturn;
  764. }
  765. //+-------------------------------------------------------------------------
  766. // Point to the content octets in a DER-encoded blob.
  767. //
  768. // Returns:
  769. // success - the number of bytes skipped, >=0
  770. // failure - <0
  771. //
  772. // Assume pbData points to a definite-length BER-encoded blob.
  773. //--------------------------------------------------------------------------
  774. LONG
  775. WINAPI
  776. TCM_ExtractContent(
  777. IN PBYTE pbDER,
  778. IN DWORD cbDER,
  779. OUT DWORD *pcbContent,
  780. OUT OPTIONAL PBYTE *ppbContent)
  781. {
  782. #define TAG_MASK 0x1f
  783. DWORD cbIdentifier;
  784. DWORD cbContent;
  785. LONG cbLength;
  786. PBYTE pb = pbDER;
  787. // Skip over the identifier octet(s)
  788. if (TAG_MASK == (*pb++ & TAG_MASK)) {
  789. // high-tag-number form
  790. for (cbIdentifier=2; *pb++ & 0x80; cbIdentifier++)
  791. ;
  792. } else {
  793. // low-tag-number form
  794. cbIdentifier = 1;
  795. }
  796. if (0 > (cbLength = TCM_DecodeLength( &cbContent, pb, cbDER-cbIdentifier)))
  797. goto DecodeLengthError;
  798. pb += cbLength;
  799. *pcbContent = cbContent;
  800. if (ppbContent)
  801. *ppbContent = pb;
  802. return cbLength + cbIdentifier;
  803. DecodeLengthError:
  804. return -1;
  805. }
  806. //+-------------------------------------------------------------------------
  807. // Functions for initializing message encode information
  808. //--------------------------------------------------------------------------
  809. void InitSignedMsgEncodeInfo(
  810. OUT PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  811. );
  812. void InitEnvelopedMsgEncodeInfo(
  813. OUT PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  814. );
  815. //+-------------------------------------------------------------------------
  816. // Functions for cleaning up message encode information
  817. //--------------------------------------------------------------------------
  818. void CleanupSignedMsgEncodeInfo(
  819. OUT PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  820. );
  821. void CleanupEnvelopedMsgEncodeInfo(
  822. OUT PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  823. );
  824. //+-------------------------------------------------------------------------
  825. // Message encode and decode routines
  826. //--------------------------------------------------------------------------
  827. BOOL EncodeAndDecodeMsg(
  828. IN DWORD dwMsgType,
  829. IN void *pvMsgEncodeInfo
  830. );
  831. BOOL EncodeMsg(
  832. IN DWORD dwMsgType,
  833. IN void *pvMsgEncodeInfo,
  834. OUT BYTE **ppbEncodedBlob,
  835. OUT DWORD *pcbEncodedBlob
  836. );
  837. BOOL DecodeMsg(
  838. IN DWORD dwExpectedMsgType,
  839. IN const BYTE *pbEncodedBlob,
  840. IN DWORD cbEncodedBlob
  841. );
  842. BOOL StreamEncodeAndDecodeMsg();
  843. BOOL StreamEncodeMsg();
  844. BOOL StreamDecodeMsg();
  845. //+-------------------------------------------------------------------------
  846. // Get signer info and verify the signed message
  847. //--------------------------------------------------------------------------
  848. BOOL GetSignerInfoAndVerify(IN HCRYPTMSG hMsg, IN BOOL fInnerNonData);
  849. BOOL GetSignerInfoAndVerify(
  850. IN HCRYPTMSG hMsg,
  851. IN BOOL fInnerNonData,
  852. IN DWORD dwSignerIndex,
  853. OUT DWORD *pdwSrcIndex
  854. );
  855. //+-------------------------------------------------------------------------
  856. // Get recipient info and decrypt the message.
  857. //--------------------------------------------------------------------------
  858. BOOL GetRecipientInfoAndDecrypt(IN HCRYPTMSG hMsg);
  859. //+-------------------------------------------------------------------------
  860. // Allocate and get the CMSG_SIGNER_CERT_INFO_PARAM or CMSG_RECIPIENT_INFO_PARAM
  861. // from the message
  862. //--------------------------------------------------------------------------
  863. PCERT_INFO GetCertIdFromMsg(
  864. IN HCRYPTMSG hMsg,
  865. IN DWORD dwParamType,
  866. IN DWORD dwIndex
  867. );
  868. //+-------------------------------------------------------------------------
  869. // Allocate and get the CMSG_SIGNER_INFO_PARAM from the message
  870. //--------------------------------------------------------------------------
  871. PCMSG_SIGNER_INFO GetSignerInfoFromMsg(
  872. IN HCRYPTMSG hMsg,
  873. IN DWORD dwIndex
  874. );
  875. //+-------------------------------------------------------------------------
  876. // Get computed digest and digest data from a decoded CMSG_HASHED
  877. //--------------------------------------------------------------------------
  878. BOOL Undigest(IN HCRYPTMSG hMsg);
  879. //+-------------------------------------------------------------------------
  880. // Countersign test functions
  881. //--------------------------------------------------------------------------
  882. BOOL CountersignAndVerify(IN HCRYPTMSG hCryptMsg);
  883. //+-------------------------------------------------------------------------
  884. // Add signer test functions
  885. //--------------------------------------------------------------------------
  886. BOOL AddSignerAndVerify(IN HCRYPTMSG hCryptMsg);
  887. //+-------------------------------------------------------------------------
  888. // Top Level Test Functions
  889. //--------------------------------------------------------------------------
  890. BOOL TestSign()
  891. {
  892. BOOL fRet;
  893. InitSignedMsgEncodeInfo(&SignedMsgEncodeInfo);
  894. fRet = EncodeAndDecodeMsg(CMSG_SIGNED, &SignedMsgEncodeInfo);
  895. CleanupSignedMsgEncodeInfo(&SignedMsgEncodeInfo);
  896. return fRet;
  897. }
  898. BOOL TestEnvelope()
  899. {
  900. BOOL fRet;
  901. InitEnvelopedMsgEncodeInfo(&EnvelopedMsgEncodeInfo);
  902. fRet = EncodeAndDecodeMsg(CMSG_ENVELOPED, &EnvelopedMsgEncodeInfo);
  903. CleanupEnvelopedMsgEncodeInfo(&EnvelopedMsgEncodeInfo);
  904. return fRet;
  905. }
  906. BOOL TestSignAndEnvelope()
  907. {
  908. BOOL fRet;
  909. return FALSE;
  910. SignedAndEnvelopedMsgEncodeInfo.cbSize =
  911. sizeof(CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO);
  912. InitSignedMsgEncodeInfo(&SignedAndEnvelopedMsgEncodeInfo.SignedInfo);
  913. InitEnvelopedMsgEncodeInfo(&SignedAndEnvelopedMsgEncodeInfo.EnvelopedInfo);
  914. fRet = EncodeAndDecodeMsg(CMSG_SIGNED_AND_ENVELOPED,
  915. &SignedAndEnvelopedMsgEncodeInfo);
  916. CleanupSignedMsgEncodeInfo(&SignedAndEnvelopedMsgEncodeInfo.SignedInfo);
  917. CleanupEnvelopedMsgEncodeInfo(&SignedAndEnvelopedMsgEncodeInfo.EnvelopedInfo);
  918. return fRet;
  919. }
  920. BOOL TestDigest()
  921. {
  922. HashedMsgEncodeInfo.cbSize = sizeof(CMSG_HASHED_ENCODE_INFO);
  923. HashedMsgEncodeInfo.hCryptProv = hDefaultVerifyProv;
  924. HashedMsgEncodeInfo.HashAlgorithm =
  925. DigestAlgorithms[ fMD5 ? DIGEST_ALG_MD5 : DIGEST_ALG_SHA];
  926. HashedMsgEncodeInfo.pvHashAuxInfo = NULL;
  927. return EncodeAndDecodeMsg(CMSG_HASHED, &HashedMsgEncodeInfo);
  928. }
  929. BOOL TestCountersign()
  930. {
  931. BOOL fRet;
  932. fCountersign = TRUE;
  933. InitSignedMsgEncodeInfo(&SignedMsgEncodeInfo);
  934. fRet = EncodeAndDecodeMsg(CMSG_SIGNED, &SignedMsgEncodeInfo);
  935. CleanupSignedMsgEncodeInfo(&SignedMsgEncodeInfo);
  936. return fRet;
  937. }
  938. BOOL TestStream()
  939. {
  940. BOOL fRet;
  941. if (NULL == (plistStream = new CStreamList))
  942. return FALSE;
  943. fStream = TRUE;
  944. InitSignedMsgEncodeInfo(&SignedMsgEncodeInfo);
  945. InitEnvelopedMsgEncodeInfo(&EnvelopedMsgEncodeInfo);
  946. fRet = StreamEncodeAndDecodeMsg();
  947. CleanupEnvelopedMsgEncodeInfo(&EnvelopedMsgEncodeInfo);
  948. CleanupSignedMsgEncodeInfo(&SignedMsgEncodeInfo);
  949. delete plistStream;
  950. plistStream = NULL;
  951. return fRet;
  952. }
  953. typedef BOOL (*PFN_TEST)(void);
  954. struct
  955. {
  956. LPCSTR pszName;
  957. PFN_TEST pfn;
  958. } Tests[] = {
  959. "Sign", TestSign,
  960. "Envelope", TestEnvelope,
  961. "SignAndEnvelope", TestSignAndEnvelope,
  962. "Digest", TestDigest,
  963. "Countersign", TestCountersign,
  964. "Stream", TestStream
  965. };
  966. #define NTESTS (sizeof(Tests)/sizeof(Tests[0]))
  967. void Usage(void)
  968. {
  969. int i;
  970. printf("Usage: tcrmsg [options] [<TestName>] [<StoreFilename>][<CertNameString>]\n");
  971. printf("Options are:\n");
  972. #ifdef CMS_PKCS7
  973. printf(" -AttrCert - Add CMS attribute certificates\n");
  974. printf(" -Crl - Add CRLs\n");
  975. printf(" -EncapsulatedContent - CMS encapsulated content\n");
  976. printf(" -OriginatorInfo - CMS EnvelopedData OriginatorInfo\n");
  977. printf(" -KeyTrans - CMS KeyTrans recipients\n");
  978. printf(" -KeyAgree - CMS KeyAgree recipients\n");
  979. printf(" -MailList - CMS MailList recipients\n");
  980. printf(" -RecipientKeyId - Use KeyId for recipients\n");
  981. printf(" -CertInfoKeyId - Use KeyId for encode CertInfo\n");
  982. printf(" -SignerId - Use SignerId instead of CertInfo\n");
  983. printf(" -HashEncryptionAlgorithm - Use for first signer info\n");
  984. printf(" -NoSignature - Use NO_SIGNATURE OID \n");
  985. printf(" -NoRecipients - No Envelope Recipients\n");
  986. printf(" -AlgorithmParameters - Algorithms have dummy parameters\n");
  987. printf(" -NoSalt - NoSalt for RC4\n");
  988. #endif // CMS_PKCS7
  989. printf(" -h - This message\n");
  990. printf(" -A - Authenticated Attributes\n");
  991. printf(" -B - Bare content (no outer ContentInfo)\n");
  992. printf(" -c - no Certs\n");
  993. printf(" -C - non-data inner Content\n");
  994. printf(" -D - Detached Signature/Digest\n");
  995. printf(" -i - indefinite-length encoding\n");
  996. printf(" -l - print command Line\n");
  997. printf(" -M - MD5 hash algorithm\n");
  998. printf(" -n<size> - Number of bytes in content\n");
  999. printf(" -N - No signers\n");
  1000. #ifdef CMS_PKCS7
  1001. printf(" -NMultiple - Multiple signers\n");
  1002. #endif // CMS_PKCS7
  1003. printf(" -p<provider#> - Crypto Provider\n");
  1004. printf(" -PEnhanced - Use enhanced crypto provider\n");
  1005. printf(" -PDefault - Use default crypto provider\n");
  1006. #ifdef CMS_PKCS7
  1007. printf(" -PRecipient - Each recipient has a crypto provider\n");
  1008. printf(" -PDSS - Use DSS provider for second signer\n");
  1009. printf(" -PDSS_DH - Use DSS_DH provider for second signer\n");
  1010. #endif // CMS_PKCS7
  1011. printf(" -P<ProviderName> - Crypto provider Name\n");
  1012. printf(" -K<ContainerName> - Provider key container Name\n");
  1013. printf(" -E<name> - Encrypt algorithm, default of \"rc2\"\n");
  1014. printf(" -e<EncryptBitLen> - Encrypt key bit length\n");
  1015. printf(" -I - Include IV in encrypt parameters\n");
  1016. printf(" -s[ES]+ - list of stream message types\n");
  1017. printf(" -S - add signer\n");
  1018. printf(" -t - tiny streaming decode buffer\n");
  1019. printf(" -v - verbose\n");
  1020. printf(" -f<filename> - Write encoded message to file\n");
  1021. printf("\n");
  1022. printf("Tests are (case insensitive name):\n");
  1023. for (i = 0; i < NTESTS; i++)
  1024. printf(" %s\n", Tests[i].pszName);
  1025. printf("\n");
  1026. printf("Default: ALL Tests\n");
  1027. }
  1028. HCRYPTPROV GetCryptProv(
  1029. DWORD dwMyProvType = dwProvType,
  1030. LPCSTR pszMyProvider = pszProvider
  1031. )
  1032. {
  1033. HCRYPTPROV hProv = 0;
  1034. BOOL fResult;
  1035. if (NULL == pszMyProvider) {
  1036. if (fEnhanced) {
  1037. if (PROV_RSA_FULL == dwMyProvType)
  1038. pszMyProvider = MS_ENHANCED_PROV_A;
  1039. }
  1040. }
  1041. fResult = CryptAcquireContextA(
  1042. &hProv,
  1043. pszContainer,
  1044. pszMyProvider,
  1045. dwMyProvType,
  1046. fNoSignature ? CRYPT_VERIFYCONTEXT : 0 // dwFlags
  1047. );
  1048. if (fResult) {
  1049. printf("Using default sign and xchg keys for provider type: %d",
  1050. dwMyProvType);
  1051. if (pszMyProvider && *pszMyProvider)
  1052. printf(" provider: %s", pszMyProvider);
  1053. if (pszContainer && *pszContainer)
  1054. printf(" container: %s", pszContainer);
  1055. printf("\n");
  1056. } else {
  1057. DWORD dwErr = GetLastError();
  1058. if (dwErr == NTE_BAD_KEYSET) {
  1059. // Need to create the keys
  1060. printf("Generating SIGNATURE and EXCHANGE private keys\n");
  1061. hProv = 0;
  1062. fResult = CryptAcquireContextA(
  1063. &hProv,
  1064. pszContainer,
  1065. pszMyProvider,
  1066. dwMyProvType,
  1067. CRYPT_NEWKEYSET
  1068. );
  1069. if (!fResult || hProv == 0) {
  1070. PrintLastError("CryptAcquireContext");
  1071. return 0;
  1072. }
  1073. HCRYPTKEY hKey = 0;
  1074. fResult = CryptGenKey(
  1075. hProv,
  1076. AT_SIGNATURE,
  1077. CRYPT_EXPORTABLE,
  1078. &hKey
  1079. );
  1080. if (!fResult || hKey == 0)
  1081. PrintLastError("CryptGenKey(AT_SIGNATURE)");
  1082. else
  1083. CryptDestroyKey(hKey);
  1084. hKey = 0;
  1085. fResult = CryptGenKey(
  1086. hProv,
  1087. AT_KEYEXCHANGE,
  1088. CRYPT_EXPORTABLE,
  1089. &hKey
  1090. );
  1091. if (!fResult || hKey == 0)
  1092. PrintLastError("CryptGenKey(AT_KEYEXCHANGE)");
  1093. else
  1094. CryptDestroyKey(hKey);
  1095. } else {
  1096. PrintLastError("CryptAcquireContext");
  1097. return 0;
  1098. }
  1099. }
  1100. return hProv;
  1101. }
  1102. BOOL
  1103. GetNonStreamedMsgContent(
  1104. IN DWORD cbContent,
  1105. OUT PBYTE *ppbContent,
  1106. OUT DWORD *pcbContent)
  1107. {
  1108. BOOL fRet;
  1109. PBYTE pbContent;
  1110. PBYTE pb;
  1111. DWORD cb;
  1112. if (fInnerContent) {
  1113. if (!GetDERFromFile(
  1114. pszInnerContentFileName,
  1115. ppbContent,
  1116. pcbContent))
  1117. goto GetDERFromFileError;
  1118. } else {
  1119. if (NULL == (pbContent = (PBYTE)TestAlloc( cbContent)))
  1120. goto AllocContentError;
  1121. for (pb=pbContent, cb=0; cb < cbContent; pb++, cb++)
  1122. *pb = rgbMsgContentFill[ cb%cbMsgContentFill];
  1123. *ppbContent = pbContent;
  1124. *pcbContent = cbContent;
  1125. }
  1126. fRet = TRUE;
  1127. CommonReturn:
  1128. return fRet;
  1129. ErrorReturn:
  1130. *ppbContent = NULL;
  1131. *pcbContent = 0;
  1132. fRet = FALSE;
  1133. goto CommonReturn;
  1134. PRINT_ERROR(GetNonStreamedMsgContent,GetDERFromFileError)
  1135. PRINT_ERROR(GetNonStreamedMsgContent,AllocContentError)
  1136. }
  1137. PCCRYPT_OID_INFO GetOIDInfo(LPCSTR pszName, DWORD dwGroupId = 0)
  1138. {
  1139. WCHAR wszName[256];
  1140. PCCRYPT_OID_INFO pInfo;
  1141. MultiByteToWideChar(
  1142. CP_ACP,
  1143. 0, // dwFlags
  1144. pszName,
  1145. -1, // null terminated
  1146. wszName,
  1147. sizeof(wszName) / sizeof(wszName[0]));
  1148. return CryptFindOIDInfo(
  1149. CRYPT_OID_INFO_NAME_KEY,
  1150. (void *) wszName,
  1151. dwGroupId
  1152. );
  1153. }
  1154. LPCSTR GetOID(LPCSTR pszName, DWORD dwGroupId = 0)
  1155. {
  1156. PCCRYPT_OID_INFO pInfo;
  1157. if (pInfo = GetOIDInfo(pszName, dwGroupId))
  1158. return pInfo->pszOID;
  1159. else
  1160. return NULL;
  1161. }
  1162. ALG_ID GetAlgid(LPCSTR pszName, DWORD dwGroupId = 0)
  1163. {
  1164. PCCRYPT_OID_INFO pInfo;
  1165. if (pInfo = GetOIDInfo(pszName, dwGroupId))
  1166. return pInfo->Algid;
  1167. else
  1168. return 0;
  1169. }
  1170. static HCERTSTORE OpenStore(LPCSTR pszStoreFilename)
  1171. {
  1172. HCERTSTORE hStore;
  1173. HANDLE hFile = 0;
  1174. if( INVALID_HANDLE_VALUE == (hFile = CreateFile(pszStoreFilename,
  1175. GENERIC_READ,
  1176. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1177. NULL, OPEN_EXISTING, 0, NULL))) {
  1178. printf( "can't open %s\n", pszStoreFilename);
  1179. hStore = NULL;
  1180. } else {
  1181. hStore = CertOpenStore(
  1182. CERT_STORE_PROV_FILE,
  1183. dwCertEncodingType,
  1184. 0, // hProv
  1185. 0, // dwFlags
  1186. hFile
  1187. );
  1188. CloseHandle(hFile);
  1189. }
  1190. if (hStore == NULL)
  1191. PrintLastError("CertOpenStore");
  1192. return hStore;
  1193. }
  1194. int _cdecl main(int argc, char * argv[])
  1195. {
  1196. BOOL fResult;
  1197. LPSTR pszTestName = NULL;
  1198. int TestIdx = 0;
  1199. LPSTR pszStoreFilename = NULL;
  1200. while (--argc>0)
  1201. {
  1202. if (**++argv == '-')
  1203. {
  1204. #ifdef CMS_PKCS7
  1205. if (0 == _stricmp(argv[0]+1, "AttrCert")) {
  1206. cAttrCert = ATTR_CERT_COUNT;
  1207. } else if (0 == _stricmp(argv[0]+1, "Crl")) {
  1208. cSignedCrl = SIGNED_CRL_COUNT;
  1209. } else if (0 == _stricmp(argv[0]+1, "EncapsulatedContent")) {
  1210. fEncapsulatedContent = TRUE;
  1211. } else if (0 == _stricmp(argv[0]+1, "OriginatorInfo")) {
  1212. fOriginatorInfo = TRUE;
  1213. } else if (0 == _stricmp(argv[0]+1, "KeyTrans")) {
  1214. fKeyTrans = TRUE;
  1215. fCmsRecipient = TRUE;
  1216. } else if (0 == _stricmp(argv[0]+1, "KeyAgree")) {
  1217. fKeyAgree = TRUE;
  1218. fCmsRecipient = TRUE;
  1219. } else if (0 == _stricmp(argv[0]+1, "MailList")) {
  1220. fMailList = TRUE;
  1221. fCmsRecipient = TRUE;
  1222. } else if (0 == _stricmp(argv[0]+1, "RecipientKeyId")) {
  1223. fRecipientKeyId = TRUE;
  1224. } else if (0 == _stricmp(argv[0]+1, "CertInfoKeyId")) {
  1225. fCertInfoKeyId = TRUE;
  1226. } else if (0 == _stricmp(argv[0]+1, "SignerId")) {
  1227. fSignerId = TRUE;
  1228. } else if (0 == _stricmp(argv[0]+1, "HashEncryptionAlgorithm")) {
  1229. fHashEncryptionAlgorithm = TRUE;
  1230. } else if (0 == _stricmp(argv[0]+1, "NoSignature")) {
  1231. fNoSignature = TRUE;
  1232. } else if (0 == _stricmp(argv[0]+1, "NoRecipients")) {
  1233. fNoRecipients = TRUE;
  1234. } else if (0 == _stricmp(argv[0]+1, "AlgorithmParameters")) {
  1235. fAlgorithmParameters = TRUE;
  1236. } else if (0 == _stricmp(argv[0]+1, "NoSalt")) {
  1237. fNoSalt = TRUE;
  1238. } else {
  1239. #endif // CMS_PKCS7
  1240. switch(argv[0][1])
  1241. {
  1242. case 'A':
  1243. fAuthAttr = TRUE;
  1244. break;
  1245. case 'B':
  1246. fBare = TRUE;
  1247. break;
  1248. case 'c':
  1249. cSignedCert = 0;
  1250. break;
  1251. case 'C':
  1252. fInnerContent = TRUE;
  1253. break;
  1254. case 'D':
  1255. fDetached = TRUE;
  1256. break;
  1257. case 'i':
  1258. fIndefinite = TRUE;
  1259. break;
  1260. case 'l':
  1261. printf("command line: %s\n", GetCommandLine());
  1262. break;
  1263. case 'M':
  1264. fMD5 = TRUE;
  1265. break;
  1266. case 'n':
  1267. cbMsgContent = strtoul( argv[0]+2, NULL, 0);
  1268. break;
  1269. case 'N':
  1270. #ifdef CMS_PKCS7
  1271. if (0 == _stricmp(argv[0]+2, "Multiple"))
  1272. fMultiSigner = TRUE;
  1273. else
  1274. #endif // CMS_PKCS7
  1275. fNoSigners = TRUE;
  1276. break;
  1277. case 'p':
  1278. dwProvType = strtoul( argv[0]+2, NULL, 0);
  1279. break;
  1280. case 'P':
  1281. if (0 == _stricmp(argv[0]+2, "Enhanced"))
  1282. fEnhanced = TRUE;
  1283. else if (0 == _stricmp(argv[0]+2, "Default"))
  1284. fDefaultVerifyProv = TRUE;
  1285. #ifdef CMS_PKCS7
  1286. else if (0 == _stricmp(argv[0]+2, "Recipient"))
  1287. fRecipientProv = TRUE;
  1288. else if (0 == _stricmp(argv[0]+2, "DSS"))
  1289. dwMultiSignerProvType = PROV_DSS;
  1290. else if (0 == _stricmp(argv[0]+2, "DSS_DH"))
  1291. dwMultiSignerProvType = PROV_DSS_DH;
  1292. #endif // CMS_PKCS7
  1293. else
  1294. pszProvider = argv[0]+2;
  1295. break;
  1296. case 'K':
  1297. pszContainer = argv[0]+2;
  1298. break;
  1299. case 'E':
  1300. pszEncryptName = argv[0]+2;
  1301. break;
  1302. case 'e':
  1303. dwEncryptBitLen = strtoul( argv[0]+2, NULL, 0);
  1304. break;
  1305. case 'I':
  1306. fEncryptIV = TRUE;
  1307. break;
  1308. case 'R':
  1309. pszEncryptName = "rc4";
  1310. break;
  1311. case 's':
  1312. pszStreamMsgTypes = argv[0]+2;
  1313. break;
  1314. case 'S':
  1315. fAddSigner = TRUE;
  1316. break;
  1317. case 't':
  1318. cbStreamDataDeltaDecode = 1;
  1319. break;
  1320. case 'v':
  1321. fVerbose = TRUE;
  1322. break;
  1323. case 'f':
  1324. pszFilename = argv[0]+2;
  1325. if (*pszFilename == '\0') {
  1326. printf("Need to specify filename\n");
  1327. Usage();
  1328. return -1;
  1329. }
  1330. break;
  1331. case 'h':
  1332. default:
  1333. Usage();
  1334. return -1;
  1335. }
  1336. #ifdef CMS_PKCS7
  1337. }
  1338. #endif // CMS_PKCS7
  1339. } else {
  1340. if(pszTestName == NULL)
  1341. pszTestName = argv[0];
  1342. else if (pszStoreFilename == NULL)
  1343. pszStoreFilename = argv[0];
  1344. else if (pszCertNameFindStr == NULL)
  1345. pszCertNameFindStr = argv[0];
  1346. else {
  1347. printf("Too many arguments\n");
  1348. Usage();
  1349. return -1;
  1350. }
  1351. }
  1352. }
  1353. if (fInnerContent && (cbMsgContent != DEFAULT_MSG_CONTENT_SIZE)) {
  1354. printf( "-n and -C not compatible\n");
  1355. return -1;
  1356. }
  1357. if (pszTestName) {
  1358. for (TestIdx = 0; TestIdx < NTESTS; TestIdx++) {
  1359. if (_stricmp(pszTestName, Tests[TestIdx].pszName) == 0)
  1360. break;
  1361. }
  1362. if (TestIdx >= NTESTS) {
  1363. printf("Bad TestName: %s\n", pszTestName);
  1364. Usage();
  1365. return -1;
  1366. }
  1367. } else
  1368. TestIdx = 0;
  1369. if (NULL == (pszEncryptOID = (LPSTR) GetOID(
  1370. pszEncryptName, CRYPT_ENCRYPT_ALG_OID_GROUP_ID))) {
  1371. printf("Failed => unknown encrypt name (%s)\n", pszEncryptName);
  1372. return -1;
  1373. }
  1374. if (fDetached) printf("Enabled: DetachedDigest/Signature\n");
  1375. if (fNoSigners) printf("Enabled: NoSigners\n");
  1376. if (fAuthAttr) printf("Enabled: Authenticated attributes\n");
  1377. if (fInnerContent) printf("Enabled: non-data Content\n");
  1378. if (0 != _stricmp("rc2", pszEncryptName))
  1379. printf("Enabled: %s\n", pszEncryptName);
  1380. if (0 != dwEncryptBitLen)
  1381. printf("Enabled: Encrypt bit length: %d\n", dwEncryptBitLen);
  1382. if (fEncryptIV) printf("Enabled: IV\n");
  1383. if (fMD5) printf("Enabled: MD5\n");
  1384. if (pszFilename) printf("Enabled: Writing encoded to file: %s\n", pszFilename);
  1385. // Get crypto provider having both signature and exchange private keys
  1386. hCryptProv = GetCryptProv();
  1387. if (hCryptProv == 0)
  1388. return -1;
  1389. // Attempt to open the store
  1390. if (pszStoreFilename) {
  1391. hSignerStore = OpenStore(pszStoreFilename);
  1392. if (NULL == hSignerStore)
  1393. return -1;
  1394. }
  1395. #ifdef CMS_PKCS7
  1396. if (fKeyAgree) {
  1397. hKeyAgreeProv = GetCryptProv(PROV_DSS_DH, NULL);
  1398. if (hKeyAgreeProv == 0)
  1399. return -1;
  1400. }
  1401. if (fMultiSigner) {
  1402. hMultiSignerCryptProv = GetCryptProv(dwMultiSignerProvType, NULL);
  1403. if (hMultiSignerCryptProv == 0)
  1404. return -1;
  1405. }
  1406. #endif // CMS_PKCS7
  1407. if (fDefaultVerifyProv) {
  1408. printf("Using default hCryptProv for encrypting and verifying\n");
  1409. hDefaultVerifyProv = 0;
  1410. } else
  1411. hDefaultVerifyProv = hCryptProv;
  1412. for ( ; TestIdx < NTESTS; TestIdx++) {
  1413. printf("Starting %s Test\n", Tests[TestIdx].pszName);
  1414. fResult = Tests[TestIdx].pfn();
  1415. if (fResult)
  1416. printf("Passed\n");
  1417. else
  1418. printf("Failed\n");
  1419. printf("\n");
  1420. if (pszTestName)
  1421. break;
  1422. }
  1423. TestFree( pbInnerContent);
  1424. if (pNamedSigner)
  1425. CertFreeCertificateContext(pNamedSigner);
  1426. if (hSignerStore)
  1427. CertCloseStore(hSignerStore, 0);
  1428. return 0;
  1429. }
  1430. //+-------------------------------------------------------------------------
  1431. // Functions for initializing message encode information
  1432. //--------------------------------------------------------------------------
  1433. static PCCERT_CONTEXT FindCertWithKey(
  1434. IN HCERTSTORE hCertStore,
  1435. IN DWORD dwKeySpec
  1436. )
  1437. {
  1438. PCCERT_CONTEXT pCert;
  1439. void *pvFindPara;
  1440. DWORD dwFindType;
  1441. if (pszCertNameFindStr) {
  1442. dwFindType = CERT_FIND_SUBJECT_STR_A;
  1443. pvFindPara = (void *) pszCertNameFindStr;
  1444. } else {
  1445. dwFindType = CERT_FIND_ANY;
  1446. pvFindPara = NULL;
  1447. }
  1448. // Find the first certificate in the store with a CRYPT_KEY_PROV_INFO
  1449. // property matching the specified dwSignKeySpec, dwCryptProvType and
  1450. // dwPubKeyBitLen
  1451. pCert = NULL;
  1452. while (TRUE) {
  1453. pCert = CertFindCertificateInStore(
  1454. hCertStore,
  1455. dwCertEncodingType,
  1456. 0, // dwFindFlags,
  1457. dwFindType,
  1458. pvFindPara,
  1459. pCert
  1460. );
  1461. if (pCert == NULL)
  1462. break;
  1463. PCRYPT_KEY_PROV_INFO pInfo = NULL;
  1464. DWORD cbInfo = 0;
  1465. CertGetCertificateContextProperty(
  1466. pCert,
  1467. CERT_KEY_PROV_INFO_PROP_ID,
  1468. NULL,
  1469. &cbInfo
  1470. );
  1471. if (cbInfo >= sizeof(CRYPT_KEY_PROV_INFO) &&
  1472. (pInfo = (PCRYPT_KEY_PROV_INFO) TestAlloc(cbInfo))) {
  1473. BOOL fMatch = FALSE;
  1474. if (CertGetCertificateContextProperty(
  1475. pCert,
  1476. CERT_KEY_PROV_INFO_PROP_ID,
  1477. pInfo,
  1478. &cbInfo) &&
  1479. dwKeySpec == pInfo->dwKeySpec)
  1480. fMatch = TRUE;
  1481. TestFree(pInfo);
  1482. if (fMatch)
  1483. break;
  1484. }
  1485. }
  1486. return pCert;
  1487. }
  1488. #ifdef CMS_PKCS7
  1489. static BYTE bZeroSerialNumber = 0;
  1490. //+-------------------------------------------------------------------------
  1491. // Create a Special Issuer and SerialNumber from a KeyId.
  1492. //--------------------------------------------------------------------------
  1493. void CreateIssuerAndSerialNumberFromKeyId(
  1494. IN const BYTE *pbKeyId,
  1495. IN DWORD cbKeyId,
  1496. IN OUT PCERT_INFO pCertInfo
  1497. )
  1498. {
  1499. CERT_RDN_ATTR KeyIdAttr;
  1500. CERT_RDN KeyIdRDN;
  1501. CERT_NAME_INFO IssuerInfo;
  1502. KeyIdAttr.pszObjId = szOID_KEYID_RDN;
  1503. KeyIdAttr.dwValueType = CERT_RDN_OCTET_STRING;
  1504. KeyIdAttr.Value.pbData = (BYTE *) pbKeyId;
  1505. KeyIdAttr.Value.cbData = cbKeyId;
  1506. KeyIdRDN.cRDNAttr = 1;
  1507. KeyIdRDN.rgRDNAttr = &KeyIdAttr;
  1508. IssuerInfo.cRDN = 1;
  1509. IssuerInfo.rgRDN = &KeyIdRDN;
  1510. // Encode the special Issuer Name containing the KeyId
  1511. AllocAndEncodeObject(
  1512. X509_NAME,
  1513. &IssuerInfo,
  1514. &pCertInfo->Issuer.pbData,
  1515. &pCertInfo->Issuer.cbData
  1516. );
  1517. pCertInfo->SerialNumber.cbData = 1;
  1518. pCertInfo->SerialNumber.pbData = &bZeroSerialNumber;
  1519. }
  1520. #endif
  1521. void InitSignerEncodeInfo()
  1522. {
  1523. DWORD cbSignerPublicKeyData;
  1524. // Update the Issuer, SerialNumber and PublicKeyAlgorithm in
  1525. // the signer's CERT_INFO
  1526. memset(&rgSignerCertInfo[0], 0, sizeof(CERT_INFO));
  1527. #ifdef CMS_PKCS7
  1528. if (fCertInfoKeyId) {
  1529. CreateIssuerAndSerialNumberFromKeyId(
  1530. (const BYTE *)"Signer 0",
  1531. strlen("Signer 0"),
  1532. &rgSignerCertInfo[0]
  1533. );
  1534. rgSignerId[0].dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  1535. rgSignerId[0].KeyId.pbData = (BYTE *)"Signer 0";
  1536. rgSignerId[0].KeyId.cbData = strlen("Signer 0");
  1537. } else {
  1538. #endif
  1539. GetDERFromFile(
  1540. pszSignerSerialNumberFileName,
  1541. &rgSignerCertInfo[0].Issuer.pbData,
  1542. &rgSignerCertInfo[0].Issuer.cbData);
  1543. rgSignerCertInfo[0].SerialNumber.cbData = sizeof(DWORD);
  1544. rgSignerCertInfo[0].SerialNumber.pbData = (BYTE *) &dwSignerSerialNumber;
  1545. #ifdef CMS_PKCS7
  1546. rgSignerId[0].dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  1547. rgSignerId[0].IssuerSerialNumber.Issuer = rgSignerCertInfo[0].Issuer;
  1548. rgSignerId[0].IssuerSerialNumber.SerialNumber =
  1549. rgSignerCertInfo[0].SerialNumber;
  1550. }
  1551. #endif
  1552. if (!fNoSignature) {
  1553. // Get crypt provider's public signature key. It will be used as the
  1554. // signer's public key algorithm
  1555. cbSignerPublicKeyData = sizeof(SignerPublicKeyData.Data);
  1556. memset(SignerPublicKeyData.Data, 0, cbSignerPublicKeyData);
  1557. CryptExportPublicKeyInfo(
  1558. hCryptProv,
  1559. AT_SIGNATURE,
  1560. X509_ASN_ENCODING,
  1561. (PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data,
  1562. &cbSignerPublicKeyData);
  1563. rgSignerCertInfo[0].SubjectPublicKeyInfo.Algorithm =
  1564. ((PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data)->Algorithm;
  1565. }
  1566. // Update the rgSignerEncodeInfo[0]
  1567. memset(&rgSignerEncodeInfo[0], 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
  1568. rgSignerEncodeInfo[0].cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
  1569. rgSignerEncodeInfo[0].pCertInfo = &rgSignerCertInfo[0];
  1570. rgSignerEncodeInfo[0].hCryptProv = hCryptProv;
  1571. rgSignerEncodeInfo[0].HashAlgorithm =
  1572. SignDigestAlgorithms[ fMD5 ? SIGNDIGEST_ALG_MD5 : SIGNDIGEST_ALG_SHA];
  1573. rgSignerEncodeInfo[0].pvHashAuxInfo = NULL;
  1574. #ifdef CMS_PKCS7
  1575. if (fAlgorithmParameters) {
  1576. rgSignerEncodeInfo[0].HashAlgorithm.Parameters.pbData = rgbOctets;
  1577. rgSignerEncodeInfo[0].HashAlgorithm.Parameters.cbData =
  1578. sizeof(rgbOctets);
  1579. }
  1580. #endif // CMS_PKCS7
  1581. if (fAuthAttr) {
  1582. rgSignerEncodeInfo[0].cAuthAttr = AUTH_ATTR_COUNT;
  1583. rgSignerEncodeInfo[0].rgAuthAttr = rgAuthAttr;
  1584. if (!fCountersign) {
  1585. rgSignerEncodeInfo[0].cUnauthAttr = UNAUTH_ATTR_COUNT;
  1586. rgSignerEncodeInfo[0].rgUnauthAttr = rgUnauthAttr;
  1587. }
  1588. }
  1589. if (hSignerStore) {
  1590. pNamedSigner = FindCertWithKey(hSignerStore, AT_SIGNATURE);
  1591. if (NULL == pNamedSigner) {
  1592. PrintLastError("FindCertWithKey(AT_SIGNATURE)");
  1593. } else {
  1594. if (!CryptAcquireCertificatePrivateKey(
  1595. pNamedSigner,
  1596. 0, // dwFlags
  1597. NULL, // pvReserved
  1598. &hNamedSignerCryptProv,
  1599. NULL, // pdwKeySpec,
  1600. NULL // pfCallerFreeProv
  1601. )) {
  1602. PrintLastError("CryptAcquireCertificatePrivateKey");
  1603. CertFreeCertificateContext(pNamedSigner);
  1604. pNamedSigner = NULL;
  1605. } else {
  1606. rgSignerEncodeInfo[0].pCertInfo = pNamedSigner->pCertInfo;
  1607. rgSignerEncodeInfo[0].hCryptProv = hNamedSignerCryptProv;
  1608. #ifdef CMS_PKCS7
  1609. rgSignerId[0].dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  1610. rgSignerId[0].IssuerSerialNumber.Issuer =
  1611. rgSignerEncodeInfo[0].pCertInfo->Issuer;
  1612. rgSignerId[0].IssuerSerialNumber.SerialNumber =
  1613. rgSignerEncodeInfo[0].pCertInfo->SerialNumber;
  1614. #endif // CMS_PKCS7
  1615. }
  1616. }
  1617. }
  1618. #ifdef CMS_PKCS7
  1619. if (fNoSignature) {
  1620. rgSignerEncodeInfo[0].HashEncryptionAlgorithm.pszObjId =
  1621. szOID_PKIX_NO_SIGNATURE;
  1622. } else if (fHashEncryptionAlgorithm) {
  1623. if (pNamedSigner)
  1624. rgSignerEncodeInfo[0].HashEncryptionAlgorithm =
  1625. pNamedSigner->pCertInfo->SignatureAlgorithm;
  1626. else
  1627. rgSignerEncodeInfo[0].HashEncryptionAlgorithm =
  1628. rgSignerCertInfo[0].SubjectPublicKeyInfo.Algorithm;
  1629. if (fAlgorithmParameters &&
  1630. 0 == rgSignerEncodeInfo[0].HashEncryptionAlgorithm.Parameters.cbData)
  1631. {
  1632. rgSignerEncodeInfo[0].HashEncryptionAlgorithm.Parameters.pbData =
  1633. rgbOctets;
  1634. rgSignerEncodeInfo[0].HashEncryptionAlgorithm.Parameters.cbData =
  1635. sizeof(rgbOctets);
  1636. }
  1637. }
  1638. if (fMultiSigner) {
  1639. // Update the Issuer, SerialNumber and PublicKeyAlgorithm in
  1640. // the signer's CERT_INFO
  1641. memset(&rgSignerCertInfo[1], 0, sizeof(CERT_INFO));
  1642. if (fCertInfoKeyId) {
  1643. CreateIssuerAndSerialNumberFromKeyId(
  1644. (const BYTE *)"Signer 1",
  1645. strlen("Signer 1"),
  1646. &rgSignerCertInfo[1]
  1647. );
  1648. rgSignerId[1].dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  1649. rgSignerId[1].KeyId.pbData = (BYTE *)"Signer 1";
  1650. rgSignerId[1].KeyId.cbData = strlen("Signer 1");
  1651. } else {
  1652. GetDERFromFile(
  1653. pszSignerSerialNumberFileName,
  1654. &rgSignerCertInfo[1].Issuer.pbData,
  1655. &rgSignerCertInfo[1].Issuer.cbData);
  1656. rgSignerCertInfo[1].SerialNumber.cbData = sizeof(DWORD);
  1657. rgSignerCertInfo[1].SerialNumber.pbData =
  1658. (BYTE *) &dwSignerSerialNumber1;
  1659. rgSignerId[1].dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  1660. rgSignerId[1].IssuerSerialNumber.Issuer =
  1661. rgSignerCertInfo[1].Issuer;
  1662. rgSignerId[1].IssuerSerialNumber.SerialNumber =
  1663. rgSignerCertInfo[1].SerialNumber;
  1664. }
  1665. if (!fNoSignature) {
  1666. // Get crypt provider's public signature key. It will be used as the
  1667. // signer's public key algorithm
  1668. cbSignerPublicKeyData = sizeof(MultiSignerPublicKeyData.Data);
  1669. memset(MultiSignerPublicKeyData.Data, 0, cbSignerPublicKeyData);
  1670. CryptExportPublicKeyInfo(
  1671. hMultiSignerCryptProv,
  1672. AT_SIGNATURE,
  1673. X509_ASN_ENCODING,
  1674. (PCERT_PUBLIC_KEY_INFO) MultiSignerPublicKeyData.Data,
  1675. &cbSignerPublicKeyData);
  1676. rgSignerCertInfo[1].SubjectPublicKeyInfo.Algorithm =
  1677. ((PCERT_PUBLIC_KEY_INFO) MultiSignerPublicKeyData.Data)->Algorithm;
  1678. }
  1679. // Update the rgSignerEncodeInfo[1]
  1680. memset(&rgSignerEncodeInfo[1], 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
  1681. rgSignerEncodeInfo[1].cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
  1682. rgSignerEncodeInfo[1].pCertInfo = &rgSignerCertInfo[1];
  1683. rgSignerEncodeInfo[1].hCryptProv = hMultiSignerCryptProv;
  1684. rgSignerEncodeInfo[1].HashAlgorithm =
  1685. SignDigestAlgorithms[SIGNDIGEST_ALG_SHA];
  1686. rgSignerEncodeInfo[1].pvHashAuxInfo = NULL;
  1687. if (fNoSignature) {
  1688. rgSignerEncodeInfo[1].HashEncryptionAlgorithm.pszObjId =
  1689. szOID_PKIX_NO_SIGNATURE;
  1690. }
  1691. if (fAuthAttr) {
  1692. rgSignerEncodeInfo[1].cAuthAttr = AUTH_ATTR_COUNT;
  1693. rgSignerEncodeInfo[1].rgAuthAttr = rgAuthAttr;
  1694. if (!fCountersign) {
  1695. rgSignerEncodeInfo[1].cUnauthAttr = UNAUTH_ATTR_COUNT;
  1696. rgSignerEncodeInfo[1].rgUnauthAttr = rgUnauthAttr;
  1697. }
  1698. }
  1699. if (fSignerId)
  1700. rgSignerEncodeInfo[1].SignerId = rgSignerId[1];
  1701. }
  1702. if (fSignerId) {
  1703. rgSignerEncodeInfo[0].SignerId = rgSignerId[0];
  1704. if (fHashEncryptionAlgorithm)
  1705. rgSignerEncodeInfo[0].pCertInfo = NULL;
  1706. }
  1707. #endif // CMS_PKCS7
  1708. }
  1709. void CleanupSignerEncodeInfo()
  1710. {
  1711. free( rgSignerCertInfo[0].Issuer.pbData);
  1712. #ifdef CMS_PKCS7
  1713. if (fMultiSigner)
  1714. free( rgSignerCertInfo[1].Issuer.pbData);
  1715. #endif // CMS_PKCS7
  1716. }
  1717. void InitSignedCertAndCrl()
  1718. {
  1719. DWORD i;
  1720. #ifdef CMS_PKCS7
  1721. if (rgSignedCertBlob[0].pbData)
  1722. return;
  1723. #endif // CMS_PKCS7
  1724. for (i = 0; i < SIGNED_CERT_COUNT; i++) {
  1725. GetDERFromFile(
  1726. rgpszSignedCertFileName[i],
  1727. &rgSignedCertBlob[i].pbData,
  1728. &rgSignedCertBlob[i].cbData);
  1729. }
  1730. #ifdef CMS_PKCS7
  1731. for (i = 0; i < SIGNED_CRL_COUNT; i++) {
  1732. GetDERFromFile(
  1733. rgpszSignedCrlFileName[i],
  1734. &rgSignedCrlBlob[i].pbData,
  1735. &rgSignedCrlBlob[i].cbData);
  1736. }
  1737. for (i = 0; i < ATTR_CERT_COUNT; i++) {
  1738. GetDERFromFile(
  1739. rgpszAttrCertFileName[i],
  1740. &rgAttrCertBlob[i].pbData,
  1741. &rgAttrCertBlob[i].cbData);
  1742. }
  1743. #endif // CMS_PKCS7
  1744. }
  1745. void CleanupSignedCertAndCrl()
  1746. {
  1747. DWORD i;
  1748. for (i = 0; i < SIGNED_CERT_COUNT; i++) {
  1749. if (rgSignedCertBlob[i].pbData) {
  1750. free( rgSignedCertBlob[i].pbData);
  1751. rgSignedCertBlob[i].pbData = NULL;
  1752. }
  1753. }
  1754. #ifdef CMS_PKCS7
  1755. for (i = 0; i < SIGNED_CRL_COUNT; i++) {
  1756. if (rgSignedCrlBlob[i].pbData) {
  1757. free( rgSignedCrlBlob[i].pbData);
  1758. rgSignedCrlBlob[i].pbData = NULL;
  1759. }
  1760. }
  1761. for (i = 0; i < ATTR_CERT_COUNT; i++) {
  1762. if (rgAttrCertBlob[i].pbData) {
  1763. free( rgAttrCertBlob[i].pbData);
  1764. rgAttrCertBlob[i].pbData = NULL;
  1765. }
  1766. }
  1767. #endif // CMS_PKCS7
  1768. }
  1769. void InitSignedMsgEncodeInfo(
  1770. OUT PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  1771. )
  1772. {
  1773. InitSignerEncodeInfo();
  1774. pSignedMsgEncodeInfo->cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
  1775. pSignedMsgEncodeInfo->cSigners = fNoSigners ? 0 : 1;
  1776. #ifdef CMS_PKCS7
  1777. if (fMultiSigner)
  1778. pSignedMsgEncodeInfo->cSigners = 2;
  1779. #endif // CMS_PKCS7
  1780. pSignedMsgEncodeInfo->rgSigners = &rgSignerEncodeInfo[0];
  1781. InitSignedCertAndCrl();
  1782. pSignedMsgEncodeInfo->cCertEncoded = cSignedCert;
  1783. pSignedMsgEncodeInfo->rgCertEncoded = rgSignedCertBlob;
  1784. #ifdef CMS_PKCS7
  1785. pSignedMsgEncodeInfo->cCrlEncoded = cSignedCrl;
  1786. pSignedMsgEncodeInfo->rgCrlEncoded = rgSignedCrlBlob;
  1787. #else
  1788. pSignedMsgEncodeInfo->cCrlEncoded = 0;
  1789. pSignedMsgEncodeInfo->rgCrlEncoded = NULL;
  1790. #endif
  1791. #ifdef CMS_PKCS7
  1792. pSignedMsgEncodeInfo->cAttrCertEncoded = cAttrCert;
  1793. pSignedMsgEncodeInfo->rgAttrCertEncoded = rgAttrCertBlob;
  1794. #endif // CMS_PKCS7
  1795. }
  1796. void CleanupSignedMsgEncodeInfo(
  1797. IN PCMSG_SIGNED_ENCODE_INFO pSignedMsgEncodeInfo
  1798. )
  1799. {
  1800. CleanupSignerEncodeInfo();
  1801. CleanupSignedCertAndCrl();
  1802. }
  1803. void InitRecipientEncodeInfo()
  1804. {
  1805. DWORD cbRecipientPublicKeyData;
  1806. int i;
  1807. // Get crypt provider's public exchange key. It will be used as the
  1808. // recipient's public key
  1809. cbRecipientPublicKeyData = sizeof(RecipientPublicKeyData.Data);
  1810. memset(RecipientPublicKeyData.Data, 0, cbRecipientPublicKeyData);
  1811. CryptExportPublicKeyInfo(
  1812. hCryptProv,
  1813. AT_KEYEXCHANGE,
  1814. X509_ASN_ENCODING,
  1815. (PCERT_PUBLIC_KEY_INFO) RecipientPublicKeyData.Data,
  1816. &cbRecipientPublicKeyData);
  1817. // Update the Issuer, SerialNumber, PublicKey and PublicKeyAlgorithm
  1818. // for each recipient. Update the rgpRecipientCertInfo[].
  1819. for (i = 0; i < RECIPIENT_COUNT; i++) {
  1820. memset(&rgRecipientCertInfo[i], 0, sizeof(CERT_INFO));
  1821. #ifdef CMS_PKCS7
  1822. if (fCertInfoKeyId) {
  1823. CreateIssuerAndSerialNumberFromKeyId(
  1824. (const BYTE *)rgpszRecipientIssuerFileName[i],
  1825. strlen(rgpszRecipientIssuerFileName[i]),
  1826. &rgRecipientCertInfo[i]
  1827. );
  1828. } else {
  1829. #endif
  1830. GetDERFromFile(
  1831. rgpszRecipientIssuerFileName[i],
  1832. &rgRecipientCertInfo[i].Issuer.pbData,
  1833. &rgRecipientCertInfo[i].Issuer.cbData);
  1834. rgRecipientCertInfo[i].SerialNumber.cbData = sizeof(DWORD);
  1835. rgRecipientCertInfo[i].SerialNumber.pbData =
  1836. (BYTE *) &rgdwRecipientSerialNumber[i];
  1837. #ifdef CMS_PKCS7
  1838. }
  1839. #endif
  1840. rgRecipientCertInfo[i].SubjectPublicKeyInfo =
  1841. *((PCERT_PUBLIC_KEY_INFO) RecipientPublicKeyData.Data);
  1842. if (0 == i)
  1843. rgRecipientCertInfo[i].SubjectPublicKeyInfo.Algorithm.pszObjId =
  1844. szOID_OIWSEC_rsaXchg;
  1845. rgpRecipientCertInfo[i] = &rgRecipientCertInfo[i];
  1846. }
  1847. }
  1848. void CleanupRecipientEncodeInfo()
  1849. {
  1850. int i;
  1851. for (i = 0; i < RECIPIENT_COUNT; i++)
  1852. free( rgRecipientCertInfo[i].Issuer.pbData);
  1853. }
  1854. #ifdef CMS_PKCS7
  1855. HCRYPTKEY
  1856. WINAPI
  1857. GenerateMailListKey(
  1858. IN HCRYPTPROV hProv,
  1859. IN PCRYPT_DATA_BLOB pKeyId
  1860. )
  1861. {
  1862. HCRYPTHASH hHash = 0;
  1863. HCRYPTKEY hDeriveKey = 0;
  1864. ALG_ID AlgId;
  1865. // Generate derive key to use to encrypt and export the content encrypt key
  1866. if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) {
  1867. PrintLastError("CryptCreateHash");
  1868. goto ErrorReturn;
  1869. }
  1870. if (!CryptHashData(hHash, pKeyId->pbData, pKeyId->cbData, 0)) {
  1871. PrintLastError("CryptHashData");
  1872. goto ErrorReturn;
  1873. }
  1874. if (0 == _stricmp(pszEncryptName, "rc2"))
  1875. AlgId = CALG_RC2;
  1876. else
  1877. AlgId = CALG_3DES;
  1878. if (!CryptDeriveKey(hProv, AlgId, hHash, 0, &hDeriveKey)) {
  1879. PrintLastError("CryptDeriveKey");
  1880. goto ErrorReturn;
  1881. }
  1882. CommonReturn:
  1883. if (hHash)
  1884. CryptDestroyHash(hHash);
  1885. return hDeriveKey;
  1886. ErrorReturn:
  1887. goto CommonReturn;
  1888. }
  1889. void InitCmsRecipientEncodeInfo(
  1890. OUT PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  1891. )
  1892. {
  1893. PCERT_PUBLIC_KEY_INFO pPublicKeyInfo;
  1894. DWORD cbRecipientPublicKeyData;
  1895. DWORD i;
  1896. DWORD cRecipients = 0;
  1897. // Get crypt provider's public exchange key. It will be used as the
  1898. // recipient's public key
  1899. cbRecipientPublicKeyData = sizeof(RecipientPublicKeyData.Data);
  1900. memset(RecipientPublicKeyData.Data, 0, cbRecipientPublicKeyData);
  1901. CryptExportPublicKeyInfo(
  1902. hCryptProv,
  1903. AT_KEYEXCHANGE,
  1904. X509_ASN_ENCODING,
  1905. (PCERT_PUBLIC_KEY_INFO) RecipientPublicKeyData.Data,
  1906. &cbRecipientPublicKeyData);
  1907. pPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO) RecipientPublicKeyData.Data;
  1908. if (fKeyTrans && fRecipientKeyId) {
  1909. PkcsRecipientCount = RECIPIENT_COUNT * 2;
  1910. for (i = 0; i < RECIPIENT_COUNT; i++) {
  1911. PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTrans =
  1912. &rgKeyTrans[cRecipients];
  1913. rgCmsRecipient[cRecipients].dwRecipientChoice =
  1914. CMSG_KEY_TRANS_RECIPIENT;
  1915. rgCmsRecipient[cRecipients].pKeyTrans = pKeyTrans;
  1916. memset(pKeyTrans, 0, sizeof(*pKeyTrans));
  1917. pKeyTrans->cbSize = sizeof(*pKeyTrans);
  1918. pKeyTrans->KeyEncryptionAlgorithm = pPublicKeyInfo->Algorithm;
  1919. // pKeyTrans->pvKeyEncryptionAuxInfo =
  1920. // pKeyTrans->hCryptProv =
  1921. pKeyTrans->RecipientPublicKey = pPublicKeyInfo->PublicKey;
  1922. pKeyTrans->RecipientId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  1923. pKeyTrans->RecipientId.KeyId.pbData =
  1924. (PBYTE) rgpszRecipientIssuerFileName[i];
  1925. pKeyTrans->RecipientId.KeyId.cbData =
  1926. strlen(rgpszRecipientIssuerFileName[i]);
  1927. cRecipients++;
  1928. }
  1929. }
  1930. if (fKeyTrans) {
  1931. for (i = 0; i < RECIPIENT_COUNT; i++) {
  1932. PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTrans =
  1933. &rgKeyTrans[cRecipients];
  1934. rgCmsRecipient[cRecipients].dwRecipientChoice =
  1935. CMSG_KEY_TRANS_RECIPIENT;
  1936. rgCmsRecipient[cRecipients].pKeyTrans = pKeyTrans;
  1937. memset(pKeyTrans, 0, sizeof(*pKeyTrans));
  1938. pKeyTrans->cbSize = sizeof(*pKeyTrans);
  1939. pKeyTrans->KeyEncryptionAlgorithm = pPublicKeyInfo->Algorithm;
  1940. // pKeyTrans->pvKeyEncryptionAuxInfo =
  1941. // pKeyTrans->hCryptProv =
  1942. pKeyTrans->RecipientPublicKey = pPublicKeyInfo->PublicKey;
  1943. pKeyTrans->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  1944. GetDERFromFile(
  1945. rgpszRecipientIssuerFileName[i],
  1946. &pKeyTrans->RecipientId.IssuerSerialNumber.Issuer.pbData,
  1947. &pKeyTrans->RecipientId.IssuerSerialNumber.Issuer.cbData
  1948. );
  1949. pKeyTrans->RecipientId.IssuerSerialNumber.SerialNumber.cbData =
  1950. sizeof(DWORD);
  1951. pKeyTrans->RecipientId.IssuerSerialNumber.SerialNumber.pbData =
  1952. (BYTE *) &rgdwRecipientSerialNumber[i];
  1953. if (fRecipientProv)
  1954. pKeyTrans->hCryptProv = GetCryptProv();
  1955. cRecipients++;
  1956. }
  1957. }
  1958. if (fKeyAgree) {
  1959. void *pvStructInfo;
  1960. DWORD cbStructInfo;
  1961. cbRecipientPublicKeyData = sizeof(KeyAgreePublicKeyData.Data);
  1962. memset(KeyAgreePublicKeyData.Data, 0, cbRecipientPublicKeyData);
  1963. CryptExportPublicKeyInfo(
  1964. hKeyAgreeProv,
  1965. AT_KEYEXCHANGE,
  1966. X509_ASN_ENCODING,
  1967. (PCERT_PUBLIC_KEY_INFO) KeyAgreePublicKeyData.Data,
  1968. &cbRecipientPublicKeyData);
  1969. pPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO) KeyAgreePublicKeyData.Data;
  1970. // Check that we can decode both as X509_DH_PARAMETERS and
  1971. // X942_DH_PARAMETERS
  1972. AllocAndDecodeObject(
  1973. X509_DH_PARAMETERS,
  1974. pPublicKeyInfo->Algorithm.Parameters.pbData,
  1975. pPublicKeyInfo->Algorithm.Parameters.cbData,
  1976. &pvStructInfo,
  1977. &cbStructInfo
  1978. );
  1979. TestFree(pvStructInfo);
  1980. AllocAndDecodeObject(
  1981. X942_DH_PARAMETERS,
  1982. pPublicKeyInfo->Algorithm.Parameters.pbData,
  1983. pPublicKeyInfo->Algorithm.Parameters.cbData,
  1984. &pvStructInfo,
  1985. &cbStructInfo
  1986. );
  1987. TestFree(pvStructInfo);
  1988. for (i = 0; i < RECIPIENT_COUNT; i++) {
  1989. PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgree =
  1990. &rgKeyAgree[cRecipients];
  1991. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO pEncryptedKey =
  1992. &rgEncryptedKey[i];
  1993. rgCmsRecipient[cRecipients].dwRecipientChoice =
  1994. CMSG_KEY_AGREE_RECIPIENT;
  1995. rgCmsRecipient[cRecipients].pKeyAgree = pKeyAgree;
  1996. memset(pKeyAgree, 0, sizeof(*pKeyAgree));
  1997. pKeyAgree->cbSize = sizeof(*pKeyAgree);
  1998. pKeyAgree->KeyEncryptionAlgorithm.pszObjId =
  1999. szOID_RSA_SMIMEalgESDH;
  2000. if (0 == _stricmp(pszEncryptName, "rc2")) {
  2001. pKeyAgree->KeyWrapAlgorithm.pszObjId =
  2002. szOID_RSA_SMIMEalgCMSRC2wrap;
  2003. // Update pvKeyWrapAuxInfo or KeyWrapAlgorithm
  2004. // Parameters
  2005. if (0 != dwEncryptBitLen) {
  2006. if (0 == i) {
  2007. int iVersion;
  2008. switch (dwEncryptBitLen) {
  2009. case 40:
  2010. iVersion = CRYPT_RC2_40BIT_VERSION;
  2011. break;
  2012. case 56:
  2013. iVersion = CRYPT_RC2_56BIT_VERSION;
  2014. break;
  2015. case 64:
  2016. iVersion = CRYPT_RC2_64BIT_VERSION;
  2017. break;
  2018. case 128:
  2019. iVersion = CRYPT_RC2_128BIT_VERSION;
  2020. break;
  2021. default:
  2022. printf("Failed => unknown RC2 length (%d)\n", dwEncryptBitLen);
  2023. iVersion = 0;
  2024. }
  2025. AllocAndEncodeObject(
  2026. X509_INTEGER,
  2027. &iVersion,
  2028. &pKeyAgree->KeyWrapAlgorithm.Parameters.pbData,
  2029. &pKeyAgree->KeyWrapAlgorithm.Parameters.cbData);
  2030. } else {
  2031. KeyAgreeRC2AuxInfo.cbSize = sizeof(KeyAgreeRC2AuxInfo);
  2032. KeyAgreeRC2AuxInfo.dwBitLen = dwEncryptBitLen;
  2033. pKeyAgree->pvKeyWrapAuxInfo =
  2034. &KeyAgreeRC2AuxInfo;
  2035. }
  2036. }
  2037. } else {
  2038. pKeyAgree->KeyWrapAlgorithm.pszObjId =
  2039. szOID_RSA_SMIMEalgCMS3DESwrap;
  2040. }
  2041. if (fRecipientProv)
  2042. pKeyAgree->hCryptProv = GetCryptProv(PROV_DSS_DH, NULL);
  2043. pKeyAgree->dwKeyChoice = CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE;
  2044. pKeyAgree->pEphemeralAlgorithm = &pPublicKeyInfo->Algorithm;
  2045. if (1 == i) {
  2046. pKeyAgree->UserKeyingMaterial.cbData =
  2047. strlen(pszUserKeyingMaterial);
  2048. pKeyAgree->UserKeyingMaterial.pbData =
  2049. (BYTE *) pszUserKeyingMaterial;
  2050. }
  2051. pKeyAgree->cRecipientEncryptedKeys = i + 1;
  2052. pKeyAgree->rgpRecipientEncryptedKeys = rgpEncryptedKey;
  2053. rgpEncryptedKey[i] = pEncryptedKey;
  2054. memset(pEncryptedKey, 0, sizeof(*pEncryptedKey));
  2055. pEncryptedKey->cbSize = sizeof(*pEncryptedKey);
  2056. pEncryptedKey->RecipientPublicKey = pPublicKeyInfo->PublicKey;
  2057. if (fRecipientKeyId) {
  2058. pEncryptedKey->RecipientId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  2059. pEncryptedKey->RecipientId.KeyId.pbData =
  2060. (PBYTE) rgpszRecipientIssuerFileName[i];
  2061. pEncryptedKey->RecipientId.KeyId.cbData =
  2062. strlen(rgpszRecipientIssuerFileName[i]);
  2063. if (1 == i) {
  2064. SYSTEMTIME st;
  2065. GetSystemTime(&st);
  2066. SystemTimeToFileTime(&st, &pEncryptedKey->Date);
  2067. pEncryptedKey->pOtherAttr = &KeyAgreeOtherAttr;
  2068. }
  2069. } else {
  2070. pEncryptedKey->RecipientId.dwIdChoice =
  2071. CERT_ID_ISSUER_SERIAL_NUMBER;
  2072. GetDERFromFile(
  2073. rgpszRecipientIssuerFileName[i],
  2074. &pEncryptedKey->RecipientId.IssuerSerialNumber.Issuer.pbData,
  2075. &pEncryptedKey->RecipientId.IssuerSerialNumber.Issuer.cbData
  2076. );
  2077. pEncryptedKey->RecipientId.IssuerSerialNumber.SerialNumber.cbData =
  2078. sizeof(DWORD);
  2079. pEncryptedKey->RecipientId.IssuerSerialNumber.SerialNumber.pbData =
  2080. (BYTE *) &rgdwRecipientSerialNumber[i];
  2081. }
  2082. cRecipients++;
  2083. }
  2084. }
  2085. if (fMailList) {
  2086. for (i = 0; i < RECIPIENT_COUNT; i++) {
  2087. PCMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO pMailList =
  2088. &rgMailList[cRecipients];
  2089. rgCmsRecipient[cRecipients].dwRecipientChoice =
  2090. CMSG_MAIL_LIST_RECIPIENT;
  2091. rgCmsRecipient[cRecipients].pMailList = pMailList;
  2092. memset(pMailList, 0, sizeof(*pMailList));
  2093. pMailList->cbSize = sizeof(*pMailList);
  2094. if (0 == _stricmp(pszEncryptName, "rc2")) {
  2095. pMailList->KeyEncryptionAlgorithm.pszObjId =
  2096. szOID_RSA_SMIMEalgCMSRC2wrap;
  2097. // Update pvKeyEncryptionAuxInfo or KeyEncryptionAlgorithm
  2098. // Parameters
  2099. if (0 != dwEncryptBitLen) {
  2100. if (0 == i) {
  2101. int iVersion;
  2102. switch (dwEncryptBitLen) {
  2103. case 40:
  2104. iVersion = CRYPT_RC2_40BIT_VERSION;
  2105. break;
  2106. case 56:
  2107. iVersion = CRYPT_RC2_56BIT_VERSION;
  2108. break;
  2109. case 64:
  2110. iVersion = CRYPT_RC2_64BIT_VERSION;
  2111. break;
  2112. case 128:
  2113. iVersion = CRYPT_RC2_128BIT_VERSION;
  2114. break;
  2115. default:
  2116. printf("Failed => unknown RC2 length (%d)\n", dwEncryptBitLen);
  2117. iVersion = 0;
  2118. }
  2119. AllocAndEncodeObject(
  2120. X509_INTEGER,
  2121. &iVersion,
  2122. &pMailList->KeyEncryptionAlgorithm.Parameters.pbData,
  2123. &pMailList->KeyEncryptionAlgorithm.Parameters.cbData);
  2124. } else {
  2125. MailListRC2AuxInfo.cbSize = sizeof(MailListRC2AuxInfo);
  2126. MailListRC2AuxInfo.dwBitLen = dwEncryptBitLen;
  2127. pMailList->pvKeyEncryptionAuxInfo =
  2128. &MailListRC2AuxInfo;
  2129. }
  2130. }
  2131. } else {
  2132. pMailList->KeyEncryptionAlgorithm.pszObjId =
  2133. szOID_RSA_SMIMEalgCMS3DESwrap;
  2134. }
  2135. pMailList->KeyId.pbData =
  2136. (PBYTE) rgpszRecipientIssuerFileName[i];
  2137. pMailList->KeyId.cbData =
  2138. strlen(rgpszRecipientIssuerFileName[i]);
  2139. if (fRecipientProv)
  2140. pMailList->hCryptProv = GetCryptProv();
  2141. else
  2142. pMailList->hCryptProv = hCryptProv;
  2143. pMailList->dwKeyChoice = CMSG_MAIL_LIST_HANDLE_KEY_CHOICE;
  2144. pMailList->hKeyEncryptionKey = GenerateMailListKey(
  2145. pMailList->hCryptProv,
  2146. &pMailList->KeyId
  2147. );
  2148. if (0 != i) {
  2149. SYSTEMTIME st;
  2150. GetSystemTime(&st);
  2151. SystemTimeToFileTime(&st, &pMailList->Date);
  2152. pMailList->pOtherAttr = &MailListOtherAttr;
  2153. }
  2154. cRecipients++;
  2155. }
  2156. }
  2157. pEnvelopedMsgEncodeInfo->cRecipients = cRecipients;
  2158. cCmsRecipients = cRecipients;
  2159. pEnvelopedMsgEncodeInfo->rgpRecipients = NULL;
  2160. pEnvelopedMsgEncodeInfo->rgCmsRecipients = rgCmsRecipient;
  2161. fNoRecipients = FALSE;
  2162. }
  2163. void CleanupCmsRecipientEncodeInfo()
  2164. {
  2165. DWORD i;
  2166. for (i = 0; i < cCmsRecipients; i++) {
  2167. switch (rgCmsRecipient[i].dwRecipientChoice) {
  2168. case CMSG_KEY_TRANS_RECIPIENT:
  2169. {
  2170. PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTrans =
  2171. &rgKeyTrans[i];
  2172. if (CERT_ID_ISSUER_SERIAL_NUMBER ==
  2173. pKeyTrans->RecipientId.dwIdChoice)
  2174. free(pKeyTrans->RecipientId.IssuerSerialNumber.Issuer.pbData);
  2175. if (pKeyTrans->hCryptProv)
  2176. CryptReleaseContext(pKeyTrans->hCryptProv, 0);
  2177. }
  2178. break;
  2179. case CMSG_KEY_AGREE_RECIPIENT:
  2180. {
  2181. PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pKeyAgree =
  2182. &rgKeyAgree[i];
  2183. TestFree(
  2184. pKeyAgree->KeyEncryptionAlgorithm.Parameters.pbData);
  2185. TestFree(pKeyAgree->KeyWrapAlgorithm.Parameters.pbData);
  2186. if (pKeyAgree->hCryptProv)
  2187. CryptReleaseContext(pKeyAgree->hCryptProv, 0);
  2188. }
  2189. break;
  2190. case CMSG_MAIL_LIST_RECIPIENT:
  2191. {
  2192. PCMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO pMailList =
  2193. &rgMailList[i];
  2194. TestFree(
  2195. pMailList->KeyEncryptionAlgorithm.Parameters.pbData);
  2196. if (pMailList->hCryptProv &&
  2197. pMailList->hCryptProv != hCryptProv)
  2198. CryptReleaseContext(pMailList->hCryptProv, 0);
  2199. if (pMailList->hKeyEncryptionKey)
  2200. CryptDestroyKey(pMailList->hKeyEncryptionKey);
  2201. }
  2202. break;
  2203. }
  2204. }
  2205. if (fKeyAgree) {
  2206. for (i = 0; i < RECIPIENT_COUNT; i++) {
  2207. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO pEncryptedKey =
  2208. &rgEncryptedKey[i];
  2209. if (CERT_ID_ISSUER_SERIAL_NUMBER ==
  2210. pEncryptedKey->RecipientId.dwIdChoice)
  2211. free(pEncryptedKey->RecipientId.IssuerSerialNumber.Issuer.pbData);
  2212. }
  2213. }
  2214. }
  2215. #endif // CMS_PKCS7
  2216. #define IV_LENGTH 8
  2217. static BOOL GetIV(BYTE rgbIV[IV_LENGTH])
  2218. {
  2219. SYSTEMTIME st;
  2220. GetSystemTime(&st);
  2221. assert(IV_LENGTH == sizeof(FILETIME));
  2222. SystemTimeToFileTime(&st, (LPFILETIME) rgbIV);
  2223. return TRUE;
  2224. }
  2225. void InitEnvelopedMsgEncodeInfo(
  2226. OUT PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  2227. )
  2228. {
  2229. PCRYPT_OBJID_BLOB pAlgPara;
  2230. InitRecipientEncodeInfo();
  2231. pEnvelopedMsgEncodeInfo->cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO);
  2232. pEnvelopedMsgEncodeInfo->hCryptProv = hDefaultVerifyProv;
  2233. pEnvelopedMsgEncodeInfo->pvEncryptionAuxInfo = NULL;
  2234. pEnvelopedMsgEncodeInfo->cRecipients = fNoRecipients ? 0 : RECIPIENT_COUNT;
  2235. pEnvelopedMsgEncodeInfo->rgpRecipients = rgpRecipientCertInfo;
  2236. #ifdef CMS_PKCS7
  2237. if (fCmsRecipient)
  2238. InitCmsRecipientEncodeInfo(pEnvelopedMsgEncodeInfo);
  2239. if (fOriginatorInfo) {
  2240. InitSignedCertAndCrl();
  2241. pEnvelopedMsgEncodeInfo->cCertEncoded = cSignedCert;
  2242. pEnvelopedMsgEncodeInfo->rgCertEncoded = rgSignedCertBlob;
  2243. pEnvelopedMsgEncodeInfo->cCrlEncoded = cSignedCrl;
  2244. pEnvelopedMsgEncodeInfo->rgCrlEncoded = rgSignedCrlBlob;
  2245. pEnvelopedMsgEncodeInfo->cAttrCertEncoded = cAttrCert;
  2246. pEnvelopedMsgEncodeInfo->rgAttrCertEncoded = rgAttrCertBlob;
  2247. }
  2248. if (fAuthAttr) {
  2249. pEnvelopedMsgEncodeInfo->cUnprotectedAttr = AUTH_ATTR_COUNT;
  2250. pEnvelopedMsgEncodeInfo->rgUnprotectedAttr = rgAuthAttr;
  2251. }
  2252. #endif // CMS_PKCS7
  2253. pEnvelopedMsgEncodeInfo->ContentEncryptionAlgorithm.pszObjId =
  2254. (LPSTR) pszEncryptOID;
  2255. pAlgPara = &pEnvelopedMsgEncodeInfo->ContentEncryptionAlgorithm.Parameters;
  2256. memset(pAlgPara, 0, sizeof(*pAlgPara));
  2257. if (0 != dwEncryptBitLen && 0 == _stricmp(pszEncryptName, "rc2")) {
  2258. CRYPT_RC2_CBC_PARAMETERS RC2Parameters;
  2259. switch (dwEncryptBitLen) {
  2260. case 40:
  2261. RC2Parameters.dwVersion = CRYPT_RC2_40BIT_VERSION;
  2262. break;
  2263. case 56:
  2264. RC2Parameters.dwVersion = CRYPT_RC2_56BIT_VERSION;
  2265. break;
  2266. case 64:
  2267. RC2Parameters.dwVersion = CRYPT_RC2_64BIT_VERSION;
  2268. break;
  2269. case 128:
  2270. RC2Parameters.dwVersion = CRYPT_RC2_128BIT_VERSION;
  2271. break;
  2272. default:
  2273. printf("Failed => unknown RC2 length (%d)\n", dwEncryptBitLen);
  2274. return;
  2275. }
  2276. RC2Parameters.fIV = fEncryptIV;
  2277. if (fEncryptIV) {
  2278. if (!GetIV(RC2Parameters.rgbIV))
  2279. return;
  2280. }
  2281. if (!AllocAndEncodeObject(
  2282. PKCS_RC2_CBC_PARAMETERS,
  2283. &RC2Parameters,
  2284. &pAlgPara->pbData,
  2285. &pAlgPara->cbData))
  2286. return;
  2287. } else if (0 == _stricmp(pszEncryptName, "rc4")) {
  2288. if (fEncryptIV) {
  2289. CRYPT_DATA_BLOB Salt;
  2290. DWORD i;
  2291. for (i = 0; i < MAX_SALT_LEN; i++)
  2292. rgbSalt[i] = (BYTE) i;
  2293. Salt.cbData = MAX_SALT_LEN;
  2294. Salt.pbData = rgbSalt;
  2295. AllocAndEncodeObject(
  2296. X509_OCTET_STRING,
  2297. &Salt,
  2298. &pAlgPara->pbData,
  2299. &pAlgPara->cbData
  2300. );
  2301. } else if (0 != dwEncryptBitLen) {
  2302. memset(&RC4AuxInfo, 0, sizeof(RC4AuxInfo));
  2303. RC4AuxInfo.cbSize = sizeof(RC4AuxInfo);
  2304. RC4AuxInfo.dwBitLen = dwEncryptBitLen;
  2305. if (fNoSalt)
  2306. RC4AuxInfo.dwBitLen |= CMSG_RC4_NO_SALT_FLAG;
  2307. pEnvelopedMsgEncodeInfo->pvEncryptionAuxInfo = &RC4AuxInfo;
  2308. }
  2309. } else if (fEncryptIV) {
  2310. BYTE rgbIV[IV_LENGTH];
  2311. CRYPT_DATA_BLOB Data;
  2312. Data.pbData = rgbIV;
  2313. Data.cbData = sizeof(rgbIV);
  2314. if (!GetIV(rgbIV))
  2315. return;
  2316. if (!AllocAndEncodeObject(
  2317. X509_OCTET_STRING,
  2318. &Data,
  2319. &pAlgPara->pbData,
  2320. &pAlgPara->cbData))
  2321. return;
  2322. }
  2323. }
  2324. void CleanupEnvelopedMsgEncodeInfo(
  2325. IN PCMSG_ENVELOPED_ENCODE_INFO pEnvelopedMsgEncodeInfo
  2326. )
  2327. {
  2328. TestFree(
  2329. pEnvelopedMsgEncodeInfo->ContentEncryptionAlgorithm.Parameters.pbData);
  2330. CleanupRecipientEncodeInfo();
  2331. #ifdef CMS_PKCS7
  2332. if (fCmsRecipient)
  2333. CleanupCmsRecipientEncodeInfo();
  2334. if (fOriginatorInfo)
  2335. CleanupSignedCertAndCrl();
  2336. #endif // CMS_PKCS7
  2337. }
  2338. //+-------------------------------------------------------------------------
  2339. // Add and delete items
  2340. //--------------------------------------------------------------------------
  2341. BOOL AddDelItems(
  2342. IN HCRYPTMSG hCryptMsg,
  2343. IN DWORD dwCountType,
  2344. IN DWORD dwAddAction,
  2345. IN DWORD dwDelAction,
  2346. IN void const *pvCtrlPara)
  2347. {
  2348. BOOL fRet;
  2349. DWORD cb;
  2350. DWORD cOrg;
  2351. DWORD cCurr;
  2352. // Get the original count of items
  2353. cb = sizeof(cOrg);
  2354. if (!CryptMsgGetParam(
  2355. hCryptMsg,
  2356. dwCountType,
  2357. 0, // dwIndex
  2358. &cOrg,
  2359. &cb))
  2360. goto GetItemCountError;
  2361. // Add an item
  2362. if (!CryptMsgControl(
  2363. hCryptMsg,
  2364. 0, // dwFlags
  2365. dwAddAction,
  2366. pvCtrlPara))
  2367. goto AddItemError;
  2368. // Check that the count of items has increased by 1
  2369. if (!CryptMsgGetParam(
  2370. hCryptMsg,
  2371. dwCountType,
  2372. 0, // dwIndex
  2373. &cCurr,
  2374. &cb))
  2375. goto GetItemCountAddError;
  2376. if (cCurr != (cOrg + 1))
  2377. goto AddCountError;
  2378. // Delete the item we just added.
  2379. // Since new items get added to the tail, we use the count of items
  2380. // prior to the add as the index of the new item.
  2381. if (!CryptMsgControl(
  2382. hCryptMsg,
  2383. 0, // dwFlags
  2384. dwDelAction,
  2385. &cOrg))
  2386. goto DelItemError;
  2387. // Check that the count of items is back to what it was
  2388. if (!CryptMsgGetParam(
  2389. hCryptMsg,
  2390. dwCountType,
  2391. 0, // dwIndex
  2392. &cCurr,
  2393. &cb))
  2394. goto GetItemCountDelError;
  2395. if (cCurr != cOrg)
  2396. goto DelCountError;
  2397. fRet = TRUE;
  2398. CommonReturn:
  2399. return fRet;
  2400. ErrorReturn:
  2401. fRet = FALSE;
  2402. goto CommonReturn;
  2403. PRINT_ERROR(AddDelItems,GetItemCountError)
  2404. PRINT_ERROR(AddDelItems,AddItemError)
  2405. PRINT_ERROR(AddDelItems,GetItemCountAddError)
  2406. PRINT_ERROR(AddDelItems,AddCountError)
  2407. PRINT_ERROR(AddDelItems,DelItemError)
  2408. PRINT_ERROR(AddDelItems,GetItemCountDelError)
  2409. PRINT_ERROR(AddDelItems,DelCountError)
  2410. }
  2411. //+-------------------------------------------------------------------------
  2412. // Insert blob at the tail of a blob list
  2413. //--------------------------------------------------------------------------
  2414. BOOL
  2415. WINAPI
  2416. TCM_InsertTailBlob(
  2417. IN OUT CBlobList *pBlobList,
  2418. IN PBYTE pbIn,
  2419. IN DWORD cbIn)
  2420. {
  2421. BOOL fRet;
  2422. CBlobNode *pnBlob = NULL;
  2423. PBYTE pb = NULL;
  2424. CRYPT_DATA_BLOB blob;
  2425. if (NULL == (pnBlob = new CBlobNode))
  2426. goto NewCBlobNodeError;
  2427. if (NULL == (pb = (PBYTE)TestAlloc( cbIn)))
  2428. goto AllocError;
  2429. memcpy( pb, pbIn, cbIn);
  2430. blob.cbData = cbIn;
  2431. blob.pbData = pb;
  2432. pnBlob->SetData( &blob);
  2433. pBlobList->InsertTail( pnBlob);
  2434. fRet = TRUE;
  2435. CommonReturn:
  2436. return fRet;
  2437. ErrorReturn:
  2438. fRet = FALSE;
  2439. TestFree( pb);
  2440. goto CommonReturn;
  2441. PRINT_ERROR(TCM_InsertTailBlob,NewCBlobNodeError)
  2442. PRINT_ERROR(TCM_InsertTailBlob,AllocError)
  2443. }
  2444. #ifdef CMS_PKCS7
  2445. BOOL VerifyCerts(IN HCRYPTMSG hMsg);
  2446. BOOL VerifyUnprotectedAttr(IN HCRYPTMSG hMsg);
  2447. BOOL GetCmsRecipientInfoAndDecrypt(IN HCRYPTMSG hMsg);
  2448. #endif // CMS_PKCS7
  2449. //+-------------------------------------------------------------------------
  2450. // Get message type, recipient info, and set the hProv needed to decrypt
  2451. // the message.
  2452. //--------------------------------------------------------------------------
  2453. BOOL StreamGetRecipientInfoAndSetHProv(
  2454. IN HCRYPTMSG hMsg,
  2455. OUT PDWORD pdwMsgType,
  2456. OUT BOOL *pfReady)
  2457. {
  2458. BOOL fRet;
  2459. PCERT_INFO pRecipientInfo = NULL;
  2460. DWORD cRecipient;
  2461. DWORD cbData;
  2462. DWORD dwIndex;
  2463. CMSG_CTRL_DECRYPT_PARA DecryptPara; ZEROSTRUCT(DecryptPara);
  2464. DWORD cbEnvelopeAlgorithm;
  2465. DWORD cKeyIdRecipient;
  2466. // Get the message type.
  2467. cbData = sizeof(DWORD);
  2468. if (!CryptMsgGetParam(
  2469. hMsg,
  2470. CMSG_TYPE_PARAM,
  2471. 0, // dwIndex
  2472. pdwMsgType,
  2473. &cbData)) {
  2474. if (GetLastError() != CRYPT_E_STREAM_MSG_NOT_READY)
  2475. goto GetMessageTypeError;
  2476. *pfReady = FALSE;
  2477. goto SuccessReturn;
  2478. }
  2479. if (CMSG_ENVELOPED != *pdwMsgType) {
  2480. *pfReady = TRUE;
  2481. goto SuccessReturn;
  2482. }
  2483. // Get content encryption algorithm.
  2484. if (!CryptMsgGetParam(
  2485. hMsg,
  2486. CMSG_ENVELOPE_ALGORITHM_PARAM,
  2487. 0, // dwIndex
  2488. NULL,
  2489. &cbEnvelopeAlgorithm)) {
  2490. if (GetLastError() != CRYPT_E_STREAM_MSG_NOT_READY)
  2491. goto GetEnvelopeAlgorithmError;
  2492. *pfReady = FALSE;
  2493. goto SuccessReturn;
  2494. }
  2495. *pfReady = TRUE;
  2496. // Get # of recipients in the message.
  2497. cbData = sizeof(cRecipient);
  2498. cRecipient = 0;
  2499. if (!CryptMsgGetParam(
  2500. hMsg,
  2501. CMSG_RECIPIENT_COUNT_PARAM,
  2502. 0, // dwIndex
  2503. &cRecipient,
  2504. &cbData))
  2505. goto GetRecipientCountError;
  2506. if (!TCM_CheckGetParam(
  2507. hMsg,
  2508. CMSG_RECIPIENT_COUNT_PARAM,
  2509. 0, // dwIndex
  2510. &cRecipient,
  2511. cbData))
  2512. goto CheckGetRecipientCountError;
  2513. if (fNoRecipients) {
  2514. if (cRecipient != 0)
  2515. goto WrongRecipientCountError;
  2516. } else {
  2517. if (cRecipient != PkcsRecipientCount)
  2518. goto WrongRecipientCountError;
  2519. }
  2520. #ifdef CMS_PKCS7
  2521. if (fKeyTrans && fRecipientKeyId && !fNoRecipients) {
  2522. // The first RECIPIENT_COUNT recipients should be KeyId recipients
  2523. cKeyIdRecipient = RECIPIENT_COUNT;
  2524. // Get all the KeyId recipients and verify
  2525. for (dwIndex = 0; dwIndex < RECIPIENT_COUNT; dwIndex++) {
  2526. // Allocate and get the CERT_INFO containing the Special
  2527. // KeyId RecipientId
  2528. PCERT_NAME_INFO pKeyIdName = NULL;
  2529. DWORD cbKeyIdName;
  2530. pRecipientInfo = GetCertIdFromMsg(
  2531. hMsg,
  2532. CMSG_RECIPIENT_INFO_PARAM,
  2533. dwIndex
  2534. );
  2535. if (pRecipientInfo == NULL)
  2536. goto GetRecipientInfoError;
  2537. if (pRecipientInfo->SerialNumber.cbData != 1 ||
  2538. *pRecipientInfo->SerialNumber.pbData != 0)
  2539. PrintError("StreamGetRecipientInfoAndSetHProv::Bad KeyId SerialNumber");
  2540. // Decode the Issuer Name. It should contain the special KeyId
  2541. // RDN
  2542. if (AllocAndDecodeObject(
  2543. X509_NAME,
  2544. pRecipientInfo->Issuer.pbData,
  2545. pRecipientInfo->Issuer.cbData,
  2546. (void **) &pKeyIdName,
  2547. &cbKeyIdName
  2548. )) {
  2549. if (pKeyIdName->cRDN != 1 ||
  2550. pKeyIdName->rgRDN[0].cRDNAttr != 1)
  2551. PrintError("StreamGetRecipientInfoAndSetHProv::Bad KeyId Issuer");
  2552. else {
  2553. PCERT_RDN_ATTR pAttr = pKeyIdName->rgRDN[0].rgRDNAttr;
  2554. if (0 != strcmp(pAttr->pszObjId, szOID_KEYID_RDN) ||
  2555. pAttr->dwValueType != CERT_RDN_OCTET_STRING ||
  2556. pAttr->Value.cbData !=
  2557. strlen(rgpszRecipientIssuerFileName[dwIndex]) ||
  2558. 0 != memcmp(pAttr->Value.pbData,
  2559. rgpszRecipientIssuerFileName[dwIndex],
  2560. pAttr->Value.cbData))
  2561. PrintError("StreamGetRecipientInfoAndSetHProv::Bad KeyId Issuer");
  2562. }
  2563. TestFree(pKeyIdName);
  2564. }
  2565. TestFree(pRecipientInfo);
  2566. pRecipientInfo = NULL;
  2567. }
  2568. } else
  2569. #endif // CMS_PKCS7
  2570. cKeyIdRecipient = 0;
  2571. // Get all the non KeyId recipients and verify
  2572. for (dwIndex = 0; dwIndex < cRecipient - cKeyIdRecipient; dwIndex++) {
  2573. // Allocate and get the CERT_INFO containing the RecipientId
  2574. // (Issuer and SerialNumber)
  2575. if (NULL == (pRecipientInfo = GetCertIdFromMsg(
  2576. hMsg,
  2577. CMSG_RECIPIENT_INFO_PARAM,
  2578. cKeyIdRecipient + dwIndex)))
  2579. goto GetRecipientInfoError;
  2580. if (pRecipientInfo->Issuer.cbData !=
  2581. rgRecipientCertInfo[dwIndex].Issuer.cbData ||
  2582. memcmp(pRecipientInfo->Issuer.pbData,
  2583. rgRecipientCertInfo[dwIndex].Issuer.pbData,
  2584. pRecipientInfo->Issuer.cbData) != 0 ||
  2585. pRecipientInfo->SerialNumber.cbData !=
  2586. rgRecipientCertInfo[dwIndex].SerialNumber.cbData ||
  2587. memcmp(pRecipientInfo->SerialNumber.pbData,
  2588. rgRecipientCertInfo[dwIndex].SerialNumber.pbData,
  2589. pRecipientInfo->SerialNumber.cbData) != 0)
  2590. goto BadRecipientInfoError;
  2591. TestFree(pRecipientInfo);
  2592. pRecipientInfo = NULL;
  2593. }
  2594. #ifdef CMS_PKCS7
  2595. if (fOriginatorInfo)
  2596. VerifyCerts(hMsg);
  2597. if (fCmsRecipient) {
  2598. fRet = GetCmsRecipientInfoAndDecrypt(hMsg);
  2599. goto CommonReturn;
  2600. }
  2601. #endif // CMS_PKCS7
  2602. if (fNoRecipients)
  2603. goto SuccessReturn;
  2604. DecryptPara.cbSize = sizeof(DecryptPara);
  2605. DecryptPara.hCryptProv = hCryptProv;
  2606. DecryptPara.dwKeySpec = 0;
  2607. DecryptPara.dwRecipientIndex = RECIPIENT_COUNT - 1;
  2608. if (!CryptMsgControl(
  2609. hMsg,
  2610. 0, // dwFlags
  2611. CMSG_CTRL_DECRYPT,
  2612. &DecryptPara))
  2613. goto SetDecryptParamError;
  2614. SuccessReturn:
  2615. fRet = TRUE;
  2616. CommonReturn:
  2617. TestFree(pRecipientInfo);
  2618. return fRet;
  2619. ErrorReturn:
  2620. fRet = FALSE;
  2621. goto CommonReturn;
  2622. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,GetEnvelopeAlgorithmError)
  2623. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,GetRecipientCountError)
  2624. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,CheckGetRecipientCountError)
  2625. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,WrongRecipientCountError)
  2626. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,GetRecipientInfoError)
  2627. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,BadRecipientInfoError)
  2628. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,SetDecryptParamError)
  2629. PRINT_ERROR(StreamGetRecipientInfoAndSetHProv,GetMessageTypeError)
  2630. }
  2631. //+-------------------------------------------------------------------------
  2632. // Fill a buffer with content.
  2633. //--------------------------------------------------------------------------
  2634. BOOL
  2635. WINAPI
  2636. FillBufferWithContent(
  2637. OUT PBYTE pbData,
  2638. IN DWORD cbData)
  2639. {
  2640. BOOL fRet;
  2641. PBYTE pb;
  2642. DWORD cb;
  2643. DWORD i;
  2644. if (fInnerContent) {
  2645. if (!pbInnerContent) {
  2646. if (!GetDERFromFile(
  2647. pszInnerContentFileName,
  2648. &pbInnerContent,
  2649. &cbInnerContent))
  2650. goto GetDERFromFileError;
  2651. }
  2652. if (iMsgContentOffset + cbData > cbInnerContent)
  2653. goto RequestForTooMuchDataError;
  2654. for (pb=pbData, cb=iMsgContentOffset, i=cbData; i>0; pb++, cb++, i--)
  2655. *pb = pbInnerContent[ cb];
  2656. iMsgContentOffset = cb;
  2657. } else {
  2658. for (pb=pbData, cb=iMsgContentOffset, i=cbData; i>0; pb++, cb++, i--)
  2659. *pb = rgbMsgContentFill[ cb%cbMsgContentFill];
  2660. iMsgContentOffset = cb%cbMsgContentFill;
  2661. }
  2662. fRet = TRUE;
  2663. CommonReturn:
  2664. return fRet;
  2665. ErrorReturn:
  2666. fRet = FALSE;
  2667. goto CommonReturn;
  2668. PRINT_ERROR(FillBufferWithContent,GetDERFromFileError)
  2669. PRINT_ERROR(FillBufferWithContent,RequestForTooMuchDataError)
  2670. }
  2671. //+-------------------------------------------------------------------------
  2672. // Compare a buffer with content.
  2673. //--------------------------------------------------------------------------
  2674. BOOL
  2675. WINAPI
  2676. BufferEqualsContent(
  2677. IN PBYTE pbData,
  2678. IN DWORD cbData)
  2679. {
  2680. BOOL fRet;
  2681. PBYTE pb;
  2682. DWORD cb;
  2683. DWORD i;
  2684. if (fInnerContent) {
  2685. if (iMsgContentOffset + cbData > cbInnerContent)
  2686. goto RequestForTooMuchDataError;
  2687. for (pb=pbData, cb=iMsgContentOffset, i=cbData; i>0; pb++, cb++, i--)
  2688. if (*pb != pbInnerContent[ cb])
  2689. goto InnerContentNotEqualError;
  2690. iMsgContentOffset = cb;
  2691. } else {
  2692. for (pb=pbData, cb=iMsgContentOffset, i=cbData; i>0; pb++, cb++, i--)
  2693. if (*pb != rgbMsgContentFill[ cb%cbMsgContentFill])
  2694. goto ContentNotEqualError;
  2695. iMsgContentOffset = cb%cbMsgContentFill;
  2696. }
  2697. fRet = TRUE;
  2698. CommonReturn:
  2699. return fRet;
  2700. ErrorReturn:
  2701. fRet = FALSE;
  2702. goto CommonReturn;
  2703. PRINT_ERROR(BufferEqualsContent,RequestForTooMuchDataError)
  2704. PRINT_ERROR(BufferEqualsContent,InnerContentNotEqualError)
  2705. PRINT_ERROR(BufferEqualsContent,ContentNotEqualError)
  2706. }
  2707. //+-------------------------------------------------------------------------
  2708. // Callback for streaming messages.
  2709. //--------------------------------------------------------------------------
  2710. BOOL
  2711. WINAPI
  2712. StreamCallback(
  2713. IN const void *pvArg,
  2714. IN BYTE *pbData,
  2715. IN DWORD cbData,
  2716. IN BOOL fFinal)
  2717. {
  2718. BOOL fRet;
  2719. CStreamNode *pnStream = (CStreamNode *)pvArg;
  2720. BOOL fEncoding = pnStream->Data()->fEncoding;
  2721. CStreamNode *pnStreamNbr;
  2722. DWORD cbWritten;
  2723. pnStreamNbr = fEncoding ? pnStream->Prev() : pnStream->Next();
  2724. if (pnStreamNbr) {
  2725. if (!CryptMsgUpdate(
  2726. pnStreamNbr->Data()->hMsg,
  2727. pbData,
  2728. cbData,
  2729. fFinal))
  2730. goto MsgUpdateError;
  2731. } else {
  2732. if (fEncoding) {
  2733. if (!WriteFile(
  2734. hFileStream,
  2735. pbData,
  2736. cbData,
  2737. &cbWritten,
  2738. NULL) ||
  2739. (cbWritten != cbData))
  2740. goto WriteFileError;
  2741. } else {
  2742. if (!WriteFile(
  2743. hFileStreamDecode,
  2744. pbData,
  2745. cbData,
  2746. &cbWritten,
  2747. NULL) ||
  2748. (cbWritten != cbData))
  2749. goto WriteFileDecodeError;
  2750. }
  2751. }
  2752. fRet = TRUE;
  2753. CommonReturn:
  2754. return fRet;
  2755. ErrorReturn:
  2756. fRet = FALSE;
  2757. goto CommonReturn;
  2758. PRINT_ERROR(StreamCallback,MsgUpdateError)
  2759. PRINT_ERROR(StreamCallback,WriteFileError)
  2760. PRINT_ERROR(StreamCallback,WriteFileDecodeError)
  2761. }
  2762. //+-------------------------------------------------------------------------
  2763. // Encodes and decodes the streamed message.
  2764. //--------------------------------------------------------------------------
  2765. BOOL StreamEncodeAndDecodeMsg()
  2766. {
  2767. BOOL fRet;
  2768. CStreamNode *pnStream = NULL;
  2769. TEST_STREAM_DATA tsd; ZEROSTRUCT(tsd);
  2770. PCMSG_STREAM_INFO pstrmi = NULL;
  2771. PBYTE pb;
  2772. DWORD cb;
  2773. LPSTR psz;
  2774. CHAR ch;
  2775. DWORD dwMsgTypeEncodingPrev;
  2776. LPSTR pszFilenameEncoded = pszFilename ? pszFilename : pszStreamFileName;
  2777. if (INVALID_HANDLE_VALUE == (hFileStream = CreateFile(
  2778. pszFilenameEncoded,
  2779. GENERIC_WRITE,
  2780. 0,
  2781. NULL,
  2782. CREATE_ALWAYS,
  2783. 0,
  2784. NULL)))
  2785. goto CreateFileError;
  2786. for (psz=pszStreamMsgTypes, dwMsgTypeEncodingPrev=0; ch=*psz; psz++) {
  2787. switch (ch) {
  2788. case 'd':
  2789. case 'D':
  2790. tsd.dwMsgTypeEncoding = CMSG_DATA;
  2791. tsd.pvMsgEncodeInfo = NULL;
  2792. break;
  2793. case 'e':
  2794. case 'E':
  2795. tsd.dwMsgTypeEncoding = CMSG_ENVELOPED;
  2796. tsd.pvMsgEncodeInfo = &EnvelopedMsgEncodeInfo;
  2797. break;
  2798. case 's':
  2799. case 'S':
  2800. tsd.dwMsgTypeEncoding = CMSG_SIGNED;
  2801. tsd.pvMsgEncodeInfo = &SignedMsgEncodeInfo;
  2802. break;
  2803. default:
  2804. goto InvalidMsgTypeError;
  2805. }
  2806. tsd.dwEncodingType = dwMsgEncodingType;
  2807. tsd.dwEncodeFlags = 0;
  2808. if ((psz != pszStreamMsgTypes) && (dwMsgTypeEncodingPrev != CMSG_DATA))
  2809. tsd.dwEncodeFlags |= CMSG_BARE_CONTENT_FLAG;
  2810. if (dwMsgTypeEncodingPrev == CMSG_ENVELOPED)
  2811. tsd.dwEncodeFlags |= CMSG_CONTENTS_OCTETS_FLAG;
  2812. if (fBare && (psz == pszStreamMsgTypes))
  2813. tsd.dwEncodeFlags |= CMSG_BARE_CONTENT_FLAG;
  2814. #ifdef CMS_PKCS7
  2815. if (fEncapsulatedContent)
  2816. tsd.dwEncodeFlags |= CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  2817. #endif // CMS_PKCS7
  2818. tsd.dwDecodeFlags = 0;
  2819. if (fBare && (psz == pszStreamMsgTypes))
  2820. tsd.dwDecodeFlags |= CMSG_BARE_CONTENT_FLAG;
  2821. if (NULL == (pstrmi = (PCMSG_STREAM_INFO)TestAllocZero(
  2822. sizeof(CMSG_STREAM_INFO))))
  2823. goto AllocTestStreamInfoError;
  2824. tsd.pStreamInfo = pstrmi;
  2825. if (NULL == (pnStream = new CStreamNode))
  2826. goto NewNodeError;
  2827. pstrmi->cbContent = CMSG_INDEFINITE_LENGTH;
  2828. pstrmi->pfnStreamOutput = StreamCallback;
  2829. pstrmi->pvArg = pnStream;
  2830. pnStream->SetData( &tsd);
  2831. plistStream->InsertTail( pnStream);
  2832. dwMsgTypeEncodingPrev = tsd.dwMsgTypeEncoding;
  2833. }
  2834. pstrmi = NULL;
  2835. if (!StreamEncodeMsg())
  2836. goto EncodeError;
  2837. if (hFileStream != INVALID_HANDLE_VALUE) {
  2838. CloseHandle( hFileStream);
  2839. hFileStream = INVALID_HANDLE_VALUE;
  2840. }
  2841. if (!StreamDecodeMsg())
  2842. goto DecodeError;
  2843. fRet = TRUE;
  2844. CommonReturn:
  2845. if (hFileStream != INVALID_HANDLE_VALUE)
  2846. CloseHandle( hFileStream);
  2847. #ifndef SAVE_STREAM_FILES
  2848. if (!pszFilename)
  2849. DeleteFile( pszStreamFileName);
  2850. #endif // SAVE_STREAM_FILES
  2851. TestFree( pstrmi);
  2852. return fRet;
  2853. ErrorReturn:
  2854. fRet = FALSE;
  2855. goto CommonReturn;
  2856. PRINT_ERROR(StreamEncodeAndDecodeMsg,CreateFileError)
  2857. PRINT_ERROR(StreamEncodeAndDecodeMsg,NewNodeError)
  2858. PRINT_ERROR(StreamEncodeAndDecodeMsg,EncodeError)
  2859. PRINT_ERROR(StreamEncodeAndDecodeMsg,DecodeError)
  2860. PRINT_ERROR(StreamEncodeAndDecodeMsg,InvalidMsgTypeError)
  2861. PRINT_ERROR(StreamEncodeAndDecodeMsg,AllocTestStreamInfoError)
  2862. }
  2863. #ifdef CMS_PKCS7
  2864. BOOL VerifyEncodedSignerComputedHash(
  2865. IN LPCSTR pszHdr,
  2866. IN HCRYPTMSG hMsg,
  2867. IN DWORD dwSignerIndex,
  2868. IN PBYTE pbExpectedHash,
  2869. IN DWORD cbExpectedHash
  2870. )
  2871. {
  2872. BOOL fResult;
  2873. DWORD cbHash;
  2874. BYTE rgbHash[MAX_HASH_LEN];
  2875. DWORD dwSrcIndex;
  2876. if (fVerbose)
  2877. printf("%s VerifyEncodedSignerComputedHash(Signer[%d])\n",
  2878. pszHdr, dwSignerIndex);
  2879. cbHash = sizeof(rgbHash);
  2880. fResult = CryptMsgGetParam(
  2881. hMsg,
  2882. CMSG_COMPUTED_HASH_PARAM,
  2883. dwSignerIndex,
  2884. rgbHash,
  2885. &cbHash
  2886. );
  2887. if (!fResult) {
  2888. printf("%s VerifyEncodedSignerComputedHash::CryptMsgGetParam(Signer[%d])",
  2889. pszHdr, dwSignerIndex);
  2890. PrintLastError("");
  2891. } else if (cbHash != cbExpectedHash ||
  2892. 0 != memcmp(rgbHash, pbExpectedHash, cbHash)) {
  2893. fResult = FALSE;
  2894. printf("%s VerifyEncodedSignerComputedHash:: failed => bad hash for Signer[%d]\n",
  2895. pszHdr, dwSignerIndex);
  2896. } else {
  2897. TCM_CheckGetParam(
  2898. hMsg,
  2899. CMSG_COMPUTED_HASH_PARAM,
  2900. dwSignerIndex,
  2901. rgbHash,
  2902. cbHash
  2903. );
  2904. }
  2905. return fResult;
  2906. }
  2907. BOOL VerifyDecodedSignerComputedHash(
  2908. IN LPCSTR pszHdr,
  2909. IN HCRYPTMSG hMsg,
  2910. IN BOOL fInnerNonData,
  2911. IN DWORD dwSignerIndex,
  2912. IN BYTE rgbExpectedHash[2][MAX_HASH_LEN],
  2913. IN DWORD rgcbExpectedHash[2]
  2914. )
  2915. {
  2916. DWORD cbHash;
  2917. BYTE rgbHash[MAX_HASH_LEN];
  2918. DWORD dwSrcIndex;
  2919. if (fVerbose)
  2920. printf("%s VerifyDecodedSignerComputedHash(Signer[%d])\n",
  2921. pszHdr, dwSignerIndex);
  2922. cbHash = sizeof(rgbHash);
  2923. if (!CryptMsgGetParam(
  2924. hMsg,
  2925. CMSG_COMPUTED_HASH_PARAM,
  2926. dwSignerIndex,
  2927. rgbHash,
  2928. &cbHash
  2929. )) {
  2930. printf("%s VerifyDecodedSignerComputedHash(before verify signature)::CryptMsgGetParam(Signer[%d])",
  2931. pszHdr, dwSignerIndex);
  2932. PrintLastError("");
  2933. return FALSE;
  2934. }
  2935. if (pNamedSigner)
  2936. dwSrcIndex = dwSignerIndex;
  2937. else if (!GetSignerInfoAndVerify(
  2938. hMsg,
  2939. fInnerNonData,
  2940. dwSignerIndex,
  2941. &dwSrcIndex
  2942. )) {
  2943. printf("%s VerifyDecodedSignerComputedHash GetSignerInfoAndVerify(Signer[%d]):: failed\n",
  2944. pszHdr, dwSignerIndex);
  2945. return FALSE;
  2946. }
  2947. if (cbHash != rgcbExpectedHash[dwSrcIndex] ||
  2948. 0 != memcmp(rgbHash, rgbExpectedHash[dwSrcIndex], cbHash)) {
  2949. printf("%s VerifyDecodedSignerComputedHash(before verify signature):: failed => unexpected hash for Signer[%d]\n",
  2950. pszHdr, dwSignerIndex);
  2951. return FALSE;
  2952. }
  2953. cbHash = sizeof(rgbHash);
  2954. if (!CryptMsgGetParam(
  2955. hMsg,
  2956. CMSG_COMPUTED_HASH_PARAM,
  2957. dwSignerIndex,
  2958. rgbHash,
  2959. &cbHash
  2960. )) {
  2961. printf("%s VerifyDecodedSignerComputedHash(after verify signature)::CryptMsgGetParam(Signer[%d])",
  2962. pszHdr, dwSignerIndex);
  2963. PrintLastError("");
  2964. return FALSE;
  2965. }
  2966. if (cbHash != rgcbExpectedHash[dwSrcIndex] ||
  2967. 0 != memcmp(rgbHash, rgbExpectedHash[dwSrcIndex], cbHash)) {
  2968. printf("%s VerifyDecodedSignerComputedHash(after verify signature):: failed => unexpected hash for Signer[%d]\n",
  2969. pszHdr, dwSignerIndex);
  2970. return FALSE;
  2971. } else {
  2972. TCM_CheckGetParam(
  2973. hMsg,
  2974. CMSG_COMPUTED_HASH_PARAM,
  2975. dwSignerIndex,
  2976. rgbHash,
  2977. cbHash
  2978. );
  2979. }
  2980. return TRUE;
  2981. }
  2982. #endif // CMS_PKCS7
  2983. //+-------------------------------------------------------------------------
  2984. // Encodes the streamed message.
  2985. //--------------------------------------------------------------------------
  2986. BOOL StreamEncodeMsg()
  2987. {
  2988. BOOL fRet;
  2989. CStreamNode *pnStream;
  2990. PTEST_STREAM_DATA ptsd;
  2991. HCRYPTMSG hMsg;
  2992. PBYTE pb;
  2993. DWORD cb;
  2994. DWORD cbRemain;
  2995. BOOL fFinal;
  2996. DWORD cbData;
  2997. DWORD cbDataInner;
  2998. LPSTR pszInnerContentType;
  2999. if (fVerbose)
  3000. printf( "Beginning stream encode\n");
  3001. if (fInnerContent && !FillBufferWithContent( NULL, 0)) // load inner content
  3002. goto NullFillBufferWithContentError;
  3003. cbDataInner = fInnerContent ? cbInnerContent : cbMsgContent;
  3004. if (fInnerContent &&
  3005. #ifdef CMS_PKCS7
  3006. !fEncapsulatedContent &&
  3007. #endif // CMS_PKCS7
  3008. (plistStream->Tail()->Data()->dwMsgTypeEncoding == CMSG_ENVELOPED)) {
  3009. if (!TCM_ExtractContent(
  3010. pbInnerContent,
  3011. cbInnerContent,
  3012. &cbDataInner,
  3013. NULL)) // ppbContent
  3014. goto ExtractContentError;
  3015. }
  3016. for (pnStream = plistStream->Tail(),
  3017. cbData=cbDataInner,
  3018. pszInnerContentType =
  3019. fInnerContent ? pszInnerContentObjId : NULL;
  3020. pnStream;
  3021. pnStream = pnStream->Prev()) {
  3022. ptsd = pnStream->Data();
  3023. ptsd->fEncoding = TRUE;
  3024. ptsd->pStreamInfo->cbContent = fIndefinite ? CMSG_INDEFINITE_LENGTH : cbData;
  3025. ptsd->pszInnerContentType = pszInnerContentType;
  3026. if (NULL == (ptsd->hMsg = CryptMsgOpenToEncode(
  3027. ptsd->dwEncodingType,
  3028. ptsd->dwEncodeFlags,
  3029. ptsd->dwMsgTypeEncoding,
  3030. ptsd->pvMsgEncodeInfo,
  3031. pszInnerContentType,
  3032. ptsd->pStreamInfo)))
  3033. goto OpenToEncodeError;
  3034. // NB- from PKCS#7, sec.10.3:
  3035. // An enveloped message encrypts only "the contents octets of a
  3036. // definite-length BER encoding of the content field of the ContentInfo"
  3037. // ie. The identifier and length octets are not included.
  3038. // Ergo, we must ask for the size of the contents octets if the outer
  3039. // message is enveloped.
  3040. if (0 == (cbData = CryptMsgCalculateEncodedLength(
  3041. ptsd->dwEncodingType,
  3042. ptsd->dwEncodeFlags,
  3043. ptsd->dwMsgTypeEncoding,
  3044. ptsd->pvMsgEncodeInfo,
  3045. pszInnerContentType,
  3046. cbData)))
  3047. goto CalculateEncodedLengthError;
  3048. switch(ptsd->dwMsgTypeEncoding) {
  3049. case CMSG_DATA:
  3050. pszInnerContentType = szOID_RSA_data;
  3051. break;
  3052. case CMSG_ENVELOPED:
  3053. pszInnerContentType = szOID_RSA_envelopedData;
  3054. break;
  3055. case CMSG_SIGNED:
  3056. pszInnerContentType = szOID_RSA_signedData;
  3057. break;
  3058. default:
  3059. goto InvalidMsgTypeError;
  3060. }
  3061. #ifdef CMS_PKCS7
  3062. if (ptsd->dwMsgTypeEncoding != CMSG_DATA &&
  3063. (fVerbose || fEncapsulatedContent || cAttrCert ||
  3064. fOriginatorInfo || fCmsRecipient)) {
  3065. BOOL fResult;
  3066. DWORD dwVersion;
  3067. DWORD cbData = sizeof(dwVersion);
  3068. fResult = CryptMsgGetParam(
  3069. ptsd->hMsg,
  3070. CMSG_VERSION_PARAM,
  3071. 0, // dwIndex
  3072. (PBYTE) &dwVersion,
  3073. &cbData
  3074. );
  3075. if (!fResult)
  3076. PrintLastError("StreamEncodeMsg::CryptMsgGetParam(CMSG_VERSION_PARAM)");
  3077. else
  3078. printf("StreamEncodeMsg(%d - %s) Version:: %d\n",
  3079. ptsd->dwMsgTypeEncoding, pszInnerContentType, dwVersion);
  3080. }
  3081. #endif // CMS_PKCS7
  3082. }
  3083. hMsg = plistStream->Tail()->Data()->hMsg;
  3084. iMsgContentOffset = 0;
  3085. cbRemain = fInnerContent ? cbInnerContent : cbMsgContent;
  3086. if (0 == cbRemain) {
  3087. if (!CryptMsgUpdate(
  3088. hMsg,
  3089. NULL,
  3090. 0,
  3091. TRUE))
  3092. goto UpdateError;
  3093. } else {
  3094. for ( ; cbRemain; cbRemain -= cb) {
  3095. fFinal = (cbRemain <= cbStreamDataDeltaEncode);
  3096. cb = fFinal ? cbRemain : cbStreamDataDeltaEncode;
  3097. FillBufferWithContent( abStreamDataDeltaEncode, cb);
  3098. if (!CryptMsgUpdate(
  3099. hMsg,
  3100. (PBYTE)abStreamDataDeltaEncode,
  3101. cb,
  3102. fFinal))
  3103. goto UpdateError;
  3104. }
  3105. }
  3106. for (pnStream = plistStream->Head();
  3107. pnStream;
  3108. pnStream = pnStream->Next()) {
  3109. ptsd = pnStream->Data();
  3110. cbData = 0;
  3111. if (CryptMsgGetParam(
  3112. ptsd->hMsg,
  3113. CMSG_CONTENT_PARAM,
  3114. 0, // dwIndex
  3115. NULL, // pvData
  3116. &cbData
  3117. ))
  3118. PrintError("CryptMsgGetParam(CMSG_CONTENT_PARAM) succeeded for streaming");
  3119. #ifdef CMS_PKCS7
  3120. if (CMSG_SIGNED == ptsd->dwMsgTypeEncoding && !fNoSigners) {
  3121. DWORD i;
  3122. DWORD c;
  3123. if (fMultiSigner)
  3124. c = 2;
  3125. else
  3126. c = 1;
  3127. for (i = 0; i < c; i++) {
  3128. ptsd->rgcbComputedHash[i] = sizeof(ptsd->rgbComputedHash[i]);
  3129. if (!CryptMsgGetParam(
  3130. ptsd->hMsg,
  3131. CMSG_COMPUTED_HASH_PARAM,
  3132. i, // dwSignerIndex
  3133. ptsd->rgbComputedHash[i],
  3134. &ptsd->rgcbComputedHash[i]
  3135. )) {
  3136. printf("StreamEncodeMsg::CryptMsgGetParam(Signer[%d] CMSG_COMPUTED_HASH_PARAM)",
  3137. i);
  3138. PrintLastError("");
  3139. } else
  3140. VerifyEncodedSignerComputedHash(
  3141. "StreamEncodeMsg", ptsd->hMsg, i,
  3142. ptsd->rgbComputedHash[i], ptsd->rgcbComputedHash[i]);
  3143. }
  3144. }
  3145. #endif // CMS_PKCS7
  3146. if (!CryptMsgClose(ptsd->hMsg))
  3147. goto CloseError;
  3148. }
  3149. fRet = TRUE;
  3150. CommonReturn:
  3151. return fRet;
  3152. ErrorReturn:
  3153. fRet = FALSE;
  3154. goto CommonReturn;
  3155. PRINT_ERROR(StreamEncodeMsg,NullFillBufferWithContentError)
  3156. PRINT_ERROR(StreamEncodeMsg,ExtractContentError)
  3157. PRINT_ERROR(StreamEncodeMsg,InvalidMsgTypeError)
  3158. PRINT_ERROR(StreamEncodeMsg,OpenToEncodeError)
  3159. PRINT_ERROR(StreamEncodeMsg,CalculateEncodedLengthError)
  3160. PRINT_ERROR(StreamEncodeMsg,UpdateError)
  3161. PRINT_ERROR(StreamEncodeMsg,CloseError)
  3162. }
  3163. //+-------------------------------------------------------------------------
  3164. // Decodes the streamed message.
  3165. //--------------------------------------------------------------------------
  3166. BOOL StreamDecodeMsg()
  3167. {
  3168. BOOL fRet;
  3169. CStreamNode *pnStream;
  3170. PTEST_STREAM_DATA ptsd;
  3171. HCRYPTMSG hMsg;
  3172. PBYTE pb;
  3173. DWORD cb;
  3174. PBYTE pbRemain;
  3175. DWORD cbRemain;
  3176. HANDLE hFile = INVALID_HANDLE_VALUE;
  3177. PBYTE pbRead = NULL;
  3178. DWORD cbRead;
  3179. BOOL fFinal;
  3180. BOOL fFirst;
  3181. DWORD cbFile;
  3182. CBlobNode *pnBlob;
  3183. PCRYPT_DATA_BLOB pblob;
  3184. BOOL fInnerNonData;
  3185. DWORD dwMsgTypeInner;
  3186. LPSTR pszFilenameEncoded = pszFilename ? pszFilename : pszStreamFileName;
  3187. if (fVerbose)
  3188. printf( "Beginning stream decode\n");
  3189. if (NULL == (pbRead = (PBYTE)TestAlloc(cbStreamDataDeltaDecode)))
  3190. goto AllocDecodeBufferError;
  3191. // Open the messages
  3192. for (pnStream = plistStream->Head();
  3193. pnStream;
  3194. pnStream = pnStream->Next()) {
  3195. ptsd = pnStream->Data();
  3196. ptsd->fEncoding = FALSE;
  3197. fFirst = (NULL == pnStream->Prev());
  3198. if (NULL == (ptsd->hMsg = CryptMsgOpenToDecode(
  3199. ptsd->dwEncodingType,
  3200. ptsd->dwDecodeFlags,
  3201. ((fFirst && fBare) ||
  3202. (!fFirst && (CMSG_DATA != pnStream->Prev()->Data()->dwMsgTypeEncoding)))
  3203. ? ptsd->dwMsgTypeEncoding : 0,
  3204. hDefaultVerifyProv,
  3205. NULL, // pRecipientInfo
  3206. ptsd->pStreamInfo)))
  3207. goto OpenToDecodeError;
  3208. }
  3209. // Open the file containing the nested messages to decode
  3210. if (INVALID_HANDLE_VALUE == (hFile = CreateFile(
  3211. pszFilenameEncoded,
  3212. GENERIC_READ,
  3213. 0,
  3214. NULL,
  3215. OPEN_EXISTING,
  3216. 0,
  3217. NULL)))
  3218. goto CreateFileError;
  3219. if (INVALID_FILE_SIZE == (cbFile = GetFileSize( hFile, NULL)))
  3220. goto GetFileSizeError;
  3221. // Create the file to hold the decoded data
  3222. if (INVALID_HANDLE_VALUE == (hFileStreamDecode = CreateFile(
  3223. pszFilenameDecode,
  3224. GENERIC_WRITE,
  3225. 0,
  3226. NULL,
  3227. CREATE_ALWAYS,
  3228. 0,
  3229. NULL)))
  3230. goto CreateFileDecodeError;
  3231. // Feed in the encoded nested messages in chunks
  3232. hMsg = plistStream->Head()->Data()->hMsg;
  3233. for (cbRemain=cbFile; cbRemain; cbRemain-=cbRead) {
  3234. if (!ReadFile(
  3235. hFile,
  3236. pbRead,
  3237. cbStreamDataDeltaDecode,
  3238. &cbRead,
  3239. NULL)) // lpOverlapped
  3240. goto ReadFileError;
  3241. fFinal = (cbRead == cbRemain);
  3242. if (!CryptMsgUpdate(
  3243. hMsg,
  3244. pbRead,
  3245. cbRead,
  3246. fFinal))
  3247. goto UpdateError;
  3248. for (pnStream = plistStream->Head();
  3249. pnStream;
  3250. pnStream = pnStream->Next()) {
  3251. ptsd = pnStream->Data();
  3252. if (((0 == ptsd->dwMsgTypeDecoding) ||
  3253. (CMSG_ENVELOPED == ptsd->dwMsgTypeDecoding)) &&
  3254. !ptsd->fReady) {
  3255. if (!StreamGetRecipientInfoAndSetHProv(
  3256. ptsd->hMsg,
  3257. &ptsd->dwMsgTypeDecoding,
  3258. &ptsd->fReady))
  3259. goto StreamGetRecipientInfoAndSetHProvError;
  3260. }
  3261. }
  3262. }
  3263. // Validate the message types
  3264. for (pnStream = plistStream->Head();
  3265. pnStream;
  3266. pnStream = pnStream->Next()) {
  3267. ptsd = pnStream->Data();
  3268. if (ptsd->dwMsgTypeEncoding != ptsd->dwMsgTypeDecoding)
  3269. goto MsgTypeMismatchError;
  3270. }
  3271. // Check signatures
  3272. if (fVerbose)
  3273. printf( "Verify signatures\n");
  3274. for (pnStream = plistStream->Tail(), dwMsgTypeInner=CMSG_DATA;
  3275. pnStream;
  3276. pnStream = pnStream->Prev()) {
  3277. ptsd = pnStream->Data();
  3278. fInnerNonData = ((pnStream == plistStream->Tail()) && fInnerContent) ||
  3279. (dwMsgTypeInner != CMSG_DATA);
  3280. #ifdef CMS_PKCS7
  3281. if (ptsd->dwMsgTypeDecoding != CMSG_DATA &&
  3282. (fVerbose || fEncapsulatedContent || cAttrCert ||
  3283. fOriginatorInfo || fCmsRecipient)) {
  3284. BOOL fResult;
  3285. DWORD dwVersion;
  3286. DWORD cbData = sizeof(dwVersion);
  3287. fResult = CryptMsgGetParam(
  3288. ptsd->hMsg,
  3289. CMSG_VERSION_PARAM,
  3290. 0, // dwIndex
  3291. (PBYTE) &dwVersion,
  3292. &cbData
  3293. );
  3294. if (!fResult)
  3295. PrintLastError("StreamDecodeMsg::CryptMsgGetParam(CMSG_VERSION_PARAM)");
  3296. else
  3297. printf("StreamDecodeMsg(%d) Version:: %d\n",
  3298. ptsd->dwMsgTypeDecoding, dwVersion);
  3299. }
  3300. if (fAuthAttr && CMSG_ENVELOPED == ptsd->dwMsgTypeDecoding)
  3301. VerifyUnprotectedAttr(hMsg);
  3302. if (CMSG_SIGNED == ptsd->dwMsgTypeDecoding && !fNoSigners) {
  3303. DWORD i;
  3304. DWORD c;
  3305. if (fMultiSigner)
  3306. c = 2;
  3307. else
  3308. c = 1;
  3309. for (i = 0; i < c; i++) {
  3310. VerifyDecodedSignerComputedHash(
  3311. "StreamDecodeMsg",
  3312. ptsd->hMsg,
  3313. fInnerNonData,
  3314. i,
  3315. ptsd->rgbComputedHash,
  3316. ptsd->rgcbComputedHash
  3317. );
  3318. }
  3319. }
  3320. #endif // CMS_PKCS7
  3321. if ((CMSG_SIGNED == ptsd->dwMsgTypeDecoding) &&
  3322. !GetSignerInfoAndVerify( ptsd->hMsg, fInnerNonData))
  3323. goto GetSignerInfoAndVerifyError;
  3324. dwMsgTypeInner = ptsd->dwMsgTypeEncoding;
  3325. }
  3326. // Verify the data
  3327. if (fVerbose)
  3328. printf( "Verify data\n");
  3329. if (INVALID_FILE_SIZE ==
  3330. (cbFileDecode = GetFileSize( hFileStreamDecode, NULL)))
  3331. goto GetFileSizeDecodeError;
  3332. if (cbFileDecode != (fInnerContent ? cbInnerContent : cbMsgContent)) {
  3333. if (fNoRecipients && 0 == cbFileDecode)
  3334. ;
  3335. else
  3336. goto WrongDataSizeError;
  3337. }
  3338. CloseHandle( hFileStreamDecode);
  3339. if (INVALID_HANDLE_VALUE == (hFileStreamDecode = CreateFile(
  3340. pszFilenameDecode,
  3341. GENERIC_READ,
  3342. 0,
  3343. NULL,
  3344. OPEN_EXISTING,
  3345. 0,
  3346. NULL)))
  3347. goto CreateFileDecodeReadError;
  3348. iMsgContentOffset = 0;
  3349. for (cbRemain=cbFileDecode; cbRemain; cbRemain-=cbRead) {
  3350. if (!ReadFile(
  3351. hFileStreamDecode,
  3352. pbRead,
  3353. cbStreamDataDeltaDecode,
  3354. &cbRead,
  3355. NULL)) // lpOverlapped
  3356. goto ReadFileDecodeError;
  3357. if (!BufferEqualsContent( pbRead, cbRead))
  3358. goto WrongDataError;
  3359. }
  3360. // Close the messages
  3361. if (fVerbose)
  3362. printf( "Close messages\n");
  3363. for (pnStream = plistStream->Head();
  3364. pnStream;
  3365. pnStream = pnStream->Next()) {
  3366. DWORD cbData = 0;
  3367. if (CryptMsgGetParam(
  3368. pnStream->Data()->hMsg,
  3369. CMSG_CONTENT_PARAM,
  3370. 0, // dwIndex
  3371. NULL, // pvData
  3372. &cbData
  3373. ))
  3374. PrintError("CryptMsgGetParam(CMSG_CONTENT_PARAM) succeeded for streaming");
  3375. if (!CryptMsgClose( pnStream->Data()->hMsg))
  3376. goto CloseError;
  3377. }
  3378. fRet = TRUE;
  3379. CommonReturn:
  3380. TestFree( pbRead);
  3381. if (hFile != INVALID_HANDLE_VALUE)
  3382. CloseHandle( hFile);
  3383. if (hFileStreamDecode != INVALID_HANDLE_VALUE)
  3384. CloseHandle( hFileStreamDecode);
  3385. #ifndef SAVE_STREAM_FILES
  3386. DeleteFile( pszFilenameDecode);
  3387. #endif // SAVE_STREAM_FILES
  3388. return fRet;
  3389. ErrorReturn:
  3390. fRet = FALSE;
  3391. goto CommonReturn;
  3392. PRINT_ERROR(StreamDecodeMsg,AllocDecodeBufferError)
  3393. PRINT_ERROR(StreamDecodeMsg,UpdateError)
  3394. PRINT_ERROR(StreamDecodeMsg,GetFileSizeError)
  3395. PRINT_ERROR(StreamDecodeMsg,CreateFileError)
  3396. PRINT_ERROR(StreamDecodeMsg,ReadFileError)
  3397. PRINT_ERROR(StreamDecodeMsg,ReadFileDecodeError)
  3398. PRINT_ERROR(StreamDecodeMsg,OpenToDecodeError)
  3399. PRINT_ERROR(StreamDecodeMsg,StreamGetRecipientInfoAndSetHProvError)
  3400. PRINT_ERROR(StreamDecodeMsg,MsgTypeMismatchError)
  3401. PRINT_ERROR(StreamDecodeMsg,GetSignerInfoAndVerifyError)
  3402. PRINT_ERROR(StreamDecodeMsg,WrongDataSizeError)
  3403. PRINT_ERROR(StreamDecodeMsg,WrongDataError)
  3404. PRINT_ERROR(StreamDecodeMsg,CloseError)
  3405. PRINT_ERROR(StreamDecodeMsg,CreateFileDecodeError)
  3406. PRINT_ERROR(StreamDecodeMsg,GetFileSizeDecodeError)
  3407. PRINT_ERROR(StreamDecodeMsg,CreateFileDecodeReadError)
  3408. }
  3409. //+-------------------------------------------------------------------------
  3410. // Encodes and decodes the message.
  3411. //--------------------------------------------------------------------------
  3412. BOOL EncodeAndDecodeMsg(
  3413. IN DWORD dwMsgType,
  3414. IN void *pvMsgEncodeInfo
  3415. )
  3416. {
  3417. BOOL fResult;
  3418. BYTE *pbEncodedBlob;
  3419. DWORD cbEncodedBlob;
  3420. fResult = EncodeMsg(
  3421. dwMsgType,
  3422. pvMsgEncodeInfo,
  3423. &pbEncodedBlob,
  3424. &cbEncodedBlob
  3425. );
  3426. if (fResult) {
  3427. if (pszFilename)
  3428. TCM_WriteBufToFile( pszFilename, pbEncodedBlob, cbEncodedBlob);
  3429. fResult = DecodeMsg(
  3430. dwMsgType,
  3431. pbEncodedBlob,
  3432. cbEncodedBlob
  3433. );
  3434. TestFree(pbEncodedBlob);
  3435. }
  3436. return fResult;
  3437. }
  3438. //+-------------------------------------------------------------------------
  3439. // Allocates and encodes the message.
  3440. //--------------------------------------------------------------------------
  3441. BOOL EncodeMsg(
  3442. IN DWORD dwMsgType,
  3443. IN void *pvMsgEncodeInfo,
  3444. OUT BYTE **ppbEncodedBlob,
  3445. OUT DWORD *pcbEncodedBlob
  3446. )
  3447. {
  3448. BOOL fResult;
  3449. PBYTE pbToBeEncoded;
  3450. DWORD cbToBeEncoded;
  3451. PBYTE pbInnerEncoded;
  3452. DWORD cbInnerEncoded;
  3453. HCRYPTMSG hMsg = NULL;
  3454. BYTE *pbEncodedBlob = NULL;
  3455. DWORD cbEncodedBlobOrg;
  3456. DWORD cbEncodedBlob;
  3457. DWORD dwFlags = fBare ? CMSG_BARE_CONTENT_FLAG : 0;
  3458. if (!GetNonStreamedMsgContent(
  3459. cbMsgContent,
  3460. &pbToBeEncoded,
  3461. &cbToBeEncoded))
  3462. goto GetNonStreamedMsgContentError;
  3463. if (fInnerContent) {
  3464. if (dwMsgType == CMSG_ENVELOPED
  3465. #ifdef CMS_PKCS7
  3466. && !fEncapsulatedContent
  3467. #endif // CMS_PKCS7
  3468. ) {
  3469. if (0 > TCM_ExtractContent(
  3470. pbToBeEncoded,
  3471. cbToBeEncoded,
  3472. &cbInnerEncoded,
  3473. &pbInnerEncoded))
  3474. goto ExtractContentError;
  3475. } else {
  3476. pbInnerEncoded = pbToBeEncoded;
  3477. cbInnerEncoded = cbToBeEncoded;
  3478. }
  3479. }
  3480. switch (dwMsgType) {
  3481. case CMSG_HASHED:
  3482. case CMSG_SIGNED:
  3483. dwFlags |= fDetached ? CMSG_DETACHED_FLAG : 0;
  3484. break;
  3485. default:
  3486. break;
  3487. }
  3488. #ifdef CMS_PKCS7
  3489. if (fEncapsulatedContent)
  3490. dwFlags |= CMSG_CMS_ENCAPSULATED_CONTENT_FLAG;
  3491. #endif // CMS_PKCS7
  3492. if (0 == (cbEncodedBlobOrg = CryptMsgCalculateEncodedLength(
  3493. dwMsgEncodingType,
  3494. dwFlags,
  3495. dwMsgType,
  3496. pvMsgEncodeInfo,
  3497. fInnerContent ? pszInnerContentObjId : NULL,
  3498. fInnerContent ? cbInnerEncoded : cbToBeEncoded))) {
  3499. PrintLastError("EncodeMsg::CryptMsgCalculateEncodedLength == 0");
  3500. goto ErrorReturn;
  3501. }
  3502. cbEncodedBlob = cbEncodedBlobOrg + 1024; // A wee bit of padding
  3503. pbEncodedBlob = (BYTE *) TestAlloc( cbEncodedBlob);
  3504. if (pbEncodedBlob == NULL) goto ErrorReturn;
  3505. hMsg = CryptMsgOpenToEncode(
  3506. dwMsgEncodingType,
  3507. dwFlags,
  3508. dwMsgType,
  3509. pvMsgEncodeInfo,
  3510. fInnerContent ? pszInnerContentObjId : NULL,
  3511. NULL // pStreamInfo
  3512. );
  3513. if (hMsg == NULL) {
  3514. PrintLastError("EncodeMsg::CryptMsgOpenToEncode");
  3515. goto ErrorReturn;
  3516. }
  3517. #ifdef CMS_PKCS7
  3518. if (fAlgorithmParameters) {
  3519. rgSignerEncodeInfo[0].HashEncryptionAlgorithm.Parameters.pbData =
  3520. rgbInvalidAsn;
  3521. rgSignerEncodeInfo[0].HashEncryptionAlgorithm.Parameters.cbData =
  3522. sizeof(rgbInvalidAsn);
  3523. rgSignerEncodeInfo[0].HashAlgorithm.Parameters.pbData =
  3524. rgbInvalidAsn;
  3525. rgSignerEncodeInfo[0].HashAlgorithm.Parameters.cbData =
  3526. sizeof(rgbInvalidAsn);
  3527. }
  3528. #endif // CMS_PKCS7
  3529. fResult = CryptMsgUpdate(
  3530. hMsg,
  3531. pbToBeEncoded,
  3532. cbToBeEncoded,
  3533. TRUE // fFinal
  3534. );
  3535. if (!fResult) {
  3536. PrintLastError("EncodeMsg::CryptMsgUpdate");
  3537. goto ErrorReturn;
  3538. }
  3539. #ifdef CMS_PKCS7
  3540. if (fAuthAttr)
  3541. XORAttributeBytes();
  3542. if (fVerbose || fEncapsulatedContent || cAttrCert ||
  3543. fOriginatorInfo || fCmsRecipient) {
  3544. DWORD dwVersion;
  3545. DWORD cbData = sizeof(dwVersion);
  3546. fResult = CryptMsgGetParam(
  3547. hMsg,
  3548. CMSG_VERSION_PARAM,
  3549. 0, // dwIndex
  3550. (PBYTE) &dwVersion,
  3551. &cbData
  3552. );
  3553. if (!fResult)
  3554. PrintLastError("EncodeMsg::CryptMsgGetParam(CMSG_VERSION_PARAM)");
  3555. else
  3556. printf("EncodeMsg Version:: %d\n", dwVersion);
  3557. }
  3558. #endif // CMS_PKCS7
  3559. fResult = CryptMsgGetParam(
  3560. hMsg,
  3561. fBare ? CMSG_BARE_CONTENT_PARAM : CMSG_CONTENT_PARAM,
  3562. 0, // dwIndex
  3563. pbEncodedBlob,
  3564. &cbEncodedBlob
  3565. );
  3566. if (!fResult) {
  3567. PrintLastError("EncodeMsg::CryptMsgGetParam(MSG_(BARE_)CONTENT_PARAM)");
  3568. goto ErrorReturn;
  3569. }
  3570. #ifdef CMS_PKCS7
  3571. if (IsDSSProv(dwProvType) || fKeyAgree ||
  3572. (fMultiSigner && PROV_RSA_FULL != dwMultiSignerProvType)
  3573. #else
  3574. if (IsDSSProv(dwProvType)
  3575. #endif // CMS_PKCS7
  3576. || hNamedSignerCryptProv) {
  3577. // For DSS the length of the encoded output may be less than
  3578. // the length returned by CryptMsgCalculateEncodedLength
  3579. // Also Key Agreement recipients containing generated ephemeral
  3580. // public keys may have an encoded length less than
  3581. // the length returned by CryptMsgCalculateEncodedLength
  3582. if (cbEncodedBlobOrg < cbEncodedBlob)
  3583. printf( "Fail: encoding size mismatch: expect=%x >= actual=%x\n",
  3584. cbEncodedBlobOrg,
  3585. cbEncodedBlob);
  3586. } else {
  3587. if (cbEncodedBlobOrg != cbEncodedBlob)
  3588. printf( "Fail: encoding size mismatch: expect=%x actual=%x\n",
  3589. cbEncodedBlobOrg,
  3590. cbEncodedBlob);
  3591. }
  3592. // NB- We depart from the usual practice here since cbEncodedBlob can be
  3593. // somewhat larger than required. A buffer size of 1 will always be too
  3594. // small.
  3595. if (!TCM_CheckGetParam(
  3596. hMsg,
  3597. fBare ? CMSG_BARE_CONTENT_PARAM : CMSG_CONTENT_PARAM,
  3598. 0, // dwIndex
  3599. pbEncodedBlob,
  3600. 2))
  3601. goto CheckGetEncodedError;
  3602. if (dwMsgType == CMSG_HASHED) {
  3603. BYTE *pbComputedDigest = NULL;
  3604. DWORD cbComputedDigest = 0;
  3605. if (!TCM_AllocGetParam(
  3606. hMsg,
  3607. CMSG_COMPUTED_HASH_PARAM,
  3608. 0, // dwIndex
  3609. &pbComputedDigest,
  3610. &cbComputedDigest))
  3611. goto GetComputedHashError;
  3612. TCM_CheckGetParam(
  3613. hMsg,
  3614. CMSG_COMPUTED_HASH_PARAM,
  3615. 0, // dwIndex
  3616. pbComputedDigest,
  3617. cbComputedDigest
  3618. );
  3619. TestFree(pbComputedDigest);
  3620. }
  3621. #ifdef CMS_PKCS7
  3622. if (dwMsgType == CMSG_SIGNED && !fNoSigners) {
  3623. DWORD i;
  3624. DWORD c;
  3625. if (fMultiSigner)
  3626. c = 2;
  3627. else
  3628. c = 1;
  3629. for (i = 0; i < c; i++) {
  3630. rgcbEncodedSignerHash[i] = sizeof(rgbEncodedSignerHash[i]);
  3631. if (!CryptMsgGetParam(
  3632. hMsg,
  3633. CMSG_COMPUTED_HASH_PARAM,
  3634. i, // dwSignerIndex
  3635. rgbEncodedSignerHash[i],
  3636. &rgcbEncodedSignerHash[i]
  3637. )) {
  3638. printf("EncodeMsg::CryptMsgGetParam(Signer[%d] CMSG_COMPUTED_HASH_PARAM)",
  3639. i);
  3640. PrintLastError("");
  3641. } else
  3642. VerifyEncodedSignerComputedHash(
  3643. "EncodeMsg", hMsg, i,
  3644. rgbEncodedSignerHash[i],
  3645. rgcbEncodedSignerHash[i]);
  3646. }
  3647. }
  3648. if (fAuthAttr)
  3649. XORAttributeBytes();
  3650. #endif // CMS_PKCS7
  3651. fResult = TRUE;
  3652. goto CommonReturn;
  3653. ErrorReturn:
  3654. fResult = FALSE;
  3655. TestFree(pbEncodedBlob);
  3656. pbEncodedBlob = NULL;
  3657. cbEncodedBlob = 0;
  3658. CommonReturn:
  3659. if (hMsg)
  3660. CryptMsgClose(hMsg);
  3661. TestFree(pbToBeEncoded);
  3662. *ppbEncodedBlob = pbEncodedBlob;
  3663. *pcbEncodedBlob = cbEncodedBlob;
  3664. return fResult;
  3665. //PRINT_ERROR(EncodeMsg,CalculateEncodedLengthWrongSizeError)
  3666. PRINT_ERROR(EncodeMsg,GetNonStreamedMsgContentError)
  3667. PRINT_ERROR(EncodeMsg,ExtractContentError)
  3668. PRINT_ERROR(EncodeMsg,CheckGetEncodedError)
  3669. PRINT_ERROR(EncodeMsg,GetComputedHashError)
  3670. }
  3671. //+-------------------------------------------------------------------------
  3672. // Decodes the message types:
  3673. // CMSG_SIGNED
  3674. // CMSG_ENVELOPED
  3675. // CMSG_SIGNED_AND_ENVELOPED
  3676. // CMSG_HASHED
  3677. //--------------------------------------------------------------------------
  3678. BOOL DecodeMsg(
  3679. IN DWORD dwExpectedMsgType,
  3680. IN const BYTE *pbEncodedBlob,
  3681. IN DWORD cbEncodedBlob
  3682. )
  3683. {
  3684. BOOL fResult;
  3685. HCRYPTMSG hMsg = NULL;
  3686. PBYTE pbContent;
  3687. DWORD cbContent;
  3688. PBYTE pbDecoded = NULL;
  3689. DWORD cbDecoded;
  3690. DWORD cbData;
  3691. DWORD dwMsgType;
  3692. DWORD dwFlags = CMSG_LENGTH_ONLY_FLAG;
  3693. if (!GetNonStreamedMsgContent(
  3694. cbMsgContent,
  3695. &pbContent,
  3696. &cbContent))
  3697. goto GetNonStreamedMsgContentError;
  3698. switch (dwExpectedMsgType) {
  3699. case CMSG_HASHED:
  3700. case CMSG_SIGNED:
  3701. dwFlags |= fDetached ? CMSG_DETACHED_FLAG : 0;
  3702. break;
  3703. default:
  3704. break;
  3705. }
  3706. // Open to decode to get the message type and content length
  3707. hMsg = CryptMsgOpenToDecode(
  3708. dwMsgEncodingType,
  3709. dwFlags,
  3710. fBare ? dwExpectedMsgType : 0,
  3711. hDefaultVerifyProv,
  3712. NULL, // pRecipientInfo
  3713. NULL // pStreamInfo
  3714. );
  3715. if (hMsg == NULL) {
  3716. PrintLastError("DecodeMsg::CryptMsgOpenToDecode(CMSG_LENGTH_ONLY_FLAG)");
  3717. goto ErrorReturn;
  3718. }
  3719. fResult = CryptMsgUpdate(
  3720. hMsg,
  3721. pbEncodedBlob,
  3722. cbEncodedBlob,
  3723. TRUE // fFinal
  3724. );
  3725. if (!fResult) {
  3726. PrintLastError("DecodeMsg::CryptMsgUpdate");
  3727. goto ErrorReturn;
  3728. }
  3729. #ifdef CMS_PKCS7
  3730. if (fVerbose || fEncapsulatedContent || cAttrCert ||
  3731. fOriginatorInfo || fCmsRecipient) {
  3732. DWORD dwVersion;
  3733. DWORD cbData = sizeof(dwVersion);
  3734. fResult = CryptMsgGetParam(
  3735. hMsg,
  3736. CMSG_VERSION_PARAM,
  3737. 0, // dwIndex
  3738. (PBYTE) &dwVersion,
  3739. &cbData
  3740. );
  3741. if (!fResult)
  3742. PrintLastError("DecodeMsg::CryptMsgGetParam(CMSG_VERSION_PARAM)");
  3743. else
  3744. printf("DecodeMsg Version:: %d\n", dwVersion);
  3745. }
  3746. #endif // CMS_PKCS7
  3747. if (fDetached) {
  3748. fResult = CryptMsgUpdate(
  3749. hMsg,
  3750. pbContent,
  3751. cbContent,
  3752. TRUE // fFinal
  3753. );
  3754. if (!fResult) {
  3755. PrintLastError("DecodeMsg::CryptMsgUpdate");
  3756. goto ErrorReturn;
  3757. }
  3758. } else if (!fNoSigners) {
  3759. cbData = sizeof(dwMsgType);
  3760. dwMsgType = 0;
  3761. fResult = CryptMsgGetParam(
  3762. hMsg,
  3763. CMSG_TYPE_PARAM,
  3764. 0, // dwIndex
  3765. &dwMsgType,
  3766. &cbData
  3767. );
  3768. if (!fResult) {
  3769. PrintLastError("DecodeMsg::CryptMsgGetParam(CMSG_TYPE_PARAM)");
  3770. goto ErrorReturn;
  3771. }
  3772. if ((dwMsgType != dwExpectedMsgType) &&
  3773. (CMSG_SIGNED != dwExpectedMsgType)) {
  3774. PrintError("DecodeMsg::Unexpected message type");
  3775. }
  3776. if (!TCM_CheckGetParam(
  3777. hMsg,
  3778. CMSG_TYPE_PARAM,
  3779. 0, // dwIndex
  3780. &dwMsgType,
  3781. cbData))
  3782. goto CheckGetTypeError;
  3783. cbDecoded = 0;
  3784. fResult = CryptMsgGetParam(
  3785. hMsg,
  3786. CMSG_CONTENT_PARAM,
  3787. 0, // dwIndex
  3788. NULL, // pvData
  3789. &cbDecoded
  3790. );
  3791. if (cbDecoded == 0) {
  3792. PrintError("DecodeMsg::message content length == 0");
  3793. goto ErrorReturn;
  3794. }
  3795. if ((cbDecoded < cbContent) && !fInnerContent)
  3796. PrintError(
  3797. "DecodeMsg::Ciphertext Length Less Than Plaintext Length");
  3798. pbDecoded = (BYTE *) TestAlloc(cbDecoded);
  3799. if (pbDecoded == NULL) goto ErrorReturn;
  3800. }
  3801. CryptMsgClose(hMsg);
  3802. hMsg = NULL;
  3803. // Re-open message to get its decoded content.
  3804. hMsg = CryptMsgOpenToDecode(
  3805. dwMsgEncodingType,
  3806. dwFlags,
  3807. fBare ? dwExpectedMsgType : 0,
  3808. hDefaultVerifyProv,
  3809. NULL, // pRecipientInfo
  3810. NULL // pStreamInfo
  3811. );
  3812. if (hMsg == NULL) {
  3813. PrintLastError("DecodeMsg::CryptMsgOpenToDecode");
  3814. goto ErrorReturn;
  3815. }
  3816. // Check that duplicate works
  3817. hMsg = CryptMsgDuplicate(hMsg);
  3818. CryptMsgClose(hMsg);
  3819. fResult = CryptMsgUpdate(
  3820. hMsg,
  3821. pbEncodedBlob,
  3822. cbEncodedBlob,
  3823. TRUE // fFinal
  3824. );
  3825. if (!fResult) {
  3826. PrintLastError("DecodeMsg::CryptMsgUpdate");
  3827. goto ErrorReturn;
  3828. }
  3829. if (fDetached) {
  3830. fResult = CryptMsgUpdate(
  3831. hMsg,
  3832. pbContent,
  3833. cbContent,
  3834. TRUE // fFinal
  3835. );
  3836. if (!fResult) {
  3837. PrintLastError("DecodeMsg::CryptMsgUpdate");
  3838. goto ErrorReturn;
  3839. }
  3840. }
  3841. if (fInnerContent) {
  3842. DWORD cbInnerContentObjId;
  3843. PBYTE pbInnerContentObjId;
  3844. if (!TCM_AllocGetParam(
  3845. hMsg,
  3846. CMSG_INNER_CONTENT_TYPE_PARAM,
  3847. 0, // dwIndex
  3848. &pbInnerContentObjId,
  3849. &cbInnerContentObjId))
  3850. goto GetInnerContentTypeError;
  3851. if ((cbInnerContentObjId != (strlen(pszInnerContentObjId) + 1)) ||
  3852. (0 != memcmp(
  3853. pszInnerContentObjId,
  3854. pbInnerContentObjId,
  3855. cbInnerContentObjId))) {
  3856. PrintError(
  3857. "DecodeMsg::Decoded Content Object ID incorrect");
  3858. }
  3859. TestFree(pbInnerContentObjId);
  3860. }
  3861. if (dwExpectedMsgType == CMSG_ENVELOPED ||
  3862. dwExpectedMsgType == CMSG_SIGNED_AND_ENVELOPED) {
  3863. fResult = GetRecipientInfoAndDecrypt(hMsg);
  3864. if (!fResult) goto ErrorReturn;
  3865. }
  3866. if (!fNoSigners &&
  3867. (dwExpectedMsgType == CMSG_SIGNED ||
  3868. dwExpectedMsgType == CMSG_SIGNED_AND_ENVELOPED)) {
  3869. if (fAuthAttr) {
  3870. DWORD cbAuthAttrs;
  3871. PBYTE pbAuthAttrs;
  3872. if (!TCM_AllocGetParam(
  3873. hMsg,
  3874. CMSG_SIGNER_AUTH_ATTR_PARAM,
  3875. 0, // dwIndex
  3876. &pbAuthAttrs,
  3877. &cbAuthAttrs)) {
  3878. TestFree(pbAuthAttrs);
  3879. goto GetAuthAttrError;
  3880. }
  3881. TestFree(pbAuthAttrs);
  3882. if (!fCountersign) {
  3883. if (!TCM_AllocGetParam(
  3884. hMsg,
  3885. CMSG_SIGNER_UNAUTH_ATTR_PARAM,
  3886. 0, // dwIndex
  3887. &pbAuthAttrs,
  3888. &cbAuthAttrs)) {
  3889. TestFree(pbAuthAttrs);
  3890. goto GetAuthAttrError;
  3891. }
  3892. TestFree(pbAuthAttrs);
  3893. }
  3894. }
  3895. #ifdef CMS_PKCS7
  3896. VerifyDecodedSignerComputedHash(
  3897. "DecodeMsg", hMsg, fInnerContent, 0,
  3898. rgbEncodedSignerHash,
  3899. rgcbEncodedSignerHash);
  3900. if (fMultiSigner) {
  3901. VerifyDecodedSignerComputedHash(
  3902. "DecodeMsg", hMsg, fInnerContent, 1,
  3903. rgbEncodedSignerHash,
  3904. rgcbEncodedSignerHash);
  3905. }
  3906. #endif // CMS_PKCS7
  3907. fResult = GetSignerInfoAndVerify(hMsg, fInnerContent);
  3908. if (!fResult) goto ErrorReturn;
  3909. if (fCountersign && !CountersignAndVerify( hMsg)) {
  3910. PrintError( "DecodeMsg::CountersignAndVerify");
  3911. goto ErrorReturn;
  3912. }
  3913. if (fAddSigner && !AddSignerAndVerify( hMsg)) {
  3914. PrintError( "DecodeMsg::AddSignerAndVerify");
  3915. goto ErrorReturn;
  3916. }
  3917. if (!AddDelItems(
  3918. hMsg,
  3919. CMSG_CERT_COUNT_PARAM,
  3920. CMSG_CTRL_ADD_CERT,
  3921. CMSG_CTRL_DEL_CERT,
  3922. rgSignedCertBlob))
  3923. goto AddDelCertsError;
  3924. if (!AddDelItems(
  3925. hMsg,
  3926. CMSG_CRL_COUNT_PARAM,
  3927. CMSG_CTRL_ADD_CRL,
  3928. CMSG_CTRL_DEL_CRL,
  3929. rgSignedCertBlob)) // This is not a cert
  3930. goto AddDelCrlsError;
  3931. #ifdef CMS_PKCS7
  3932. if (cAttrCert || (fEncapsulatedContent && fInnerContent)) {
  3933. if (!AddDelItems(
  3934. hMsg,
  3935. CMSG_ATTR_CERT_COUNT_PARAM,
  3936. CMSG_CTRL_ADD_ATTR_CERT,
  3937. CMSG_CTRL_DEL_ATTR_CERT,
  3938. rgSignedCertBlob))
  3939. goto AddDelAttrCertsError;
  3940. }
  3941. #endif // CMS_PKCS7
  3942. }
  3943. if (!fDetached && !fNoSigners
  3944. #ifdef CMS_PKCS7
  3945. && !fNoRecipients
  3946. #endif // CMS_PKCS7
  3947. ) {
  3948. fResult = CryptMsgGetParam(
  3949. hMsg,
  3950. CMSG_CONTENT_PARAM,
  3951. 0, // dwIndex
  3952. pbDecoded,
  3953. &cbDecoded
  3954. );
  3955. if (!fResult) {
  3956. PrintLastError("DecodeMsg::CryptMsgGetParam(CMSG_CONTENT_PARAM)");
  3957. goto ErrorReturn;
  3958. }
  3959. if (!TCM_CheckGetParam(
  3960. hMsg,
  3961. CMSG_CONTENT_PARAM,
  3962. 0, // dwIndex
  3963. pbDecoded,
  3964. cbDecoded))
  3965. goto CheckGetContentError;
  3966. if (cbDecoded != cbContent ||
  3967. memcmp(pbContent, pbDecoded, cbContent) != 0) {
  3968. PrintError(
  3969. "DecodeMsg::Decoded Content doesn't match ToBeEncoded Content");
  3970. }
  3971. }
  3972. if (dwExpectedMsgType == CMSG_HASHED) {
  3973. fResult = Undigest(hMsg);
  3974. if (!fResult) goto ErrorReturn;
  3975. }
  3976. fResult = TRUE;
  3977. goto CommonReturn;
  3978. ErrorReturn:
  3979. fResult = FALSE;
  3980. CommonReturn:
  3981. if (hMsg)
  3982. CryptMsgClose(hMsg);
  3983. TestFree(pbDecoded);
  3984. TestFree(pbContent);
  3985. return fResult;
  3986. PRINT_ERROR(DecodeMsg,GetNonStreamedMsgContentError)
  3987. PRINT_ERROR(DecodeMsg,CheckGetTypeError)
  3988. PRINT_ERROR(DecodeMsg,GetInnerContentTypeError)
  3989. PRINT_ERROR(DecodeMsg,GetAuthAttrError)
  3990. PRINT_ERROR(DecodeMsg,CheckGetContentError)
  3991. PRINT_ERROR(DecodeMsg,AddDelCrlsError)
  3992. PRINT_ERROR(DecodeMsg,AddDelCertsError)
  3993. #ifdef CMS_PKCS7
  3994. PRINT_ERROR(DecodeMsg,AddDelAttrCertsError)
  3995. #endif // CMS_PKCS7
  3996. }
  3997. //+-------------------------------------------------------------------------
  3998. // Decode and encode a SignerInfo, and check that the input matches the output
  3999. //--------------------------------------------------------------------------
  4000. BOOL VerifyEncodedSigner(
  4001. IN PBYTE pbEncodedSigner,
  4002. IN DWORD cbEncodedSigner)
  4003. {
  4004. BOOL fRet;
  4005. PCMSG_SIGNER_INFO psi = NULL;
  4006. #ifdef CMS_PKCS7
  4007. PCMSG_CMS_SIGNER_INFO pCMSsi = NULL;
  4008. #endif // CMS_PKCS7
  4009. DWORD cbsi;
  4010. PBYTE pbEncodedSignerNew = NULL;
  4011. DWORD cbEncodedSignerNew;
  4012. cbsi = 0;
  4013. if (!CryptDecodeObject(
  4014. PKCS_7_ASN_ENCODING,
  4015. PKCS7_SIGNER_INFO,
  4016. pbEncodedSigner,
  4017. cbEncodedSigner,
  4018. 0, // dwFlags
  4019. NULL,
  4020. &cbsi))
  4021. goto DecodeSizeError;
  4022. if (NULL == (psi = (PCMSG_SIGNER_INFO)TestAlloc( cbsi)))
  4023. goto AllocDecodeError;
  4024. if (!CryptDecodeObject(
  4025. PKCS_7_ASN_ENCODING,
  4026. PKCS7_SIGNER_INFO,
  4027. pbEncodedSigner,
  4028. cbEncodedSigner,
  4029. 0, // dwFlags
  4030. psi,
  4031. &cbsi))
  4032. goto DecodeError;
  4033. cbEncodedSignerNew = 0;
  4034. if (!CryptEncodeObject(
  4035. PKCS_7_ASN_ENCODING,
  4036. PKCS7_SIGNER_INFO,
  4037. psi,
  4038. NULL,
  4039. &cbEncodedSignerNew))
  4040. goto EncodeSizeError;
  4041. if (NULL == (pbEncodedSignerNew = (PBYTE)TestAlloc( cbEncodedSignerNew)))
  4042. goto AllocEncodeError;
  4043. if (!CryptEncodeObject(
  4044. PKCS_7_ASN_ENCODING,
  4045. PKCS7_SIGNER_INFO,
  4046. psi,
  4047. pbEncodedSignerNew,
  4048. &cbEncodedSignerNew))
  4049. goto EncodeError;
  4050. if (cbEncodedSigner != cbEncodedSignerNew)
  4051. goto UnequalEncodedSignerSizeError;
  4052. if (0 != memcmp( pbEncodedSigner, pbEncodedSignerNew, cbEncodedSigner))
  4053. goto UnequalEncodedSignerError;
  4054. #ifdef CMS_PKCS7
  4055. TestFree(pbEncodedSignerNew);
  4056. pbEncodedSignerNew = NULL;
  4057. cbsi = 0;
  4058. if (!CryptDecodeObject(
  4059. PKCS_7_ASN_ENCODING,
  4060. CMS_SIGNER_INFO,
  4061. pbEncodedSigner,
  4062. cbEncodedSigner,
  4063. 0, // dwFlags
  4064. NULL,
  4065. &cbsi))
  4066. goto CMSDecodeSizeError;
  4067. if (NULL == (pCMSsi = (PCMSG_CMS_SIGNER_INFO)TestAlloc( cbsi)))
  4068. goto CMSAllocDecodeError;
  4069. if (!CryptDecodeObject(
  4070. PKCS_7_ASN_ENCODING,
  4071. CMS_SIGNER_INFO,
  4072. pbEncodedSigner,
  4073. cbEncodedSigner,
  4074. 0, // dwFlags
  4075. pCMSsi,
  4076. &cbsi))
  4077. goto CMSDecodeError;
  4078. cbEncodedSignerNew = 0;
  4079. if (!CryptEncodeObject(
  4080. PKCS_7_ASN_ENCODING,
  4081. CMS_SIGNER_INFO,
  4082. pCMSsi,
  4083. NULL,
  4084. &cbEncodedSignerNew))
  4085. goto CMSEncodeSizeError;
  4086. if (NULL == (pbEncodedSignerNew = (PBYTE)TestAlloc( cbEncodedSignerNew)))
  4087. goto CMSAllocEncodeError;
  4088. if (!CryptEncodeObject(
  4089. PKCS_7_ASN_ENCODING,
  4090. CMS_SIGNER_INFO,
  4091. pCMSsi,
  4092. pbEncodedSignerNew,
  4093. &cbEncodedSignerNew))
  4094. goto CMSEncodeError;
  4095. if (cbEncodedSigner != cbEncodedSignerNew)
  4096. goto CMSUnequalEncodedSignerSizeError;
  4097. if (0 != memcmp( pbEncodedSigner, pbEncodedSignerNew, cbEncodedSigner))
  4098. goto CMSUnequalEncodedSignerError;
  4099. #endif // CMS_PKCS7
  4100. fRet = TRUE;
  4101. CommonReturn:
  4102. TestFree(psi);
  4103. #ifdef CMS_PKCS7
  4104. TestFree(pCMSsi);
  4105. #endif // CMS_PKCS7
  4106. TestFree(pbEncodedSignerNew);
  4107. return fRet;
  4108. ErrorReturn:
  4109. fRet = FALSE;
  4110. goto CommonReturn;
  4111. PRINT_ERROR(VerifyEncodedSigner,DecodeSizeError)
  4112. PRINT_ERROR(VerifyEncodedSigner,AllocDecodeError)
  4113. PRINT_ERROR(VerifyEncodedSigner,DecodeError)
  4114. PRINT_ERROR(VerifyEncodedSigner,EncodeSizeError)
  4115. PRINT_ERROR(VerifyEncodedSigner,AllocEncodeError)
  4116. PRINT_ERROR(VerifyEncodedSigner,EncodeError)
  4117. PRINT_ERROR(VerifyEncodedSigner,UnequalEncodedSignerSizeError)
  4118. PRINT_ERROR(VerifyEncodedSigner,UnequalEncodedSignerError)
  4119. #ifdef CMS_PKCS7
  4120. PRINT_ERROR(VerifyEncodedSigner,CMSDecodeSizeError)
  4121. PRINT_ERROR(VerifyEncodedSigner,CMSAllocDecodeError)
  4122. PRINT_ERROR(VerifyEncodedSigner,CMSDecodeError)
  4123. PRINT_ERROR(VerifyEncodedSigner,CMSEncodeSizeError)
  4124. PRINT_ERROR(VerifyEncodedSigner,CMSAllocEncodeError)
  4125. PRINT_ERROR(VerifyEncodedSigner,CMSEncodeError)
  4126. PRINT_ERROR(VerifyEncodedSigner,CMSUnequalEncodedSignerSizeError)
  4127. PRINT_ERROR(VerifyEncodedSigner,CMSUnequalEncodedSignerError)
  4128. #endif // CMS_PKCS7
  4129. }
  4130. //+-------------------------------------------------------------------------
  4131. // Countersign the signed message and verify the countersignature
  4132. //--------------------------------------------------------------------------
  4133. BOOL CountersignAndVerify(IN HCRYPTMSG hCryptMsg)
  4134. {
  4135. BOOL fRet;
  4136. HCRYPTMSG hMsgNew = NULL;
  4137. PBYTE pbEncodedMessage = NULL;
  4138. DWORD cbEncodedMessage;
  4139. PBYTE pbSignerInfo = NULL;
  4140. DWORD cbSignerInfo;
  4141. PCRYPT_ATTRIBUTES patrs = NULL;
  4142. DWORD cbatrs;
  4143. PCERT_INFO pciCountersigner = NULL;
  4144. DWORD cbSignerPublicKeyData;
  4145. // Allocate and get the CERT_INFO containing the SignerId
  4146. // (Issuer and SerialNumber) of the countersigner.
  4147. // NB: For this particular test, the signer and countersigner are the same.
  4148. if (NULL == (pciCountersigner = GetCertIdFromMsg(
  4149. hCryptMsg,
  4150. CMSG_SIGNER_CERT_INFO_PARAM,
  4151. 0))) // dwIndex
  4152. goto GetCertIdFromMsgError;
  4153. // countersign
  4154. if (!CryptMsgCountersign(
  4155. hCryptMsg,
  4156. 0, // dwIndex
  4157. 1, // cCountersigners
  4158. &rgSignerEncodeInfo[0]))
  4159. goto CountersignError;
  4160. if (!TCM_AllocGetParam(
  4161. hCryptMsg,
  4162. CMSG_ENCODED_MESSAGE,
  4163. 0, // dwIndex
  4164. &pbEncodedMessage,
  4165. &cbEncodedMessage))
  4166. goto GetEncodedMessageError;
  4167. if (pszFilename)
  4168. TCM_WriteBufToFile( pszFilename, pbEncodedMessage, cbEncodedMessage);
  4169. // Re-open message to get its decoded content.
  4170. if (NULL == (hMsgNew = CryptMsgOpenToDecode(
  4171. dwMsgEncodingType,
  4172. 0, // dwFlags
  4173. 0, // dwMsgType
  4174. hDefaultVerifyProv,
  4175. NULL, // pRecipientInfo
  4176. NULL))) // pStreamInfo
  4177. goto CryptMsgOpenToDecodeError;
  4178. if (!CryptMsgUpdate(
  4179. hMsgNew,
  4180. pbEncodedMessage,
  4181. cbEncodedMessage,
  4182. TRUE)) // fFinal
  4183. goto CryptMsgUpdateError;
  4184. // Get the SignerInfo which was countersigned
  4185. if (!TCM_AllocGetParam(
  4186. hMsgNew,
  4187. CMSG_ENCODED_SIGNER,
  4188. 0, // dwIndex
  4189. &pbSignerInfo,
  4190. &cbSignerInfo))
  4191. goto GetEncodedSignerInfoError;
  4192. if (!VerifyEncodedSigner( pbSignerInfo, cbSignerInfo))
  4193. goto VerifyEncodedSignerError;
  4194. // Get the unauth attrs, and find the countersignature
  4195. if (!TCM_AllocGetParam(
  4196. hMsgNew,
  4197. CMSG_SIGNER_UNAUTH_ATTR_PARAM,
  4198. 0, // dwIndex
  4199. (PBYTE *)&patrs,
  4200. &cbatrs))
  4201. goto GetUnauthAttrsError;
  4202. // Do some consistency checks
  4203. if (patrs->cAttr != 1)
  4204. goto AttrCountError;
  4205. if (strcmp( patrs->rgAttr->pszObjId, szOID_RSA_counterSign))
  4206. goto AttrOidNotCountersignError;
  4207. if (patrs->rgAttr->cValue != 1)
  4208. goto CountersignCountError;
  4209. // Get the signer's public key
  4210. cbSignerPublicKeyData = sizeof(SignerPublicKeyData.Data);
  4211. memset(SignerPublicKeyData.Data, 0, cbSignerPublicKeyData);
  4212. if (!CryptExportPublicKeyInfo(
  4213. hCryptProv,
  4214. AT_SIGNATURE,
  4215. X509_ASN_ENCODING,
  4216. (PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data,
  4217. &cbSignerPublicKeyData))
  4218. goto ExportPublicKeyInfoError;
  4219. pciCountersigner->SubjectPublicKeyInfo =
  4220. *((PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data);
  4221. // Verify the countersignature
  4222. if (!CryptMsgVerifyCountersignatureEncoded(
  4223. hDefaultVerifyProv,
  4224. PKCS_7_ASN_ENCODING,
  4225. pbSignerInfo,
  4226. cbSignerInfo,
  4227. patrs->rgAttr->rgValue->pbData,
  4228. patrs->rgAttr->rgValue->cbData,
  4229. pciCountersigner))
  4230. goto VerifyCountersignatureEncodedError;
  4231. fRet = TRUE;
  4232. CommonReturn:
  4233. if (hMsgNew)
  4234. CryptMsgClose(hMsgNew);
  4235. TestFree(pciCountersigner);
  4236. TestFree(pbEncodedMessage);
  4237. TestFree(pbSignerInfo);
  4238. TestFree(patrs);
  4239. return fRet;
  4240. ErrorReturn:
  4241. fRet = FALSE;
  4242. goto CommonReturn;
  4243. PRINT_ERROR(CountersignAndVerify,GetEncodedMessageError)
  4244. PRINT_ERROR(CountersignAndVerify,CryptMsgOpenToDecodeError)
  4245. PRINT_ERROR(CountersignAndVerify,CryptMsgUpdateError)
  4246. PRINT_ERROR(CountersignAndVerify,GetCertIdFromMsgError)
  4247. PRINT_ERROR(CountersignAndVerify,CountersignError)
  4248. PRINT_ERROR(CountersignAndVerify,GetEncodedSignerInfoError)
  4249. PRINT_ERROR(CountersignAndVerify,VerifyEncodedSignerError)
  4250. PRINT_ERROR(CountersignAndVerify,GetUnauthAttrsError)
  4251. PRINT_ERROR(CountersignAndVerify,AttrCountError)
  4252. PRINT_ERROR(CountersignAndVerify,AttrOidNotCountersignError)
  4253. PRINT_ERROR(CountersignAndVerify,CountersignCountError)
  4254. PRINT_ERROR(CountersignAndVerify,ExportPublicKeyInfoError)
  4255. PRINT_ERROR(CountersignAndVerify,VerifyCountersignatureEncodedError)
  4256. }
  4257. //+-------------------------------------------------------------------------
  4258. // Add signers to the signed message and verify the new signatures
  4259. //--------------------------------------------------------------------------
  4260. BOOL AddSignerAndVerify(IN HCRYPTMSG hCryptMsg)
  4261. {
  4262. BOOL fRet;
  4263. HCRYPTMSG hMsgNew = NULL;
  4264. PBYTE pbEncodedMessage = NULL;
  4265. DWORD cbEncodedMessage;
  4266. CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo1 = rgSignerEncodeInfo[0];
  4267. CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo2 = rgSignerEncodeInfo[0];
  4268. PCERT_INFO pciSigner0 = NULL;
  4269. PCERT_INFO pciSigner1 = NULL;
  4270. PCERT_INFO pciSigner2 = NULL;
  4271. if (NULL == (pciSigner0 = GetCertIdFromMsg(
  4272. hCryptMsg,
  4273. CMSG_SIGNER_CERT_INFO_PARAM,
  4274. 0))) // dwIndex
  4275. goto GetCertId0Error;
  4276. if (NULL == (pciSigner1 = GetCertIdFromMsg(
  4277. hCryptMsg,
  4278. CMSG_SIGNER_CERT_INFO_PARAM,
  4279. 0))) // dwIndex
  4280. goto GetCertId1Error;
  4281. if (NULL == (pciSigner2 = GetCertIdFromMsg(
  4282. hCryptMsg,
  4283. CMSG_SIGNER_CERT_INFO_PARAM,
  4284. 0))) // dwIndex
  4285. goto GetCertId2Error;
  4286. // Give the new signers different serial numbers
  4287. pciSigner1->SerialNumber.pbData = (PBYTE)&dwSignerSerialNumber1;
  4288. pciSigner2->SerialNumber.pbData = (PBYTE)&dwSignerSerialNumber2;
  4289. // Fill in the public key info
  4290. // NB- We are relying on this already having been filled in by GetSignerInfoAndVerify
  4291. pciSigner0->SubjectPublicKeyInfo =
  4292. *((PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data);
  4293. pciSigner1->SubjectPublicKeyInfo =
  4294. *((PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data);
  4295. pciSigner2->SubjectPublicKeyInfo =
  4296. *((PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data);
  4297. SignerEncodeInfo1.pCertInfo = pciSigner1;
  4298. SignerEncodeInfo2.pCertInfo = pciSigner2;
  4299. if (IsDSSProv(dwProvType))
  4300. // DSS only supports signing of sha1
  4301. SignerEncodeInfo2.HashAlgorithm =
  4302. SignDigestAlgorithms[fMD5 ? SIGNDIGEST_ALG_MD5 : SIGNDIGEST_ALG_SHA];
  4303. else
  4304. // Use a different hash algorithm to force adding a hash node and
  4305. // hashing the content again.
  4306. SignerEncodeInfo2.HashAlgorithm =
  4307. SignDigestAlgorithms[ !fMD5 ? SIGNDIGEST_ALG_MD5 : SIGNDIGEST_ALG_SHA];
  4308. // Add the signers
  4309. if (!CryptMsgControl(
  4310. hCryptMsg,
  4311. 0, // dwFlags
  4312. CMSG_CTRL_ADD_SIGNER,
  4313. &SignerEncodeInfo1))
  4314. goto AddSigner1Error;
  4315. if (!CryptMsgControl(
  4316. hCryptMsg,
  4317. 0, // dwFlags
  4318. CMSG_CTRL_ADD_SIGNER,
  4319. &SignerEncodeInfo2))
  4320. goto AddSigner2Error;
  4321. if (!AddDelItems(
  4322. hCryptMsg,
  4323. CMSG_SIGNER_COUNT_PARAM,
  4324. CMSG_CTRL_ADD_SIGNER,
  4325. CMSG_CTRL_DEL_SIGNER,
  4326. &SignerEncodeInfo2))
  4327. goto AddDelSignersError;
  4328. // Verify all the signatures
  4329. if (!CryptMsgControl(
  4330. hCryptMsg,
  4331. 0, // dwFlags
  4332. CMSG_CTRL_VERIFY_SIGNATURE,
  4333. pciSigner0))
  4334. goto VerifySigner0Error;
  4335. if (!CryptMsgControl(
  4336. hCryptMsg,
  4337. 0, // dwFlags
  4338. CMSG_CTRL_VERIFY_SIGNATURE,
  4339. pciSigner1))
  4340. goto VerifySigner1Error;
  4341. if (!CryptMsgControl(
  4342. hCryptMsg,
  4343. 0, // dwFlags
  4344. CMSG_CTRL_VERIFY_SIGNATURE,
  4345. pciSigner2))
  4346. goto VerifySigner2Error;
  4347. // Re-encode the message, with the new signers
  4348. if (!TCM_AllocGetParam(
  4349. hCryptMsg,
  4350. CMSG_ENCODED_MESSAGE,
  4351. 0, // dwIndex
  4352. &pbEncodedMessage,
  4353. &cbEncodedMessage))
  4354. goto GetEncodedMessageError;
  4355. if (pszFilename)
  4356. TCM_WriteBufToFile( pszFilename, pbEncodedMessage, cbEncodedMessage);
  4357. // Re-open message to get its decoded content.
  4358. if (NULL == (hMsgNew = CryptMsgOpenToDecode(
  4359. dwMsgEncodingType,
  4360. 0, // dwFlags
  4361. 0, // dwMsgType
  4362. hDefaultVerifyProv,
  4363. NULL, // pRecipientInfo
  4364. NULL))) // pStreamInfo
  4365. goto CryptMsgOpenToDecodeError;
  4366. if (!CryptMsgUpdate(
  4367. hMsgNew,
  4368. pbEncodedMessage,
  4369. cbEncodedMessage,
  4370. TRUE)) // fFinal
  4371. goto CryptMsgUpdateError;
  4372. // Verify all the signatures, again
  4373. if (!CryptMsgControl(
  4374. hMsgNew,
  4375. 0, // dwFlags
  4376. CMSG_CTRL_VERIFY_SIGNATURE,
  4377. pciSigner0))
  4378. goto ReVerifySigner0Error;
  4379. if (!CryptMsgControl(
  4380. hMsgNew,
  4381. 0, // dwFlags
  4382. CMSG_CTRL_VERIFY_SIGNATURE,
  4383. pciSigner1))
  4384. goto ReVerifySigner1Error;
  4385. if (!CryptMsgControl(
  4386. hMsgNew,
  4387. 0, // dwFlags
  4388. CMSG_CTRL_VERIFY_SIGNATURE,
  4389. pciSigner2))
  4390. goto ReVerifySigner2Error;
  4391. fRet = TRUE;
  4392. CommonReturn:
  4393. if (hMsgNew)
  4394. CryptMsgClose(hMsgNew);
  4395. TestFree(pciSigner0);
  4396. TestFree(pciSigner1);
  4397. TestFree(pciSigner2);
  4398. TestFree(pbEncodedMessage);
  4399. return fRet;
  4400. ErrorReturn:
  4401. fRet = FALSE;
  4402. goto CommonReturn;
  4403. PRINT_ERROR(AddSignerAndVerify,GetCertId0Error)
  4404. PRINT_ERROR(AddSignerAndVerify,GetCertId1Error)
  4405. PRINT_ERROR(AddSignerAndVerify,GetCertId2Error)
  4406. PRINT_ERROR(AddSignerAndVerify,AddSigner1Error)
  4407. PRINT_ERROR(AddSignerAndVerify,AddSigner2Error)
  4408. PRINT_ERROR(AddSignerAndVerify,VerifySigner0Error)
  4409. PRINT_ERROR(AddSignerAndVerify,VerifySigner1Error)
  4410. PRINT_ERROR(AddSignerAndVerify,VerifySigner2Error)
  4411. PRINT_ERROR(AddSignerAndVerify,GetEncodedMessageError)
  4412. PRINT_ERROR(AddSignerAndVerify,CryptMsgOpenToDecodeError)
  4413. PRINT_ERROR(AddSignerAndVerify,CryptMsgUpdateError)
  4414. PRINT_ERROR(AddSignerAndVerify,ReVerifySigner0Error)
  4415. PRINT_ERROR(AddSignerAndVerify,ReVerifySigner1Error)
  4416. PRINT_ERROR(AddSignerAndVerify,ReVerifySigner2Error)
  4417. PRINT_ERROR(AddSignerAndVerify,AddDelSignersError)
  4418. }
  4419. //+-------------------------------------------------------------------------
  4420. // Verify certificates and CRLs in a signed or enveloped message.
  4421. //--------------------------------------------------------------------------
  4422. BOOL VerifyCerts(IN HCRYPTMSG hMsg)
  4423. {
  4424. BOOL fResult;
  4425. BYTE *pbCertEncoded = NULL;
  4426. DWORD cCert;
  4427. #ifdef CMS_PKCS7
  4428. BYTE *pbCrlEncoded = NULL;
  4429. DWORD cCrl;
  4430. #endif // CMS_PKCS7
  4431. DWORD cbData;
  4432. DWORD dwIndex;
  4433. //--------------------------------------------------------------
  4434. // Get count of certificates in the message
  4435. cCert = 0;
  4436. cbData = sizeof(cCert);
  4437. fResult = CryptMsgGetParam(
  4438. hMsg,
  4439. CMSG_CERT_COUNT_PARAM,
  4440. 0, // dwIndex
  4441. &cCert,
  4442. &cbData
  4443. );
  4444. if (!fResult) {
  4445. PrintLastError(
  4446. "VerifyCerts::CryptMsgGetParam(CMSG_CERT_COUNT_PARAM)");
  4447. goto ErrorReturn;
  4448. }
  4449. if (cCert != cSignedCert) {
  4450. PrintError("VerifyCerts::cCert != cSignedCert");
  4451. goto ErrorReturn;
  4452. }
  4453. if (!TCM_CheckGetParam(
  4454. hMsg,
  4455. CMSG_CERT_COUNT_PARAM,
  4456. 0, // dwIndex
  4457. &cCert,
  4458. cbData))
  4459. goto CheckGetCertCountError;
  4460. // Get certs from the message and verify
  4461. for (dwIndex = 0; dwIndex < cCert; dwIndex++) {
  4462. if (!TCM_AllocGetParam(
  4463. hMsg,
  4464. CMSG_CERT_PARAM,
  4465. dwIndex,
  4466. &pbCertEncoded,
  4467. &cbData))
  4468. goto GetCertError;
  4469. if (cbData != rgSignedCertBlob[dwIndex].cbData ||
  4470. memcmp(pbCertEncoded, rgSignedCertBlob[dwIndex].pbData,
  4471. cbData) != 0) {
  4472. PrintError("VerifyCerts::Bad Cert content");
  4473. }
  4474. TestFree(pbCertEncoded);
  4475. pbCertEncoded = NULL;
  4476. }
  4477. #ifdef CMS_PKCS7
  4478. //--------------------------------------------------------------
  4479. // Get count of attribute certificates in the message
  4480. cCert = 0;
  4481. cbData = sizeof(cCert);
  4482. fResult = CryptMsgGetParam(
  4483. hMsg,
  4484. CMSG_ATTR_CERT_COUNT_PARAM,
  4485. 0, // dwIndex
  4486. &cCert,
  4487. &cbData
  4488. );
  4489. if (!fResult) {
  4490. PrintLastError(
  4491. "VerifyCerts::CryptMsgGetParam(CMSG_ATTR_CERT_COUNT_PARAM)");
  4492. goto ErrorReturn;
  4493. }
  4494. if (cCert != cAttrCert) {
  4495. PrintError("VerifyCerts::cAttrCert != cAttrCert");
  4496. goto ErrorReturn;
  4497. }
  4498. if (!TCM_CheckGetParam(
  4499. hMsg,
  4500. CMSG_ATTR_CERT_COUNT_PARAM,
  4501. 0, // dwIndex
  4502. &cCert,
  4503. cbData))
  4504. goto CheckGetCertCountError;
  4505. // Get attribute certs from the message and verify
  4506. for (dwIndex = 0; dwIndex < cCert; dwIndex++) {
  4507. if (!TCM_AllocGetParam(
  4508. hMsg,
  4509. CMSG_ATTR_CERT_PARAM,
  4510. dwIndex,
  4511. &pbCertEncoded,
  4512. &cbData))
  4513. goto GetCertError;
  4514. if (cbData != rgAttrCertBlob[dwIndex].cbData ||
  4515. memcmp(pbCertEncoded, rgAttrCertBlob[dwIndex].pbData,
  4516. cbData) != 0) {
  4517. PrintError("VerifyCerts::Bad Attribute Cert content");
  4518. }
  4519. TestFree(pbCertEncoded);
  4520. pbCertEncoded = NULL;
  4521. }
  4522. //--------------------------------------------------------------
  4523. // Get count of CRLs in the message
  4524. cCrl = 0;
  4525. cbData = sizeof(cCrl);
  4526. fResult = CryptMsgGetParam(
  4527. hMsg,
  4528. CMSG_CRL_COUNT_PARAM,
  4529. 0, // dwIndex
  4530. &cCrl,
  4531. &cbData
  4532. );
  4533. if (!fResult) {
  4534. PrintLastError(
  4535. "VerifyCrls::CryptMsgGetParam(CMSG_CRL_COUNT_PARAM)");
  4536. goto ErrorReturn;
  4537. }
  4538. if (cCrl != cSignedCrl) {
  4539. PrintError("VerifyCrls::cCrl != cSignedCrl");
  4540. goto ErrorReturn;
  4541. }
  4542. if (!TCM_CheckGetParam(
  4543. hMsg,
  4544. CMSG_CRL_COUNT_PARAM,
  4545. 0, // dwIndex
  4546. &cCrl,
  4547. cbData))
  4548. goto CheckGetCrlCountError;
  4549. // Get CRLs from the message and verify
  4550. for (dwIndex = 0; dwIndex < cCrl; dwIndex++) {
  4551. if (!TCM_AllocGetParam(
  4552. hMsg,
  4553. CMSG_CRL_PARAM,
  4554. dwIndex,
  4555. &pbCrlEncoded,
  4556. &cbData))
  4557. goto GetCrlError;
  4558. if (cbData != rgSignedCrlBlob[dwIndex].cbData ||
  4559. memcmp(pbCrlEncoded, rgSignedCrlBlob[dwIndex].pbData,
  4560. cbData) != 0) {
  4561. PrintError("VerifyCrls::Bad Crl content");
  4562. }
  4563. TestFree(pbCrlEncoded);
  4564. pbCrlEncoded = NULL;
  4565. }
  4566. #endif // CMS_PKCS7
  4567. fResult = TRUE;
  4568. goto CommonReturn;
  4569. ErrorReturn:
  4570. fResult = FALSE;
  4571. CommonReturn:
  4572. TestFree(pbCertEncoded);
  4573. #ifdef CMS_PKCS7
  4574. TestFree(pbCrlEncoded);
  4575. #endif // CMS_PKCS7
  4576. return fResult;
  4577. PRINT_ERROR(VerifyCerts,CheckGetCertCountError)
  4578. PRINT_ERROR(VerifyCerts,GetCertError)
  4579. #ifdef CMS_PKCS7
  4580. PRINT_ERROR(VerifyCerts,CheckGetCrlCountError)
  4581. PRINT_ERROR(VerifyCerts,GetCrlError)
  4582. #endif // CMS_PKCS7
  4583. }
  4584. //+-------------------------------------------------------------------------
  4585. // Get signer info and verify the signed message
  4586. //--------------------------------------------------------------------------
  4587. BOOL GetSignerInfoAndVerify(
  4588. IN HCRYPTMSG hMsg,
  4589. IN BOOL fInnerNonData,
  4590. IN DWORD dwSignerIndex,
  4591. OUT DWORD *pdwSrcIndex
  4592. )
  4593. {
  4594. BOOL fResult;
  4595. PCERT_INFO pSignerCertInfo = NULL;
  4596. PCMSG_SIGNER_INFO pSignerInfo = NULL;
  4597. DWORD cbData;
  4598. BOOL fEqual;
  4599. DWORD i;
  4600. PCRYPT_ATTRIBUTE patr1;
  4601. PCRYPT_ATTRIBUTE patr2;
  4602. DWORD cbSignerPublicKeyData;
  4603. DWORD dwSrcIndex = 0;
  4604. HCRYPTPROV hVerifyProv;
  4605. #ifdef CMS_PKCS7
  4606. if (fMultiSigner) {
  4607. DWORD cSigner = 0;
  4608. cbData = sizeof(cSigner);
  4609. if (!CryptMsgGetParam(
  4610. hMsg,
  4611. CMSG_SIGNER_COUNT_PARAM,
  4612. 0, // dwIndex
  4613. &cSigner,
  4614. &cbData) || cSigner != 2) {
  4615. PrintLastError(
  4616. "GetSignerInfoAndVerify:: Invalid multisigner count");
  4617. }
  4618. }
  4619. #endif // CMS_PKCS7
  4620. // Allocate and get the CERT_INFO containing the SignerId
  4621. // (Issuer and SerialNumber)
  4622. pSignerCertInfo = GetCertIdFromMsg(
  4623. hMsg,
  4624. CMSG_SIGNER_CERT_INFO_PARAM,
  4625. dwSignerIndex
  4626. );
  4627. if (pSignerCertInfo == NULL) {
  4628. PrintLastError(
  4629. "GetSignerInfoAndVerify::CryptMsgGetParam(CMSG_SIGNER_CERT_INFO_PARAM)");
  4630. goto ErrorReturn;
  4631. }
  4632. #ifdef CMS_PKCS7
  4633. if (!(fCertInfoKeyId && fMultiSigner)) {
  4634. #endif // CMS_PKCS7
  4635. if (pSignerCertInfo->Issuer.cbData != rgSignerCertInfo[0].Issuer.cbData ||
  4636. memcmp(pSignerCertInfo->Issuer.pbData, rgSignerCertInfo[0].Issuer.pbData,
  4637. pSignerCertInfo->Issuer.cbData) != 0) {
  4638. PrintError("GetSignerInfoAndVerify::Bad SignerIssuerName");
  4639. }
  4640. #ifdef CMS_PKCS7
  4641. }
  4642. #endif // CMS_PKCS7
  4643. #ifdef CMS_PKCS7
  4644. if (fMultiSigner) {
  4645. if (pSignerCertInfo->SerialNumber.cbData ==
  4646. rgSignerCertInfo[0].SerialNumber.cbData &&
  4647. memcmp(pSignerCertInfo->SerialNumber.pbData,
  4648. rgSignerCertInfo[0].SerialNumber.pbData,
  4649. pSignerCertInfo->SerialNumber.cbData) == 0) {
  4650. dwSrcIndex = 0;
  4651. } else if (pSignerCertInfo->SerialNumber.cbData ==
  4652. rgSignerCertInfo[1].SerialNumber.cbData &&
  4653. memcmp(pSignerCertInfo->SerialNumber.pbData,
  4654. rgSignerCertInfo[1].SerialNumber.pbData,
  4655. pSignerCertInfo->SerialNumber.cbData) == 0) {
  4656. dwSrcIndex = 1;
  4657. } else {
  4658. PrintError("GetSignerInfoAndVerify::Bad SignerSerialNumber");
  4659. }
  4660. if (fCertInfoKeyId) {
  4661. if (pSignerCertInfo->Issuer.cbData ==
  4662. rgSignerCertInfo[0].Issuer.cbData &&
  4663. memcmp(pSignerCertInfo->Issuer.pbData,
  4664. rgSignerCertInfo[0].Issuer.pbData,
  4665. pSignerCertInfo->Issuer.cbData) == 0) {
  4666. dwSrcIndex = 0;
  4667. } else if (pSignerCertInfo->Issuer.cbData ==
  4668. rgSignerCertInfo[1].Issuer.cbData &&
  4669. memcmp(pSignerCertInfo->Issuer.pbData,
  4670. rgSignerCertInfo[1].Issuer.pbData,
  4671. pSignerCertInfo->Issuer.cbData) == 0) {
  4672. dwSrcIndex = 1;
  4673. } else {
  4674. PrintError("GetSignerInfoAndVerify::Bad CertInfoKeyId");
  4675. }
  4676. }
  4677. } else
  4678. #endif // CMS_PKCS7
  4679. if (pSignerCertInfo->SerialNumber.cbData !=
  4680. rgSignerCertInfo[0].SerialNumber.cbData ||
  4681. memcmp(pSignerCertInfo->SerialNumber.pbData,
  4682. rgSignerCertInfo[0].SerialNumber.pbData,
  4683. pSignerCertInfo->SerialNumber.cbData) != 0) {
  4684. PrintError("GetSignerInfoAndVerify::Bad SignerSerialNumber");
  4685. }
  4686. //--------------------------------------------------------------
  4687. // Allocate and get the CMSG_SIGNER_INFO for the signer
  4688. if (NULL == (pSignerInfo = GetSignerInfoFromMsg(
  4689. hMsg,
  4690. dwSignerIndex))) {
  4691. PrintLastError(
  4692. "GetSignerInfoAndVerify::CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM)");
  4693. goto ErrorReturn;
  4694. }
  4695. fEqual = (pSignerInfo->Issuer.cbData ==
  4696. rgSignerCertInfo[dwSrcIndex].Issuer.cbData);
  4697. if (fEqual) {
  4698. fEqual &= (memcmp( pSignerInfo->Issuer.pbData,
  4699. rgSignerCertInfo[dwSrcIndex].Issuer.pbData,
  4700. pSignerInfo->Issuer.cbData) == 0);
  4701. }
  4702. fEqual &= (pSignerInfo->SerialNumber.cbData ==
  4703. rgSignerCertInfo[dwSrcIndex].SerialNumber.cbData);
  4704. if (fEqual) {
  4705. fEqual &= (memcmp( pSignerInfo->SerialNumber.pbData,
  4706. rgSignerCertInfo[dwSrcIndex].SerialNumber.pbData,
  4707. pSignerInfo->SerialNumber.cbData) == 0);
  4708. }
  4709. if (fAuthAttr) {
  4710. fEqual &= EqualAlgorithm( &rgSignerEncodeInfo[dwSrcIndex].HashAlgorithm,
  4711. &pSignerInfo->HashAlgorithm);
  4712. // Allow for the 2 auth attrs which get added automatically
  4713. fEqual &= ((rgSignerEncodeInfo[dwSrcIndex].cAuthAttr + 2) ==
  4714. pSignerInfo->AuthAttrs.cAttr);
  4715. if (fEqual) {
  4716. for (i=pSignerInfo->AuthAttrs.cAttr,
  4717. patr1=rgSignerEncodeInfo[dwSrcIndex].rgAuthAttr,
  4718. patr2=pSignerInfo->AuthAttrs.rgAttr;
  4719. i>0;
  4720. i--, patr2++) {
  4721. // NB: We skip over the 2 auth attrs added by the system.
  4722. if ( (0 == strcmp( szOID_RSA_contentType, patr2->pszObjId)) ||
  4723. (0 == strcmp( szOID_RSA_messageDigest, patr2->pszObjId)))
  4724. continue;
  4725. fEqual &= EqualAttribute( patr1++, patr2);
  4726. }
  4727. }
  4728. if (!fCountersign) {
  4729. fEqual &= (rgSignerEncodeInfo[dwSrcIndex].cUnauthAttr ==
  4730. pSignerInfo->UnauthAttrs.cAttr);
  4731. if (fEqual) {
  4732. for (i=pSignerInfo->UnauthAttrs.cAttr,
  4733. patr1=rgSignerEncodeInfo[dwSrcIndex].rgUnauthAttr,
  4734. patr2=pSignerInfo->UnauthAttrs.rgAttr;
  4735. i>0;
  4736. i--, patr1++, patr2++) {
  4737. fEqual &= EqualAttribute( patr1, patr2);
  4738. }
  4739. }
  4740. }
  4741. } else {
  4742. // It would be more thorough to check the message digest and
  4743. // content type auth attrs are present in the fInnerContent case.
  4744. if (fInnerNonData)
  4745. {
  4746. fEqual &= (pSignerInfo->AuthAttrs.cAttr == 2) ? 1 : 0;
  4747. }
  4748. else
  4749. {
  4750. fEqual &= (pSignerInfo->AuthAttrs.cAttr == 0) ? 1 : 0;
  4751. }
  4752. // fEqual &= fInnerNonData
  4753. // ? (2 == pSignerInfo->AuthAttrs.cAttr)
  4754. // : (0 == pSignerInfo->AuthAttrs.cAttr);
  4755. }
  4756. if (!fAuthAttr || fCountersign)
  4757. fEqual &= (0 == pSignerInfo->UnauthAttrs.cAttr);
  4758. if (!fEqual) {
  4759. PrintError("GetSignerInfoAndVerify::Bad SignerInfo");
  4760. goto ErrorReturn;
  4761. }
  4762. VerifyCerts(hMsg);
  4763. // Get crypt provider's public signature key. It will be used as the
  4764. // signer's public key
  4765. cbSignerPublicKeyData = sizeof(SignerPublicKeyData.Data);
  4766. memset(SignerPublicKeyData.Data, 0, cbSignerPublicKeyData);
  4767. hVerifyProv = hCryptProv;
  4768. #ifdef CMS_PKCS7
  4769. if (fMultiSigner) {
  4770. if (dwSrcIndex != 0)
  4771. hVerifyProv = hMultiSignerCryptProv;
  4772. }
  4773. #endif // CMS_PKCS7
  4774. if (fNoSignature) {
  4775. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA Para;
  4776. memset(&Para, 0, sizeof(Para));
  4777. Para.cbSize = sizeof(Para);
  4778. // Para.hCryptProv =
  4779. Para.dwSignerIndex = dwSignerIndex;
  4780. Para.dwSignerType = CMSG_VERIFY_SIGNER_NULL;
  4781. // Para.pvSigner =
  4782. fResult = CryptMsgControl(
  4783. hMsg,
  4784. 0, // dwFlags
  4785. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  4786. &Para
  4787. );
  4788. if (!fResult) {
  4789. PrintLastError(
  4790. "GetSignerInfoAndVerify::CryptMsgControl(CMSG_VERIFY_SIGNER_NULL)");
  4791. goto ErrorReturn;
  4792. }
  4793. goto CommonReturn;
  4794. }
  4795. CryptExportPublicKeyInfo(
  4796. hVerifyProv,
  4797. AT_SIGNATURE,
  4798. X509_ASN_ENCODING,
  4799. (PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data,
  4800. &cbSignerPublicKeyData);
  4801. pSignerCertInfo->SubjectPublicKeyInfo =
  4802. *((PCERT_PUBLIC_KEY_INFO) SignerPublicKeyData.Data);
  4803. fResult = CryptMsgControl(
  4804. hMsg,
  4805. 0, // dwFlags
  4806. CMSG_CTRL_VERIFY_SIGNATURE,
  4807. pSignerCertInfo
  4808. );
  4809. if (!fResult) {
  4810. PrintLastError(
  4811. "GetSignerInfoAndVerify::CryptMsgControl(CMSG_CTRL_VERIFY_SIGNATURE)");
  4812. goto ErrorReturn;
  4813. }
  4814. #ifdef CMS_PKCS7
  4815. // Modify public key. Verify should fail.
  4816. XORBitBlob(&pSignerCertInfo->SubjectPublicKeyInfo.PublicKey);
  4817. fResult = CryptMsgControl(
  4818. hMsg,
  4819. 0, // dwFlags
  4820. CMSG_CTRL_VERIFY_SIGNATURE,
  4821. pSignerCertInfo
  4822. );
  4823. if (fResult)
  4824. printf("GetSignerInfoAndVerify::CryptMsgControl(CMSG_CTRL_VERIFY_SIGNATURE) failed => verified with bad public key");
  4825. XORBitBlob(&pSignerCertInfo->SubjectPublicKeyInfo.PublicKey);
  4826. if (!fCertInfoKeyId) {
  4827. // Modify serial number. Verify should fail.
  4828. XORBlob(&pSignerCertInfo->SerialNumber);
  4829. fResult = CryptMsgControl(
  4830. hMsg,
  4831. 0, // dwFlags
  4832. CMSG_CTRL_VERIFY_SIGNATURE,
  4833. pSignerCertInfo
  4834. );
  4835. if (fResult)
  4836. printf("GetSignerInfoAndVerify::CryptMsgControl(CMSG_CTRL_VERIFY_SIGNATURE) failed => verified with bad serial number");
  4837. XORBlob(&pSignerCertInfo->SerialNumber);
  4838. // Modify issuer. Verify should fail.
  4839. XORBlob(&pSignerCertInfo->Issuer);
  4840. fResult = CryptMsgControl(
  4841. hMsg,
  4842. 0, // dwFlags
  4843. CMSG_CTRL_VERIFY_SIGNATURE,
  4844. pSignerCertInfo
  4845. );
  4846. if (fResult)
  4847. printf("GetSignerInfoAndVerify::CryptMsgControl(CMSG_CTRL_VERIFY_SIGNATURE) failed => verified with bad issuer");
  4848. XORBlob(&pSignerCertInfo->Issuer);
  4849. }
  4850. fResult = TRUE;
  4851. #endif // CMS_PKCS7
  4852. goto CommonReturn;
  4853. ErrorReturn:
  4854. fResult = FALSE;
  4855. CommonReturn:
  4856. TestFree(pSignerCertInfo);
  4857. TestFree(pSignerInfo);
  4858. *pdwSrcIndex = dwSrcIndex;
  4859. return fResult;
  4860. }
  4861. BOOL NamedSignerVerify(IN HCRYPTMSG hMsg, IN BOOL fInnerNonData)
  4862. {
  4863. BOOL fResult;
  4864. #ifdef CMS_PKCS7
  4865. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  4866. CERT_CHAIN_PARA ChainPara;
  4867. CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA CtrlPara;
  4868. // Build a chain. This is necessary for DSA with public key algorithm
  4869. // parameter inheritance.
  4870. memset(&ChainPara, 0, sizeof(ChainPara));
  4871. ChainPara.cbSize = sizeof(ChainPara);
  4872. if (!CertGetCertificateChain(
  4873. NULL, // hChainEngine
  4874. pNamedSigner,
  4875. NULL, // pTime
  4876. hSignerStore,
  4877. &ChainPara,
  4878. CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL,
  4879. NULL, // pvReserved
  4880. &pChainContext
  4881. )) {
  4882. PrintLastError(
  4883. "NamedSignerVerify::CertGetCertificateChain");
  4884. return FALSE;
  4885. }
  4886. // Test that we can verify a certificate signature using a chain
  4887. if (2 <= pChainContext->rgpChain[0]->cElement) {
  4888. PCCERT_CONTEXT pIssuer =
  4889. pChainContext->rgpChain[0]->rgpElement[1]->pCertContext;
  4890. PCCERT_CHAIN_CONTEXT pIssuerChainContext = NULL;
  4891. if (!CertGetCertificateChain(
  4892. NULL, // hChainEngine
  4893. pIssuer,
  4894. NULL, // pTime
  4895. hSignerStore,
  4896. &ChainPara,
  4897. CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL,
  4898. NULL, // pvReserved
  4899. &pIssuerChainContext
  4900. )) {
  4901. PrintLastError(
  4902. "NamedSignerVerify::CertGetCertificateChain(Issuer)");
  4903. } else {
  4904. if (!CryptVerifyCertificateSignatureEx(
  4905. 0, // hCryptProv
  4906. dwCertEncodingType,
  4907. CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
  4908. (void *) pNamedSigner,
  4909. CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN,
  4910. (void *) pIssuerChainContext,
  4911. 0, // dwFlags
  4912. NULL // pvReserved
  4913. )) {
  4914. PrintLastError(
  4915. "NamedSignerVerify::CryptVerifyCertificateSignatureEx(Chain)");
  4916. }
  4917. CertFreeCertificateChain(pIssuerChainContext);
  4918. }
  4919. }
  4920. memset(&CtrlPara, 0, sizeof(CtrlPara));
  4921. CtrlPara.cbSize = sizeof(CtrlPara);
  4922. CtrlPara.hCryptProv = hNamedSignerCryptProv;
  4923. CtrlPara.dwSignerIndex = 0;
  4924. CtrlPara.dwSignerType = CMSG_VERIFY_SIGNER_CHAIN;
  4925. CtrlPara.pvSigner = (void *) pChainContext;
  4926. fResult = CryptMsgControl(
  4927. hMsg,
  4928. 0,
  4929. CMSG_CTRL_VERIFY_SIGNATURE_EX,
  4930. &CtrlPara
  4931. );
  4932. if (!fResult) {
  4933. PrintLastError(
  4934. "NamedSignerVerify::CryptMsgControl(CMSG_CTRL_VERIFY_SIGNATURE_EX)");
  4935. }
  4936. CertFreeCertificateChain(pChainContext);
  4937. return fResult;
  4938. #else
  4939. fResult = CryptMsgControl(
  4940. hMsg,
  4941. 0, // dwFlags
  4942. CMSG_CTRL_VERIFY_SIGNATURE,
  4943. pNamedSigner->pCertInfo
  4944. );
  4945. if (!fResult) {
  4946. PrintLastError(
  4947. "NamedSignerVerify::CryptMsgControl(CMSG_CTRL_VERIFY_SIGNATURE)");
  4948. }
  4949. return fResult;
  4950. #endif // CMS_PKCS7
  4951. }
  4952. //+-------------------------------------------------------------------------
  4953. // Get signer info and verify the signed message
  4954. //--------------------------------------------------------------------------
  4955. BOOL GetSignerInfoAndVerify(IN HCRYPTMSG hMsg, IN BOOL fInnerNonData)
  4956. {
  4957. BOOL fResult;
  4958. DWORD dwSrcIndex;
  4959. if (pNamedSigner)
  4960. fResult = NamedSignerVerify(hMsg, fInnerNonData);
  4961. else
  4962. fResult = GetSignerInfoAndVerify(hMsg, fInnerNonData, 0, &dwSrcIndex);
  4963. #ifdef CMS_PKCS7
  4964. if (fMultiSigner) {
  4965. DWORD dwSrcIndex1;
  4966. fResult &= GetSignerInfoAndVerify(hMsg, fInnerNonData, 1, &dwSrcIndex1);
  4967. if (fResult && dwSrcIndex == dwSrcIndex1)
  4968. PrintError("Multiple signer:: Didn't get different signers");
  4969. }
  4970. #endif // CMS_PKCS7
  4971. return fResult;
  4972. }
  4973. #ifdef CMS_PKCS7
  4974. //+-------------------------------------------------------------------------
  4975. // Allocate and get the CMSG_CMS_RECIPIENT_INFO_PARAM
  4976. // from the message
  4977. //--------------------------------------------------------------------------
  4978. PCMSG_CMS_RECIPIENT_INFO GetCmsRecipientFromMsg(
  4979. IN HCRYPTMSG hMsg,
  4980. IN DWORD dwIndex
  4981. )
  4982. {
  4983. PCMSG_CMS_RECIPIENT_INFO pRecipientInfo;
  4984. DWORD cbData;
  4985. if (!TCM_AllocGetParam(
  4986. hMsg,
  4987. CMSG_CMS_RECIPIENT_INFO_PARAM,
  4988. dwIndex,
  4989. (PBYTE *)&pRecipientInfo,
  4990. &cbData))
  4991. return NULL;
  4992. return pRecipientInfo;
  4993. }
  4994. BOOL blobcmp(
  4995. IN PCRYPT_DATA_BLOB pBlob1,
  4996. IN PCRYPT_DATA_BLOB pBlob2
  4997. )
  4998. {
  4999. if (pBlob1->cbData != pBlob2->cbData)
  5000. return FALSE;
  5001. else if (0 == pBlob1->cbData)
  5002. return TRUE;
  5003. else if (0 == memcmp(pBlob1->pbData, pBlob2->pbData, pBlob1->cbData))
  5004. return TRUE;
  5005. else
  5006. return FALSE;
  5007. }
  5008. BOOL bitblobcmp(
  5009. IN PCRYPT_BIT_BLOB pBlob1,
  5010. IN PCRYPT_BIT_BLOB pBlob2
  5011. )
  5012. {
  5013. if (pBlob1->cbData != pBlob2->cbData)
  5014. return FALSE;
  5015. else if (0 == pBlob1->cbData)
  5016. return TRUE;
  5017. else if (0 == memcmp(pBlob1->pbData, pBlob2->pbData, pBlob1->cbData))
  5018. return TRUE;
  5019. else
  5020. return FALSE;
  5021. }
  5022. //+-------------------------------------------------------------------------
  5023. // Get CMS Recipient info and decrypt the message.
  5024. //--------------------------------------------------------------------------
  5025. BOOL GetCmsRecipientInfoAndDecrypt(IN HCRYPTMSG hMsg)
  5026. {
  5027. BOOL fResult;
  5028. PCMSG_CMS_RECIPIENT_INFO pRecipientInfo = NULL;
  5029. DWORD cRecipient;
  5030. DWORD cbData;
  5031. DWORD dwIndex;
  5032. // Get # of CMS recipients in the message.
  5033. cbData = sizeof(cRecipient);
  5034. cRecipient = 0;
  5035. fResult = CryptMsgGetParam(
  5036. hMsg,
  5037. CMSG_CMS_RECIPIENT_COUNT_PARAM,
  5038. 0, // dwIndex
  5039. &cRecipient,
  5040. &cbData
  5041. );
  5042. if (!fResult) {
  5043. PrintLastError(
  5044. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_CMS_RECIPIENT_COUNT_PARAM)");
  5045. goto ErrorReturn;
  5046. }
  5047. if (!TCM_CheckGetParam(
  5048. hMsg,
  5049. CMSG_CMS_RECIPIENT_COUNT_PARAM,
  5050. 0, // dwIndex
  5051. &cRecipient,
  5052. cbData))
  5053. goto CheckGetCmsRecipientCountError;
  5054. if (cRecipient != cCmsRecipients) {
  5055. PrintError("GetCmsRecipientInfoAndDecrypt::cRecipient != cCmsRecipients");
  5056. goto ErrorReturn;
  5057. }
  5058. // Get all the recipients and verify
  5059. for (dwIndex = 0; dwIndex < cRecipient; dwIndex++) {
  5060. pRecipientInfo = GetCmsRecipientFromMsg(
  5061. hMsg,
  5062. dwIndex
  5063. );
  5064. if (pRecipientInfo == NULL) {
  5065. PrintLastError(
  5066. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_CMS_RECIPIENT_INFO_PARAM)");
  5067. goto ErrorReturn;
  5068. }
  5069. if (pRecipientInfo->dwRecipientChoice !=
  5070. rgCmsRecipient[dwIndex].dwRecipientChoice) {
  5071. PrintError("GetCmsRecipientInfoAndDecrypt::Bad RecipientChoice");
  5072. goto ErrorReturn;
  5073. }
  5074. switch (pRecipientInfo->dwRecipientChoice) {
  5075. case CMSG_KEY_TRANS_RECIPIENT:
  5076. {
  5077. PCMSG_KEY_TRANS_RECIPIENT_INFO pDecode =
  5078. pRecipientInfo->pKeyTrans;
  5079. PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pEncode =
  5080. &rgKeyTrans[dwIndex];
  5081. if (0 != strcmp(pDecode->KeyEncryptionAlgorithm.pszObjId,
  5082. pEncode->KeyEncryptionAlgorithm.pszObjId))
  5083. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyEncryptionAlgorithm");
  5084. if (pDecode->RecipientId.dwIdChoice !=
  5085. pEncode->RecipientId.dwIdChoice)
  5086. PrintError("GetCmsRecipientInfoAndDecrypt::Bad dwIdChoice");
  5087. else {
  5088. switch (pDecode->RecipientId.dwIdChoice) {
  5089. case CERT_ID_ISSUER_SERIAL_NUMBER:
  5090. {
  5091. PCERT_ISSUER_SERIAL_NUMBER pDecodeRid =
  5092. &pDecode->RecipientId.IssuerSerialNumber;
  5093. PCERT_ISSUER_SERIAL_NUMBER pEncodeRid =
  5094. &pEncode->RecipientId.IssuerSerialNumber;
  5095. if (CMSG_KEY_TRANS_PKCS_1_5_VERSION !=
  5096. pDecode->dwVersion)
  5097. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyTransPkcsVersion");
  5098. if (!blobcmp(&pDecodeRid->Issuer,
  5099. &pEncodeRid->Issuer) ||
  5100. !blobcmp(&pDecodeRid->SerialNumber,
  5101. &pEncodeRid->SerialNumber))
  5102. PrintError("GetCmsRecipientInfoAndDecrypt::Bad IssuerSerialNumber");
  5103. }
  5104. break;
  5105. case CERT_ID_KEY_IDENTIFIER:
  5106. {
  5107. PCRYPT_HASH_BLOB pDecodeRid =
  5108. &pDecode->RecipientId.KeyId;
  5109. PCRYPT_HASH_BLOB pEncodeRid =
  5110. &pEncode->RecipientId.KeyId;
  5111. if (CMSG_KEY_TRANS_CMS_VERSION !=
  5112. pDecode->dwVersion)
  5113. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyTransCmsVersion");
  5114. if (!blobcmp(pDecodeRid, pEncodeRid))
  5115. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyId");
  5116. }
  5117. break;
  5118. default:
  5119. PrintError("GetCmsRecipientInfoAndDecrypt::Bad dwIdChoice");
  5120. }
  5121. }
  5122. }
  5123. break;
  5124. case CMSG_KEY_AGREE_RECIPIENT:
  5125. {
  5126. PCMSG_KEY_AGREE_RECIPIENT_INFO pDecode =
  5127. pRecipientInfo->pKeyAgree;
  5128. PCMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO pEncode =
  5129. &rgKeyAgree[dwIndex];
  5130. if (CMSG_KEY_AGREE_VERSION != pDecode->dwVersion)
  5131. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyAgreePkcsVersion");
  5132. if (!blobcmp(&pEncode->UserKeyingMaterial,
  5133. &pDecode->UserKeyingMaterial))
  5134. PrintError("GetCmsRecipientInfoAndDecrypt::Bad UserKeyingMaterial");
  5135. if (0 != strcmp(pDecode->KeyEncryptionAlgorithm.pszObjId,
  5136. pEncode->KeyEncryptionAlgorithm.pszObjId))
  5137. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyEncryptionAlgorithm");
  5138. #if 0
  5139. if (0 == _stricmp(pszEncryptName, "rc2")) {
  5140. if (0 == pDecode->KeyEncryptionAlgorithm.Parameters.cbData)
  5141. PrintError("GetCmsRecipientInfoAndDecrypt::Missing rc2 KeyEncryptionAlgorithm Parameters");
  5142. else {
  5143. int iVersion;
  5144. DWORD cbData;
  5145. cbData = sizeof(iVersion);
  5146. if (!CryptDecodeObject(
  5147. PKCS_7_ASN_ENCODING,
  5148. X509_INTEGER,
  5149. pDecode->KeyEncryptionAlgorithm.Parameters.pbData,
  5150. pDecode->KeyEncryptionAlgorithm.Parameters.cbData,
  5151. 0, // dwFlags
  5152. &iVersion,
  5153. &cbData))
  5154. PrintLastError("GetCmsRecipientInfoAndDecrypt::CryptDecodeObject(rc2 KeyEncryptionAlgorithm Parameters)");
  5155. else {
  5156. DWORD dwEncodeBitLen;
  5157. DWORD dwDecodeBitLen;
  5158. dwEncodeBitLen = dwEncryptBitLen;
  5159. if (0 == dwEncodeBitLen)
  5160. dwEncodeBitLen = 40;
  5161. switch (iVersion) {
  5162. case CRYPT_RC2_40BIT_VERSION:
  5163. dwDecodeBitLen = 40;
  5164. break;
  5165. case CRYPT_RC2_56BIT_VERSION:
  5166. dwDecodeBitLen = 56;
  5167. break;
  5168. case CRYPT_RC2_64BIT_VERSION:
  5169. dwDecodeBitLen = 64;
  5170. break;
  5171. case CRYPT_RC2_128BIT_VERSION:
  5172. dwDecodeBitLen = 128;
  5173. break;
  5174. default:
  5175. dwDecodeBitLen = 0;
  5176. PrintError("GetCmsRecipientInfoAndDecrypt::Bad Decode BitLen");
  5177. }
  5178. if (dwDecodeBitLen != dwEncodeBitLen)
  5179. PrintError("GetCmsRecipientInfoAndDecrypt::Decode != Encode BitLen");
  5180. }
  5181. }
  5182. } else {
  5183. BYTE rgbNull[] = {0x5, 0x0};
  5184. CRYPT_DATA_BLOB NullBlob = {sizeof(rgbNull), rgbNull};
  5185. if (!blobcmp(&NullBlob,
  5186. &pDecode->KeyEncryptionAlgorithm.Parameters))
  5187. PrintError("GetCmsRecipientInfoAndDecrypt::Expected NULL KeyEncryptionAlgorithm Parameters");
  5188. }
  5189. #endif
  5190. if (CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY !=
  5191. pDecode->dwOriginatorChoice)
  5192. PrintError("GetCmsRecipientInfoAndDecrypt::Bad dwOriginatorChoice");
  5193. else {
  5194. if (0 != strcmp(
  5195. pDecode->OriginatorPublicKeyInfo.Algorithm.pszObjId,
  5196. pEncode->pEphemeralAlgorithm->pszObjId))
  5197. PrintError("GetCmsRecipientInfoAndDecrypt::Bad Originator public key Algorithm");
  5198. if (0 != pDecode->OriginatorPublicKeyInfo.Algorithm.Parameters.cbData)
  5199. PrintError("GetCmsRecipientInfoAndDecrypt::Not NO Originator public key Parameters");
  5200. }
  5201. if (pEncode->cRecipientEncryptedKeys !=
  5202. pDecode->cRecipientEncryptedKeys)
  5203. PrintError("GetCmsRecipientInfoAndDecrypt::Bad Encrypted Key Agree Count");
  5204. else {
  5205. DWORD i;
  5206. for (i = 0; i < pEncode->cRecipientEncryptedKeys; i++) {
  5207. PCMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO pEncodeKey =
  5208. pEncode->rgpRecipientEncryptedKeys[i];
  5209. PCMSG_RECIPIENT_ENCRYPTED_KEY_INFO pDecodeKey =
  5210. pDecode->rgpRecipientEncryptedKeys[i];
  5211. if (pDecodeKey->RecipientId.dwIdChoice !=
  5212. pEncodeKey->RecipientId.dwIdChoice)
  5213. PrintError("GetCmsRecipientInfoAndDecrypt::Bad dwIdChoice");
  5214. else {
  5215. switch (pDecodeKey->RecipientId.dwIdChoice) {
  5216. case CERT_ID_ISSUER_SERIAL_NUMBER:
  5217. {
  5218. PCERT_ISSUER_SERIAL_NUMBER pDecodeRid =
  5219. &pDecodeKey->RecipientId.IssuerSerialNumber;
  5220. PCERT_ISSUER_SERIAL_NUMBER pEncodeRid =
  5221. &pEncodeKey->RecipientId.IssuerSerialNumber;
  5222. if (!blobcmp(&pDecodeRid->Issuer,
  5223. &pEncodeRid->Issuer) ||
  5224. !blobcmp(&pDecodeRid->SerialNumber,
  5225. &pEncodeRid->SerialNumber))
  5226. PrintError("GetCmsRecipientInfoAndDecrypt::Bad IssuerSerialNumber");
  5227. }
  5228. break;
  5229. case CERT_ID_KEY_IDENTIFIER:
  5230. {
  5231. PCRYPT_HASH_BLOB pDecodeRid =
  5232. &pDecodeKey->RecipientId.KeyId;
  5233. PCRYPT_HASH_BLOB pEncodeRid =
  5234. &pEncodeKey->RecipientId.KeyId;
  5235. if (!blobcmp(pDecodeRid, pEncodeRid))
  5236. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyId");
  5237. if (0 != CompareFileTime(&pDecodeKey->Date,
  5238. &pEncodeKey->Date))
  5239. PrintError("GetCmsRecipientInfoAndDecrypt::Bad Date");
  5240. if (NULL == pEncodeKey->pOtherAttr) {
  5241. if (NULL != pDecodeKey->pOtherAttr)
  5242. PrintError("GetCmsRecipientInfoAndDecrypt::Unexpected OtherAttr");
  5243. } else if (NULL == pDecodeKey->pOtherAttr) {
  5244. PrintError("GetCmsRecipientInfoAndDecrypt::Missing OtherAttr");
  5245. } else {
  5246. PCRYPT_ATTRIBUTE_TYPE_VALUE
  5247. pDecodeOther =
  5248. pDecodeKey->pOtherAttr;
  5249. PCRYPT_ATTRIBUTE_TYPE_VALUE
  5250. pEncodeOther =
  5251. pEncodeKey->pOtherAttr;
  5252. if (0 != strcmp(pDecodeOther->pszObjId,
  5253. pEncodeOther->pszObjId))
  5254. PrintError("GetCmsRecipientInfoAndDecrypt::Bad OtherAttr OID");
  5255. if (!blobcmp(&pDecodeOther->Value, &pEncodeOther->Value))
  5256. PrintError("GetCmsRecipientInfoAndDecrypt::Bad OtherAttr Value");
  5257. }
  5258. }
  5259. break;
  5260. default:
  5261. PrintError("GetCmsRecipientInfoAndDecrypt::Bad dwIdChoice");
  5262. }
  5263. }
  5264. }
  5265. }
  5266. }
  5267. break;
  5268. case CMSG_MAIL_LIST_RECIPIENT:
  5269. {
  5270. PCMSG_MAIL_LIST_RECIPIENT_INFO pDecode =
  5271. pRecipientInfo->pMailList;
  5272. PCMSG_MAIL_LIST_RECIPIENT_ENCODE_INFO pEncode =
  5273. &rgMailList[dwIndex];
  5274. if (CMSG_MAIL_LIST_VERSION != pDecode->dwVersion)
  5275. PrintError("GetCmsRecipientInfoAndDecrypt::Bad MailListVersion");
  5276. {
  5277. PCRYPT_HASH_BLOB pDecodeKeyId =
  5278. &pDecode->KeyId;
  5279. PCRYPT_HASH_BLOB pEncodeKeyId =
  5280. &pEncode->KeyId;
  5281. if (!blobcmp(pDecodeKeyId, pEncodeKeyId))
  5282. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyId");
  5283. }
  5284. if (0 != strcmp(pDecode->KeyEncryptionAlgorithm.pszObjId,
  5285. pEncode->KeyEncryptionAlgorithm.pszObjId))
  5286. PrintError("GetCmsRecipientInfoAndDecrypt::Bad KeyEncryptionAlgorithm");
  5287. if (0 == _stricmp(pszEncryptName, "rc2")) {
  5288. if (0 == pDecode->KeyEncryptionAlgorithm.Parameters.cbData)
  5289. PrintError("GetCmsRecipientInfoAndDecrypt::Missing rc2 KeyEncryptionAlgorithm Parameters");
  5290. else {
  5291. int iVersion;
  5292. DWORD cbData;
  5293. cbData = sizeof(iVersion);
  5294. if (!CryptDecodeObject(
  5295. PKCS_7_ASN_ENCODING,
  5296. X509_INTEGER,
  5297. pDecode->KeyEncryptionAlgorithm.Parameters.pbData,
  5298. pDecode->KeyEncryptionAlgorithm.Parameters.cbData,
  5299. 0, // dwFlags
  5300. &iVersion,
  5301. &cbData))
  5302. PrintLastError("GetCmsRecipientInfoAndDecrypt::CryptDecodeObject(rc2 KeyEncryptionAlgorithm Parameters)");
  5303. else {
  5304. DWORD dwEncodeBitLen;
  5305. DWORD dwDecodeBitLen;
  5306. dwEncodeBitLen = dwEncryptBitLen;
  5307. if (0 == dwEncodeBitLen)
  5308. dwEncodeBitLen = 40;
  5309. switch (iVersion) {
  5310. case CRYPT_RC2_40BIT_VERSION:
  5311. dwDecodeBitLen = 40;
  5312. break;
  5313. case CRYPT_RC2_56BIT_VERSION:
  5314. dwDecodeBitLen = 56;
  5315. break;
  5316. case CRYPT_RC2_64BIT_VERSION:
  5317. dwDecodeBitLen = 64;
  5318. break;
  5319. case CRYPT_RC2_128BIT_VERSION:
  5320. dwDecodeBitLen = 128;
  5321. break;
  5322. default:
  5323. dwDecodeBitLen = 0;
  5324. PrintError("GetCmsRecipientInfoAndDecrypt::Bad Decode BitLen");
  5325. }
  5326. if (dwDecodeBitLen != dwEncodeBitLen)
  5327. PrintError("GetCmsRecipientInfoAndDecrypt::Decode != Encode BitLen");
  5328. }
  5329. }
  5330. } else {
  5331. if (0 != pDecode->KeyEncryptionAlgorithm.Parameters.cbData)
  5332. PrintError("GetCmsRecipientInfoAndDecrypt::Expected NO, NULL KeyEncryptionAlgorithm Parameters");
  5333. }
  5334. if (0 != CompareFileTime(&pDecode->Date, &pEncode->Date))
  5335. PrintError("GetCmsRecipientInfoAndDecrypt::Bad Date");
  5336. if (NULL == pEncode->pOtherAttr) {
  5337. if (NULL != pDecode->pOtherAttr)
  5338. PrintError("GetCmsRecipientInfoAndDecrypt::Unexpected OtherAttr");
  5339. } else if (NULL == pDecode->pOtherAttr) {
  5340. PrintError("GetCmsRecipientInfoAndDecrypt::Missing OtherAttr");
  5341. } else {
  5342. PCRYPT_ATTRIBUTE_TYPE_VALUE pDecodeOther =
  5343. pDecode->pOtherAttr;
  5344. PCRYPT_ATTRIBUTE_TYPE_VALUE pEncodeOther =
  5345. pEncode->pOtherAttr;
  5346. if (0 != strcmp(pDecodeOther->pszObjId,
  5347. pEncodeOther->pszObjId))
  5348. PrintError("GetCmsRecipientInfoAndDecrypt::Bad OtherAttr OID");
  5349. if (!blobcmp(&pDecodeOther->Value, &pEncodeOther->Value))
  5350. PrintError("GetCmsRecipientInfoAndDecrypt::Bad OtherAttr Value");
  5351. }
  5352. }
  5353. break;
  5354. default:
  5355. PrintError( "GetCmsRecipientInfoAndDecrypt::Bad RecipientChoice");
  5356. goto ErrorReturn;
  5357. }
  5358. TestFree(pRecipientInfo);
  5359. pRecipientInfo = NULL;
  5360. }
  5361. pRecipientInfo = GetCmsRecipientFromMsg(hMsg, cRecipient -1);
  5362. if (pRecipientInfo == NULL) {
  5363. PrintLastError(
  5364. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_CMS_RECIPIENT_INFO_PARAM)");
  5365. goto ErrorReturn;
  5366. }
  5367. switch (pRecipientInfo->dwRecipientChoice) {
  5368. case CMSG_KEY_TRANS_RECIPIENT:
  5369. {
  5370. CMSG_CTRL_KEY_TRANS_DECRYPT_PARA DecryptPara;
  5371. DWORD dwDecryptIndex;
  5372. DecryptPara.cbSize = sizeof(DecryptPara);
  5373. DecryptPara.hCryptProv = hCryptProv;
  5374. DecryptPara.dwKeySpec = 0;
  5375. DecryptPara.pKeyTrans = pRecipientInfo->pKeyTrans;
  5376. DecryptPara.dwRecipientIndex = cRecipient -1;
  5377. fResult = CryptMsgControl(
  5378. hMsg,
  5379. 0, // dwFlags
  5380. CMSG_CTRL_KEY_TRANS_DECRYPT,
  5381. &DecryptPara
  5382. );
  5383. if (!fResult) {
  5384. PrintLastError(
  5385. "GetCmsRecipientInfoAndDecrypt::CryptMsgControl(CMSG_CTRL_KEY_TRANS_DECRYPT)");
  5386. goto ErrorReturn;
  5387. }
  5388. cbData = sizeof(dwDecryptIndex);
  5389. dwDecryptIndex = 0;
  5390. fResult = CryptMsgGetParam(
  5391. hMsg,
  5392. CMSG_CMS_RECIPIENT_INDEX_PARAM,
  5393. 0, // dwIndex
  5394. &dwDecryptIndex,
  5395. &cbData
  5396. );
  5397. if (!fResult)
  5398. PrintLastError(
  5399. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_CMS_RECIPIENT_INDEX_PARAM)");
  5400. else if (dwDecryptIndex != cRecipient -1)
  5401. PrintLastError(
  5402. "GetCmsRecipientInfoAndDecrypt::Bad CMS decrypt Index");
  5403. cbData = sizeof(dwDecryptIndex);
  5404. dwDecryptIndex = 0;
  5405. fResult = CryptMsgGetParam(
  5406. hMsg,
  5407. CMSG_RECIPIENT_INDEX_PARAM,
  5408. 0, // dwIndex
  5409. &dwDecryptIndex,
  5410. &cbData
  5411. );
  5412. if (!fResult)
  5413. PrintLastError(
  5414. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_RECIPIENT_INDEX_PARAM)");
  5415. else if (dwDecryptIndex != PkcsRecipientCount -1)
  5416. PrintLastError(
  5417. "GetCmsRecipientInfoAndDecrypt::Bad PKCS decrypt Index");
  5418. }
  5419. break;
  5420. case CMSG_KEY_AGREE_RECIPIENT:
  5421. {
  5422. CMSG_CTRL_KEY_AGREE_DECRYPT_PARA DecryptPara;
  5423. DWORD dwDecryptIndex;
  5424. DecryptPara.cbSize = sizeof(DecryptPara);
  5425. DecryptPara.hCryptProv = hKeyAgreeProv;
  5426. DecryptPara.dwKeySpec = AT_KEYEXCHANGE;
  5427. DecryptPara.pKeyAgree = pRecipientInfo->pKeyAgree;
  5428. DecryptPara.dwRecipientIndex = cRecipient -1;
  5429. DecryptPara.dwRecipientEncryptedKeyIndex =
  5430. pRecipientInfo->pKeyAgree->cRecipientEncryptedKeys -1;
  5431. DecryptPara.OriginatorPublicKey =
  5432. pRecipientInfo->pKeyAgree->OriginatorPublicKeyInfo.PublicKey;
  5433. fResult = CryptMsgControl(
  5434. hMsg,
  5435. 0, // dwFlags
  5436. CMSG_CTRL_KEY_AGREE_DECRYPT,
  5437. &DecryptPara
  5438. );
  5439. if (!fResult) {
  5440. PrintLastError(
  5441. "GetCmsRecipientInfoAndDecrypt::CryptMsgControl(CMSG_CTRL_KEY_AGREE_DECRYPT)");
  5442. goto ErrorReturn;
  5443. }
  5444. cbData = sizeof(dwDecryptIndex);
  5445. dwDecryptIndex = 0;
  5446. fResult = CryptMsgGetParam(
  5447. hMsg,
  5448. CMSG_CMS_RECIPIENT_INDEX_PARAM,
  5449. 0, // dwIndex
  5450. &dwDecryptIndex,
  5451. &cbData
  5452. );
  5453. if (!fResult)
  5454. PrintLastError(
  5455. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_CMS_RECIPIENT_INDEX_PARAM)");
  5456. else if (dwDecryptIndex != cRecipient -1)
  5457. PrintLastError(
  5458. "GetCmsRecipientInfoAndDecrypt::Bad CMS decrypt Index");
  5459. cbData = sizeof(dwDecryptIndex);
  5460. dwDecryptIndex = 0;
  5461. fResult = CryptMsgGetParam(
  5462. hMsg,
  5463. CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM,
  5464. 0, // dwIndex
  5465. &dwDecryptIndex,
  5466. &cbData
  5467. );
  5468. if (!fResult)
  5469. PrintLastError(
  5470. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM)");
  5471. else if (dwDecryptIndex != DecryptPara.dwRecipientEncryptedKeyIndex)
  5472. PrintLastError(
  5473. "GetCmsRecipientInfoAndDecrypt::Bad CMS encrypted key Index");
  5474. }
  5475. break;
  5476. case CMSG_MAIL_LIST_RECIPIENT:
  5477. {
  5478. CMSG_CTRL_MAIL_LIST_DECRYPT_PARA DecryptPara;
  5479. DWORD dwDecryptIndex;
  5480. DecryptPara.cbSize = sizeof(DecryptPara);
  5481. DecryptPara.pMailList = pRecipientInfo->pMailList;
  5482. DecryptPara.dwRecipientIndex = cRecipient -1;
  5483. DecryptPara.dwKeyChoice = CMSG_MAIL_LIST_HANDLE_KEY_CHOICE;
  5484. if (fRecipientProv)
  5485. DecryptPara.hCryptProv = GetCryptProv();
  5486. else
  5487. DecryptPara.hCryptProv = hCryptProv;
  5488. DecryptPara.hKeyEncryptionKey = GenerateMailListKey(
  5489. DecryptPara.hCryptProv,
  5490. &DecryptPara.pMailList->KeyId
  5491. );
  5492. printf("Decrypting using MailList recipient\n");
  5493. fResult = CryptMsgControl(
  5494. hMsg,
  5495. fRecipientProv ? CMSG_CRYPT_RELEASE_CONTEXT_FLAG : 0,
  5496. CMSG_CTRL_MAIL_LIST_DECRYPT,
  5497. &DecryptPara
  5498. );
  5499. if (DecryptPara.hKeyEncryptionKey) {
  5500. DWORD dwErr = GetLastError();
  5501. CryptDestroyKey(DecryptPara.hKeyEncryptionKey);
  5502. SetLastError(dwErr);
  5503. }
  5504. if (!fResult) {
  5505. PrintLastError(
  5506. "GetCmsRecipientInfoAndDecrypt::CryptMsgControl(CMSG_CTRL_MAIL_LIST_DECRYPT)");
  5507. goto ErrorReturn;
  5508. }
  5509. cbData = sizeof(dwDecryptIndex);
  5510. dwDecryptIndex = 0;
  5511. fResult = CryptMsgGetParam(
  5512. hMsg,
  5513. CMSG_CMS_RECIPIENT_INDEX_PARAM,
  5514. 0, // dwIndex
  5515. &dwDecryptIndex,
  5516. &cbData
  5517. );
  5518. if (!fResult)
  5519. PrintLastError(
  5520. "GetCmsRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_CMS_RECIPIENT_INDEX_PARAM)");
  5521. else if (dwDecryptIndex != cRecipient -1)
  5522. PrintLastError(
  5523. "GetCmsRecipientInfoAndDecrypt::Bad CMS decrypt Index");
  5524. }
  5525. break;
  5526. default:
  5527. PrintError("GetCmsRecipientInfoAndDecrypt::Bad RecipientChoice");
  5528. goto ErrorReturn;
  5529. }
  5530. CommonReturn:
  5531. TestFree(pRecipientInfo);
  5532. return fResult;
  5533. ErrorReturn:
  5534. fResult = FALSE;
  5535. goto CommonReturn;
  5536. PRINT_ERROR(GetCmsRecipientInfoAndDecrypt,CheckGetCmsRecipientCountError)
  5537. }
  5538. BOOL VerifyUnprotectedAttr(IN HCRYPTMSG hMsg)
  5539. {
  5540. BOOL fResult;
  5541. DWORD cbAttrs;
  5542. DWORD i;
  5543. PCRYPT_ATTRIBUTES pAttrs = NULL;
  5544. PCRYPT_ATTRIBUTE patr1;
  5545. PCRYPT_ATTRIBUTE patr2;
  5546. if (!TCM_AllocGetParam(
  5547. hMsg,
  5548. CMSG_UNPROTECTED_ATTR_PARAM,
  5549. 0, // dwIndex
  5550. (PBYTE *) &pAttrs,
  5551. &cbAttrs)) {
  5552. goto GetAttrError;
  5553. }
  5554. if (pAttrs->cAttr != EnvelopedMsgEncodeInfo.cUnprotectedAttr)
  5555. goto AttrCountError;
  5556. for (i=pAttrs->cAttr,
  5557. patr1=EnvelopedMsgEncodeInfo.rgUnprotectedAttr,
  5558. patr2=pAttrs->rgAttr;
  5559. i>0;
  5560. i--, patr1++, patr2++) {
  5561. if (!EqualAttribute( patr1, patr2))
  5562. goto AttrValueError;
  5563. }
  5564. fResult = TRUE;
  5565. CommonReturn:
  5566. TestFree(pAttrs);
  5567. return fResult;
  5568. ErrorReturn:
  5569. fResult = FALSE;
  5570. goto CommonReturn;
  5571. PRINT_ERROR(VerifyUnprotectedAttr,GetAttrError)
  5572. PRINT_ERROR(VerifyUnprotectedAttr,AttrCountError)
  5573. PRINT_ERROR(VerifyUnprotectedAttr,AttrValueError)
  5574. }
  5575. #endif // CMS_PKCS7
  5576. //+-------------------------------------------------------------------------
  5577. // Get recipient info and decrypt the message.
  5578. //--------------------------------------------------------------------------
  5579. BOOL GetRecipientInfoAndDecrypt(IN HCRYPTMSG hMsg)
  5580. {
  5581. BOOL fResult;
  5582. PCERT_INFO pRecipientInfo = NULL;
  5583. DWORD cRecipient;
  5584. DWORD cbData;
  5585. DWORD dwIndex;
  5586. CMSG_CTRL_DECRYPT_PARA DecryptPara;
  5587. #ifdef CMS_PKCS7
  5588. BYTE *pbCiphertext = NULL;
  5589. DWORD cbCiphertext;
  5590. #endif // CMS_PKCS7
  5591. DWORD cKeyIdRecipient;
  5592. // Get # of recipients in the message.
  5593. cbData = sizeof(cRecipient);
  5594. cRecipient = 0;
  5595. fResult = CryptMsgGetParam(
  5596. hMsg,
  5597. CMSG_RECIPIENT_COUNT_PARAM,
  5598. 0, // dwIndex
  5599. &cRecipient,
  5600. &cbData
  5601. );
  5602. if (!fResult) {
  5603. PrintLastError(
  5604. "GetRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_RECIPIENT_COUNT_PARAM)");
  5605. goto ErrorReturn;
  5606. }
  5607. if (!TCM_CheckGetParam(
  5608. hMsg,
  5609. CMSG_RECIPIENT_COUNT_PARAM,
  5610. 0, // dwIndex
  5611. &cRecipient,
  5612. cbData))
  5613. goto CheckGetRecipientCountError;
  5614. if (fNoRecipients
  5615. #ifdef CMS_PKCS7
  5616. || ((fMailList || fKeyAgree) && !fKeyTrans)
  5617. #endif // CMS_PKCS7
  5618. ) {
  5619. if (cRecipient != 0) {
  5620. PrintError("GetRecipientInfoAndDecrypt::cRecipient != 0");
  5621. goto ErrorReturn;
  5622. }
  5623. } else {
  5624. if (cRecipient != PkcsRecipientCount) {
  5625. PrintError("GetRecipientInfoAndDecrypt::cRecipient != PkcsRecipientCount");
  5626. goto ErrorReturn;
  5627. }
  5628. }
  5629. #ifdef CMS_PKCS7
  5630. if (fKeyTrans && fRecipientKeyId && !fNoRecipients) {
  5631. // The first RECIPIENT_COUNT recipients should be KeyId recipients
  5632. cKeyIdRecipient = RECIPIENT_COUNT;
  5633. // Get all the KeyId recipients and verify
  5634. for (dwIndex = 0; dwIndex < RECIPIENT_COUNT; dwIndex++) {
  5635. // Allocate and get the CERT_INFO containing the Special
  5636. // KeyId RecipientId
  5637. PCERT_NAME_INFO pKeyIdName = NULL;
  5638. DWORD cbKeyIdName;
  5639. CRYPT_HASH_BLOB KeyId;
  5640. pRecipientInfo = GetCertIdFromMsg(
  5641. hMsg,
  5642. CMSG_RECIPIENT_INFO_PARAM,
  5643. dwIndex
  5644. );
  5645. if (pRecipientInfo == NULL) {
  5646. PrintLastError(
  5647. "GetRecipientInfoAndDecrypt::CryptMsgGetParam(KEYID CMSG_RECIPIENT_INFO_PARAM)");
  5648. goto ErrorReturn;
  5649. }
  5650. if (pRecipientInfo->SerialNumber.cbData != 1 ||
  5651. *pRecipientInfo->SerialNumber.pbData != 0)
  5652. PrintError("GetRecipientInfoAndDecrypt::Bad KeyId SerialNumber");
  5653. // Decode the Issuer Name. It should contain the special KeyId
  5654. // RDN
  5655. if (AllocAndDecodeObject(
  5656. X509_NAME,
  5657. pRecipientInfo->Issuer.pbData,
  5658. pRecipientInfo->Issuer.cbData,
  5659. (void **) &pKeyIdName,
  5660. &cbKeyIdName
  5661. )) {
  5662. if (pKeyIdName->cRDN != 1 ||
  5663. pKeyIdName->rgRDN[0].cRDNAttr != 1)
  5664. PrintError("GetRecipientInfoAndDecrypt::Bad KeyId Issuer");
  5665. else {
  5666. PCERT_RDN_ATTR pAttr = pKeyIdName->rgRDN[0].rgRDNAttr;
  5667. if (0 != strcmp(pAttr->pszObjId, szOID_KEYID_RDN) ||
  5668. pAttr->dwValueType != CERT_RDN_OCTET_STRING ||
  5669. pAttr->Value.cbData !=
  5670. strlen(rgpszRecipientIssuerFileName[dwIndex]) ||
  5671. 0 != memcmp(pAttr->Value.pbData,
  5672. rgpszRecipientIssuerFileName[dwIndex],
  5673. pAttr->Value.cbData))
  5674. PrintError("GetRecipientInfoAndDecrypt::Bad KeyId Issuer");
  5675. }
  5676. TestFree(pKeyIdName);
  5677. }
  5678. if (!Asn1UtilExtractKeyIdFromCertInfo(
  5679. pRecipientInfo,
  5680. &KeyId))
  5681. PrintError("GetRecipientInfoAndDecrypt::Asn1UtilExtractKeyIdFromCertInfo failed");
  5682. else if (KeyId.cbData !=
  5683. strlen(rgpszRecipientIssuerFileName[dwIndex]) ||
  5684. 0 != memcmp(KeyId.pbData,
  5685. rgpszRecipientIssuerFileName[dwIndex], KeyId.cbData))
  5686. PrintError("GetRecipientInfoAndDecrypt::Asn1UtilExtractKeyIdFromCertInfo compare failed");
  5687. TestFree(pRecipientInfo);
  5688. pRecipientInfo = NULL;
  5689. }
  5690. } else
  5691. #endif // CMS_PKCS7
  5692. cKeyIdRecipient = 0;
  5693. // Get all the non KeyId recipients and verify
  5694. for (dwIndex = 0; dwIndex < cRecipient - cKeyIdRecipient; dwIndex++) {
  5695. // Allocate and get the CERT_INFO containing the RecipientId
  5696. // (Issuer and SerialNumber)
  5697. #ifdef CMS_PKCS7
  5698. CRYPT_HASH_BLOB KeyId;
  5699. BOOL fExtractKeyId;
  5700. #endif // CMS_PKCS7
  5701. pRecipientInfo = GetCertIdFromMsg(
  5702. hMsg,
  5703. CMSG_RECIPIENT_INFO_PARAM,
  5704. cKeyIdRecipient + dwIndex
  5705. );
  5706. if (pRecipientInfo == NULL) {
  5707. PrintLastError(
  5708. "GetRecipientInfoAndDecrypt::CryptMsgGetParam(CMSG_RECIPIENT_INFO_PARAM)");
  5709. goto ErrorReturn;
  5710. }
  5711. if (pRecipientInfo->Issuer.cbData !=
  5712. rgRecipientCertInfo[dwIndex].Issuer.cbData ||
  5713. memcmp(pRecipientInfo->Issuer.pbData,
  5714. rgRecipientCertInfo[dwIndex].Issuer.pbData,
  5715. pRecipientInfo->Issuer.cbData) != 0 ||
  5716. pRecipientInfo->SerialNumber.cbData !=
  5717. rgRecipientCertInfo[dwIndex].SerialNumber.cbData ||
  5718. memcmp(pRecipientInfo->SerialNumber.pbData,
  5719. rgRecipientCertInfo[dwIndex].SerialNumber.pbData,
  5720. pRecipientInfo->SerialNumber.cbData) != 0) {
  5721. PrintError("GetRecipientInfoAndDecrypt::Bad RecipientInfo");
  5722. }
  5723. #ifdef CMS_PKCS7
  5724. fExtractKeyId = Asn1UtilExtractKeyIdFromCertInfo(
  5725. pRecipientInfo,
  5726. &KeyId);
  5727. if (fCertInfoKeyId) {
  5728. if (!fExtractKeyId)
  5729. PrintError("GetRecipientInfoAndDecrypt::Asn1UtilExtractKeyIdFromCertInfo failed for CertInfoKeyId");
  5730. } else if (fExtractKeyId)
  5731. PrintError("GetRecipientInfoAndDecrypt::Asn1UtilExtractKeyIdFromCertInfo should have failed for nonKeyId");
  5732. #endif // CMS_PKCS7
  5733. TestFree(pRecipientInfo);
  5734. pRecipientInfo = NULL;
  5735. }
  5736. #ifdef CMS_PKCS7
  5737. if (fOriginatorInfo)
  5738. VerifyCerts(hMsg);
  5739. if (fAuthAttr)
  5740. VerifyUnprotectedAttr(hMsg);
  5741. // Get ciphertext
  5742. fResult = CryptMsgGetParam(
  5743. hMsg,
  5744. CMSG_CONTENT_PARAM,
  5745. 0, // dwIndex
  5746. NULL, // pvData
  5747. &cbCiphertext
  5748. );
  5749. if (!fResult)
  5750. PrintLastError("GetRecipientInfoAndDecrypt::CryptMsgGetParam(ciphertext length)");
  5751. else {
  5752. if (pbCiphertext = (BYTE *) TestAlloc(cbCiphertext)) {
  5753. fResult = CryptMsgGetParam(
  5754. hMsg,
  5755. CMSG_CONTENT_PARAM,
  5756. 0, // dwIndex
  5757. pbCiphertext,
  5758. &cbCiphertext
  5759. );
  5760. if (!fResult)
  5761. PrintLastError("GetRecipientInfoAndDecrypt::CryptMsgGetParam(ciphertext content)");
  5762. TestFree(pbCiphertext);
  5763. pbCiphertext = NULL;
  5764. }
  5765. }
  5766. if (fCmsRecipient) {
  5767. fResult = GetCmsRecipientInfoAndDecrypt(hMsg);
  5768. goto CommonReturn;
  5769. }
  5770. #endif // CMS_PKCS7
  5771. if (fNoRecipients) {
  5772. fResult = TRUE;
  5773. goto CommonReturn;
  5774. }
  5775. DecryptPara.cbSize = sizeof(DecryptPara);
  5776. DecryptPara.hCryptProv = hCryptProv;
  5777. DecryptPara.dwKeySpec = 0;
  5778. DecryptPara.dwRecipientIndex = RECIPIENT_COUNT -1;
  5779. fResult = CryptMsgControl(
  5780. hMsg,
  5781. 0, // dwFlags
  5782. CMSG_CTRL_DECRYPT,
  5783. &DecryptPara
  5784. );
  5785. if (!fResult) {
  5786. PrintLastError(
  5787. "GetRecipientInfoAndDecrypt::CryptMsgControl(CMSG_CTRL_DECRYPT)");
  5788. goto ErrorReturn;
  5789. }
  5790. goto CommonReturn;
  5791. ErrorReturn:
  5792. fResult = FALSE;
  5793. CommonReturn:
  5794. TestFree(pRecipientInfo);
  5795. return fResult;
  5796. PRINT_ERROR(GetRecipientInfoAndDecrypt,CheckGetRecipientCountError)
  5797. }
  5798. void CompareCertIdWithCertInfo(
  5799. IN PCERT_ID pCertId,
  5800. IN PCERT_INFO pCertInfo
  5801. )
  5802. {
  5803. BOOL fKeyId;
  5804. CRYPT_HASH_BLOB KeyId;
  5805. fKeyId = Asn1UtilExtractKeyIdFromCertInfo(pCertInfo, &KeyId);
  5806. switch(pCertId->dwIdChoice) {
  5807. case CERT_ID_ISSUER_SERIAL_NUMBER:
  5808. if (fKeyId)
  5809. printf("CompareCertIdWithCertInfo:: failed => bad IssuerSerialNumber choice\n");
  5810. else if (pCertInfo->Issuer.cbData !=
  5811. pCertId->IssuerSerialNumber.Issuer.cbData ||
  5812. 0 != memcmp(pCertInfo->Issuer.pbData,
  5813. pCertId->IssuerSerialNumber.Issuer.pbData,
  5814. pCertInfo->Issuer.cbData) ||
  5815. pCertInfo->SerialNumber.cbData !=
  5816. pCertId->IssuerSerialNumber.SerialNumber.cbData ||
  5817. 0 != memcmp(pCertInfo->SerialNumber.pbData,
  5818. pCertId->IssuerSerialNumber.SerialNumber.pbData,
  5819. pCertInfo->SerialNumber.cbData))
  5820. printf("CompareCertIdWithCertInfo:: failed => bad IssuerSerialNumber comparison\n");
  5821. break;
  5822. case CERT_ID_KEY_IDENTIFIER:
  5823. if (!fKeyId)
  5824. printf("CompareCertIdWithCertInfo:: failed => bad KeyId choice\n");
  5825. else if (KeyId.cbData != pCertId->KeyId.cbData ||
  5826. 0 != memcmp(KeyId.pbData,
  5827. pCertId->KeyId.pbData,
  5828. KeyId.cbData))
  5829. printf("CompareCertIdWithCertInfo:: failed => bad KeyId comparison\n");
  5830. break;
  5831. default:
  5832. printf("CompareCertIdWithCertInfo:: failed => invalid dwIdChoice\n");
  5833. break;
  5834. }
  5835. }
  5836. //+-------------------------------------------------------------------------
  5837. // Allocate and get the CMSG_SIGNER_INFO_PARAM from the message
  5838. //--------------------------------------------------------------------------
  5839. PCMSG_SIGNER_INFO GetSignerInfoFromMsg(
  5840. IN HCRYPTMSG hMsg,
  5841. IN DWORD dwIndex
  5842. )
  5843. {
  5844. PCMSG_SIGNER_INFO psi;
  5845. DWORD cbData;
  5846. if (!TCM_AllocGetParam(
  5847. hMsg,
  5848. CMSG_SIGNER_INFO_PARAM,
  5849. dwIndex,
  5850. (PBYTE *)&psi,
  5851. &cbData))
  5852. return NULL;
  5853. #ifdef CMS_PKCS7
  5854. PCMSG_CMS_SIGNER_INFO pCMSsi;
  5855. if (TCM_AllocGetParam(
  5856. hMsg,
  5857. CMSG_CMS_SIGNER_INFO_PARAM,
  5858. dwIndex,
  5859. (PBYTE *)&pCMSsi,
  5860. &cbData)) {
  5861. CERT_INFO CertInfo;
  5862. CertInfo.Issuer = psi->Issuer;
  5863. CertInfo.SerialNumber = psi->SerialNumber;
  5864. CompareCertIdWithCertInfo(&pCMSsi->SignerId, &CertInfo);
  5865. TestFree(pCMSsi);
  5866. }
  5867. #endif // CMS_PKCS7
  5868. return psi;
  5869. }
  5870. //+-------------------------------------------------------------------------
  5871. // Allocate and get the CMSG_SIGNER_CERT_INFO_PARAM or CMSG_RECIPIENT_INFO_PARAM
  5872. // from the message
  5873. //--------------------------------------------------------------------------
  5874. PCERT_INFO GetCertIdFromMsg(
  5875. IN HCRYPTMSG hMsg,
  5876. IN DWORD dwParamType,
  5877. IN DWORD dwIndex
  5878. )
  5879. {
  5880. PCERT_INFO pCertId;
  5881. DWORD cbData;
  5882. if (!TCM_AllocGetParam(
  5883. hMsg,
  5884. dwParamType,
  5885. dwIndex,
  5886. (PBYTE *)&pCertId,
  5887. &cbData))
  5888. return NULL;
  5889. #ifdef CMS_PKCS7
  5890. if (CMSG_SIGNER_CERT_INFO_PARAM == dwParamType) {
  5891. PCERT_ID pSignerId;
  5892. if (TCM_AllocGetParam(
  5893. hMsg,
  5894. CMSG_SIGNER_CERT_ID_PARAM,
  5895. dwIndex,
  5896. (PBYTE *)&pSignerId,
  5897. &cbData)) {
  5898. CompareCertIdWithCertInfo(pSignerId, pCertId);
  5899. TestFree(pSignerId);
  5900. }
  5901. }
  5902. #endif // CMS_PKCS7
  5903. return pCertId;
  5904. }
  5905. //+-------------------------------------------------------------------------
  5906. // Get computed digest and digest data from a decoded CMSG_HASHED
  5907. //--------------------------------------------------------------------------
  5908. BOOL Undigest(IN HCRYPTMSG hMsg)
  5909. {
  5910. return CryptMsgControl( hMsg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
  5911. }