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.

1991 lines
70 KiB

  1. #ifdef SMIME_V3
  2. #include <windows.h>
  3. //#include "oss\global.hxx"
  4. //#include "oss\ossconv.h"
  5. #include "mimeole.h"
  6. #include "badstrfunctions.h"
  7. extern "C" {
  8. #include "ess.h"
  9. }
  10. #include "essOut.h"
  11. #include "pkiasn1.h"
  12. #include "crypttls.h"
  13. #include "msoert.h"
  14. #include "demand2.h"
  15. #define wcslen my_wcslen
  16. extern int my_wcslen(LPCWSTR pwsz);
  17. //
  18. //
  19. HCRYPTASN1MODULE ICM_hAsn1Module;
  20. typedef struct {
  21. LPSTR szOID;
  22. LPSTR szFunc;
  23. } OIDFunction;
  24. static const OIDFunction EssEncodeExFuncTable[] = {
  25. {szOID_SMIME_Content_Hints, "EssContentHintEncodeEx"},
  26. {szOID_SMIME_Receipt_Request, "EssReceiptRequestEncodeEx"},
  27. {szOID_SMIME_ContentType_Receipt, "EssReceiptEncodeEx"},
  28. {szOID_SMIME_Security_Label, "EssSecurityLabelEncodeEx"},
  29. {szOID_SMIME_MLExpansion_History, "EssMLHistoryEncodeEx"},
  30. {szOID_SMIME_Encryption_Key_Preference, "EssKeyExchPreferenceEncodeEx"},
  31. {szOID_SMIME_Signing_Certificate, "EssSignCertificateEncodeEx"},
  32. };
  33. const int EssEncodeExFuncCount = (sizeof(EssEncodeExFuncTable)/
  34. sizeof(EssEncodeExFuncTable[0]));
  35. static const OIDFunction EssDecodeExFuncTable[] = {
  36. {szOID_SMIME_Content_Hints, "EssContentHintDecodeEx"},
  37. {szOID_SMIME_Receipt_Request, "EssReceiptRequestDecodeEx"},
  38. {szOID_SMIME_ContentType_Receipt, "EssReceiptDecodeEx"},
  39. {szOID_SMIME_Security_Label, "EssSecurityLabelDecodeEx"},
  40. {szOID_SMIME_MLExpansion_History, "EssMLHistoryDecodeEx"},
  41. {szOID_SMIME_Encryption_Key_Preference, "EssKeyExchPreferenceDecodeEx"},
  42. {szOID_SMIME_Signing_Certificate, "EssSignCertificateDecodeEx"},
  43. };
  44. const int EssDecodeExFuncCount = (sizeof(EssDecodeExFuncTable)/
  45. sizeof(EssDecodeExFuncTable[0]));
  46. STDAPI EssRegisterServer(void)
  47. {
  48. HRESULT hr;
  49. int i;
  50. // M00BUG -- need to put in a path for inetcomm.dll!!!!!
  51. for (i=0; i<EssEncodeExFuncCount; i++) {
  52. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  53. CRYPT_OID_ENCODE_OBJECT_EX_FUNC,
  54. EssEncodeExFuncTable[i].szOID,
  55. L"inetcomm.dll",
  56. EssEncodeExFuncTable[i].szFunc)) {
  57. goto InstallError;
  58. }
  59. }
  60. for (i=0; i<EssDecodeExFuncCount; i++) {
  61. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  62. CRYPT_OID_DECODE_OBJECT_EX_FUNC,
  63. EssDecodeExFuncTable[i].szOID,
  64. L"inetcomm.dll",
  65. EssDecodeExFuncTable[i].szFunc)) {
  66. goto InstallError;
  67. }
  68. }
  69. hr = S_OK;
  70. CommonReturn:
  71. return hr;
  72. InstallError:
  73. hr = E_FAIL;
  74. goto CommonReturn;
  75. }
  76. STDAPI EssUnRegisterServer(void)
  77. {
  78. return S_OK;
  79. }
  80. BOOL WINAPI
  81. EssASNDllMain(HMODULE hInst, ULONG ulReason, LPVOID lpv)
  82. {
  83. BOOL fRet;
  84. switch (ulReason) {
  85. case DLL_PROCESS_ATTACH:
  86. ESS_InitDemandLoadLibs();
  87. break;
  88. case DLL_PROCESS_DETACH:
  89. if (ICM_hAsn1Module != NULL) {
  90. I_CryptUninstallAsn1Module(ICM_hAsn1Module);
  91. ESS_Module_Cleanup();
  92. }
  93. ESS_FreeDemandLoadLibs();
  94. break;
  95. }
  96. fRet = TRUE;
  97. return fRet;
  98. }
  99. #if 0
  100. ///////////////////////////////// STOLEN FUNCTIONS ///////////////////////////
  101. //
  102. // The following functions were taken from the wincert.cpp file in the
  103. // ISPU tree. If possible we should get these exported from crypt32.
  104. //
  105. ///////////////////////////////////////////////////////////////////////////////
  106. #define INFO_LEN_ALIGN(a) a
  107. //+-------------------------------------------------------------------------
  108. // Set/Get Encoded Object Identifier string
  109. //--------------------------------------------------------------------------
  110. //+-------------------------------------------------------------------------
  111. // Set/Get Object Identifier string
  112. //--------------------------------------------------------------------------
  113. static BOOL OssX509SetObjId(
  114. IN LPCSTR pszObjId,
  115. OUT ObjectID *pOss
  116. )
  117. {
  118. pOss->count = sizeof(pOss->value) / sizeof(pOss->value[0]);
  119. if (OssConvToObjectIdentifier(pszObjId, &pOss->count, pOss->value))
  120. return TRUE;
  121. else {
  122. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  123. return FALSE;
  124. }
  125. }
  126. static void OssX509GetObjId(
  127. IN ObjectID *pOss,
  128. IN DWORD dwFlags,
  129. OUT LPSTR *ppszObjId,
  130. IN OUT BYTE **ppbExtra,
  131. IN OUT LONG *plRemainExtra
  132. )
  133. {
  134. LONG lRemainExtra = *plRemainExtra;
  135. BYTE *pbExtra = *ppbExtra;
  136. LONG lAlignExtra;
  137. DWORD cbObjId;
  138. cbObjId = lRemainExtra > 0 ? lRemainExtra : 0;
  139. OssConvFromObjectIdentifier(
  140. pOss->count,
  141. pOss->value,
  142. (LPSTR) pbExtra,
  143. &cbObjId
  144. );
  145. lAlignExtra = INFO_LEN_ALIGN(cbObjId);
  146. lRemainExtra -= lAlignExtra;
  147. if (lRemainExtra >= 0) {
  148. if(cbObjId) {
  149. *ppszObjId = (LPSTR) pbExtra;
  150. } else
  151. *ppszObjId = NULL;
  152. pbExtra += lAlignExtra;
  153. }
  154. *plRemainExtra = lRemainExtra;
  155. *ppbExtra = pbExtra;
  156. }
  157. //#define OssX509SetEncodedObjId(pszObjId, pOss) \
  158. // I_CryptSetOssEncodedOID(pszObjId, (OssEncodedOID *) (pOss))
  159. //#define OssX509GetEncodedObjId(pOss, dwFlags, \
  160. // ppszObjId, ppbExtra, plRemainExtra) \
  161. // I_CryptGetOssEncodedOID((OssEncodedOID *) (pOss), dwFlags, \
  162. // ppszObjId, ppbExtra, plRemainExtra)
  163. //+-------------------------------------------------------------------------
  164. // Set/Get "Any" DER BLOB
  165. //--------------------------------------------------------------------------
  166. inline void OssX509SetAny(
  167. IN PCRYPT_OBJID_BLOB pInfo,
  168. OUT NOCOPYANY *pOss
  169. )
  170. {
  171. OssUtilSetAny(pInfo, (OpenType *) pOss);
  172. }
  173. inline void OssX509GetAny(
  174. IN NOCOPYANY *pOss,
  175. IN DWORD dwFlags,
  176. OUT PCRYPT_OBJID_BLOB pInfo,
  177. IN OUT BYTE **ppbExtra,
  178. IN OUT LONG *plRemainExtra
  179. )
  180. {
  181. OssUtilGetAny((OpenType *) pOss, dwFlags, pInfo, ppbExtra, plRemainExtra);
  182. }
  183. //+-------------------------------------------------------------------------
  184. // Set/Get CRYPT_DATA_BLOB (Octet String)
  185. //--------------------------------------------------------------------------
  186. inline void OssX509SetOctetString(
  187. IN PCRYPT_DATA_BLOB pInfo,
  188. OUT OCTETSTRING *pOss
  189. )
  190. {
  191. pOss->value = pInfo->pbData;
  192. pOss->length = pInfo->cbData;
  193. }
  194. inline void OssX509GetOctetString(
  195. IN OCTETSTRING *pOss,
  196. IN DWORD dwFlags,
  197. OUT PCRYPT_DATA_BLOB pInfo,
  198. IN OUT BYTE **ppbExtra,
  199. IN OUT LONG *plRemainExtra
  200. )
  201. {
  202. OssUtilGetOctetString(pOss->length, pOss->value, dwFlags,
  203. pInfo, ppbExtra, plRemainExtra);
  204. }
  205. #if 0
  206. //+-------------------------------------------------------------------------
  207. // Set/Free/Get CERT_ALT_NAME_ENTRY
  208. //--------------------------------------------------------------------------
  209. BOOL OssX509SetAltNameEntry(
  210. IN PCERT_ALT_NAME_ENTRY pInfo,
  211. OUT GeneralName *pOss,
  212. IN DWORD dwEntryIndex,
  213. OUT DWORD *pdwErrLocation
  214. )
  215. {
  216. BOOL fResult;
  217. // Assumption: OSS choice == dwAltNameChoice
  218. // OssX509GetAltNameEntry has asserts to verify
  219. pOss->choice = (unsigned short) pInfo->dwAltNameChoice;
  220. *pdwErrLocation = 0;
  221. switch (pInfo->dwAltNameChoice) {
  222. case CERT_ALT_NAME_OTHER_NAME:
  223. if (!OssX509SetEncodedObjId(pInfo->pOtherName->pszObjId,
  224. &pOss->u.otherName.type))
  225. goto ErrorReturn;
  226. OssX509SetAny(&pInfo->pOtherName->Value, &pOss->u.otherName.value);
  227. break;
  228. case CERT_ALT_NAME_DIRECTORY_NAME:
  229. OssX509SetAny(&pInfo->DirectoryName, &pOss->u.directoryName);
  230. break;
  231. case CERT_ALT_NAME_RFC822_NAME:
  232. case CERT_ALT_NAME_DNS_NAME:
  233. case CERT_ALT_NAME_URL:
  234. if (!OssX509SetUnicodeConvertedToIA5(pInfo->pwszRfc822Name,
  235. &pOss->u.rfc822Name, dwEntryIndex, pdwErrLocation))
  236. goto ErrorReturn;
  237. break;
  238. case CERT_ALT_NAME_IP_ADDRESS:
  239. OssX509SetOctetString(&pInfo->IPAddress, &pOss->u.iPAddress);
  240. break;
  241. case CERT_ALT_NAME_REGISTERED_ID:
  242. if (!OssX509SetEncodedObjId(pInfo->pszRegisteredID, &pOss->u.registeredID))
  243. goto ErrorReturn;
  244. break;
  245. case CERT_ALT_NAME_X400_ADDRESS:
  246. case CERT_ALT_NAME_EDI_PARTY_NAME:
  247. default:
  248. SetLastError((DWORD) E_INVALIDARG);
  249. goto ErrorReturn;
  250. }
  251. fResult = TRUE;
  252. CommonReturn:
  253. return fResult;
  254. ErrorReturn:
  255. fResult = FALSE;
  256. goto CommonReturn;
  257. }
  258. void OssX509FreeAltNameEntry(
  259. IN GeneralName *pOss
  260. )
  261. {
  262. switch (pOss->choice) {
  263. case CERT_ALT_NAME_RFC822_NAME:
  264. case CERT_ALT_NAME_DNS_NAME:
  265. case CERT_ALT_NAME_URL:
  266. OssX509FreeUnicodeConvertedToIA5(&pOss->u.rfc822Name);
  267. break;
  268. default:
  269. break;
  270. }
  271. }
  272. BOOL OssX509GetAltNameEntry(
  273. IN GeneralName *pOss,
  274. IN DWORD dwFlags,
  275. OUT PCERT_ALT_NAME_ENTRY pInfo,
  276. IN OUT BYTE **ppbExtra,
  277. IN OUT LONG *plRemainExtra
  278. )
  279. {
  280. DWORD dwAltNameChoice;
  281. assert(otherName_chosen == CERT_ALT_NAME_OTHER_NAME);
  282. assert(rfc822Name_chosen == CERT_ALT_NAME_RFC822_NAME);
  283. assert(dNSName_chosen == CERT_ALT_NAME_DNS_NAME);
  284. assert(x400Address_chosen == CERT_ALT_NAME_X400_ADDRESS);
  285. assert(directoryName_chosen == CERT_ALT_NAME_DIRECTORY_NAME);
  286. assert(ediPartyName_chosen == CERT_ALT_NAME_EDI_PARTY_NAME);
  287. assert(uniformResourceLocator_chosen == CERT_ALT_NAME_URL);
  288. assert(iPAddress_chosen == CERT_ALT_NAME_IP_ADDRESS);
  289. assert(registeredID_chosen == CERT_ALT_NAME_REGISTERED_ID);
  290. dwAltNameChoice = pOss->choice;
  291. if (*plRemainExtra >= 0)
  292. pInfo->dwAltNameChoice = dwAltNameChoice;
  293. switch (dwAltNameChoice) {
  294. case CERT_ALT_NAME_OTHER_NAME:
  295. {
  296. LONG lAlignExtra;
  297. PCERT_OTHER_NAME pOtherName;
  298. lAlignExtra = INFO_LEN_ALIGN(sizeof(CERT_OTHER_NAME));
  299. *plRemainExtra -= lAlignExtra;
  300. if (*plRemainExtra >= 0) {
  301. pOtherName = (PCERT_OTHER_NAME) *ppbExtra;
  302. pInfo->pOtherName = pOtherName;
  303. *ppbExtra += lAlignExtra;
  304. } else
  305. pOtherName = NULL;
  306. OssX509GetEncodedObjId(&pOss->u.otherName.type, dwFlags,
  307. &pOtherName->pszObjId, ppbExtra, plRemainExtra);
  308. OssX509GetAny(&pOss->u.otherName.value, dwFlags,
  309. &pOtherName->Value, ppbExtra, plRemainExtra);
  310. }
  311. break;
  312. case CERT_ALT_NAME_DIRECTORY_NAME:
  313. OssX509GetAny(&pOss->u.directoryName, dwFlags,
  314. &pInfo->DirectoryName, ppbExtra, plRemainExtra);
  315. break;
  316. case CERT_ALT_NAME_RFC822_NAME:
  317. case CERT_ALT_NAME_DNS_NAME:
  318. case CERT_ALT_NAME_URL:
  319. OssX509GetIA5ConvertedToUnicode(&pOss->u.rfc822Name, dwFlags,
  320. &pInfo->pwszRfc822Name, ppbExtra, plRemainExtra);
  321. break;
  322. case CERT_ALT_NAME_IP_ADDRESS:
  323. OssX509GetOctetString(&pOss->u.iPAddress, dwFlags,
  324. &pInfo->IPAddress, ppbExtra, plRemainExtra);
  325. break;
  326. case CERT_ALT_NAME_REGISTERED_ID:
  327. OssX509GetEncodedObjId(&pOss->u.registeredID, dwFlags,
  328. &pInfo->pszRegisteredID, ppbExtra, plRemainExtra);
  329. break;
  330. case CERT_ALT_NAME_X400_ADDRESS:
  331. case CERT_ALT_NAME_EDI_PARTY_NAME:
  332. break;
  333. default:
  334. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  335. return FALSE;
  336. }
  337. return TRUE;
  338. }
  339. //+-------------------------------------------------------------------------
  340. // Set/Free/Get CERT_ALT_NAME_INFO
  341. //--------------------------------------------------------------------------
  342. BOOL OssX509SetAltNames(
  343. IN PCERT_ALT_NAME_INFO pInfo,
  344. OUT AltNames *pOss,
  345. IN DWORD dwIndex,
  346. OUT DWORD *pdwErrLocation
  347. )
  348. {
  349. BOOL fResult;
  350. DWORD i;
  351. DWORD cEntry;
  352. PCERT_ALT_NAME_ENTRY pEntry;
  353. GeneralName *pOssEntry;
  354. *pdwErrLocation = 0;
  355. cEntry = pInfo->cAltEntry;
  356. pEntry = pInfo->rgAltEntry;
  357. pOss->count = cEntry;
  358. pOss->value = NULL;
  359. if (cEntry > 0) {
  360. pOssEntry =
  361. (GeneralName *) PkiZeroAlloc(cEntry * sizeof(GeneralName));
  362. if (pOssEntry == NULL)
  363. goto ErrorReturn;
  364. pOss->value = pOssEntry;
  365. }
  366. // Array of AltName entries
  367. for (i = 0; i < cEntry; i++, pEntry++, pOssEntry++) {
  368. if (!OssX509SetAltNameEntry(pEntry, pOssEntry,
  369. (dwIndex << 8) | i, pdwErrLocation))
  370. goto ErrorReturn;
  371. }
  372. fResult = TRUE;
  373. CommonReturn:
  374. return fResult;
  375. ErrorReturn:
  376. fResult = FALSE;
  377. goto CommonReturn;
  378. }
  379. void OssX509FreeAltNames(
  380. OUT AltNames *pOss
  381. )
  382. {
  383. if (pOss->value) {
  384. DWORD cEntry = pOss->count;
  385. GeneralName *pOssEntry = pOss->value;
  386. for ( ; cEntry > 0; cEntry--, pOssEntry++)
  387. OssX509FreeAltNameEntry(pOssEntry);
  388. PkiFree(pOss->value);
  389. }
  390. }
  391. BOOL OssX509GetAltNames(
  392. IN AltNames *pOss,
  393. IN DWORD dwFlags,
  394. OUT PCERT_ALT_NAME_INFO pInfo,
  395. IN OUT BYTE **ppbExtra,
  396. IN OUT LONG *plRemainExtra
  397. )
  398. {
  399. LONG lAlignExtra;
  400. DWORD cEntry;
  401. PCERT_ALT_NAME_ENTRY pEntry;
  402. GeneralName *pOssEntry;
  403. cEntry = pOss->count;
  404. lAlignExtra = INFO_LEN_ALIGN(cEntry * sizeof(CERT_ALT_NAME_ENTRY));
  405. *plRemainExtra -= lAlignExtra;
  406. if (*plRemainExtra >= 0) {
  407. pInfo->cAltEntry = cEntry;
  408. pEntry = (PCERT_ALT_NAME_ENTRY) *ppbExtra;
  409. pInfo->rgAltEntry = pEntry;
  410. *ppbExtra += lAlignExtra;
  411. } else
  412. pEntry = NULL;
  413. // Array of AltName entries
  414. pOssEntry = pOss->value;
  415. for (; cEntry > 0; cEntry--, pEntry++, pOssEntry++) {
  416. if (!OssX509GetAltNameEntry(pOssEntry, dwFlags,
  417. pEntry, ppbExtra, plRemainExtra))
  418. return FALSE;
  419. }
  420. return TRUE;
  421. }
  422. #endif // 0
  423. //+-------------------------------------------------------------------------
  424. // Function: GetPog
  425. //
  426. // Synopsis: Initialize thread local storage for the asn libs
  427. //
  428. // Returns: pointer to an initialized OssGlobal data structure
  429. //--------------------------------------------------------------------------
  430. static inline POssGlobal GetPog(void)
  431. {
  432. return I_CryptGetOssGlobal(hX509OssGlobal);
  433. }
  434. #endif // 0
  435. //+-------------------------------------------------------------------------
  436. // Function: GetEncoder/GetDecoder
  437. //
  438. // Synopsis: Initialize thread local storage for the asn libs
  439. //
  440. // Returns: pointer to an initialized Asn1 encoder/decoder data
  441. // structures
  442. //--------------------------------------------------------------------------
  443. static inline ASN1encoding_t GetEncoder(void)
  444. {
  445. if (ICM_hAsn1Module == NULL) {
  446. ESS_Module_Startup();
  447. if (0 == (ICM_hAsn1Module = I_CryptInstallAsn1Module(ESS_Module, 0, NULL))) {
  448. return NULL;
  449. }
  450. }
  451. return I_CryptGetAsn1Encoder(ICM_hAsn1Module);
  452. }
  453. static inline ASN1decoding_t GetDecoder(void)
  454. {
  455. if (ICM_hAsn1Module == NULL) {
  456. ESS_Module_Startup();
  457. if (0 == (ICM_hAsn1Module = I_CryptInstallAsn1Module(ESS_Module, 0, NULL))) {
  458. return NULL;
  459. }
  460. }
  461. return I_CryptGetAsn1Decoder(ICM_hAsn1Module);
  462. }
  463. //+-------------------------------------------------------------------------
  464. // Encode an OSS formatted info structure
  465. //
  466. // Called by the OssX509*Encode() functions.
  467. //--------------------------------------------------------------------------
  468. static BOOL OssInfoEncodeEx(
  469. IN int pdunum,
  470. IN void *pvOssInfo,
  471. IN DWORD dwFlags,
  472. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  473. OUT OPTIONAL void *pvEncoded,
  474. IN OUT DWORD *pcbEncoded
  475. )
  476. {
  477. return PkiAsn1EncodeInfoEx(GetEncoder(), pdunum, pvOssInfo, dwFlags,
  478. pEncodePara, pvEncoded, pcbEncoded);
  479. }
  480. //+-------------------------------------------------------------------------
  481. // Decode into an OSS formatted info structure. Call the callback
  482. // function to convert into the 'C' data structure. If
  483. // CRYPT_DECODE_ALLOC_FLAG is set, call the callback twice. First,
  484. // to get the length of the 'C' data structure. Then after allocating,
  485. // call again to update the 'C' data structure.
  486. //
  487. // Called by the OssX509*Decode() functions.
  488. //--------------------------------------------------------------------------
  489. static BOOL OssInfoDecodeAndAllocEx(
  490. IN int pdunum,
  491. IN const BYTE *pbEncoded,
  492. IN DWORD cbEncoded,
  493. IN DWORD dwFlags,
  494. IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  495. IN PFN_PKI_ASN1_DECODE_EX_CALLBACK pfnDecodeExCallback,
  496. OUT OPTIONAL void *pvStructInfo,
  497. IN OUT DWORD *pcbStructInfo
  498. )
  499. {
  500. return PkiAsn1DecodeAndAllocInfoEx(
  501. GetDecoder(),
  502. pdunum,
  503. pbEncoded,
  504. cbEncoded,
  505. dwFlags,
  506. pDecodePara,
  507. pfnDecodeExCallback,
  508. pvStructInfo,
  509. pcbStructInfo
  510. );
  511. }
  512. //+-------------------------------------------------------------------------
  513. // Set/Get "Any" DER BLOB
  514. //--------------------------------------------------------------------------
  515. inline void OssX509SetAny(
  516. IN PCRYPT_OBJID_BLOB pInfo,
  517. OUT NOCOPYANY *pOss
  518. )
  519. {
  520. PkiAsn1SetAny(pInfo, pOss);
  521. }
  522. inline void OssX509GetAny(
  523. IN NOCOPYANY *pOss,
  524. IN DWORD dwFlags,
  525. OUT PCRYPT_OBJID_BLOB pInfo,
  526. IN OUT BYTE **ppbExtra,
  527. IN OUT LONG *plRemainExtra
  528. )
  529. {
  530. PkiAsn1GetAny(pOss, dwFlags, pInfo, ppbExtra, plRemainExtra);
  531. }
  532. //+-------------------------------------------------------------------------
  533. // Set/Get CRYPT_DATA_BLOB (Octet String)
  534. //--------------------------------------------------------------------------
  535. inline void OssX509SetOctetString(
  536. IN PCRYPT_DATA_BLOB pInfo,
  537. OUT OCTETSTRING *pOss
  538. )
  539. {
  540. pOss->value = pInfo->pbData;
  541. pOss->length = pInfo->cbData;
  542. }
  543. inline void OssX509GetOctetString(
  544. IN OCTETSTRING *pOss,
  545. IN DWORD dwFlags,
  546. OUT PCRYPT_DATA_BLOB pInfo,
  547. IN OUT BYTE **ppbExtra,
  548. IN OUT LONG *plRemainExtra
  549. )
  550. {
  551. PkiAsn1GetOctetString(pOss, dwFlags,
  552. pInfo, ppbExtra, plRemainExtra);
  553. }
  554. #define OssX509SetEncodedObjId(pszObjId, pOss) \
  555. PkiAsn1ToObjectIdentifier(pszObjId, &(pOss)->count, (pOss)->value)
  556. // I_CryptSetEncodedOID(pszObjId, pOss)
  557. #define OssX509GetEncodedObjId(pOss, dwFlags, \
  558. ppszObjId, ppbExtra, plRemainExtra) \
  559. PkiAsn1FromObjectIdentifier((pOss)->count, (pOss)->value, \
  560. ppszObjId, ppbExtra, plRemainExtra)
  561. // I_CryptGetEncodedOID(pOss, dwFlags, \
  562. // ppszObjId, ppbExtra, plRemainExtra)
  563. BOOL
  564. WINAPI
  565. I_CryptSetEncodedOID(
  566. IN LPSTR pszObjId,
  567. OUT ASN1encodedOID_t *pEncodedOid
  568. );
  569. void I_CryptGetEncodedOID(
  570. IN ASN1encodedOID_t *pEncodedOid,
  571. IN DWORD dwFlags,
  572. OUT LPSTR *ppszObjId,
  573. IN OUT BYTE **ppbExtra,
  574. IN OUT LONG *plRemainExtra
  575. );
  576. inline BOOL
  577. WINAPI
  578. PkiAsn1SetUTF8String(LPCWSTR pwsz, ASN1wstring_t * pAsn1String)
  579. {
  580. pAsn1String->length = my_wcslen(pwsz);
  581. pAsn1String->value = (LPWSTR) pwsz;
  582. return TRUE;
  583. }
  584. //+-------------------------------------------------------------------------
  585. // Get UTF8 String
  586. //--------------------------------------------------------------------------
  587. void
  588. WINAPI
  589. PkiAsn1GetUTF8String(
  590. IN ASN1wstring_t *putf8String,
  591. IN DWORD dwFlags,
  592. OUT LPWSTR *pwszPrivacyMark,
  593. IN OUT BYTE **ppbExtra,
  594. IN OUT LONG *plRemainExtra
  595. )
  596. {
  597. LONG lRemainExtra = *plRemainExtra;
  598. ULONG ulSize = putf8String->length * sizeof(WCHAR);
  599. lRemainExtra -= (sizeof(WCHAR) + ulSize);
  600. if (lRemainExtra < 0) {
  601. ;
  602. }
  603. else {
  604. LPBYTE pbExtra = *ppbExtra;
  605. *pwszPrivacyMark = (LPWSTR) pbExtra;
  606. memcpy(pbExtra, putf8String->value, ulSize);
  607. pbExtra += ulSize;
  608. (* ((LPWSTR) pbExtra) ) = '\0'; // null terminate the wsz.
  609. pbExtra += sizeof(WCHAR);
  610. *ppbExtra = pbExtra;
  611. }
  612. *plRemainExtra = lRemainExtra;
  613. }
  614. #define OssX509GetEncodedUTF8String(putf8String, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra) \
  615. PkiAsn1GetUTF8String(putf8String, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra)
  616. //+-------------------------------------------------------------------------
  617. // Get PString
  618. //--------------------------------------------------------------------------
  619. void
  620. WINAPI
  621. PkiAsn1GetPString(
  622. IN ASN1ztcharstring_t *pPString,
  623. IN DWORD dwFlags,
  624. OUT LPWSTR *pwszPrivacyMark,
  625. IN OUT BYTE **ppbExtra,
  626. IN OUT LONG *plRemainExtra
  627. )
  628. {
  629. LONG lRemainExtra = *plRemainExtra;
  630. INT cwch = MultiByteToWideChar(CP_ACP, 0, *pPString, -1, NULL, 0);
  631. ULONG ulSize = cwch * sizeof(WCHAR);
  632. if (cwch != 0) {
  633. lRemainExtra -= ulSize;
  634. if (lRemainExtra < 0) {
  635. ;
  636. }
  637. else {
  638. *pwszPrivacyMark = (LPWSTR) *ppbExtra;
  639. cwch = MultiByteToWideChar(CP_ACP, 0, *pPString, -1, (LPWSTR) *ppbExtra, cwch);
  640. *ppbExtra += ulSize;
  641. }
  642. *plRemainExtra = lRemainExtra;
  643. }
  644. }
  645. #define OssX509GetEncodedPString(PString, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra) \
  646. PkiAsn1GetPString(PString, dwFlags, pwszPrivacyMark, ppbExtra, plRemainExtra)
  647. /////////////////////////////////////////////////////////////////////////////
  648. /////////////////////////////////////////////////////////////////////////////
  649. //// EssContentHintEncodeEx
  650. //
  651. // Description:
  652. // This function is used to encode the ContentHint attribute found in
  653. // some S/MIME messages. Defintion of this object may be found in
  654. // draft-ietf-smime-ess
  655. //
  656. // Parameters:
  657. // dwCertEncodingType - should be ASN_X509_ENCODE
  658. // lpszStructType - should be szOID_Content_Hints
  659. // pInfo - external passed structure with content hints
  660. // dwFlags - control flags
  661. // pEncodePara - allocation functions
  662. // pvEncoded - Return encoded bytes here
  663. // pcbEncoded - Return size of encoded object
  664. //
  665. STDAPI_(BOOL) EssContentHintEncodeEx(IN DWORD dwCertEncodingType,
  666. IN LPCSTR lpszStructType,
  667. IN PSMIME_CONTENT_HINTS pInfo,
  668. IN DWORD dwFlags,
  669. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  670. OUT OPTIONAL void *pvEncoded,
  671. IN OUT DWORD *pcbEncoded
  672. )
  673. {
  674. BOOL fResult;
  675. ContentHints OssInfo;
  676. memset(&OssInfo, 0, sizeof(OssInfo));
  677. if (pInfo->pszDescription != NULL) {
  678. OssInfo.bit_mask |= contentDescription_present;
  679. OssInfo.contentDescription.length = wcslen(pInfo->pszDescription)*2;
  680. OssInfo.contentDescription.value = pInfo->pszDescription;
  681. }
  682. OssInfo.contentType.count = sizeof(OssInfo.contentType.value)/sizeof(OssInfo.contentType.value[0]);
  683. if (!OssX509SetEncodedObjId(pInfo->pszOIDContent, &OssInfo.contentType)) {
  684. goto ErrorReturn;
  685. }
  686. fResult = OssInfoEncodeEx(ContentHints_PDU, &OssInfo, dwFlags,
  687. pEncodePara, pvEncoded, pcbEncoded);
  688. CommonReturn:
  689. return fResult;
  690. ErrorReturn:
  691. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  692. *((void **) pvEncoded) = NULL;
  693. }
  694. *pcbEncoded = 0;
  695. fResult = FALSE;
  696. goto CommonReturn;
  697. }
  698. ////
  699. STDAPI_(BOOL) EssContentHintDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
  700. PCRYPT_DECODE_PARA pDecodePara,
  701. void *pvStructInfo, LONG *plRemainExtra)
  702. {
  703. LONG lRemainExtra = *plRemainExtra;
  704. LPBYTE pbExtra;
  705. PSMIME_CONTENT_HINTS pInfo = (PSMIME_CONTENT_HINTS) pvStructInfo;
  706. ContentHints * pOssInfo = (ContentHints *) pvOssInfo;
  707. // Remove space of base object
  708. lRemainExtra -= sizeof(SMIME_CONTENT_HINTS);
  709. if (lRemainExtra >= 0) {
  710. pbExtra = (BYTE *) pInfo + sizeof(SMIME_CONTENT_HINTS);
  711. }
  712. else {
  713. pbExtra = NULL;
  714. }
  715. // decode the content-hint description.
  716. if (pOssInfo->bit_mask & contentDescription_present) {
  717. OssX509GetEncodedUTF8String(&pOssInfo->contentDescription, dwFlags,
  718. (pInfo == NULL) ? NULL : &pInfo->pszDescription,
  719. &pbExtra, &lRemainExtra);
  720. }
  721. // decode the content-hint oid.
  722. OssX509GetEncodedObjId(&pOssInfo->contentType, dwFlags, &pInfo->pszOIDContent,
  723. &pbExtra, &lRemainExtra);
  724. *plRemainExtra = lRemainExtra;
  725. return TRUE;
  726. }
  727. //// EssContentHintDecodeEx
  728. //
  729. // Description:
  730. //
  731. // Parameter:
  732. // dwCertEncodingType in -
  733. // lpszStructType in -
  734. // pbEncoded in - ASN encoded structure to be parsed
  735. // cbEncoded in - size of pbEncoded
  736. // dwFlags in -
  737. // pDecodePara in - Allocation parameters
  738. // pvStructInfo out - Returned Content Hints decoded
  739. // pcbStructInfo in/out - sizeof pvStructInfo
  740. //
  741. STDAPI_(BOOL) EssContentHintDecodeEx(IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType,
  742. IN const BYTE *pbEncoded, IN DWORD cbEncoded,
  743. IN DWORD dwFlags, IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  744. OUT OPTIONAL void *pvStructInfo, IN OUT DWORD *pcbStructInfo)
  745. {
  746. return OssInfoDecodeAndAllocEx(ContentHints_PDU, pbEncoded, cbEncoded,
  747. dwFlags, pDecodePara,
  748. EssContentHintDecodeExCallback, pvStructInfo,
  749. pcbStructInfo);
  750. }
  751. //// EssReceiptRequestEncodeEx
  752. //
  753. // Description:
  754. // This function is used to encode the ReceiptRequest attribute found in
  755. // some S/MIME messages. Defintion of this object may be found in
  756. // draft-ietf-smime-ess
  757. //
  758. // Parameters:
  759. // dwCertEncodingType - should be ASN_X509_ENCODE
  760. // lpszStructType - should be szOID_Content_Hints
  761. // pInfo - external passed structure with content hints
  762. // dwFlags - control flags
  763. // pEncodePara - allocation functions
  764. // pvEncoded - Return encoded bytes here
  765. // pcbEncoded - Return size of encoded object
  766. //
  767. STDAPI_(BOOL) EssReceiptRequestEncodeEx(IN DWORD dwCertEncodingType,
  768. IN LPCSTR lpszStructType,
  769. IN PSMIME_RECEIPT_REQUEST pInfo,
  770. IN DWORD dwFlags,
  771. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  772. OUT OPTIONAL void *pvEncoded,
  773. IN OUT DWORD *pcbEncoded
  774. )
  775. {
  776. BOOL fResult;
  777. DWORD i;
  778. ReceiptRequest OssInfo;
  779. memset(&OssInfo, 0, sizeof(OssInfo));
  780. // ContentIdentifier
  781. OssInfo.signedContentIdentifier.length = pInfo->ContentIdentifier.cbData;
  782. OssInfo.signedContentIdentifier.value = pInfo->ContentIdentifier.pbData;
  783. // Receipts From
  784. if (pInfo->ReceiptsFrom.cNames > 0) {
  785. OssInfo.receiptsFrom.choice = receiptList_chosen;
  786. OssInfo.receiptsFrom.u.receiptList.count = pInfo->ReceiptsFrom.cNames;
  787. OssInfo.receiptsFrom.u.receiptList.value =
  788. (NOCOPYANY *) malloc(pInfo->ReceiptsFrom.cNames * sizeof(NOCOPYANY));
  789. if (OssInfo.receiptsFrom.u.receiptList.value == NULL) {
  790. goto ErrorReturn;
  791. }
  792. for (i=0; i<pInfo->ReceiptsFrom.cNames; i++) {
  793. OssX509SetAny(&pInfo->ReceiptsFrom.rgNames[i],
  794. &OssInfo.receiptsFrom.u.receiptList.value[i]);
  795. }
  796. }
  797. else {
  798. OssInfo.receiptsFrom.choice = allOrFirstTier_chosen;
  799. OssInfo.receiptsFrom.u.allOrFirstTier = pInfo->ReceiptsFrom.AllOrFirstTier;
  800. }
  801. // Receipts To
  802. OssInfo.receiptsTo.count = (USHORT) pInfo->cReceiptsTo;
  803. OssInfo.receiptsTo.value =
  804. (NOCOPYANY *) malloc(pInfo->cReceiptsTo * sizeof(NOCOPYANY));
  805. if (OssInfo.receiptsTo.value == NULL) {
  806. goto ErrorReturn;
  807. }
  808. for (i=0; i<pInfo->cReceiptsTo; i++) {
  809. OssX509SetAny(&pInfo->rgReceiptsTo[i],
  810. &OssInfo.receiptsTo.value[i]);
  811. }
  812. fResult = OssInfoEncodeEx(ReceiptRequest_PDU, &OssInfo, dwFlags,
  813. pEncodePara, pvEncoded, pcbEncoded);
  814. CommonReturn:
  815. if (OssInfo.receiptsFrom.u.receiptList.value != NULL) {
  816. free(OssInfo.receiptsFrom.u.receiptList.value);
  817. }
  818. if (OssInfo.receiptsTo.value != NULL) {
  819. free(OssInfo.receiptsTo.value);
  820. }
  821. return fResult;
  822. ErrorReturn:
  823. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  824. *((void **) pvEncoded) = NULL;
  825. }
  826. *pcbEncoded = 0;
  827. fResult = FALSE;
  828. goto CommonReturn;
  829. }
  830. ////
  831. STDAPI_(BOOL) EssReceiptRequestDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
  832. PCRYPT_DECODE_PARA pDecodePara,
  833. void *pvStructInfo, LONG *plRemainExtra)
  834. {
  835. DWORD cb;
  836. DWORD i;
  837. LONG lRemainExtra = *plRemainExtra;
  838. LPBYTE pbExtra;
  839. PSMIME_RECEIPT_REQUEST pInfo = (PSMIME_RECEIPT_REQUEST) pvStructInfo;
  840. ReceiptRequest * pOssInfo = (ReceiptRequest *) pvOssInfo;
  841. // Remove space of base object
  842. lRemainExtra -= sizeof(SMIME_RECEIPT_REQUEST);
  843. if (lRemainExtra >= 0) {
  844. pbExtra = (BYTE *) pInfo + sizeof(SMIME_RECEIPT_REQUEST);
  845. memset(pInfo, 0, sizeof(SMIME_RECEIPT_REQUEST));
  846. }
  847. else {
  848. pbExtra = NULL;
  849. pInfo = NULL;
  850. }
  851. //
  852. // ContentIdentifier
  853. //
  854. if (pOssInfo->signedContentIdentifier.length > 0) {
  855. lRemainExtra -= pOssInfo->signedContentIdentifier.length;
  856. if (lRemainExtra >= 0) {
  857. pInfo->ContentIdentifier.cbData =
  858. pOssInfo->signedContentIdentifier.length;
  859. pInfo->ContentIdentifier.pbData = pbExtra;
  860. memcpy(pbExtra, pOssInfo->signedContentIdentifier.value,
  861. pOssInfo->signedContentIdentifier.length);
  862. pbExtra += pOssInfo->signedContentIdentifier.length;
  863. }
  864. }
  865. //
  866. // ReceiptsFrom
  867. //
  868. if (pOssInfo->receiptsFrom.choice == receiptList_chosen) {
  869. cb = pOssInfo->receiptsFrom.u.receiptList.count * sizeof(CERT_NAME_BLOB);
  870. lRemainExtra -= cb;
  871. if (lRemainExtra >= 0) {
  872. pInfo->ReceiptsFrom.cNames = pOssInfo->receiptsFrom.u.receiptList.count;
  873. pInfo->ReceiptsFrom.rgNames = (CERT_NAME_BLOB *) pbExtra;
  874. pbExtra += cb;
  875. }
  876. for (i=0; i<pOssInfo->receiptsFrom.u.receiptList.count; i++) {
  877. OssX509GetAny(&pOssInfo->receiptsFrom.u.receiptList.value[i], dwFlags,
  878. (pInfo == NULL) ? NULL : &pInfo->ReceiptsFrom.rgNames[i],
  879. &pbExtra, &lRemainExtra);
  880. }
  881. }
  882. else {
  883. if (pInfo != NULL) {
  884. pInfo->ReceiptsFrom.AllOrFirstTier =
  885. pOssInfo->receiptsFrom.u.allOrFirstTier;
  886. }
  887. }
  888. // ReceiptsTo
  889. cb = pOssInfo->receiptsTo.count * sizeof(CERT_NAME_BLOB);
  890. lRemainExtra -= cb;
  891. if (lRemainExtra >= 0) {
  892. pInfo->cReceiptsTo = pOssInfo->receiptsTo.count;
  893. pInfo->rgReceiptsTo = (CERT_NAME_BLOB *) pbExtra;
  894. pbExtra += cb;
  895. }
  896. for (i=0; i<pOssInfo->receiptsTo.count; i++) {
  897. OssX509GetAny(&pOssInfo->receiptsTo.value[i], dwFlags,
  898. (pInfo == NULL) ? NULL : &pInfo->rgReceiptsTo[i],
  899. &pbExtra, &lRemainExtra);
  900. }
  901. *plRemainExtra = lRemainExtra;
  902. return TRUE;
  903. }
  904. //// EssReceiptRequestDecodeEx
  905. //
  906. // Description:
  907. //
  908. // Parameter:
  909. // dwCertEncodingType in -
  910. // lpszStructType in -
  911. // pbEncoded in - ASN encoded structure to be parsed
  912. // cbEncoded in - size of pbEncoded
  913. // dwFlags in -
  914. // pDecodePara in - Allocation parameters
  915. // pvStructInfo out - Returned Content Hints decoded
  916. // pcbStructInfo in/out - sizeof pvStructInfo
  917. //
  918. STDAPI_(BOOL) EssReceiptRequestDecodeEx(IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType,
  919. IN const BYTE *pbEncoded, IN DWORD cbEncoded,
  920. IN DWORD dwFlags, IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  921. OUT OPTIONAL void *pvStructInfo, IN OUT DWORD *pcbStructInfo)
  922. {
  923. return OssInfoDecodeAndAllocEx(ReceiptRequest_PDU, pbEncoded, cbEncoded,
  924. dwFlags, pDecodePara,
  925. EssReceiptRequestDecodeExCallback, pvStructInfo,
  926. pcbStructInfo);
  927. }
  928. ////////////////////////////// Receipt Content Type ///////////////////////////////////
  929. //// EssReceiptEncodeEx
  930. //
  931. // Description:
  932. // This function is used to encode the Receipt content type found in
  933. // some S/MIME messages. Defintion of this object may be found in
  934. // draft-ietf-smime-ess
  935. //
  936. // Parameters:
  937. // dwCertEncodingType - should be ASN_X509_ENCODE
  938. // lpszStructType - should be szOID_Content_Hints
  939. // pInfo - external passed structure with content hints
  940. // dwFlags - control flags
  941. // pEncodePara - allocation functions
  942. // pvEncoded - Return encoded bytes here
  943. // pcbEncoded - Return size of encoded object
  944. //
  945. STDAPI_(BOOL) EssReceiptEncodeEx(IN DWORD dwCertEncodingType,
  946. IN LPCSTR lpszStructType,
  947. IN PSMIME_RECEIPT pInfo,
  948. IN DWORD dwFlags,
  949. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  950. OUT OPTIONAL void *pvEncoded,
  951. IN OUT DWORD *pcbEncoded
  952. )
  953. {
  954. BOOL fResult;
  955. DWORD i;
  956. Receipt OssInfo;
  957. memset(&OssInfo, 0, sizeof(OssInfo));
  958. // Version number
  959. OssInfo.version = pInfo->Version;
  960. // ContentType
  961. OssInfo.contentType.count = sizeof(OssInfo.contentType.value)/sizeof(OssInfo.contentType.value[0]);
  962. fResult = OssX509SetEncodedObjId(pInfo->pszOIDContent, &OssInfo.contentType);
  963. if (!fResult) {
  964. goto ErrorReturn;
  965. }
  966. // ContentIdentifier
  967. OssInfo.signedContentIdentifier.length = pInfo->ContentIdentifier.cbData;
  968. OssInfo.signedContentIdentifier.value = pInfo->ContentIdentifier.pbData;
  969. // Originator signature
  970. OssX509SetOctetString(&pInfo->OriginatorSignature,
  971. &OssInfo.originatorSignatureValue);
  972. // Do the actual encoding
  973. fResult = OssInfoEncodeEx(Receipt_PDU, &OssInfo, dwFlags, pEncodePara,
  974. pvEncoded, pcbEncoded);
  975. CommonReturn:
  976. return fResult;
  977. ErrorReturn:
  978. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  979. *((void **) pvEncoded) = NULL;
  980. }
  981. *pcbEncoded = 0;
  982. fResult = FALSE;
  983. goto CommonReturn;
  984. }
  985. ////
  986. STDAPI_(BOOL) EssReceiptDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
  987. PCRYPT_DECODE_PARA pDecodePara,
  988. void *pvStructInfo, LONG *plRemainExtra)
  989. {
  990. DWORD cb;
  991. DWORD i;
  992. LONG lRemainExtra = *plRemainExtra;
  993. LPBYTE pbExtra;
  994. PSMIME_RECEIPT pInfo = (PSMIME_RECEIPT) pvStructInfo;
  995. Receipt * pOssInfo = (Receipt *) pvOssInfo;
  996. // Remove space of base object
  997. lRemainExtra -= sizeof(SMIME_RECEIPT);
  998. if (lRemainExtra >= 0) {
  999. pbExtra = (BYTE *) pInfo + sizeof(SMIME_RECEIPT);
  1000. memset(pInfo, 0, sizeof(SMIME_RECEIPT));
  1001. }
  1002. else {
  1003. pbExtra = NULL;
  1004. }
  1005. //
  1006. // VersionNumber
  1007. //
  1008. if (pInfo != NULL) {
  1009. pInfo->Version = pOssInfo->version;
  1010. }
  1011. // ContentType
  1012. #pragma prefast(suppress:11, "&pInfo->pszOIDContent is OK when pInfo is NULL");
  1013. OssX509GetEncodedObjId(&pOssInfo->contentType, dwFlags, &pInfo->pszOIDContent,
  1014. &pbExtra, &lRemainExtra);
  1015. //
  1016. // ContentIdentifier
  1017. //
  1018. if (pOssInfo->signedContentIdentifier.length > 0) {
  1019. lRemainExtra -= pOssInfo->signedContentIdentifier.length;
  1020. if (lRemainExtra >= 0) {
  1021. pInfo->ContentIdentifier.cbData =
  1022. pOssInfo->signedContentIdentifier.length;
  1023. pInfo->ContentIdentifier.pbData = pbExtra;
  1024. memcpy(pbExtra, pOssInfo->signedContentIdentifier.value,
  1025. pOssInfo->signedContentIdentifier.length);
  1026. pbExtra += pOssInfo->signedContentIdentifier.length;
  1027. }
  1028. }
  1029. //
  1030. // Originator signature
  1031. //
  1032. #pragma prefast(suppress:11, "&pInfo->OriginatorSignature is OK when pInfo is NULL");
  1033. OssX509GetOctetString(&pOssInfo->originatorSignatureValue, dwFlags,
  1034. &pInfo->OriginatorSignature, &pbExtra, &lRemainExtra);
  1035. *plRemainExtra = lRemainExtra;
  1036. return TRUE;
  1037. }
  1038. //// EssReceiptDecodeEx
  1039. //
  1040. // Description:
  1041. //
  1042. // Parameter:
  1043. // dwCertEncodingType in -
  1044. // lpszStructType in -
  1045. // pbEncoded in - ASN encoded structure to be parsed
  1046. // cbEncoded in - size of pbEncoded
  1047. // dwFlags in -
  1048. // pDecodePara in - Allocation parameters
  1049. // pvStructInfo out - Returned Content Hints decoded
  1050. // pcbStructInfo in/out - sizeof pvStructInfo
  1051. //
  1052. STDAPI_(BOOL) EssReceiptDecodeEx(IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType,
  1053. IN const BYTE *pbEncoded, IN DWORD cbEncoded,
  1054. IN DWORD dwFlags, IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1055. OUT OPTIONAL void *pvStructInfo, IN OUT DWORD *pcbStructInfo)
  1056. {
  1057. return OssInfoDecodeAndAllocEx(Receipt_PDU, pbEncoded, cbEncoded,
  1058. dwFlags, pDecodePara,
  1059. EssReceiptDecodeExCallback, pvStructInfo,
  1060. pcbStructInfo);
  1061. }
  1062. ////////////////////////////// ML Expansion History /////////////////////////////////
  1063. //// EssMLHistoryEncodeEx
  1064. //
  1065. // Description:
  1066. // This function is used to encode the MLHistory content type found in
  1067. // some S/MIME messages. Defintion of this object may be found in
  1068. // draft-ietf-smime-ess
  1069. //
  1070. // Parameters:
  1071. // dwCertEncodingType - should be ASN_X509_ENCODE
  1072. // lpszStructType - should be szOID_Content_Hints
  1073. // pInfo - external passed structure with content hints
  1074. // dwFlags - control flags
  1075. // pEncodePara - allocation functions
  1076. // pvEncoded - Return encoded bytes here
  1077. // pcbEncoded - Return size of encoded object
  1078. //
  1079. STDAPI_(BOOL) EssMLHistoryEncodeEx(IN DWORD dwCertEncodingType,
  1080. IN LPCSTR lpszStructType,
  1081. IN PSMIME_ML_EXPANSION_HISTORY pInfo,
  1082. IN DWORD dwFlags,
  1083. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1084. OUT OPTIONAL void *pvEncoded,
  1085. IN OUT DWORD *pcbEncoded
  1086. )
  1087. {
  1088. BOOL fResult;
  1089. DWORD i;
  1090. DWORD i1;
  1091. MLExpansionHistory OssInfo;
  1092. MLData * pData;
  1093. PSMIME_MLDATA pMLData;
  1094. memset(&OssInfo, 0, sizeof(OssInfo));
  1095. // Move over the count
  1096. OssInfo.count = (USHORT) pInfo->cMLData;
  1097. pData = OssInfo.value = (MLData *) malloc(OssInfo.count * sizeof(MLData));
  1098. if (pData == NULL) {
  1099. goto ErrorReturn;
  1100. }
  1101. memset(OssInfo.value, 0, OssInfo.count*sizeof(MLData));
  1102. // Assert(none_chosen == SMIME_MLPOLICY_NONE);
  1103. // Assert(insteadOf_chosen == SMIME_MLPOLICY_INSTEAD_OF);
  1104. // Assert(inAdditionTo_chosen == SMIME_MLPOLICY_IN_ADDITION_TO);
  1105. pMLData = pInfo->rgMLData;
  1106. for (i=0; i<OssInfo.count; i++, pData++, pMLData++) {
  1107. if (pMLData->dwChoice == SMIME_MLDATA_SUBJECT_KEY_IDENTIFIER) {
  1108. pData->mailListIdentifier.choice = subjectKeyIdentifier_chosen;
  1109. PkiAsn1SetOctetString(&pMLData->SubjectKeyIdentifier,
  1110. &pData->mailListIdentifier.u.subjectKeyIdentifier);
  1111. }
  1112. else {
  1113. pData->mailListIdentifier.choice = EntityIdentifier_issuerAndSerialNumber_chosen;
  1114. PkiAsn1SetHugeInteger(&pMLData->u.SerialNumber,
  1115. &pData->mailListIdentifier.u.issuerAndSerialNumber.serialNumber);
  1116. PkiAsn1SetAny(&pMLData->u.Issuer,
  1117. &pData->mailListIdentifier.u.issuerAndSerialNumber.issuer);
  1118. }
  1119. PkiAsn1ToGeneralizedTime(&pMLData->ExpansionTime, &pData->expansionTime);
  1120. if (pMLData->dwPolicy != SMIME_MLPOLICY_NO_CHANGE) {
  1121. pData->bit_mask |= mlReceiptPolicy_present;
  1122. pData->mlReceiptPolicy.choice = (USHORT) pMLData->dwPolicy;
  1123. if (pData->mlReceiptPolicy.choice != SMIME_MLPOLICY_NONE) {
  1124. pData->mlReceiptPolicy.u.insteadOf.count = pMLData->cNames;
  1125. pData->mlReceiptPolicy.u.insteadOf.value = (GeneralNames *)
  1126. malloc(pData->mlReceiptPolicy.u.insteadOf.count * sizeof(GeneralNames));
  1127. if (pData->mlReceiptPolicy.u.insteadOf.value == NULL) {
  1128. goto ErrorReturn;
  1129. }
  1130. for (i1=0; i1<pData->mlReceiptPolicy.u.insteadOf.count; i1++) {
  1131. OssX509SetAny(&pMLData->rgNames[i1],
  1132. &pData->mlReceiptPolicy.u.insteadOf.value[i1]);
  1133. }
  1134. }
  1135. }
  1136. }
  1137. // Do the actual encoding
  1138. fResult = OssInfoEncodeEx(MLExpansionHistory_PDU, &OssInfo, dwFlags, pEncodePara,
  1139. pvEncoded, pcbEncoded);
  1140. CommonReturn:
  1141. if (OssInfo.value != NULL) {
  1142. for (pData = OssInfo.value, i=0; i<OssInfo.count; i++, pData++) {
  1143. PkiAsn1FreeHugeInteger(pData->mailListIdentifier.u.issuerAndSerialNumber.serialNumber);
  1144. if (pData->mlReceiptPolicy.u.insteadOf.value != NULL) {
  1145. free(pData->mlReceiptPolicy.u.insteadOf.value);
  1146. }
  1147. }
  1148. free(OssInfo.value);
  1149. }
  1150. return fResult;
  1151. ErrorReturn:
  1152. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  1153. *((void **) pvEncoded) = NULL;
  1154. }
  1155. *pcbEncoded = 0;
  1156. fResult = FALSE;
  1157. goto CommonReturn;
  1158. }
  1159. ////
  1160. STDAPI_(BOOL) EssMLHistoryDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
  1161. PCRYPT_DECODE_PARA pDecodePara,
  1162. void *pvStructInfo, LONG *plRemainExtra)
  1163. {
  1164. DWORD cb;
  1165. DWORD i;
  1166. DWORD i1;
  1167. LONG lRemainExtra = *plRemainExtra;
  1168. LPBYTE pbExtra;
  1169. MLData * pData;
  1170. PSMIME_ML_EXPANSION_HISTORY pInfo = (PSMIME_ML_EXPANSION_HISTORY) pvStructInfo;
  1171. PSMIME_MLDATA pMLData;
  1172. MLExpansionHistory * pOssInfo = (MLExpansionHistory *) pvOssInfo;
  1173. // Remove space of base object
  1174. lRemainExtra -= sizeof(SMIME_ML_EXPANSION_HISTORY);
  1175. if (lRemainExtra >= 0) {
  1176. pbExtra = (BYTE *) pInfo + sizeof(SMIME_ML_EXPANSION_HISTORY);
  1177. memset(pInfo, 0, sizeof(SMIME_ML_EXPANSION_HISTORY));
  1178. }
  1179. else {
  1180. pbExtra = NULL;
  1181. pInfo = NULL;
  1182. }
  1183. lRemainExtra -= pOssInfo->count * sizeof(SMIME_MLDATA);
  1184. if (lRemainExtra >= 0) {
  1185. pInfo->cMLData = pOssInfo->count;
  1186. pMLData = pInfo->rgMLData = (PSMIME_MLDATA) pbExtra;
  1187. pbExtra += pOssInfo->count * sizeof(SMIME_MLDATA);
  1188. }
  1189. for (i=0, pData = pOssInfo->value; i<pOssInfo->count; i++, pData++) {
  1190. if (pData->mailListIdentifier.choice == subjectKeyIdentifier_chosen) {
  1191. pData->mailListIdentifier.choice = subjectKeyIdentifier_chosen;
  1192. PkiAsn1GetOctetString(&pData->mailListIdentifier.u.subjectKeyIdentifier,
  1193. dwFlags, &pMLData->SubjectKeyIdentifier,
  1194. &pbExtra, &lRemainExtra);
  1195. }
  1196. else {
  1197. pData->mailListIdentifier.choice = EntityIdentifier_issuerAndSerialNumber_chosen;
  1198. PkiAsn1GetHugeInteger(pData->mailListIdentifier.u.issuerAndSerialNumber.serialNumber,
  1199. dwFlags, &pMLData->u.SerialNumber,
  1200. &pbExtra, &lRemainExtra);
  1201. PkiAsn1GetAny(&pData->mailListIdentifier.u.issuerAndSerialNumber.issuer,
  1202. dwFlags, &pMLData->u.Issuer,
  1203. &pbExtra, &lRemainExtra);
  1204. }
  1205. if (lRemainExtra >= 0) {
  1206. PkiAsn1FromGeneralizedTime(&pData->expansionTime, &pMLData->ExpansionTime);
  1207. }
  1208. if (pData->bit_mask & mlReceiptPolicy_present) {
  1209. if (lRemainExtra >= 0) {
  1210. pMLData->dwPolicy = pData->mlReceiptPolicy.choice;
  1211. }
  1212. if (pData->mlReceiptPolicy.choice != none_chosen) {
  1213. lRemainExtra -= pData->mlReceiptPolicy.u.insteadOf.count * sizeof(GeneralNames);
  1214. if (lRemainExtra >= 0) {
  1215. pMLData->cNames = pData->mlReceiptPolicy.u.insteadOf.count;
  1216. pMLData->rgNames = (CERT_NAME_BLOB *) pbExtra;
  1217. pbExtra += pMLData->cNames * sizeof(CERT_NAME_BLOB);
  1218. }
  1219. for (i1=0; i1<pData->mlReceiptPolicy.u.insteadOf.count; i1++) {
  1220. OssX509GetAny(&pData->mlReceiptPolicy.u.insteadOf.value[i1],
  1221. dwFlags, &pMLData->rgNames[i1], &pbExtra,
  1222. &lRemainExtra);
  1223. }
  1224. }
  1225. }
  1226. else if (lRemainExtra >= 0) {
  1227. pMLData->dwPolicy = SMIME_MLPOLICY_NO_CHANGE;
  1228. }
  1229. }
  1230. *plRemainExtra = lRemainExtra;
  1231. return TRUE;
  1232. }
  1233. //// EssMLHistoryDecodeEx
  1234. //
  1235. // Description:
  1236. //
  1237. // Parameter:
  1238. // dwCertEncodingType in -
  1239. // lpszStructType in -
  1240. // pbEncoded in - ASN encoded structure to be parsed
  1241. // cbEncoded in - size of pbEncoded
  1242. // dwFlags in -
  1243. // pDecodePara in - Allocation parameters
  1244. // pvStructInfo out - Returned Content Hints decoded
  1245. // pcbStructInfo in/out - sizeof pvStructInfo
  1246. //
  1247. STDAPI_(BOOL) EssMLHistoryDecodeEx(IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType,
  1248. IN const BYTE *pbEncoded, IN DWORD cbEncoded,
  1249. IN DWORD dwFlags, IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1250. OUT OPTIONAL void *pvStructInfo, IN OUT DWORD *pcbStructInfo)
  1251. {
  1252. return OssInfoDecodeAndAllocEx(MLExpansionHistory_PDU, pbEncoded, cbEncoded,
  1253. dwFlags, pDecodePara,
  1254. EssMLHistoryDecodeExCallback, pvStructInfo,
  1255. pcbStructInfo);
  1256. }
  1257. /////////////////////////////////////////////////////////////////////////////
  1258. //// EssSecurityLabelEncodeEx
  1259. //
  1260. // Description:
  1261. // This function is used to encode the SecurityLabel attribute found in
  1262. // some S/MIME messages. Defintion of this object may be found in
  1263. // draft-ietf-smime-ess
  1264. //
  1265. // Parameters:
  1266. // dwCertEncodingType - should be ASN_X509_ENCODE
  1267. // lpszStructType - should be szOID_Security_Label
  1268. // pInfo - external passed structure with Security Label
  1269. // dwFlags - control flags
  1270. // pEncodePara - allocation functions
  1271. // pvEncoded - Return encoded bytes here
  1272. // pcbEncoded - Return size of encoded object
  1273. //
  1274. STDAPI_(BOOL) EssSecurityLabelEncodeEx(IN DWORD dwCertEncodingType,
  1275. IN LPCSTR lpszStructType,
  1276. IN PSMIME_SECURITY_LABEL pInfo,
  1277. IN DWORD dwFlags,
  1278. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1279. OUT OPTIONAL void *pvEncoded,
  1280. IN OUT DWORD *pcbEncoded
  1281. )
  1282. {
  1283. BOOL fResult;
  1284. DWORD i;
  1285. ESSSecurityLabel OssInfo;
  1286. memset(&OssInfo, 0, sizeof(OssInfo));
  1287. OssInfo.security_policy_identifier.count = sizeof(OssInfo.security_policy_identifier.value)/sizeof(OssInfo.security_policy_identifier.value[0]);
  1288. if (!OssX509SetEncodedObjId(pInfo->pszObjIdSecurityPolicy,
  1289. &OssInfo.security_policy_identifier)) {
  1290. goto ErrorReturn;
  1291. }
  1292. if (pInfo->fHasClassification) {
  1293. OssInfo.bit_mask |= security_classification_present;
  1294. OssInfo.security_classification = (USHORT) pInfo->dwClassification;
  1295. }
  1296. if (pInfo->wszPrivacyMark != NULL) {
  1297. OssInfo.bit_mask |= privacy_mark_present;
  1298. OssInfo.privacy_mark.choice = utf8String_chosen;
  1299. PkiAsn1SetUTF8String(pInfo->wszPrivacyMark, &OssInfo.privacy_mark.u.utf8String);
  1300. }
  1301. if (pInfo->cCategories != 0) {
  1302. OssInfo.bit_mask |= security_categories_present;
  1303. OssInfo.security_categories.count = (USHORT) pInfo->cCategories;
  1304. OssInfo.security_categories.value = (SecurityCategory *)
  1305. malloc(OssInfo.security_categories.count * sizeof(SecurityCategory));
  1306. for (i=0; i<pInfo->cCategories; i++) {
  1307. OssInfo.security_categories.value[i].type.count = sizeof(OssInfo.security_categories.value[0].type.value)/sizeof(OssInfo.security_categories.value[0].type.value[0]);
  1308. if (!OssX509SetEncodedObjId(pInfo->rgCategories[i].pszObjId,
  1309. &OssInfo.security_categories.value[i].type)) {
  1310. goto ErrorReturn;
  1311. }
  1312. OssX509SetAny(&pInfo->rgCategories[i].Value,
  1313. &OssInfo.security_categories.value[i].value);
  1314. }
  1315. }
  1316. fResult = OssInfoEncodeEx(ESSSecurityLabel_PDU, &OssInfo, dwFlags,
  1317. pEncodePara, pvEncoded, pcbEncoded);
  1318. CommonReturn:
  1319. if (OssInfo.security_categories.value != NULL) {
  1320. free(OssInfo.security_categories.value);
  1321. }
  1322. return fResult;
  1323. ErrorReturn:
  1324. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  1325. *((void **) pvEncoded) = NULL;
  1326. }
  1327. *pcbEncoded = 0;
  1328. fResult = FALSE;
  1329. goto CommonReturn;
  1330. }
  1331. ////
  1332. STDAPI_(BOOL) EssSecurityLabelDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
  1333. PCRYPT_DECODE_PARA pDecodePara,
  1334. void *pvStructInfo, LONG *plRemainExtra)
  1335. {
  1336. DWORD cb;
  1337. DWORD i;
  1338. LONG lRemainExtra = *plRemainExtra;
  1339. CRYPT_ATTRIBUTE_TYPE_VALUE * pattr;
  1340. LPBYTE pbExtra;
  1341. PSMIME_SECURITY_LABEL pInfo = (PSMIME_SECURITY_LABEL) pvStructInfo;
  1342. ESSSecurityLabel * pOssInfo = (ESSSecurityLabel *) pvOssInfo;
  1343. // Remove space of base object
  1344. lRemainExtra -= sizeof(SMIME_SECURITY_LABEL);
  1345. if (lRemainExtra >= 0) {
  1346. pbExtra = (BYTE *) pInfo + sizeof(SMIME_SECURITY_LABEL);
  1347. memset(pInfo, 0, sizeof(*pInfo));
  1348. }
  1349. else {
  1350. pbExtra = NULL;
  1351. pInfo = NULL;
  1352. }
  1353. if (lRemainExtra >= 0) {
  1354. pInfo->pszObjIdSecurityPolicy = (LPSTR) pbExtra;
  1355. }
  1356. OssX509GetEncodedObjId(&pOssInfo->security_policy_identifier, dwFlags,
  1357. (pInfo == NULL) ? NULL : &pInfo->pszObjIdSecurityPolicy,
  1358. &pbExtra, &lRemainExtra);
  1359. if ((pInfo != NULL) &&
  1360. (pOssInfo->bit_mask & security_classification_present)) {
  1361. pInfo->dwClassification = pOssInfo->security_classification;
  1362. pInfo->fHasClassification = TRUE;
  1363. }
  1364. if (pOssInfo->bit_mask & privacy_mark_present) {
  1365. if (utf8String_chosen == pOssInfo->privacy_mark.choice) {
  1366. OssX509GetEncodedUTF8String(&pOssInfo->privacy_mark.u.utf8String, dwFlags,
  1367. (pInfo == NULL) ? NULL : &pInfo->wszPrivacyMark,
  1368. &pbExtra, &lRemainExtra);
  1369. }
  1370. else if (pString_chosen == pOssInfo->privacy_mark.choice) {
  1371. Assert(NULL != pOssInfo->privacy_mark.u.pString);
  1372. OssX509GetEncodedPString(&pOssInfo->privacy_mark.u.pString, dwFlags,
  1373. (pInfo == NULL) ? NULL : &pInfo->wszPrivacyMark,
  1374. &pbExtra, &lRemainExtra);
  1375. }
  1376. else {
  1377. return FALSE; // unknown privacy_mark encoding...
  1378. }
  1379. }
  1380. if (pOssInfo->bit_mask & security_categories_present) {
  1381. cb = pOssInfo->security_categories.count *
  1382. sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE);
  1383. lRemainExtra -= cb;
  1384. if (lRemainExtra >= 0) {
  1385. pInfo->cCategories = pOssInfo->security_categories.count;
  1386. pattr = pInfo->rgCategories = (CRYPT_ATTRIBUTE_TYPE_VALUE *) pbExtra;
  1387. pbExtra += cb;
  1388. }
  1389. else {
  1390. pattr = NULL;
  1391. }
  1392. for (i=0; i<pOssInfo->security_categories.count; i++, pattr++) {
  1393. OssX509GetEncodedObjId(&pOssInfo->security_categories.value[i].type,
  1394. dwFlags, (pattr == NULL) ? NULL : &pattr->pszObjId,
  1395. &pbExtra, &lRemainExtra);
  1396. OssX509GetAny(&pOssInfo->security_categories.value[i].value,
  1397. dwFlags, (pattr == NULL) ? NULL : &pattr->Value,
  1398. &pbExtra, &lRemainExtra);
  1399. }
  1400. }
  1401. *plRemainExtra = lRemainExtra;
  1402. return TRUE;
  1403. }
  1404. //// EssSecurityLabelDecodeEx
  1405. //
  1406. // Description:
  1407. //
  1408. // Parameter:
  1409. // dwCertEncodingType in -
  1410. // lpszStructType in -
  1411. // pbEncoded in - ASN encoded structure to be parsed
  1412. // cbEncoded in - size of pbEncoded
  1413. // dwFlags in -
  1414. // pDecodePara in - Allocation parameters
  1415. // pvStructInfo out - Returned Security Label decoded
  1416. // pcbStructInfo in/out - sizeof pvStructInfo
  1417. //
  1418. STDAPI_(BOOL) EssSecurityLabelDecodeEx(IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType,
  1419. IN const BYTE *pbEncoded, IN DWORD cbEncoded,
  1420. IN DWORD dwFlags, IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1421. OUT OPTIONAL void *pvStructInfo, IN OUT DWORD *pcbStructInfo)
  1422. {
  1423. return OssInfoDecodeAndAllocEx(ESSSecurityLabel_PDU, pbEncoded, cbEncoded,
  1424. dwFlags, pDecodePara,
  1425. EssSecurityLabelDecodeExCallback, pvStructInfo,
  1426. pcbStructInfo);
  1427. }
  1428. ///////////////////////////////////////////////////////////////////////
  1429. BOOL DH_ImportPublicKeyInfoEx(HCRYPTPROV hprov, DWORD dwCertEncodingType,
  1430. PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID algId,
  1431. DWORD dwFlags,
  1432. void * pvAuxInfo, HCRYPTKEY * phKey)
  1433. {
  1434. DWORD cb;
  1435. int cbBlob;
  1436. DWORD cbKey;
  1437. BOOL fRet = FALSE;
  1438. HRESULT hr;
  1439. LPBYTE pb;
  1440. CRYPT_UINT_BLOB * pblob = NULL;
  1441. LPBYTE pbBlob = NULL;
  1442. DHPUBKEY * pdhPubKey;
  1443. PCERT_DSS_PARAMETERS pDssParameters = NULL;
  1444. PUBLICKEYSTRUC * pKeyBlob;
  1445. hr = HrDecodeObject(pInfo->Algorithm.Parameters.pbData,
  1446. pInfo->Algorithm.Parameters.cbData,
  1447. X509_DSS_PARAMETERS, 0, &cb, (LPVOID*) &pDssParameters);
  1448. if (FAILED(hr)) {
  1449. goto Exit;
  1450. }
  1451. cbKey = pDssParameters->p.cbData;
  1452. if (0 == cbKey) {
  1453. goto Exit;
  1454. }
  1455. cbBlob = sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY) + 3*cbKey;
  1456. pbBlob = (LPBYTE) malloc(cbBlob);
  1457. pKeyBlob = (PUBLICKEYSTRUC *) pbBlob;
  1458. pKeyBlob->bType = PUBLICKEYBLOB;
  1459. pKeyBlob->bVersion = CUR_BLOB_VERSION;
  1460. pKeyBlob->aiKeyAlg = CALG_DH_EPHEM;
  1461. pdhPubKey = (DHPUBKEY *) &pKeyBlob[1];
  1462. pdhPubKey->magic = 0x33484400;
  1463. pdhPubKey->bitlen = cbKey*8;
  1464. pb = (LPBYTE) &pdhPubKey[1];
  1465. memcpy(pb, pDssParameters->p.pbData, cbKey);
  1466. pb += cbKey;
  1467. // memcpy(pb, pDssParameters->q.pbData, pDssParameters->q.cbData);
  1468. // pb += pDssParameters->q.cbData;
  1469. memcpy(pb, pDssParameters->g.pbData, cbKey);
  1470. pb += cbKey;
  1471. memcpy(pb, pInfo->PublicKey.pbData, cbKey);
  1472. pb += cbKey;
  1473. Assert(cbBlob == (pb - pbBlob));
  1474. // memcpy(pb, &seed, sizeof(seed));
  1475. if (!CryptImportKey(hprov, pbBlob, cbBlob, NULL, 0, phKey)) {
  1476. goto Exit;
  1477. }
  1478. fRet = TRUE;
  1479. Exit:
  1480. if (pblob != NULL) LocalFree(pblob);
  1481. if (pbBlob != NULL) free(pbBlob);
  1482. if (pDssParameters != NULL) LocalFree(pDssParameters);
  1483. return fRet;
  1484. }
  1485. #endif // SMIME_V3
  1486. ////////////////////////////////////////////////////////////////////////////////
  1487. //// EssContentHintEncodeEx
  1488. //
  1489. // Description:
  1490. // This function is used to encode the ContentHint attribute found in
  1491. // some S/MIME messages. Defintion of this object may be found in
  1492. // draft-ietf-smime-ess
  1493. //
  1494. // Parameters:
  1495. // dwCertEncodingType - should be ASN_X509_ENCODE
  1496. // lpszStructType - should be szOID_Content_Hints
  1497. // pInfo - external passed structure with content hints
  1498. // dwFlags - control flags
  1499. // pEncodePara - allocation functions
  1500. // pvEncoded - Return encoded bytes here
  1501. // pcbEncoded - Return size of encoded object
  1502. //
  1503. STDAPI_(BOOL) EssKeyExchPreferenceEncodeEx(IN DWORD dwCertEncodingType,
  1504. IN LPCSTR lpszStructType,
  1505. IN PSMIME_ENC_KEY_PREFERENCE pInfo,
  1506. IN DWORD dwFlags,
  1507. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1508. OUT OPTIONAL void *pvEncoded,
  1509. IN OUT DWORD *pcbEncoded)
  1510. {
  1511. BOOL fResult;
  1512. SMIMEEncryptionKeyPreference OssInfo;
  1513. memset(&OssInfo, 0, sizeof(OssInfo));
  1514. switch (pInfo->RecipientId.dwIdChoice) {
  1515. case CERT_ID_ISSUER_SERIAL_NUMBER:
  1516. OssInfo.choice = SMIMEEncryptionKeyPreference_issuerAndSerialNumber_chosen;
  1517. PkiAsn1SetHugeInteger(&pInfo->RecipientId.IssuerSerialNumber.SerialNumber,
  1518. &OssInfo.u.issuerAndSerialNumber.serialNumber);
  1519. PkiAsn1SetAny(&pInfo->RecipientId.IssuerSerialNumber.Issuer,
  1520. &OssInfo.u.issuerAndSerialNumber.issuer);
  1521. break;
  1522. case CERT_ID_KEY_IDENTIFIER:
  1523. OssInfo.choice = recipientKeyId_chosen;
  1524. OssX509SetOctetString(&pInfo->RecipientId.KeyId,
  1525. &OssInfo.u.recipientKeyId.subjectKeyIdentifier);
  1526. if ((pInfo->Date.dwLowDateTime != 0) || (pInfo->Date.dwHighDateTime != 0)) {
  1527. PkiAsn1ToGeneralizedTime(&pInfo->Date, &OssInfo.u.recipientKeyId.date);
  1528. }
  1529. if (pInfo->pOtherAttr != NULL) {
  1530. if (!OssX509SetEncodedObjId(pInfo->pOtherAttr->pszObjId,
  1531. &OssInfo.u.recipientKeyId.other.keyAttrId)) {
  1532. goto ErrorReturn;
  1533. }
  1534. if (pInfo->pOtherAttr->Value.cbData != 0) {
  1535. OssInfo.u.recipientKeyId.other.bit_mask |= keyAttr_present;
  1536. PkiAsn1SetAny(&pInfo->pOtherAttr->Value,
  1537. &OssInfo.u.recipientKeyId.other.keyAttr);
  1538. }
  1539. }
  1540. break;
  1541. case CERT_ID_SHA1_HASH:
  1542. OssInfo.choice = subjectAltKeyIdentifier_chosen;
  1543. OssX509SetOctetString(&pInfo->RecipientId.HashId,
  1544. &OssInfo.u.subjectAltKeyIdentifier);
  1545. break;
  1546. default:
  1547. goto ErrorReturn;
  1548. }
  1549. fResult = OssInfoEncodeEx(SMIMEEncryptionKeyPreference_PDU, &OssInfo, dwFlags,
  1550. pEncodePara, pvEncoded, pcbEncoded);
  1551. CommonReturn:
  1552. return fResult;
  1553. ErrorReturn:
  1554. fResult = FALSE;
  1555. goto CommonReturn;
  1556. }
  1557. STDAPI_(BOOL) EssKeyExchPreferenceDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
  1558. PCRYPT_DECODE_PARA pDecodePara,
  1559. void *pvStructInfo, LONG *plRemainExtra)
  1560. {
  1561. LONG lRemainExtra = *plRemainExtra;
  1562. LPBYTE pbExtra;
  1563. PSMIME_ENC_KEY_PREFERENCE pInfo = (PSMIME_ENC_KEY_PREFERENCE) pvStructInfo;
  1564. SMIMEEncryptionKeyPreference * pOssInfo = (SMIMEEncryptionKeyPreference *) pvOssInfo;
  1565. // Remove space of base object
  1566. lRemainExtra -= sizeof(SMIME_ENC_KEY_PREFERENCE);
  1567. if (lRemainExtra >= 0) {
  1568. pbExtra = (BYTE *) pInfo + sizeof(SMIME_ENC_KEY_PREFERENCE);
  1569. }
  1570. else {
  1571. pbExtra = NULL;
  1572. }
  1573. switch (pOssInfo->choice) {
  1574. case SMIMEEncryptionKeyPreference_issuerAndSerialNumber_chosen:
  1575. if (pInfo != NULL) {
  1576. pInfo->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
  1577. }
  1578. PkiAsn1GetHugeInteger(pOssInfo->u.issuerAndSerialNumber.serialNumber,
  1579. dwFlags, (pInfo == NULL) ? NULL :
  1580. &pInfo->RecipientId.IssuerSerialNumber.SerialNumber,
  1581. &pbExtra, &lRemainExtra);
  1582. PkiAsn1GetAny(&pOssInfo->u.issuerAndSerialNumber.issuer, dwFlags,
  1583. (pInfo == NULL) ? NULL :
  1584. &pInfo->RecipientId.IssuerSerialNumber.Issuer,
  1585. &pbExtra, &lRemainExtra);
  1586. break;
  1587. case recipientKeyId_chosen:
  1588. if (pInfo != NULL) {
  1589. pInfo->RecipientId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
  1590. }
  1591. OssX509GetOctetString(&pOssInfo->u.recipientKeyId.subjectKeyIdentifier,
  1592. dwFlags, &pInfo->RecipientId.KeyId,
  1593. &pbExtra, &lRemainExtra);
  1594. if ((lRemainExtra >= 0) &&
  1595. (pOssInfo->u.recipientKeyId.bit_mask & date_present)) {
  1596. PkiAsn1FromGeneralizedTime(&pOssInfo->u.recipientKeyId.date,
  1597. &pInfo->Date);
  1598. }
  1599. if (pOssInfo->u.recipientKeyId.bit_mask & other_present) {
  1600. OssX509GetEncodedObjId(&pOssInfo->u.recipientKeyId.other.keyAttrId,
  1601. dwFlags, (pInfo == NULL) ? NULL :
  1602. &pInfo->pOtherAttr->pszObjId,
  1603. &pbExtra, &lRemainExtra);
  1604. if (pOssInfo->u.recipientKeyId.other.bit_mask & keyAttr_present) {
  1605. PkiAsn1GetAny(&pOssInfo->u.recipientKeyId.other.keyAttr,
  1606. dwFlags, (pInfo == NULL) ? NULL :
  1607. &pInfo->pOtherAttr->Value, &pbExtra, &lRemainExtra);
  1608. }
  1609. }
  1610. break;
  1611. case subjectAltKeyIdentifier_chosen:
  1612. if (pInfo != NULL) {
  1613. pInfo->RecipientId.dwIdChoice = CERT_ID_SHA1_HASH;
  1614. }
  1615. OssX509GetOctetString(&pOssInfo->u.subjectAltKeyIdentifier, dwFlags,
  1616. &pInfo->RecipientId.HashId, &pbExtra, &lRemainExtra);
  1617. break;
  1618. default:
  1619. return FALSE;
  1620. }
  1621. *plRemainExtra = lRemainExtra;
  1622. return TRUE;
  1623. }
  1624. //// EssKeyExchPreferenceDecodeEx
  1625. //
  1626. // Description:
  1627. //
  1628. // Parameter:
  1629. // dwCertEncodingType in -
  1630. // lpszStructType in -
  1631. // pbEncoded in - ASN encoded structure to be parsed
  1632. // cbEncoded in - size of pbEncoded
  1633. // dwFlags in -
  1634. // pDecodePara in - Allocation parameters
  1635. // pvStructInfo out - Returned Content Hints decoded
  1636. // pcbStructInfo in/out - sizeof pvStructInfo
  1637. //
  1638. STDAPI_(BOOL) EssKeyExchPreferenceDecodeEx(IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType,
  1639. IN const BYTE *pbEncoded, IN DWORD cbEncoded,
  1640. IN DWORD dwFlags, IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1641. OUT OPTIONAL void *pvStructInfo, IN OUT DWORD *pcbStructInfo)
  1642. {
  1643. return OssInfoDecodeAndAllocEx(SMIMEEncryptionKeyPreference_PDU, pbEncoded,
  1644. cbEncoded, dwFlags, pDecodePara,
  1645. EssKeyExchPreferenceDecodeExCallback,
  1646. pvStructInfo, pcbStructInfo);
  1647. }
  1648. //// EssSignCertificateEncodeEx
  1649. //
  1650. // Description:
  1651. // This function is used to encode the ContentHint attribute found in
  1652. // some S/MIME messages. Defintion of this object may be found in
  1653. // draft-ietf-smime-ess
  1654. //
  1655. // Parameters:
  1656. // dwCertEncodingType - should be ASN_X509_ENCODE
  1657. // lpszStructType - should be szOID_Content_Hints
  1658. // pInfo - external passed structure with content hints
  1659. // dwFlags - control flags
  1660. // pEncodePara - allocation functions
  1661. // pvEncoded - Return encoded bytes here
  1662. // pcbEncoded - Return size of encoded object
  1663. //
  1664. STDAPI_(BOOL) EssSignCertificateEncodeEx(IN DWORD dwCertEncodingType,
  1665. IN LPCSTR lpszStructType,
  1666. IN PSMIME_SIGNING_CERTIFICATE pInfo,
  1667. IN DWORD dwFlags,
  1668. IN OPTIONAL PCRYPT_ENCODE_PARA pEncodePara,
  1669. OUT OPTIONAL void *pvEncoded,
  1670. IN OUT DWORD *pcbEncoded)
  1671. {
  1672. BOOL fResult;
  1673. SigningCertificate OssInfo;
  1674. memset(&OssInfo, 0, sizeof(OssInfo));
  1675. fResult = OssInfoEncodeEx(SigningCertificate_PDU, &OssInfo, dwFlags,
  1676. pEncodePara, pvEncoded, pcbEncoded);
  1677. //CommonReturn:
  1678. return fResult;
  1679. #if 0
  1680. ErrorReturn:
  1681. if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
  1682. *((void **) pvEncoded) = NULL;
  1683. }
  1684. *pcbEncoded = 0;
  1685. fResult = FALSE;
  1686. goto CommonReturn;
  1687. #endif // 0
  1688. }
  1689. STDAPI_(BOOL) EssSignCertificateDecodeExCallback(void *pvOssInfo, DWORD dwFlags,
  1690. PCRYPT_DECODE_PARA pDecodePara,
  1691. void *pvStructInfo, LONG *plRemainExtra)
  1692. {
  1693. LONG lRemainExtra = *plRemainExtra;
  1694. LPBYTE pbExtra;
  1695. PSMIME_CONTENT_HINTS pInfo = (PSMIME_CONTENT_HINTS) pvStructInfo;
  1696. ContentHints * pOssInfo = (ContentHints *) pvOssInfo;
  1697. // Remove space of base object
  1698. lRemainExtra -= sizeof(SMIME_CONTENT_HINTS);
  1699. if (lRemainExtra >= 0) {
  1700. pbExtra = (BYTE *) pInfo + sizeof(SMIME_CONTENT_HINTS);
  1701. }
  1702. else {
  1703. pbExtra = NULL;
  1704. }
  1705. OssX509GetEncodedObjId(&pOssInfo->contentType, dwFlags, &pInfo->pszOIDContent,
  1706. &pbExtra, &lRemainExtra);
  1707. *plRemainExtra = lRemainExtra;
  1708. return TRUE;
  1709. }
  1710. //// EssSignCertificateDecodeEx
  1711. //
  1712. // Description:
  1713. //
  1714. // Parameter:
  1715. // dwCertEncodingType in -
  1716. // lpszStructType in -
  1717. // pbEncoded in - ASN encoded structure to be parsed
  1718. // cbEncoded in - size of pbEncoded
  1719. // dwFlags in -
  1720. // pDecodePara in - Allocation parameters
  1721. // pvStructInfo out - Returned Content Hints decoded
  1722. // pcbStructInfo in/out - sizeof pvStructInfo
  1723. //
  1724. STDAPI_(BOOL) EssSignCertificateDecodeEx(IN DWORD dwCertEncodingType, IN LPCSTR lpszStructType,
  1725. IN const BYTE *pbEncoded, IN DWORD cbEncoded,
  1726. IN DWORD dwFlags, IN OPTIONAL PCRYPT_DECODE_PARA pDecodePara,
  1727. OUT OPTIONAL void *pvStructInfo, IN OUT DWORD *pcbStructInfo)
  1728. {
  1729. return OssInfoDecodeAndAllocEx(SigningCertificate_PDU, pbEncoded, cbEncoded,
  1730. dwFlags, pDecodePara,
  1731. EssSignCertificateDecodeExCallback, pvStructInfo,
  1732. pcbStructInfo);
  1733. }