Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1340 lines
41 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: setx509.cpp
  8. //
  9. // Contents: SET Certificate Extension Encode/Decode Functions
  10. //
  11. // ASN.1 implementation uses the OSS compiler.
  12. //
  13. // Functions: DllRegisterServer
  14. // DllUnregisterServer
  15. // DllMain
  16. // SetAsn1AccountAliasEncode
  17. // SetAsn1AccountAliasDecode
  18. // SetAsn1HashedRootKeyEncode
  19. // SetAsn1HashedRootKeyDecode
  20. // SetAsn1CertificateTypeEncode
  21. // SetAsn1CertificateTypeDecode
  22. // SetAsn1MerchantDataEncode
  23. // SetAsn1MerchantDataDecode
  24. //
  25. // CertDllVerifyRevocation
  26. //
  27. // History: 21-Nov-96 philh created
  28. //
  29. //--------------------------------------------------------------------------
  30. #include "global.hxx"
  31. #include <dbgdef.h>
  32. // All the *pvInfo extra stuff needs to be aligned
  33. #define INFO_LEN_ALIGN(Len) ((Len + 7) & ~7)
  34. static HCRYPTASN1MODULE hAsn1Module;
  35. // The following is for test purposes
  36. #define TLS_TEST_COUNT 20
  37. static HCRYPTTLS hTlsTest[TLS_TEST_COUNT];
  38. static HMODULE hMyModule;
  39. // Set to 1 via InterlockedExchange when installed. Only install the
  40. // first time when changed from 0 to 1.
  41. static LONG lInstallDecodeFunctions = 0;
  42. static LONG lInstallRevFunctions = 0;
  43. //+-------------------------------------------------------------------------
  44. // Function: GetEncoder/GetDecoder
  45. //
  46. // Synopsis: Initialize thread local storage for the asn libs
  47. //
  48. // Returns: pointer to an initialized Asn1 encoder/decoder data
  49. // structures
  50. //--------------------------------------------------------------------------
  51. static ASN1encoding_t GetEncoder(void)
  52. {
  53. // The following is for test purposes only
  54. for (DWORD i = 0; i < TLS_TEST_COUNT; i++) {
  55. DWORD_PTR dw = (DWORD_PTR) I_CryptGetTls(hTlsTest[i]);
  56. if (dw == 0)
  57. dw = i;
  58. else
  59. dw++;
  60. I_CryptSetTls(hTlsTest[i], (void *) dw);
  61. }
  62. return I_CryptGetAsn1Encoder(hAsn1Module);
  63. }
  64. static ASN1decoding_t GetDecoder(void)
  65. {
  66. // The following is for test purposes only
  67. for (DWORD i = 0; i < TLS_TEST_COUNT; i++) {
  68. DWORD_PTR dw = (DWORD_PTR) I_CryptGetTls(hTlsTest[i]);
  69. if (dw == 0)
  70. dw = i;
  71. else
  72. dw++;
  73. I_CryptSetTls(hTlsTest[i], (void *) dw);
  74. }
  75. return I_CryptGetAsn1Decoder(hAsn1Module);
  76. }
  77. //+-------------------------------------------------------------------------
  78. // SetX509 allocation and free functions
  79. //--------------------------------------------------------------------------
  80. static void *SetX509Alloc(
  81. IN size_t cbBytes
  82. )
  83. {
  84. void *pv;
  85. pv = malloc(cbBytes);
  86. if (pv == NULL)
  87. SetLastError((DWORD) E_OUTOFMEMORY);
  88. return pv;
  89. }
  90. static void SetX509Free(
  91. IN void *pv
  92. )
  93. {
  94. free(pv);
  95. }
  96. static HRESULT HError()
  97. {
  98. DWORD dw = GetLastError();
  99. HRESULT hr;
  100. if ( dw <= 0xFFFF )
  101. hr = HRESULT_FROM_WIN32 ( dw );
  102. else
  103. hr = dw;
  104. if ( ! FAILED ( hr ) )
  105. {
  106. // somebody failed a call without properly setting an error condition
  107. hr = E_UNEXPECTED;
  108. }
  109. return hr;
  110. }
  111. //+-------------------------------------------------------------------------
  112. // OSS X509 v3 SET Private Extension ASN.1 Encode / Decode functions
  113. //--------------------------------------------------------------------------
  114. BOOL
  115. WINAPI
  116. SetAsn1AccountAliasEncode(
  117. IN DWORD dwCertEncodingType,
  118. IN LPCSTR lpszStructType,
  119. IN BOOL *pbInfo,
  120. OUT BYTE *pbEncoded,
  121. IN OUT DWORD *pcbEncoded
  122. );
  123. BOOL
  124. WINAPI
  125. SetAsn1AccountAliasDecode(
  126. IN DWORD dwCertEncodingType,
  127. IN LPCSTR lpszStructType,
  128. IN const BYTE *pbEncoded,
  129. IN DWORD cbEncoded,
  130. IN DWORD dwFlags,
  131. OUT BOOL *pbInfo,
  132. IN OUT DWORD *pcbInfo
  133. );
  134. BOOL
  135. WINAPI
  136. SetAsn1HashedRootKeyEncode(
  137. IN DWORD dwCertEncodingType,
  138. IN LPCSTR lpszStructType,
  139. IN BYTE rgbInfo[SET_HASHED_ROOT_LEN],
  140. OUT BYTE *pbEncoded,
  141. IN OUT DWORD *pcbEncoded
  142. );
  143. BOOL
  144. WINAPI
  145. SetAsn1HashedRootKeyDecode(
  146. IN DWORD dwCertEncodingType,
  147. IN LPCSTR lpszStructType,
  148. IN const BYTE *pbEncoded,
  149. IN DWORD cbEncoded,
  150. IN DWORD dwFlags,
  151. OUT BYTE rgbInfo[SET_HASHED_ROOT_LEN],
  152. IN OUT DWORD *pcbInfo
  153. );
  154. BOOL
  155. WINAPI
  156. SetAsn1CertificateTypeEncode(
  157. IN DWORD dwCertEncodingType,
  158. IN LPCSTR lpszStructType,
  159. IN PCRYPT_BIT_BLOB pInfo,
  160. OUT BYTE *pbEncoded,
  161. IN OUT DWORD *pcbEncoded
  162. );
  163. BOOL
  164. WINAPI
  165. SetAsn1CertificateTypeDecode(
  166. IN DWORD dwCertEncodingType,
  167. IN LPCSTR lpszStructType,
  168. IN const BYTE *pbEncoded,
  169. IN DWORD cbEncoded,
  170. IN DWORD dwFlags,
  171. OUT PCRYPT_BIT_BLOB pInfo,
  172. IN OUT DWORD *pcbInfo
  173. );
  174. BOOL
  175. WINAPI
  176. SetAsn1MerchantDataEncode(
  177. IN DWORD dwCertEncodingType,
  178. IN LPCSTR lpszStructType,
  179. IN PSET_MERCHANT_DATA_INFO pInfo,
  180. OUT BYTE *pbEncoded,
  181. IN OUT DWORD *pcbEncoded
  182. );
  183. BOOL
  184. WINAPI
  185. SetAsn1MerchantDataDecode(
  186. IN DWORD dwCertEncodingType,
  187. IN LPCSTR lpszStructType,
  188. IN const BYTE *pbEncoded,
  189. IN DWORD cbEncoded,
  190. IN DWORD dwFlags,
  191. OUT PSET_MERCHANT_DATA_INFO pInfo,
  192. IN OUT DWORD *pcbInfo
  193. );
  194. typedef struct _OID_REG_ENTRY {
  195. LPCSTR pszOID;
  196. LPCSTR pszOverrideFuncName;
  197. } OID_REG_ENTRY, *POID_REG_ENTRY;
  198. static const OID_REG_ENTRY RegEncodeBeforeTable[] = {
  199. szOID_SET_ACCOUNT_ALIAS, "SetAsn1AccountAliasEncode",
  200. szOID_SET_HASHED_ROOT_KEY, "SetAsn1HashedRootKeyEncode",
  201. X509_SET_ACCOUNT_ALIAS, "SetAsn1AccountAliasEncode",
  202. X509_SET_HASHED_ROOT_KEY, "SetAsn1HashedRootKeyEncode",
  203. };
  204. #define REG_ENCODE_BEFORE_COUNT (sizeof(RegEncodeBeforeTable) / sizeof(RegEncodeBeforeTable[0]))
  205. static const OID_REG_ENTRY RegEncodeAfterTable[] = {
  206. szOID_SET_CERTIFICATE_TYPE, "SetAsn1CertificateTypeEncode",
  207. szOID_SET_MERCHANT_DATA, "SetAsn1MerchantDataEncode",
  208. X509_SET_CERTIFICATE_TYPE, "SetAsn1CertificateTypeEncode",
  209. X509_SET_MERCHANT_DATA, "SetAsn1MerchantDataEncode"
  210. };
  211. #define REG_ENCODE_AFTER_COUNT (sizeof(RegEncodeAfterTable) / sizeof(RegEncodeAfterTable[0]))
  212. static const OID_REG_ENTRY RegDecodeTable[] = {
  213. szOID_SET_ACCOUNT_ALIAS, "SetAsn1AccountAliasDecode",
  214. szOID_SET_HASHED_ROOT_KEY, "SetAsn1HashedRootKeyDecode",
  215. szOID_SET_CERTIFICATE_TYPE, "SetAsn1CertificateTypeDecode",
  216. szOID_SET_MERCHANT_DATA, "SetAsn1MerchantDataDecode",
  217. X509_SET_ACCOUNT_ALIAS, "SetAsn1AccountAliasDecode",
  218. X509_SET_HASHED_ROOT_KEY, "SetAsn1HashedRootKeyDecode",
  219. X509_SET_CERTIFICATE_TYPE, "SetAsn1CertificateTypeDecode",
  220. X509_SET_MERCHANT_DATA, "SetAsn1MerchantDataDecode"
  221. };
  222. #define REG_DECODE_COUNT (sizeof(RegDecodeTable) / sizeof(RegDecodeTable[0]))
  223. #define OID_INFO_LEN sizeof(CRYPT_OID_INFO)
  224. // Ordered lists of acceptable RDN attribute value types. 0 terminates.
  225. static const DWORD rgdwPrintableValueType[] = { CERT_RDN_PRINTABLE_STRING, 0 };
  226. static const DWORD rgdwIA5ValueType[] = { CERT_RDN_IA5_STRING, 0 };
  227. static const DWORD rgdwNumericValueType[] = { CERT_RDN_NUMERIC_STRING, 0 };
  228. #define RDN_ATTR_ENTRY(pszOID, pwszName, rgdwValueType) \
  229. OID_INFO_LEN, pszOID, pwszName, CRYPT_RDN_ATTR_OID_GROUP_ID, 64, \
  230. sizeof(rgdwValueType), (BYTE *) rgdwValueType
  231. #define DEFAULT_RDN_ATTR_ENTRY(pszOID, pwszName) \
  232. OID_INFO_LEN, pszOID, pwszName, CRYPT_RDN_ATTR_OID_GROUP_ID, 128, 0, NULL
  233. #define EXT_ATTR_ENTRY(pszOID, pwszName) \
  234. OID_INFO_LEN, pszOID, pwszName, CRYPT_EXT_OR_ATTR_OID_GROUP_ID, 0, 0, NULL
  235. #define PUBKEY_ALG_ENTRY(pszOID, pwszName, Algid) \
  236. OID_INFO_LEN, pszOID, pwszName, CRYPT_PUBKEY_ALG_OID_GROUP_ID, \
  237. Algid, 0, NULL
  238. #define PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, Algid, dwFlags) \
  239. OID_INFO_LEN, pszOID, pwszName, CRYPT_PUBKEY_ALG_OID_GROUP_ID, \
  240. Algid, sizeof(dwFlags), (BYTE *) &dwFlags
  241. static const DWORD dwDSSTestFlags = CRYPT_OID_USE_PUBKEY_PARA_FOR_PKCS7_FLAG;
  242. static const DWORD rgdwTestRsaSign[] = {
  243. CALG_RSA_SIGN,
  244. 0,
  245. PROV_RSA_FULL
  246. };
  247. #define TEST_SIGN_EXTRA_ALG_ENTRY(pszOID, pwszName, aiHash, rgdwExtra) \
  248. OID_INFO_LEN, pszOID, pwszName, CRYPT_SIGN_ALG_OID_GROUP_ID, aiHash, \
  249. sizeof(rgdwExtra), (BYTE *) rgdwExtra
  250. #define TEST_RSA_SIGN_ALG_ENTRY(pszOID, pwszName, aiHash) \
  251. TEST_SIGN_EXTRA_ALG_ENTRY(pszOID, pwszName, aiHash, rgdwTestRsaSign)
  252. static CCRYPT_OID_INFO OIDInfoAfterTable[] = {
  253. DEFAULT_RDN_ATTR_ENTRY("1.2.1", L"TestRDNAttr #1"),
  254. RDN_ATTR_ENTRY("1.2.2", L"TestRDNAttr #2", rgdwPrintableValueType),
  255. EXT_ATTR_ENTRY(szOID_SET_CERTIFICATE_TYPE, L"SETCertificateType"),
  256. EXT_ATTR_ENTRY(szOID_SET_HASHED_ROOT_KEY, L"SETHashedRootKey"),
  257. };
  258. #define OID_INFO_AFTER_CNT (sizeof(OIDInfoAfterTable) / \
  259. sizeof(OIDInfoAfterTable[0]))
  260. static CCRYPT_OID_INFO OIDInfoBeforeTable[] = {
  261. // PUBKEY_EXTRA_ALG_ENTRY(szOID_OIWSEC_dsa, L"SETDSSTest", CALG_DSS_SIGN,
  262. // dwDSSTestFlags),
  263. // TEST_RSA_SIGN_ALG_ENTRY(szOID_RSA_SHA1RSA, L"sha1RSA", CALG_SHA1),
  264. // TEST_RSA_SIGN_ALG_ENTRY(szOID_RSA_MD5RSA, L"md5RSA", CALG_MD5),
  265. EXT_ATTR_ENTRY(szOID_SET_ACCOUNT_ALIAS, L"SETAccountAlias"),
  266. EXT_ATTR_ENTRY(szOID_SET_MERCHANT_DATA, L"SETMerchantData"),
  267. };
  268. #define OID_INFO_BEFORE_CNT (sizeof(OIDInfoBeforeTable) / \
  269. sizeof(OIDInfoBeforeTable[0]))
  270. //+-------------------------------------------------------------------------
  271. // Localized Name Table
  272. //--------------------------------------------------------------------------
  273. typedef struct _LOCALIZED_NAME_INFO {
  274. LPCWSTR pwszCryptName;
  275. LPCWSTR pwszLocalizedName;
  276. } LOCALIZED_NAME_INFO, *PLOCALIZED_NAME_INFO;
  277. static LOCALIZED_NAME_INFO LocalizedNameTable[] = {
  278. L"Test", L"*** Test ***",
  279. L"TestTrust", L"### TestTrust ###",
  280. };
  281. #define LOCALIZED_NAME_CNT (sizeof(LocalizedNameTable) / \
  282. sizeof(LocalizedNameTable[0]))
  283. BOOL
  284. WINAPI
  285. CertDllVerifyRevocation(
  286. IN DWORD dwEncodingType,
  287. IN DWORD dwRevType,
  288. IN DWORD cContext,
  289. IN PVOID rgpvContext[],
  290. IN DWORD dwRevFlags,
  291. IN PVOID pvReserved,
  292. IN OUT PCERT_REVOCATION_STATUS pRevStatus
  293. );
  294. STDAPI DllRegisterServer(void)
  295. {
  296. int i;
  297. for (i = 0; i < REG_ENCODE_BEFORE_COUNT; i++) {
  298. DWORD dwFlags = CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG;
  299. if (!CryptRegisterOIDFunction(
  300. X509_ASN_ENCODING,
  301. CRYPT_OID_ENCODE_OBJECT_FUNC,
  302. RegEncodeBeforeTable[i].pszOID,
  303. L"setx509.dll",
  304. RegEncodeBeforeTable[i].pszOverrideFuncName
  305. ))
  306. return HError();
  307. if (!CryptSetOIDFunctionValue(
  308. X509_ASN_ENCODING,
  309. CRYPT_OID_ENCODE_OBJECT_FUNC,
  310. RegEncodeBeforeTable[i].pszOID,
  311. CRYPT_OID_REG_FLAGS_VALUE_NAME,
  312. REG_DWORD,
  313. (BYTE *) &dwFlags,
  314. sizeof(dwFlags)
  315. ))
  316. return HError();
  317. }
  318. for (i = 0; i < REG_ENCODE_AFTER_COUNT; i++)
  319. if (!CryptRegisterOIDFunction(
  320. X509_ASN_ENCODING,
  321. CRYPT_OID_ENCODE_OBJECT_FUNC,
  322. RegEncodeAfterTable[i].pszOID,
  323. L"setx509.dll",
  324. RegEncodeAfterTable[i].pszOverrideFuncName
  325. ))
  326. return HError();
  327. for (i = 0; i < REG_DECODE_COUNT; i++)
  328. if (!CryptRegisterOIDFunction(
  329. X509_ASN_ENCODING,
  330. CRYPT_OID_DECODE_OBJECT_FUNC,
  331. RegDecodeTable[i].pszOID,
  332. L"setx509.dll",
  333. RegDecodeTable[i].pszOverrideFuncName
  334. ))
  335. return HError();
  336. if (!CryptRegisterDefaultOIDFunction(
  337. X509_ASN_ENCODING,
  338. CRYPT_OID_VERIFY_REVOCATION_FUNC,
  339. CRYPT_REGISTER_LAST_INDEX,
  340. L"setx509.dll"
  341. )) {
  342. if (ERROR_FILE_EXISTS != GetLastError())
  343. return HError();
  344. }
  345. for (i = 0; i < OID_INFO_BEFORE_CNT; i++)
  346. if (!CryptRegisterOIDInfo(
  347. &OIDInfoBeforeTable[i],
  348. CRYPT_INSTALL_OID_INFO_BEFORE_FLAG
  349. ))
  350. return HError();
  351. for (i = 0; i < OID_INFO_AFTER_CNT; i++)
  352. if (!CryptRegisterOIDInfo(
  353. &OIDInfoAfterTable[i],
  354. 0 // dwFlags
  355. ))
  356. return HError();
  357. for (i = 0; i < LOCALIZED_NAME_CNT; i++)
  358. if (!CryptSetOIDFunctionValue(
  359. CRYPT_LOCALIZED_NAME_ENCODING_TYPE,
  360. CRYPT_OID_FIND_LOCALIZED_NAME_FUNC,
  361. CRYPT_LOCALIZED_NAME_OID,
  362. LocalizedNameTable[i].pwszCryptName,
  363. REG_SZ,
  364. (const BYTE *) LocalizedNameTable[i].pwszLocalizedName,
  365. (wcslen(LocalizedNameTable[i].pwszLocalizedName) + 1) *
  366. sizeof(WCHAR)
  367. ))
  368. return HError();
  369. return S_OK;
  370. }
  371. STDAPI DllUnregisterServer(void)
  372. {
  373. HRESULT hr = S_OK;
  374. int i;
  375. for (i = 0; i < REG_ENCODE_BEFORE_COUNT; i++) {
  376. if (!CryptUnregisterOIDFunction(
  377. X509_ASN_ENCODING,
  378. CRYPT_OID_ENCODE_OBJECT_FUNC,
  379. RegEncodeBeforeTable[i].pszOID
  380. )) {
  381. if (ERROR_FILE_NOT_FOUND != GetLastError())
  382. hr = HError();
  383. }
  384. }
  385. for (i = 0; i < REG_ENCODE_AFTER_COUNT; i++) {
  386. if (!CryptUnregisterOIDFunction(
  387. X509_ASN_ENCODING,
  388. CRYPT_OID_ENCODE_OBJECT_FUNC,
  389. RegEncodeAfterTable[i].pszOID
  390. )) {
  391. if (ERROR_FILE_NOT_FOUND != GetLastError())
  392. hr = HError();
  393. }
  394. }
  395. for (i = 0; i < REG_DECODE_COUNT; i++) {
  396. if (!CryptUnregisterOIDFunction(
  397. X509_ASN_ENCODING,
  398. CRYPT_OID_DECODE_OBJECT_FUNC,
  399. RegDecodeTable[i].pszOID
  400. )) {
  401. if (ERROR_FILE_NOT_FOUND != GetLastError())
  402. hr = HError();
  403. }
  404. }
  405. if (!CryptUnregisterDefaultOIDFunction(
  406. X509_ASN_ENCODING,
  407. CRYPT_OID_VERIFY_REVOCATION_FUNC,
  408. L"setx509.dll"
  409. )) {
  410. if (ERROR_FILE_NOT_FOUND != GetLastError())
  411. hr = HError();
  412. }
  413. for (i = 0; i < OID_INFO_BEFORE_CNT; i++) {
  414. if (!CryptUnregisterOIDInfo(
  415. &OIDInfoBeforeTable[i]
  416. )) {
  417. if (ERROR_FILE_NOT_FOUND != GetLastError())
  418. hr = HError();
  419. }
  420. }
  421. for (i = 0; i < OID_INFO_AFTER_CNT; i++) {
  422. if (!CryptUnregisterOIDInfo(
  423. &OIDInfoAfterTable[i]
  424. )) {
  425. if (ERROR_FILE_NOT_FOUND != GetLastError())
  426. hr = HError();
  427. }
  428. }
  429. for (i = 0; i < LOCALIZED_NAME_CNT; i++)
  430. if (!CryptSetOIDFunctionValue(
  431. CRYPT_LOCALIZED_NAME_ENCODING_TYPE,
  432. CRYPT_OID_FIND_LOCALIZED_NAME_FUNC,
  433. CRYPT_LOCALIZED_NAME_OID,
  434. LocalizedNameTable[i].pwszCryptName,
  435. REG_SZ,
  436. NULL,
  437. 0
  438. ))
  439. return HError();
  440. return hr;
  441. }
  442. static const CRYPT_OID_FUNC_ENTRY SetEncodeFuncTable[] = {
  443. szOID_SET_ACCOUNT_ALIAS, SetAsn1AccountAliasEncode,
  444. szOID_SET_HASHED_ROOT_KEY, SetAsn1HashedRootKeyEncode,
  445. szOID_SET_CERTIFICATE_TYPE, SetAsn1CertificateTypeEncode,
  446. szOID_SET_MERCHANT_DATA, SetAsn1MerchantDataEncode,
  447. X509_SET_ACCOUNT_ALIAS, SetAsn1AccountAliasEncode,
  448. X509_SET_HASHED_ROOT_KEY, SetAsn1HashedRootKeyEncode,
  449. X509_SET_CERTIFICATE_TYPE, SetAsn1CertificateTypeEncode,
  450. X509_SET_MERCHANT_DATA, SetAsn1MerchantDataEncode,
  451. };
  452. #define SET_ENCODE_FUNC_COUNT (sizeof(SetEncodeFuncTable) / \
  453. sizeof(SetEncodeFuncTable[0]))
  454. static const CRYPT_OID_FUNC_ENTRY SetDecodeFuncTable[] = {
  455. szOID_SET_ACCOUNT_ALIAS, SetAsn1AccountAliasDecode,
  456. szOID_SET_HASHED_ROOT_KEY, SetAsn1HashedRootKeyDecode,
  457. szOID_SET_CERTIFICATE_TYPE, SetAsn1CertificateTypeDecode,
  458. szOID_SET_MERCHANT_DATA, SetAsn1MerchantDataDecode,
  459. X509_SET_ACCOUNT_ALIAS, SetAsn1AccountAliasDecode,
  460. X509_SET_HASHED_ROOT_KEY, SetAsn1HashedRootKeyDecode,
  461. X509_SET_CERTIFICATE_TYPE, SetAsn1CertificateTypeDecode,
  462. X509_SET_MERCHANT_DATA, SetAsn1MerchantDataDecode
  463. };
  464. #define SET_DECODE_FUNC_COUNT (sizeof(SetDecodeFuncTable) / \
  465. sizeof(SetDecodeFuncTable[0]))
  466. static const CRYPT_OID_FUNC_ENTRY SetRevFuncTable[] = {
  467. CRYPT_DEFAULT_OID, CertDllVerifyRevocation
  468. };
  469. #define SET_REV_FUNC_COUNT (sizeof(SetRevFuncTable) / \
  470. sizeof(SetRevFuncTable[0]))
  471. //+-------------------------------------------------------------------------
  472. // Dll initialization
  473. //--------------------------------------------------------------------------
  474. BOOL
  475. WINAPI
  476. DllMain(
  477. HMODULE hModule,
  478. ULONG ulReason,
  479. LPVOID lpReserved)
  480. {
  481. BOOL fRet;
  482. DWORD i;
  483. DWORD_PTR dwTlsValue;
  484. switch (ulReason) {
  485. case DLL_PROCESS_ATTACH:
  486. // The following is for test purposes only
  487. for (i = 0; i < TLS_TEST_COUNT; i++) {
  488. if (NULL == (hTlsTest[i] = I_CryptAllocTls()))
  489. goto CryptAllocTlsError;
  490. }
  491. #ifdef OSS_CRYPT_ASN1
  492. if (0 == (hAsn1Module = I_CryptInstallAsn1Module(ossx509, 0, NULL)))
  493. #else
  494. X509_Module_Startup();
  495. if (0 == (hAsn1Module = I_CryptInstallAsn1Module(
  496. X509_Module, 0, NULL)))
  497. #endif // OSS_CRYPT_ASN1
  498. goto CryptInstallAsn1ModuleError;
  499. #if 0
  500. // For testing purposes not installed. Always want to call the
  501. // encode functions via dll load.
  502. if (!CryptInstallOIDFunctionAddress(
  503. hModule,
  504. X509_ASN_ENCODING,
  505. CRYPT_OID_ENCODE_OBJECT_FUNC,
  506. SET_ENCODE_FUNC_COUNT,
  507. SetEncodeFuncTable,
  508. 0)) // dwFlags
  509. goto CryptInstallOIDFunctionAddressError;
  510. #endif
  511. #if 0
  512. // For testing purposes deferred until first Decode
  513. if (!CryptInstallOIDFunctionAddress(
  514. hModule,
  515. X509_ASN_ENCODING,
  516. CRYPT_OID_DECODE_OBJECT_FUNC,
  517. SET_DECODE_FUNC_COUNT,
  518. SetDecodeFuncTable,
  519. 0)) // dwFlags
  520. goto CryptInstallOIDFunctionAddressError;
  521. #endif
  522. hMyModule = hModule;
  523. break;
  524. case DLL_PROCESS_DETACH:
  525. I_CryptUninstallAsn1Module(hAsn1Module);
  526. #ifndef OSS_CRYPT_ASN1
  527. X509_Module_Cleanup();
  528. #endif // OSS_CRYPT_ASN1
  529. // The following is for test purposes only
  530. for (i = 0; i < TLS_TEST_COUNT; i++) {
  531. I_CryptFreeTls(hTlsTest[i], NULL);
  532. }
  533. break;
  534. case DLL_THREAD_DETACH:
  535. // The following is for test purposes only
  536. for (i = 0; i < TLS_TEST_COUNT; i++)
  537. dwTlsValue = (DWORD_PTR) I_CryptDetachTls(hTlsTest[i]);
  538. break;
  539. default:
  540. break;
  541. }
  542. fRet = TRUE;
  543. CommonReturn:
  544. return fRet;
  545. ErrorReturn:
  546. fRet = FALSE;
  547. goto CommonReturn;
  548. TRACE_ERROR(CryptAllocTlsError)
  549. TRACE_ERROR(CryptInstallAsn1ModuleError)
  550. #if 0
  551. TRACE_ERROR(CryptInstallOIDFunctionAddressError)
  552. #endif
  553. }
  554. // Defer installation until the first decode. Called by each of the decode
  555. // functions.
  556. //
  557. // Do the InterlockedExchange to ensure a single installation
  558. static void InstallDecodeFunctions()
  559. {
  560. #if 0
  561. if (0 == InterlockedExchange(&lInstallDecodeFunctions, 1)) {
  562. if (!CryptInstallOIDFunctionAddress(
  563. hMyModule,
  564. X509_ASN_ENCODING,
  565. CRYPT_OID_DECODE_OBJECT_FUNC,
  566. SET_DECODE_FUNC_COUNT,
  567. SetDecodeFuncTable,
  568. 0)) // dwFlags
  569. goto CryptInstallOIDFunctionAddressError;
  570. }
  571. CommonReturn:
  572. return;
  573. ErrorReturn:
  574. goto CommonReturn;
  575. TRACE_ERROR(CryptInstallOIDFunctionAddressError)
  576. #endif
  577. }
  578. // Defer installation until the first revocation.
  579. //
  580. // Do the InterlockedExchange to ensure a single installation
  581. static void InstallRevFunctions()
  582. {
  583. if (0 == InterlockedExchange(&lInstallRevFunctions, 1)) {
  584. if (!CryptInstallOIDFunctionAddress(
  585. hMyModule,
  586. X509_ASN_ENCODING,
  587. CRYPT_OID_VERIFY_REVOCATION_FUNC,
  588. SET_REV_FUNC_COUNT,
  589. SetRevFuncTable,
  590. 0)) // dwFlags
  591. goto CryptInstallOIDFunctionAddressError;
  592. }
  593. CommonReturn:
  594. return;
  595. ErrorReturn:
  596. goto CommonReturn;
  597. TRACE_ERROR(CryptInstallOIDFunctionAddressError)
  598. }
  599. BOOL
  600. WINAPI
  601. CertDllVerifyRevocation(
  602. IN DWORD dwEncodingType,
  603. IN DWORD dwRevType,
  604. IN DWORD cContext,
  605. IN PVOID rgpvContext[],
  606. IN DWORD dwRevFlags,
  607. IN PVOID pvReserved,
  608. IN OUT PCERT_REVOCATION_STATUS pRevStatus
  609. )
  610. {
  611. BOOL fResult = FALSE;
  612. DWORD dwIndex = 0;
  613. DWORD dwError = 0;
  614. HCERTSTORE hStore = NULL;
  615. HCERTSTORE hLinkStore = NULL;
  616. InstallRevFunctions();
  617. if (GET_CERT_ENCODING_TYPE(dwEncodingType) != CRYPT_ASN_ENCODING)
  618. goto NoRevocationCheckForEncodingTypeError;
  619. if (dwRevType != CERT_CONTEXT_REVOCATION_TYPE)
  620. goto NoRevocationCheckForRevTypeError;
  621. hStore = CertOpenSystemStore(NULL, "Test");
  622. if (NULL == hStore)
  623. goto OpenTestStoreError;
  624. hLinkStore = CertOpenStore(
  625. CERT_STORE_PROV_MEMORY,
  626. 0, // dwEncodingType
  627. 0, // hCryptProv
  628. 0, // dwFlags
  629. NULL // pvPara
  630. );
  631. if (NULL == hLinkStore)
  632. goto OpenLinkStoreError;
  633. for (dwIndex = 0; dwIndex < cContext; dwIndex++) {
  634. PCCERT_CONTEXT pCert = (PCCERT_CONTEXT) rgpvContext[dwIndex];
  635. PCERT_EXTENSION pExt;
  636. PCCERT_CONTEXT pIssuer;
  637. DWORD dwFlags;
  638. // Check that the certificate has a SET extension
  639. if (NULL == (pExt = CertFindExtension(szOID_SET_CERTIFICATE_TYPE,
  640. pCert->pCertInfo->cExtension,
  641. pCert->pCertInfo->rgExtension)))
  642. goto NoSETX509ExtensionError;
  643. // Attempt to get the certificate's issuer from the test store.
  644. // If found check signature and revocation.
  645. // For testing purposes: first found issuer.
  646. dwFlags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
  647. if (NULL == (pIssuer = CertGetIssuerCertificateFromStore(
  648. hStore,
  649. pCert,
  650. NULL, // pPrevIssuerContext,
  651. &dwFlags)))
  652. goto NoIssuerError;
  653. else {
  654. BOOL fLinkResult;
  655. DWORD dwLinkFlags =
  656. CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
  657. PCCERT_CONTEXT pLinkIssuer = NULL;
  658. // Check that we get the same results if we put a link to the
  659. // issuer in a store and try to verify using the link.
  660. fLinkResult = CertAddCertificateLinkToStore(
  661. hLinkStore,
  662. pIssuer,
  663. CERT_STORE_ADD_ALWAYS,
  664. &pLinkIssuer
  665. );
  666. CertFreeCertificateContext(pIssuer);
  667. if (!fLinkResult)
  668. goto AddCertificateLinkError;
  669. if (!CertVerifySubjectCertificateContext(
  670. pCert,
  671. pLinkIssuer,
  672. &dwLinkFlags
  673. ))
  674. goto VerifySubjectCertificateContextError;
  675. if (dwLinkFlags != dwFlags)
  676. goto BadLinkVerifyResults;
  677. if (dwFlags & CERT_STORE_SIGNATURE_FLAG)
  678. goto BadCertificateSignatureError;
  679. if (dwFlags & CERT_STORE_NO_CRL_FLAG)
  680. goto NoCRLError;
  681. if (dwFlags & CERT_STORE_REVOCATION_FLAG) {
  682. pRevStatus->dwReason = CRL_REASON_KEY_COMPROMISE;
  683. goto CertificateRevocationError;
  684. }
  685. // else
  686. // A checked certificate that hasn't been revoked.
  687. assert(dwFlags == 0);
  688. }
  689. }
  690. fResult = TRUE;
  691. dwIndex = 0;
  692. CommonReturn:
  693. if (hStore)
  694. CertCloseStore(hStore, 0);
  695. if (hLinkStore)
  696. CertCloseStore(hLinkStore, CERT_CLOSE_STORE_FORCE_FLAG);
  697. pRevStatus->dwIndex = dwIndex;
  698. pRevStatus->dwError = dwError;
  699. return fResult;
  700. ErrorReturn:
  701. dwError = GetLastError();
  702. fResult = FALSE;
  703. goto CommonReturn;
  704. TRACE_ERROR(OpenTestStoreError)
  705. TRACE_ERROR(OpenLinkStoreError)
  706. SET_ERROR(NoRevocationCheckForEncodingTypeError, CRYPT_E_NO_REVOCATION_CHECK)
  707. SET_ERROR(NoRevocationCheckForRevTypeError, CRYPT_E_NO_REVOCATION_CHECK)
  708. SET_ERROR(NoSETX509ExtensionError, CRYPT_E_NO_REVOCATION_CHECK)
  709. TRACE_ERROR(NoIssuerError)
  710. SET_ERROR(BadCertificateSignatureError, CRYPT_E_NO_REVOCATION_CHECK)
  711. SET_ERROR(NoCRLError, CRYPT_E_NO_REVOCATION_CHECK)
  712. SET_ERROR(CertificateRevocationError, CRYPT_E_REVOKED)
  713. TRACE_ERROR(AddCertificateLinkError)
  714. TRACE_ERROR(VerifySubjectCertificateContextError)
  715. SET_ERROR(BadLinkVerifyResults, E_UNEXPECTED)
  716. }
  717. //+-------------------------------------------------------------------------
  718. // OSS X509 v3 ASN.1 Set / Get functions
  719. //
  720. // Called by the OSS X509 encode/decode functions.
  721. //
  722. // Assumption: all types are UNBOUNDED.
  723. //
  724. // The Get functions decrement *plRemainExtra and advance
  725. // *ppbExtra. When *plRemainExtra becomes negative, the functions continue
  726. // with the length calculation but stop doing any copies.
  727. // The functions don't return an error for a negative *plRemainExtra.
  728. //--------------------------------------------------------------------------
  729. //+-------------------------------------------------------------------------
  730. // Set/Get CRYPT_DATA_BLOB (Octet String)
  731. //--------------------------------------------------------------------------
  732. static inline void SetX509SetOctetString(
  733. IN PCRYPT_DATA_BLOB pInfo,
  734. OUT OCTETSTRING *pOss
  735. )
  736. {
  737. pOss->value = pInfo->pbData;
  738. pOss->length = pInfo->cbData;
  739. }
  740. static inline void SetX509GetOctetString(
  741. IN OCTETSTRING *pOss,
  742. IN DWORD dwFlags,
  743. OUT PCRYPT_DATA_BLOB pInfo,
  744. IN OUT BYTE **ppbExtra,
  745. IN OUT LONG *plRemainExtra
  746. )
  747. {
  748. PkiAsn1GetOctetString(pOss->length, pOss->value, dwFlags,
  749. pInfo, ppbExtra, plRemainExtra);
  750. }
  751. //+-------------------------------------------------------------------------
  752. // Set/Get CRYPT_BIT_BLOB
  753. //--------------------------------------------------------------------------
  754. static inline void SetX509SetBit(
  755. IN PCRYPT_BIT_BLOB pInfo,
  756. OUT BITSTRING *pOss
  757. )
  758. {
  759. PkiAsn1SetBitString(pInfo, &pOss->length, &pOss->value);
  760. }
  761. static inline void SetX509GetBit(
  762. IN BITSTRING *pOss,
  763. IN DWORD dwFlags,
  764. OUT PCRYPT_BIT_BLOB pInfo,
  765. IN OUT BYTE **ppbExtra,
  766. IN OUT LONG *plRemainExtra
  767. )
  768. {
  769. PkiAsn1GetBitString(pOss->length, pOss->value, dwFlags,
  770. pInfo, ppbExtra, plRemainExtra);
  771. }
  772. //+-------------------------------------------------------------------------
  773. // Set/Get LPSTR (IA5 String)
  774. //--------------------------------------------------------------------------
  775. static inline void SetX509SetIA5(
  776. IN LPSTR psz,
  777. OUT IA5STRING *pOss
  778. )
  779. {
  780. pOss->value = psz;
  781. pOss->length = strlen(psz);
  782. }
  783. static inline void SetX509GetIA5(
  784. IN IA5STRING *pOss,
  785. IN DWORD dwFlags,
  786. OUT LPSTR *ppsz,
  787. IN OUT BYTE **ppbExtra,
  788. IN OUT LONG *plRemainExtra
  789. )
  790. {
  791. PkiAsn1GetIA5String(pOss->length, pOss->value, dwFlags,
  792. ppsz, ppbExtra, plRemainExtra);
  793. }
  794. //+-------------------------------------------------------------------------
  795. // Encode an OSS formatted info structure
  796. //
  797. // Called by the SetX509*Encode() functions.
  798. //--------------------------------------------------------------------------
  799. static BOOL SetAsn1Encode(
  800. IN int pdunum,
  801. IN void *pOssInfo,
  802. OUT BYTE *pbEncoded,
  803. IN OUT DWORD *pcbEncoded
  804. )
  805. {
  806. return PkiAsn1EncodeInfo(
  807. GetEncoder(),
  808. pdunum,
  809. pOssInfo,
  810. pbEncoded,
  811. pcbEncoded);
  812. }
  813. //+-------------------------------------------------------------------------
  814. // Decode into an allocated, OSS formatted info structure
  815. //
  816. // Called by the SetX509*Decode() functions.
  817. //--------------------------------------------------------------------------
  818. static BOOL SetAsn1DecodeAndAlloc(
  819. IN int pdunum,
  820. IN const BYTE *pbEncoded,
  821. IN DWORD cbEncoded,
  822. OUT void **ppOssInfo
  823. )
  824. {
  825. // For testing purposes, defer installation of decode functions until
  826. // first decode which is loaded via being registered.
  827. InstallDecodeFunctions();
  828. return PkiAsn1DecodeAndAllocInfo(
  829. GetDecoder(),
  830. pdunum,
  831. pbEncoded,
  832. cbEncoded,
  833. ppOssInfo);
  834. }
  835. //+-------------------------------------------------------------------------
  836. // Free an allocated, OSS formatted info structure
  837. //
  838. // Called by the SetX509*Decode() functions.
  839. //--------------------------------------------------------------------------
  840. static void SetAsn1Free(
  841. IN int pdunum,
  842. IN void *pOssInfo
  843. )
  844. {
  845. if (pOssInfo) {
  846. DWORD dwErr = GetLastError();
  847. // TlsGetValue globbers LastError
  848. PkiAsn1FreeInfo(GetDecoder(), pdunum, pOssInfo);
  849. SetLastError(dwErr);
  850. }
  851. }
  852. //+-------------------------------------------------------------------------
  853. // SET Account Alias Private Extension Encode (OSS X509)
  854. //--------------------------------------------------------------------------
  855. BOOL
  856. WINAPI
  857. SetAsn1AccountAliasEncode(
  858. IN DWORD dwCertEncodingType,
  859. IN LPCSTR lpszStructType,
  860. IN BOOL *pbInfo,
  861. OUT BYTE *pbEncoded,
  862. IN OUT DWORD *pcbEncoded
  863. )
  864. {
  865. ossBoolean OssSETAccountAlias = (ossBoolean) *pbInfo;
  866. return SetAsn1Encode(
  867. SETAccountAlias_PDU,
  868. &OssSETAccountAlias,
  869. pbEncoded,
  870. pcbEncoded
  871. );
  872. }
  873. //+-------------------------------------------------------------------------
  874. // SET Account Alias Private Extension Decode (OSS X509)
  875. //--------------------------------------------------------------------------
  876. BOOL
  877. WINAPI
  878. SetAsn1AccountAliasDecode(
  879. IN DWORD dwCertEncodingType,
  880. IN LPCSTR lpszStructType,
  881. IN const BYTE *pbEncoded,
  882. IN DWORD cbEncoded,
  883. IN DWORD dwFlags,
  884. OUT BOOL *pbInfo,
  885. IN OUT DWORD *pcbInfo
  886. )
  887. {
  888. BOOL fResult;
  889. ossBoolean *pSETAccountAlias = NULL;
  890. if ((fResult = SetAsn1DecodeAndAlloc(
  891. SETAccountAlias_PDU,
  892. pbEncoded,
  893. cbEncoded,
  894. (void **) &pSETAccountAlias))) {
  895. if (*pcbInfo < sizeof(BOOL)) {
  896. if (pbInfo) {
  897. fResult = FALSE;
  898. SetLastError((DWORD) ERROR_MORE_DATA);
  899. }
  900. } else
  901. *pbInfo = (BOOL) *pSETAccountAlias;
  902. *pcbInfo = sizeof(BOOL);
  903. } else {
  904. if (*pcbInfo >= sizeof(BOOL))
  905. *pbInfo = FALSE;
  906. *pcbInfo = 0;
  907. }
  908. SetAsn1Free(SETAccountAlias_PDU, pSETAccountAlias);
  909. return fResult;
  910. }
  911. //+-------------------------------------------------------------------------
  912. // SET Hashed Root Private Extension Encode (OSS X509)
  913. //--------------------------------------------------------------------------
  914. BOOL
  915. WINAPI
  916. SetAsn1HashedRootKeyEncode(
  917. IN DWORD dwCertEncodingType,
  918. IN LPCSTR lpszStructType,
  919. IN BYTE rgbInfo[SET_HASHED_ROOT_LEN],
  920. OUT BYTE *pbEncoded,
  921. IN OUT DWORD *pcbEncoded
  922. )
  923. {
  924. OCTETSTRING OssSETHashedRootKey;
  925. OssSETHashedRootKey.value = rgbInfo;
  926. OssSETHashedRootKey.length = SET_HASHED_ROOT_LEN;
  927. return SetAsn1Encode(
  928. SETHashedRootKey_PDU,
  929. &OssSETHashedRootKey,
  930. pbEncoded,
  931. pcbEncoded
  932. );
  933. }
  934. //+-------------------------------------------------------------------------
  935. // SET Hashed Root Private Extension Decode (OSS X509)
  936. //--------------------------------------------------------------------------
  937. BOOL
  938. WINAPI
  939. SetAsn1HashedRootKeyDecode(
  940. IN DWORD dwCertEncodingType,
  941. IN LPCSTR lpszStructType,
  942. IN const BYTE *pbEncoded,
  943. IN DWORD cbEncoded,
  944. IN DWORD dwFlags,
  945. OUT BYTE rgbInfo[SET_HASHED_ROOT_LEN],
  946. IN OUT DWORD *pcbInfo
  947. )
  948. {
  949. BOOL fResult;
  950. OCTETSTRING *pSETHashedRootKey = NULL;
  951. if ((fResult = SetAsn1DecodeAndAlloc(
  952. SETHashedRootKey_PDU,
  953. pbEncoded,
  954. cbEncoded,
  955. (void **) &pSETHashedRootKey))) {
  956. if (pSETHashedRootKey->length != SET_HASHED_ROOT_LEN) {
  957. fResult = FALSE;
  958. SetLastError((DWORD) CRYPT_E_BAD_ENCODE);
  959. *pcbInfo = 0;
  960. } else {
  961. if (*pcbInfo < SET_HASHED_ROOT_LEN) {
  962. if (rgbInfo) {
  963. fResult = FALSE;
  964. SetLastError((DWORD) ERROR_MORE_DATA);
  965. }
  966. } else
  967. memcpy(rgbInfo, pSETHashedRootKey->value, SET_HASHED_ROOT_LEN);
  968. *pcbInfo = SET_HASHED_ROOT_LEN;
  969. }
  970. } else
  971. *pcbInfo = 0;
  972. SetAsn1Free(SETHashedRootKey_PDU, pSETHashedRootKey);
  973. return fResult;
  974. }
  975. //+-------------------------------------------------------------------------
  976. // SET Certificate Type Private Extension Encode (OSS X509)
  977. //--------------------------------------------------------------------------
  978. BOOL
  979. WINAPI
  980. SetAsn1CertificateTypeEncode(
  981. IN DWORD dwCertEncodingType,
  982. IN LPCSTR lpszStructType,
  983. IN PCRYPT_BIT_BLOB pInfo,
  984. OUT BYTE *pbEncoded,
  985. IN OUT DWORD *pcbEncoded
  986. )
  987. {
  988. BITSTRING OssSETCertificateType;
  989. SetX509SetBit(pInfo, &OssSETCertificateType);
  990. return SetAsn1Encode(
  991. SETCertificateType_PDU,
  992. &OssSETCertificateType,
  993. pbEncoded,
  994. pcbEncoded
  995. );
  996. }
  997. //+-------------------------------------------------------------------------
  998. // SET Certificate Type Private Extension Decode (OSS X509)
  999. //--------------------------------------------------------------------------
  1000. BOOL
  1001. WINAPI
  1002. SetAsn1CertificateTypeDecode(
  1003. IN DWORD dwCertEncodingType,
  1004. IN LPCSTR lpszStructType,
  1005. IN const BYTE *pbEncoded,
  1006. IN DWORD cbEncoded,
  1007. IN DWORD dwFlags,
  1008. OUT PCRYPT_BIT_BLOB pInfo,
  1009. IN OUT DWORD *pcbInfo
  1010. )
  1011. {
  1012. BOOL fResult;
  1013. BITSTRING *pSETCertificateType = NULL;
  1014. BYTE *pbExtra;
  1015. LONG lRemainExtra;
  1016. if (pInfo == NULL)
  1017. *pcbInfo = 0;
  1018. if (!SetAsn1DecodeAndAlloc(
  1019. SETCertificateType_PDU,
  1020. pbEncoded,
  1021. cbEncoded,
  1022. (void **) &pSETCertificateType))
  1023. goto ErrorReturn;
  1024. // for lRemainExtra < 0, LENGTH_ONLY calculation
  1025. lRemainExtra = (LONG) *pcbInfo - sizeof(CRYPT_BIT_BLOB);
  1026. if (lRemainExtra < 0) {
  1027. pbExtra = NULL;
  1028. } else
  1029. pbExtra = (BYTE *) pInfo + sizeof(CRYPT_BIT_BLOB);
  1030. SetX509GetBit(pSETCertificateType, dwFlags, pInfo, &pbExtra, &lRemainExtra);
  1031. if (lRemainExtra >= 0)
  1032. *pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
  1033. else {
  1034. *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
  1035. if (pInfo) goto LengthError;
  1036. }
  1037. fResult = TRUE;
  1038. goto CommonReturn;
  1039. LengthError:
  1040. SetLastError((DWORD) ERROR_MORE_DATA);
  1041. fResult = FALSE;
  1042. goto CommonReturn;
  1043. ErrorReturn:
  1044. *pcbInfo = 0;
  1045. fResult = FALSE;
  1046. CommonReturn:
  1047. SetAsn1Free(SETCertificateType_PDU, pSETCertificateType);
  1048. return fResult;
  1049. }
  1050. //+-------------------------------------------------------------------------
  1051. // SET Merchant Data Private Extension Encode (OSS X509)
  1052. //--------------------------------------------------------------------------
  1053. BOOL
  1054. WINAPI
  1055. SetAsn1MerchantDataEncode(
  1056. IN DWORD dwCertEncodingType,
  1057. IN LPCSTR lpszStructType,
  1058. IN PSET_MERCHANT_DATA_INFO pInfo,
  1059. OUT BYTE *pbEncoded,
  1060. IN OUT DWORD *pcbEncoded
  1061. )
  1062. {
  1063. SETMerchantData OssSETMerchantData;
  1064. HCRYPTOIDFUNCSET hX509EncodeFuncSet;
  1065. void *pvFuncAddr;
  1066. HCRYPTOIDFUNCADDR hFuncAddr;
  1067. SetX509SetIA5(pInfo->pszMerID, &OssSETMerchantData.merID);
  1068. SetX509SetIA5(pInfo->pszMerAcquirerBIN,
  1069. (IA5STRING *) &OssSETMerchantData.merAcquirerBIN);
  1070. SetX509SetIA5(pInfo->pszMerTermID, &OssSETMerchantData.merTermID);
  1071. SetX509SetIA5(pInfo->pszMerName, &OssSETMerchantData.merName);
  1072. SetX509SetIA5(pInfo->pszMerCity, &OssSETMerchantData.merCity);
  1073. SetX509SetIA5(pInfo->pszMerStateProvince,
  1074. &OssSETMerchantData.merStateProvince);
  1075. SetX509SetIA5(pInfo->pszMerPostalCode, &OssSETMerchantData.merPostalCode);
  1076. SetX509SetIA5(pInfo->pszMerCountry, &OssSETMerchantData.merCountry);
  1077. SetX509SetIA5(pInfo->pszMerPhone, &OssSETMerchantData.merPhone);
  1078. OssSETMerchantData.merPhoneRelease = (pInfo->fMerPhoneRelease != 0);
  1079. OssSETMerchantData.merAuthFlag = (pInfo->fMerAuthFlag != 0);
  1080. // For testing purposes, verify that CryptGetOIDFunctionAddress fails
  1081. // to find a pre-installed function
  1082. if (NULL == (hX509EncodeFuncSet = CryptInitOIDFunctionSet(
  1083. CRYPT_OID_ENCODE_OBJECT_FUNC,
  1084. 0)))
  1085. goto CryptInitOIDFunctionSetError;
  1086. if (CryptGetOIDFunctionAddress(
  1087. hX509EncodeFuncSet,
  1088. X509_ASN_ENCODING,
  1089. szOID_SET_MERCHANT_DATA,
  1090. CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
  1091. &pvFuncAddr,
  1092. &hFuncAddr
  1093. )) {
  1094. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  1095. goto GotUnexpectedPreinstalledFunction;
  1096. }
  1097. // Verify we get our registered address
  1098. if (!CryptGetOIDFunctionAddress(
  1099. hX509EncodeFuncSet,
  1100. X509_ASN_ENCODING,
  1101. szOID_SET_MERCHANT_DATA,
  1102. 0, // dwFlags
  1103. &pvFuncAddr,
  1104. &hFuncAddr
  1105. ))
  1106. goto DidNotGetRegisteredFunction;
  1107. else
  1108. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  1109. return SetAsn1Encode(
  1110. SETMerchantData_PDU,
  1111. &OssSETMerchantData,
  1112. pbEncoded,
  1113. pcbEncoded
  1114. );
  1115. ErrorReturn:
  1116. *pcbEncoded = 0;
  1117. return FALSE;
  1118. TRACE_ERROR(CryptInitOIDFunctionSetError)
  1119. SET_ERROR(GotUnexpectedPreinstalledFunction, E_UNEXPECTED)
  1120. SET_ERROR(DidNotGetRegisteredFunction, E_UNEXPECTED)
  1121. }
  1122. //+-------------------------------------------------------------------------
  1123. // SET Merchant Data Private Extension Decode (OSS X509)
  1124. //--------------------------------------------------------------------------
  1125. BOOL
  1126. WINAPI
  1127. SetAsn1MerchantDataDecode(
  1128. IN DWORD dwCertEncodingType,
  1129. IN LPCSTR lpszStructType,
  1130. IN const BYTE *pbEncoded,
  1131. IN DWORD cbEncoded,
  1132. IN DWORD dwFlags,
  1133. OUT PSET_MERCHANT_DATA_INFO pInfo,
  1134. IN OUT DWORD *pcbInfo
  1135. )
  1136. {
  1137. BOOL fResult;
  1138. SETMerchantData *pSETMerchantData = NULL;
  1139. BYTE *pbExtra;
  1140. LONG lRemainExtra;
  1141. if (pInfo == NULL)
  1142. *pcbInfo = 0;
  1143. if (!SetAsn1DecodeAndAlloc(
  1144. SETMerchantData_PDU,
  1145. pbEncoded,
  1146. cbEncoded,
  1147. (void **) &pSETMerchantData))
  1148. goto ErrorReturn;
  1149. // for lRemainExtra < 0, LENGTH_ONLY calculation
  1150. lRemainExtra = (LONG) *pcbInfo - sizeof(SET_MERCHANT_DATA_INFO);
  1151. if (lRemainExtra < 0) {
  1152. pbExtra = NULL;
  1153. } else {
  1154. // Update fields not needing extra memory after the
  1155. // SET_MERCHANT_DATA_INFO
  1156. pInfo->fMerPhoneRelease = pSETMerchantData->merPhoneRelease;
  1157. pInfo->fMerAuthFlag = pSETMerchantData->merAuthFlag;
  1158. pbExtra = (BYTE *) pInfo + sizeof(SET_MERCHANT_DATA_INFO);
  1159. }
  1160. SetX509GetIA5(&pSETMerchantData->merID, dwFlags, &pInfo->pszMerID,
  1161. &pbExtra, &lRemainExtra);
  1162. SetX509GetIA5((IA5STRING *) &pSETMerchantData->merAcquirerBIN, dwFlags,
  1163. &pInfo->pszMerAcquirerBIN, &pbExtra, &lRemainExtra);
  1164. SetX509GetIA5(&pSETMerchantData->merTermID, dwFlags, &pInfo->pszMerTermID,
  1165. &pbExtra, &lRemainExtra);
  1166. SetX509GetIA5(&pSETMerchantData->merName, dwFlags, &pInfo->pszMerName,
  1167. &pbExtra, &lRemainExtra);
  1168. SetX509GetIA5(&pSETMerchantData->merCity, dwFlags, &pInfo->pszMerCity,
  1169. &pbExtra, &lRemainExtra);
  1170. SetX509GetIA5(&pSETMerchantData->merStateProvince, dwFlags,
  1171. &pInfo->pszMerStateProvince, &pbExtra, &lRemainExtra);
  1172. SetX509GetIA5(&pSETMerchantData->merPostalCode, dwFlags,
  1173. &pInfo->pszMerPostalCode, &pbExtra, &lRemainExtra);
  1174. SetX509GetIA5(&pSETMerchantData->merCountry, dwFlags, &pInfo->pszMerCountry,
  1175. &pbExtra, &lRemainExtra);
  1176. SetX509GetIA5(&pSETMerchantData->merPhone, dwFlags, &pInfo->pszMerPhone,
  1177. &pbExtra, &lRemainExtra);
  1178. if (lRemainExtra >= 0)
  1179. *pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
  1180. else {
  1181. *pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
  1182. if (pInfo) goto LengthError;
  1183. }
  1184. fResult = TRUE;
  1185. goto CommonReturn;
  1186. LengthError:
  1187. SetLastError((DWORD) ERROR_MORE_DATA);
  1188. fResult = FALSE;
  1189. goto CommonReturn;
  1190. ErrorReturn:
  1191. *pcbInfo = 0;
  1192. fResult = FALSE;
  1193. CommonReturn:
  1194. SetAsn1Free(SETMerchantData_PDU, pSETMerchantData);
  1195. return fResult;
  1196. }