PageRenderTime 37ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/referencesource/System/security/system/security/cryptography/x509/x509certificate2collection.cs

https://github.com/pruiz/mono
C# | 1070 lines | 810 code | 162 blank | 98 comment | 181 complexity | 754c6d7ecaa656608e5d4649c8730003 MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. //
  7. // X509Certificate2Collection.cs
  8. //
  9. namespace System.Security.Cryptography.X509Certificates {
  10. using System;
  11. using System.Collections;
  12. using System.Globalization;
  13. using System.IO;
  14. using System.Runtime.InteropServices;
  15. using System.Runtime.InteropServices.ComTypes;
  16. using System.Security.Cryptography;
  17. using System.Security.Permissions;
  18. using System.Text;
  19. using System.Runtime.Versioning;
  20. using _FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
  21. public enum X509FindType {
  22. FindByThumbprint = 0,
  23. FindBySubjectName = 1,
  24. FindBySubjectDistinguishedName = 2,
  25. FindByIssuerName = 3,
  26. FindByIssuerDistinguishedName = 4,
  27. FindBySerialNumber = 5,
  28. FindByTimeValid = 6,
  29. FindByTimeNotYetValid = 7,
  30. FindByTimeExpired = 8,
  31. FindByTemplateName = 9,
  32. FindByApplicationPolicy = 10,
  33. FindByCertificatePolicy = 11,
  34. FindByExtension = 12,
  35. FindByKeyUsage = 13,
  36. FindBySubjectKeyIdentifier = 14
  37. }
  38. public class X509Certificate2Collection : X509CertificateCollection {
  39. public X509Certificate2Collection() {}
  40. public X509Certificate2Collection(X509Certificate2 certificate) {
  41. this.Add(certificate);
  42. }
  43. public X509Certificate2Collection(X509Certificate2Collection certificates) {
  44. this.AddRange(certificates);
  45. }
  46. public X509Certificate2Collection(X509Certificate2[] certificates) {
  47. this.AddRange(certificates);
  48. }
  49. public new X509Certificate2 this[int index] {
  50. get {
  51. return (X509Certificate2) List[index];
  52. }
  53. set {
  54. if (value == null)
  55. throw new ArgumentNullException("value");
  56. List[index] = value;
  57. }
  58. }
  59. public int Add(X509Certificate2 certificate) {
  60. if (certificate == null)
  61. throw new ArgumentNullException("certificate");
  62. return List.Add(certificate);
  63. }
  64. public void AddRange(X509Certificate2[] certificates) {
  65. if (certificates == null)
  66. throw new ArgumentNullException("certificates");
  67. int i=0;
  68. try {
  69. for (; i<certificates.Length; i++) {
  70. Add(certificates[i]);
  71. }
  72. } catch {
  73. for (int j=0; j<i; j++) {
  74. Remove(certificates[j]);
  75. }
  76. throw;
  77. }
  78. }
  79. public void AddRange(X509Certificate2Collection certificates) {
  80. if (certificates == null)
  81. throw new ArgumentNullException("certificates");
  82. int i = 0;
  83. try {
  84. foreach (X509Certificate2 certificate in certificates) {
  85. Add(certificate);
  86. i++;
  87. }
  88. } catch {
  89. for (int j=0; j<i; j++) {
  90. Remove(certificates[j]);
  91. }
  92. throw;
  93. }
  94. }
  95. public bool Contains(X509Certificate2 certificate) {
  96. if (certificate == null)
  97. throw new ArgumentNullException("certificate");
  98. return List.Contains(certificate);
  99. }
  100. public void Insert(int index, X509Certificate2 certificate) {
  101. if (certificate == null)
  102. throw new ArgumentNullException("certificate");
  103. List.Insert(index, certificate);
  104. }
  105. public new X509Certificate2Enumerator GetEnumerator() {
  106. return new X509Certificate2Enumerator(this);
  107. }
  108. public void Remove(X509Certificate2 certificate) {
  109. if (certificate == null)
  110. throw new ArgumentNullException("certificate");
  111. List.Remove(certificate);
  112. }
  113. public void RemoveRange(X509Certificate2[] certificates) {
  114. if (certificates == null)
  115. throw new ArgumentNullException("certificates");
  116. int i=0;
  117. try {
  118. for (; i<certificates.Length; i++) {
  119. Remove(certificates[i]);
  120. }
  121. } catch {
  122. for (int j=0; j<i; j++) {
  123. Add(certificates[j]);
  124. }
  125. throw;
  126. }
  127. }
  128. public void RemoveRange(X509Certificate2Collection certificates) {
  129. if (certificates == null)
  130. throw new ArgumentNullException("certificates");
  131. int i = 0;
  132. try {
  133. foreach (X509Certificate2 certificate in certificates) {
  134. Remove(certificate);
  135. i++;
  136. }
  137. } catch {
  138. for (int j=0; j<i; j++) {
  139. Add(certificates[j]);
  140. }
  141. throw;
  142. }
  143. }
  144. #if FEATURE_CORESYSTEM
  145. [SecuritySafeCritical]
  146. #endif
  147. public X509Certificate2Collection Find(X509FindType findType, Object findValue, bool validOnly) {
  148. #if !FEATURE_CORESYSTEM
  149. //
  150. // We need to Assert all StorePermission flags since this is a memory store and we want
  151. // semi-trusted code to be able to find certificates in a memory store.
  152. //
  153. StorePermission sp = new StorePermission(StorePermissionFlags.AllFlags);
  154. sp.Assert();
  155. #endif
  156. SafeCertStoreHandle safeSourceStoreHandle = X509Utils.ExportToMemoryStore(this);
  157. SafeCertStoreHandle safeTargetStoreHandle = FindCertInStore(safeSourceStoreHandle, findType, findValue, validOnly);
  158. X509Certificate2Collection collection = X509Utils.GetCertificates(safeTargetStoreHandle);
  159. safeTargetStoreHandle.Dispose();
  160. safeSourceStoreHandle.Dispose();
  161. return collection;
  162. }
  163. public void Import(byte[] rawData) {
  164. Import(rawData, null, X509KeyStorageFlags.DefaultKeySet);
  165. }
  166. #if FEATURE_CORESYSTEM
  167. [SecuritySafeCritical]
  168. #endif
  169. public void Import(byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags) {
  170. uint dwFlags = X509Utils.MapKeyStorageFlags(keyStorageFlags);
  171. SafeCertStoreHandle safeCertStoreHandle = SafeCertStoreHandle.InvalidHandle;
  172. #if !FEATURE_CORESYSTEM
  173. //
  174. // We need to Assert all StorePermission flags since this is a memory store and we want
  175. // semi-trusted code to be able to import certificates to a memory store.
  176. //
  177. StorePermission sp = new StorePermission(StorePermissionFlags.AllFlags);
  178. sp.Assert();
  179. #endif
  180. safeCertStoreHandle = LoadStoreFromBlob(rawData, password, dwFlags, (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) != 0);
  181. X509Certificate2Collection collection = X509Utils.GetCertificates(safeCertStoreHandle);
  182. safeCertStoreHandle.Dispose();
  183. X509Certificate2[] x509Certs = new X509Certificate2[collection.Count];
  184. collection.CopyTo(x509Certs, 0);
  185. this.AddRange(x509Certs);
  186. }
  187. [ResourceExposure(ResourceScope.Machine)]
  188. #if !FEATURE_CORESYSTEM
  189. [ResourceConsumption(ResourceScope.Machine)]
  190. #endif
  191. public void Import(string fileName) {
  192. Import(fileName, null, X509KeyStorageFlags.DefaultKeySet);
  193. }
  194. #if FEATURE_CORESYSTEM
  195. [SecuritySafeCritical]
  196. #endif
  197. [ResourceExposure(ResourceScope.Machine)]
  198. #if !FEATURE_CORESYSTEM
  199. [ResourceConsumption(ResourceScope.Machine)]
  200. #endif
  201. public void Import(string fileName, string password, X509KeyStorageFlags keyStorageFlags) {
  202. uint dwFlags = X509Utils.MapKeyStorageFlags(keyStorageFlags);
  203. SafeCertStoreHandle safeCertStoreHandle = SafeCertStoreHandle.InvalidHandle;
  204. #if !FEATURE_CORESYSTEM
  205. //
  206. // We need to Assert all StorePermission flags since this is a memory store and we want
  207. // semi-trusted code to be able to import certificates to a memory store.
  208. //
  209. StorePermission sp = new StorePermission(StorePermissionFlags.AllFlags);
  210. sp.Assert();
  211. #endif
  212. safeCertStoreHandle = LoadStoreFromFile(fileName, password, dwFlags, (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) != 0);
  213. X509Certificate2Collection collection = X509Utils.GetCertificates(safeCertStoreHandle);
  214. safeCertStoreHandle.Dispose();
  215. X509Certificate2[] x509Certs = new X509Certificate2[collection.Count];
  216. collection.CopyTo(x509Certs, 0);
  217. this.AddRange(x509Certs);
  218. }
  219. #if FEATURE_CORESYSTEM
  220. [SecuritySafeCritical]
  221. #endif
  222. public byte[] Export(X509ContentType contentType) {
  223. return Export(contentType, null);
  224. }
  225. #if FEATURE_CORESYSTEM
  226. [SecuritySafeCritical]
  227. #endif
  228. public byte[] Export(X509ContentType contentType, string password) {
  229. #if !FEATURE_CORESYSTEM
  230. //
  231. // We need to Assert all StorePermission flags since this is a memory store and we want
  232. // semi-trusted code to be able to export certificates to a memory store.
  233. //
  234. StorePermission sp = new StorePermission(StorePermissionFlags.AllFlags);
  235. sp.Assert();
  236. #endif
  237. SafeCertStoreHandle safeCertStoreHandle = X509Utils.ExportToMemoryStore(this);
  238. byte[] result = ExportCertificatesToBlob(safeCertStoreHandle, contentType, password);
  239. safeCertStoreHandle.Dispose();
  240. return result;
  241. }
  242. #if FEATURE_CORESYSTEM
  243. [SecurityCritical]
  244. #endif
  245. private unsafe static byte[] ExportCertificatesToBlob(SafeCertStoreHandle safeCertStoreHandle, X509ContentType contentType, string password) {
  246. SafeCertContextHandle safeCertContextHandle = SafeCertContextHandle.InvalidHandle;
  247. uint dwSaveAs = CAPI.CERT_STORE_SAVE_AS_PKCS7;
  248. byte[] pbBlob = null;
  249. CAPI.CRYPTOAPI_BLOB DataBlob = new CAPI.CRYPTOAPI_BLOB();
  250. SafeLocalAllocHandle pbEncoded = SafeLocalAllocHandle.InvalidHandle;
  251. switch(contentType) {
  252. case X509ContentType.Cert:
  253. safeCertContextHandle = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, safeCertContextHandle);
  254. if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) {
  255. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  256. pbBlob = new byte[pCertContext.cbCertEncoded];
  257. Marshal.Copy(pCertContext.pbCertEncoded, pbBlob, 0, pbBlob.Length);
  258. }
  259. break;
  260. case X509ContentType.SerializedCert:
  261. safeCertContextHandle = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, safeCertContextHandle);
  262. uint cbEncoded = 0;
  263. if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) {
  264. if (!CAPI.CertSerializeCertificateStoreElement(safeCertContextHandle,
  265. 0,
  266. pbEncoded,
  267. new IntPtr(&cbEncoded)))
  268. throw new CryptographicException(Marshal.GetLastWin32Error());
  269. pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbEncoded));
  270. if (!CAPI.CertSerializeCertificateStoreElement(safeCertContextHandle,
  271. 0,
  272. pbEncoded,
  273. new IntPtr(&cbEncoded)))
  274. throw new CryptographicException(Marshal.GetLastWin32Error());
  275. pbBlob = new byte[cbEncoded];
  276. Marshal.Copy(pbEncoded.DangerousGetHandle(), pbBlob, 0, pbBlob.Length);
  277. }
  278. break;
  279. case X509ContentType.Pkcs12:
  280. if (!CAPI.PFXExportCertStore(safeCertStoreHandle,
  281. new IntPtr(&DataBlob),
  282. password,
  283. CAPI.EXPORT_PRIVATE_KEYS | CAPI.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
  284. throw new CryptographicException(Marshal.GetLastWin32Error());
  285. pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(DataBlob.cbData));
  286. DataBlob.pbData = pbEncoded.DangerousGetHandle();
  287. if (!CAPI.PFXExportCertStore(safeCertStoreHandle,
  288. new IntPtr(&DataBlob),
  289. password,
  290. CAPI.EXPORT_PRIVATE_KEYS | CAPI.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
  291. throw new CryptographicException(Marshal.GetLastWin32Error());
  292. pbBlob = new byte[DataBlob.cbData];
  293. Marshal.Copy(DataBlob.pbData, pbBlob, 0, pbBlob.Length);
  294. break;
  295. case X509ContentType.SerializedStore:
  296. // falling through
  297. case X509ContentType.Pkcs7:
  298. if (contentType == X509ContentType.SerializedStore)
  299. dwSaveAs = CAPI.CERT_STORE_SAVE_AS_STORE;
  300. // determine the required length
  301. if (!CAPI.CertSaveStore(safeCertStoreHandle,
  302. CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  303. dwSaveAs,
  304. CAPI.CERT_STORE_SAVE_TO_MEMORY,
  305. new IntPtr(&DataBlob),
  306. 0))
  307. throw new CryptographicException(Marshal.GetLastWin32Error());
  308. pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(DataBlob.cbData));
  309. DataBlob.pbData = pbEncoded.DangerousGetHandle();
  310. // now save the store to a memory blob
  311. if (!CAPI.CertSaveStore(safeCertStoreHandle,
  312. CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  313. dwSaveAs,
  314. CAPI.CERT_STORE_SAVE_TO_MEMORY,
  315. new IntPtr(&DataBlob),
  316. 0))
  317. throw new CryptographicException(Marshal.GetLastWin32Error());
  318. pbBlob = new byte[DataBlob.cbData];
  319. Marshal.Copy(DataBlob.pbData, pbBlob, 0, pbBlob.Length);
  320. break;
  321. default:
  322. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidContentType));
  323. }
  324. pbEncoded.Dispose();
  325. safeCertContextHandle.Dispose();
  326. return pbBlob;
  327. }
  328. #if FEATURE_CORESYSTEM
  329. [SecurityCritical]
  330. #endif
  331. internal delegate int FindProcDelegate (SafeCertContextHandle safeCertContextHandle, object pvCallbackData);
  332. #if FEATURE_CORESYSTEM
  333. [SecuritySafeCritical]
  334. #endif
  335. private unsafe static SafeCertStoreHandle FindCertInStore(SafeCertStoreHandle safeSourceStoreHandle, X509FindType findType, Object findValue, bool validOnly) {
  336. if (findValue == null)
  337. throw new ArgumentNullException("findValue");
  338. IntPtr pvFindPara = IntPtr.Zero;
  339. object pvCallbackData1 = null;
  340. object pvCallbackData2 = null;
  341. FindProcDelegate pfnCertCallback1 = null;
  342. FindProcDelegate pfnCertCallback2 = null;
  343. uint dwFindType = CAPI.CERT_FIND_ANY;
  344. string subject, issuer;
  345. CAPI.CRYPTOAPI_BLOB HashBlob = new CAPI.CRYPTOAPI_BLOB();
  346. SafeLocalAllocHandle pb = SafeLocalAllocHandle.InvalidHandle;
  347. _FILETIME ft = new _FILETIME();
  348. string oidValue = null;
  349. switch(findType) {
  350. case X509FindType.FindByThumbprint:
  351. if (findValue.GetType() != typeof(string))
  352. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  353. byte[] hex = X509Utils.DecodeHexString((string) findValue);
  354. pb = X509Utils.ByteToPtr(hex);
  355. HashBlob.pbData = pb.DangerousGetHandle();
  356. HashBlob.cbData = (uint) hex.Length;
  357. dwFindType = CAPI.CERT_FIND_HASH;
  358. pvFindPara = new IntPtr(&HashBlob);
  359. break;
  360. case X509FindType.FindBySubjectName:
  361. if (findValue.GetType() != typeof(string))
  362. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  363. subject = (string) findValue;
  364. dwFindType = CAPI.CERT_FIND_SUBJECT_STR;
  365. pb = X509Utils.StringToUniPtr(subject);
  366. pvFindPara = pb.DangerousGetHandle();
  367. break;
  368. case X509FindType.FindBySubjectDistinguishedName:
  369. if (findValue.GetType() != typeof(string))
  370. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  371. subject = (string) findValue;
  372. pfnCertCallback1 = new FindProcDelegate(FindSubjectDistinguishedNameCallback);
  373. pvCallbackData1 = subject;
  374. break;
  375. case X509FindType.FindByIssuerName:
  376. if (findValue.GetType() != typeof(string))
  377. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  378. issuer = (string) findValue;
  379. dwFindType = CAPI.CERT_FIND_ISSUER_STR;
  380. pb = X509Utils.StringToUniPtr(issuer);
  381. pvFindPara = pb.DangerousGetHandle();
  382. break;
  383. case X509FindType.FindByIssuerDistinguishedName:
  384. if (findValue.GetType() != typeof(string))
  385. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  386. issuer = (string) findValue;
  387. pfnCertCallback1 = new FindProcDelegate(FindIssuerDistinguishedNameCallback);
  388. pvCallbackData1 = issuer;
  389. break;
  390. case X509FindType.FindBySerialNumber:
  391. if (findValue.GetType() != typeof(string))
  392. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  393. pfnCertCallback1 = new FindProcDelegate(FindSerialNumberCallback);
  394. pfnCertCallback2 = new FindProcDelegate(FindSerialNumberCallback);
  395. BigInt h = new BigInt();
  396. h.FromHexadecimal((string) findValue);
  397. pvCallbackData1 = (byte[]) h.ToByteArray();
  398. h.FromDecimal((string) findValue);
  399. pvCallbackData2 = (byte[]) h.ToByteArray();
  400. break;
  401. case X509FindType.FindByTimeValid:
  402. if (findValue.GetType() != typeof(DateTime))
  403. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  404. *((long*) &ft) = ((DateTime) findValue).ToFileTime();
  405. pfnCertCallback1 = new FindProcDelegate(FindTimeValidCallback);
  406. pvCallbackData1 = ft;
  407. break;
  408. case X509FindType.FindByTimeNotYetValid:
  409. if (findValue.GetType() != typeof(DateTime))
  410. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  411. *((long*) &ft) = ((DateTime) findValue).ToFileTime();
  412. pfnCertCallback1 = new FindProcDelegate(FindTimeNotBeforeCallback);
  413. pvCallbackData1 = ft;
  414. break;
  415. case X509FindType.FindByTimeExpired:
  416. if (findValue.GetType() != typeof(DateTime))
  417. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  418. *((long*) &ft) = ((DateTime) findValue).ToFileTime();
  419. pfnCertCallback1 = new FindProcDelegate(FindTimeNotAfterCallback);
  420. pvCallbackData1 = ft;
  421. break;
  422. case X509FindType.FindByTemplateName:
  423. if (findValue.GetType() != typeof(string))
  424. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  425. pvCallbackData1 = (string) findValue;
  426. pfnCertCallback1 = new FindProcDelegate(FindTemplateNameCallback);
  427. break;
  428. case X509FindType.FindByApplicationPolicy:
  429. if (findValue.GetType() != typeof(string))
  430. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  431. // If we were passed the friendly name, retrieve the value string.
  432. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string) findValue, OidGroup.Policy);
  433. if (oidValue == null) {
  434. oidValue = (string) findValue;
  435. X509Utils.ValidateOidValue(oidValue);
  436. }
  437. pvCallbackData1 = oidValue;
  438. pfnCertCallback1 = new FindProcDelegate(FindApplicationPolicyCallback);
  439. break;
  440. case X509FindType.FindByCertificatePolicy:
  441. if (findValue.GetType() != typeof(string))
  442. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  443. // If we were passed the friendly name, retrieve the value string.
  444. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)findValue, OidGroup.Policy);
  445. if (oidValue == null) {
  446. oidValue = (string) findValue;
  447. X509Utils.ValidateOidValue(oidValue);
  448. }
  449. pvCallbackData1 = oidValue;
  450. pfnCertCallback1 = new FindProcDelegate(FindCertificatePolicyCallback);
  451. break;
  452. case X509FindType.FindByExtension:
  453. if (findValue.GetType() != typeof(string))
  454. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  455. // If we were passed the friendly name, retrieve the value string.
  456. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)findValue, OidGroup.ExtensionOrAttribute);
  457. if (oidValue == null) {
  458. oidValue = (string) findValue;
  459. X509Utils.ValidateOidValue(oidValue);
  460. }
  461. pvCallbackData1 = oidValue;
  462. pfnCertCallback1 = new FindProcDelegate(FindExtensionCallback);
  463. break;
  464. case X509FindType.FindByKeyUsage:
  465. // The findValue object can be either a friendly name, a X509KeyUsageFlags enum or an integer.
  466. if (findValue.GetType() == typeof(string)) {
  467. CAPI.KEY_USAGE_STRUCT[] KeyUsages = new CAPI.KEY_USAGE_STRUCT[] {
  468. new CAPI.KEY_USAGE_STRUCT("DigitalSignature", CAPI.CERT_DIGITAL_SIGNATURE_KEY_USAGE),
  469. new CAPI.KEY_USAGE_STRUCT("NonRepudiation", CAPI.CERT_NON_REPUDIATION_KEY_USAGE),
  470. new CAPI.KEY_USAGE_STRUCT("KeyEncipherment", CAPI.CERT_KEY_ENCIPHERMENT_KEY_USAGE),
  471. new CAPI.KEY_USAGE_STRUCT("DataEncipherment", CAPI.CERT_DATA_ENCIPHERMENT_KEY_USAGE),
  472. new CAPI.KEY_USAGE_STRUCT("KeyAgreement", CAPI.CERT_KEY_AGREEMENT_KEY_USAGE),
  473. new CAPI.KEY_USAGE_STRUCT("KeyCertSign", CAPI.CERT_KEY_CERT_SIGN_KEY_USAGE),
  474. new CAPI.KEY_USAGE_STRUCT("CrlSign", CAPI.CERT_CRL_SIGN_KEY_USAGE),
  475. new CAPI.KEY_USAGE_STRUCT("EncipherOnly", CAPI.CERT_ENCIPHER_ONLY_KEY_USAGE),
  476. new CAPI.KEY_USAGE_STRUCT("DecipherOnly", CAPI.CERT_DECIPHER_ONLY_KEY_USAGE)
  477. };
  478. for (uint index = 0; index < KeyUsages.Length; index++) {
  479. if (String.Compare(KeyUsages[index].pwszKeyUsage, (string) findValue, StringComparison.OrdinalIgnoreCase) == 0) {
  480. pvCallbackData1 = KeyUsages[index].dwKeyUsageBit;
  481. break;
  482. }
  483. }
  484. if (pvCallbackData1 == null)
  485. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType));
  486. } else if (findValue.GetType() == typeof(X509KeyUsageFlags)) {
  487. pvCallbackData1 = findValue;
  488. } else if (findValue.GetType() == typeof(uint) || findValue.GetType() == typeof(int)) {
  489. // We got the actual DWORD
  490. pvCallbackData1 = findValue;
  491. } else
  492. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType));
  493. pfnCertCallback1 = new FindProcDelegate(FindKeyUsageCallback);
  494. break;
  495. case X509FindType.FindBySubjectKeyIdentifier:
  496. if (findValue.GetType() != typeof(string))
  497. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue));
  498. pvCallbackData1 = (byte[]) X509Utils.DecodeHexString((string) findValue);
  499. pfnCertCallback1 = new FindProcDelegate(FindSubjectKeyIdentifierCallback);
  500. break;
  501. default:
  502. throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType));
  503. }
  504. // First, create a memory store
  505. SafeCertStoreHandle safeTargetStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_MEMORY),
  506. CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  507. IntPtr.Zero,
  508. CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG,
  509. null);
  510. if (safeTargetStoreHandle == null || safeTargetStoreHandle.IsInvalid)
  511. throw new CryptographicException(Marshal.GetLastWin32Error());
  512. // FindByCert will throw an exception in case of failures.
  513. FindByCert(safeSourceStoreHandle,
  514. dwFindType,
  515. pvFindPara,
  516. validOnly,
  517. pfnCertCallback1,
  518. pfnCertCallback2,
  519. pvCallbackData1,
  520. pvCallbackData2,
  521. safeTargetStoreHandle);
  522. pb.Dispose();
  523. return safeTargetStoreHandle;
  524. }
  525. #if FEATURE_CORESYSTEM
  526. [SecuritySafeCritical]
  527. #endif
  528. private static void FindByCert(SafeCertStoreHandle safeSourceStoreHandle,
  529. uint dwFindType,
  530. IntPtr pvFindPara,
  531. bool validOnly,
  532. FindProcDelegate pfnCertCallback1,
  533. FindProcDelegate pfnCertCallback2,
  534. object pvCallbackData1,
  535. object pvCallbackData2,
  536. SafeCertStoreHandle safeTargetStoreHandle) {
  537. int hr = CAPI.S_OK;
  538. SafeCertContextHandle pEnumContext = SafeCertContextHandle.InvalidHandle;
  539. pEnumContext = CAPI.CertFindCertificateInStore(safeSourceStoreHandle,
  540. CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  541. 0,
  542. dwFindType,
  543. pvFindPara,
  544. pEnumContext);
  545. while (pEnumContext != null && !pEnumContext.IsInvalid) {
  546. if (pfnCertCallback1 != null) {
  547. hr = pfnCertCallback1(pEnumContext, pvCallbackData1);
  548. if (hr == CAPI.S_FALSE) {
  549. if (pfnCertCallback2 != null)
  550. hr = pfnCertCallback2(pEnumContext, pvCallbackData2);
  551. if (hr == CAPI.S_FALSE) // skip this certificate
  552. goto skip;
  553. }
  554. if (hr != CAPI.S_OK)
  555. break;
  556. }
  557. if (validOnly) {
  558. hr = X509Utils.VerifyCertificate(pEnumContext,
  559. null,
  560. null,
  561. X509RevocationMode.NoCheck,
  562. X509RevocationFlag.ExcludeRoot,
  563. DateTime.Now,
  564. new TimeSpan(0, 0, 0), // default
  565. null,
  566. new IntPtr(CAPI.CERT_CHAIN_POLICY_BASE),
  567. IntPtr.Zero);
  568. if (hr == CAPI.S_FALSE) // skip this certificate
  569. goto skip;
  570. if (hr != CAPI.S_OK)
  571. break;
  572. }
  573. //
  574. // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get
  575. // applied to the original store. This has a limit of 99 links per cert context however.
  576. //
  577. if (!CAPI.CertAddCertificateLinkToStore(safeTargetStoreHandle,
  578. pEnumContext,
  579. CAPI.CERT_STORE_ADD_ALWAYS,
  580. SafeCertContextHandle.InvalidHandle)) {
  581. hr = Marshal.GetHRForLastWin32Error();
  582. break;
  583. }
  584. skip:
  585. // CertFindCertificateInStore always releases the context regardless of success
  586. // or failure so we don't need to manually release it
  587. GC.SuppressFinalize(pEnumContext);
  588. pEnumContext = CAPI.CertFindCertificateInStore(safeSourceStoreHandle,
  589. CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  590. 0,
  591. dwFindType,
  592. pvFindPara,
  593. pEnumContext);
  594. }
  595. if (pEnumContext != null && !pEnumContext.IsInvalid)
  596. pEnumContext.Dispose();
  597. if (hr != CAPI.S_FALSE && hr != CAPI.S_OK)
  598. throw new CryptographicException(hr);
  599. }
  600. //
  601. // Callback method to find certificates by subject DN.
  602. //
  603. #if FEATURE_CORESYSTEM
  604. [SecurityCritical]
  605. #endif
  606. private static unsafe int FindSubjectDistinguishedNameCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  607. string rdn = CAPI.GetCertNameInfo(safeCertContextHandle, 0, CAPI.CERT_NAME_RDN_TYPE);
  608. if (String.Compare(rdn, (string) pvCallbackData, StringComparison.OrdinalIgnoreCase) != 0)
  609. return CAPI.S_FALSE;
  610. return CAPI.S_OK;
  611. }
  612. //
  613. // Callback method to find certificates by issuer DN.
  614. //
  615. #if FEATURE_CORESYSTEM
  616. [SecurityCritical]
  617. #endif
  618. private static unsafe int FindIssuerDistinguishedNameCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  619. string rdn = CAPI.GetCertNameInfo(safeCertContextHandle, CAPI.CERT_NAME_ISSUER_FLAG, CAPI.CERT_NAME_RDN_TYPE);
  620. if (String.Compare(rdn, (string) pvCallbackData, StringComparison.OrdinalIgnoreCase) != 0)
  621. return CAPI.S_FALSE;
  622. return CAPI.S_OK;
  623. }
  624. //
  625. // Callback method to find certificates by serial number.
  626. // This can be useful when using XML Digital Signature and X509Data.
  627. //
  628. #if FEATURE_CORESYSTEM
  629. [SecurityCritical]
  630. #endif
  631. private static unsafe int FindSerialNumberCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  632. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  633. CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));
  634. byte[] hex = new byte[pCertInfo.SerialNumber.cbData];
  635. Marshal.Copy(pCertInfo.SerialNumber.pbData, hex, 0, hex.Length);
  636. int size = X509Utils.GetHexArraySize(hex);
  637. byte[] serialNumber = (byte[]) pvCallbackData;
  638. if (serialNumber.Length != size)
  639. return CAPI.S_FALSE;
  640. for (int index = 0; index < serialNumber.Length; index++) {
  641. if (serialNumber[index] != hex[index])
  642. return CAPI.S_FALSE;
  643. }
  644. return CAPI.S_OK;
  645. }
  646. //
  647. // Callback method to find certificates by validity time.
  648. // The callback data has to be a UTC FILETEME.
  649. //
  650. #if FEATURE_CORESYSTEM
  651. [SecurityCritical]
  652. #endif
  653. private static unsafe int FindTimeValidCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  654. _FILETIME ft = (_FILETIME) pvCallbackData;
  655. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  656. if (CAPI.CertVerifyTimeValidity(ref ft, pCertContext.pCertInfo) == 0)
  657. return CAPI.S_OK;
  658. return CAPI.S_FALSE;
  659. }
  660. //
  661. // Callback method to find certificates expired at a certain DateTime.
  662. // The callback data has to be a UTC FILETEME.
  663. //
  664. #if FEATURE_CORESYSTEM
  665. [SecurityCritical]
  666. #endif
  667. private static unsafe int FindTimeNotAfterCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  668. _FILETIME ft = (_FILETIME) pvCallbackData;
  669. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  670. if (CAPI.CertVerifyTimeValidity(ref ft, pCertContext.pCertInfo) == 1)
  671. return CAPI.S_OK;
  672. return CAPI.S_FALSE;
  673. }
  674. //
  675. // Callback method to find certificates effective after a certain DateTime.
  676. // The callback data has to be a UTC FILETEME.
  677. //
  678. #if FEATURE_CORESYSTEM
  679. [SecurityCritical]
  680. #endif
  681. private static unsafe int FindTimeNotBeforeCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  682. _FILETIME ft = (_FILETIME) pvCallbackData;
  683. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  684. if (CAPI.CertVerifyTimeValidity(ref ft, pCertContext.pCertInfo) == -1)
  685. return CAPI.S_OK;
  686. return CAPI.S_FALSE;
  687. }
  688. //
  689. // Callback method to find certificates by template name.
  690. // The template name can have 2 different formats: V1 format (<= Win2K) is just a string
  691. // V2 format (XP only) can be a friendly name or an OID.
  692. // An example of Template Name can be "ClientAuth".
  693. //
  694. #if FEATURE_CORESYSTEM
  695. [SecurityCritical]
  696. #endif
  697. private static unsafe int FindTemplateNameCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  698. IntPtr pV1Template = IntPtr.Zero;
  699. IntPtr pV2Template = IntPtr.Zero;
  700. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  701. CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));
  702. pV1Template = CAPI.CertFindExtension(CAPI.szOID_ENROLL_CERTTYPE_EXTENSION,
  703. pCertInfo.cExtension,
  704. pCertInfo.rgExtension);
  705. pV2Template = CAPI.CertFindExtension(CAPI.szOID_CERTIFICATE_TEMPLATE,
  706. pCertInfo.cExtension,
  707. pCertInfo.rgExtension);
  708. if (pV1Template == IntPtr.Zero && pV2Template == IntPtr.Zero)
  709. return CAPI.S_FALSE;
  710. if (pV1Template != IntPtr.Zero) {
  711. CAPI.CERT_EXTENSION extension = (CAPI.CERT_EXTENSION) Marshal.PtrToStructure(pV1Template, typeof(CAPI.CERT_EXTENSION));
  712. byte[] rawData = new byte[extension.Value.cbData];
  713. Marshal.Copy(extension.Value.pbData, rawData, 0, rawData.Length);
  714. uint cbDecoded = 0;
  715. SafeLocalAllocHandle decoded = null;
  716. // Decode the extension.
  717. bool result = CAPI.DecodeObject(new IntPtr(CAPI.X509_UNICODE_ANY_STRING),
  718. rawData,
  719. out decoded,
  720. out cbDecoded);
  721. if (result) {
  722. CAPI.CERT_NAME_VALUE pNameValue = (CAPI.CERT_NAME_VALUE) Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CERT_NAME_VALUE));
  723. string s = Marshal.PtrToStringUni(pNameValue.Value.pbData);
  724. if (String.Compare(s, (string) pvCallbackData, StringComparison.OrdinalIgnoreCase) == 0)
  725. return CAPI.S_OK;
  726. }
  727. }
  728. if (pV2Template != IntPtr.Zero) {
  729. CAPI.CERT_EXTENSION extension = (CAPI.CERT_EXTENSION) Marshal.PtrToStructure(pV2Template, typeof(CAPI.CERT_EXTENSION));
  730. byte[] rawData = new byte[extension.Value.cbData];
  731. Marshal.Copy(extension.Value.pbData, rawData, 0, rawData.Length);
  732. uint cbDecoded = 0;
  733. SafeLocalAllocHandle decoded = null;
  734. // Decode the extension.
  735. bool result = CAPI.DecodeObject(new IntPtr(CAPI.X509_CERTIFICATE_TEMPLATE),
  736. rawData,
  737. out decoded,
  738. out cbDecoded);
  739. if (result) {
  740. CAPI.CERT_TEMPLATE_EXT pTemplate = (CAPI.CERT_TEMPLATE_EXT) Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CERT_TEMPLATE_EXT));
  741. // If we were passed the friendly name, retrieve the value string.
  742. string oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)pvCallbackData, OidGroup.Template);
  743. if (oidValue == null)
  744. oidValue = (string) pvCallbackData;
  745. if (String.Compare(pTemplate.pszObjId, oidValue, StringComparison.OrdinalIgnoreCase) == 0)
  746. return CAPI.S_OK;
  747. }
  748. }
  749. return CAPI.S_FALSE;
  750. }
  751. //
  752. // Callback method to find certificates by application policy (also known as EKU)
  753. // An example of application policy can be: "Encrypting File System"
  754. //
  755. #if FEATURE_CORESYSTEM
  756. [SecurityCritical]
  757. #endif
  758. private static unsafe int FindApplicationPolicyCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  759. string eku = (string) pvCallbackData;
  760. if (eku.Length == 0)
  761. return CAPI.S_FALSE;
  762. IntPtr pCertContext = safeCertContextHandle.DangerousGetHandle();
  763. int cNumOIDs = 0;
  764. uint cbOIDs = 0;
  765. SafeLocalAllocHandle rghOIDs = SafeLocalAllocHandle.InvalidHandle;
  766. if (!CAPI.CertGetValidUsages(1, new IntPtr(&pCertContext), new IntPtr(&cNumOIDs), rghOIDs, new IntPtr(&cbOIDs)))
  767. return CAPI.S_FALSE;
  768. rghOIDs = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbOIDs));
  769. if (!CAPI.CertGetValidUsages(1, new IntPtr(&pCertContext), new IntPtr(&cNumOIDs), rghOIDs, new IntPtr(&cbOIDs)))
  770. return CAPI.S_FALSE;
  771. // -1 means the certificate is good for all usages.
  772. if (cNumOIDs == -1)
  773. return CAPI.S_OK;
  774. for (int index = 0; index < cNumOIDs; index++) {
  775. IntPtr pszOid = Marshal.ReadIntPtr(new IntPtr((long) rghOIDs.DangerousGetHandle() + index * Marshal.SizeOf(typeof(IntPtr))));
  776. string oidValue = Marshal.PtrToStringAnsi(pszOid);
  777. if (String.Compare(eku, oidValue, StringComparison.OrdinalIgnoreCase) == 0)
  778. return CAPI.S_OK;
  779. }
  780. return CAPI.S_FALSE;
  781. }
  782. //
  783. // Callback method to find certificates by certificate policy.
  784. // This is only recognized in XP platforms. However, passing in an OID value should work on downlevel platforms as well.
  785. //
  786. #if FEATURE_CORESYSTEM
  787. [SecurityCritical]
  788. #endif
  789. private static unsafe int FindCertificatePolicyCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  790. string certPolicy = (string) pvCallbackData;
  791. if (certPolicy.Length == 0)
  792. return CAPI.S_FALSE;
  793. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  794. CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));
  795. IntPtr pExtension = CAPI.CertFindExtension(CAPI.szOID_CERT_POLICIES,
  796. pCertInfo.cExtension,
  797. pCertInfo.rgExtension);
  798. if (pExtension == IntPtr.Zero)
  799. return CAPI.S_FALSE;
  800. CAPI.CERT_EXTENSION extension = (CAPI.CERT_EXTENSION) Marshal.PtrToStructure(pExtension, typeof(CAPI.CERT_EXTENSION));
  801. byte[] rawData = new byte[extension.Value.cbData];
  802. Marshal.Copy(extension.Value.pbData, rawData, 0, rawData.Length);
  803. uint cbDecoded = 0;
  804. SafeLocalAllocHandle decoded = null;
  805. // Decode the extension.
  806. bool result = CAPI.DecodeObject(new IntPtr(CAPI.X509_CERT_POLICIES),
  807. rawData,
  808. out decoded,
  809. out cbDecoded);
  810. if (result) {
  811. CAPI.CERT_POLICIES_INFO pInfo = (CAPI.CERT_POLICIES_INFO) Marshal.PtrToStructure(decoded.DangerousGetHandle(), typeof(CAPI.CERT_POLICIES_INFO));
  812. for (int index = 0; index < pInfo.cPolicyInfo; index++) {
  813. IntPtr pPolicyInfoPtr = new IntPtr((long) pInfo.rgPolicyInfo + index * Marshal.SizeOf(typeof(CAPI.CERT_POLICY_INFO)));
  814. CAPI.CERT_POLICY_INFO pPolicyInfo = (CAPI.CERT_POLICY_INFO) Marshal.PtrToStructure(pPolicyInfoPtr, typeof(CAPI.CERT_POLICY_INFO));
  815. if (String.Compare(certPolicy, pPolicyInfo.pszPolicyIdentifier, StringComparison.OrdinalIgnoreCase) == 0)
  816. return CAPI.S_OK;
  817. }
  818. }
  819. return CAPI.S_FALSE;
  820. }
  821. //
  822. // Callback method to find certificates that have a particular extension.
  823. // The callback data can be either an OID friendly name or value (all should be ANSI strings).
  824. //
  825. #if FEATURE_CORESYSTEM
  826. [SecurityCritical]
  827. #endif
  828. private static unsafe int FindExtensionCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  829. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  830. CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));
  831. IntPtr pExtension = CAPI.CertFindExtension((string) pvCallbackData,
  832. pCertInfo.cExtension,
  833. pCertInfo.rgExtension);
  834. if (pExtension == IntPtr.Zero)
  835. return CAPI.S_FALSE;
  836. return CAPI.S_OK;
  837. }
  838. //
  839. // Callback method to find certificates that have a particular Key Usage.
  840. // The callback data can be either a string (example: "KeyEncipherment") or a DWORD which can have multiple bits set in it.
  841. // If the callback data is a string, we can achieve the effect of a bit union by calling it multiple times, each time
  842. // further restricting the set of selected certificates.
  843. //
  844. #if FEATURE_CORESYSTEM
  845. [SecurityCritical]
  846. #endif
  847. private static unsafe int FindKeyUsageCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  848. CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle());
  849. uint dwUsages = 0;
  850. if (!CAPI.CertGetIntendedKeyUsage(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
  851. pCertContext.pCertInfo,
  852. new IntPtr(&dwUsages),
  853. 4 /* sizeof(DWORD) */))
  854. return CAPI.S_OK; // no key usage means it is valid for all key usages.
  855. uint dwCheckUsage = Convert.ToUInt32(pvCallbackData, null);
  856. if ((dwUsages & dwCheckUsage) == dwCheckUsage)
  857. return CAPI.S_OK;
  858. return CAPI.S_FALSE;
  859. }
  860. //
  861. // Callback method to find certificates by subject key identifier.
  862. // This can be useful when using XML Digital Signature and X509Data.
  863. //
  864. #if FEATURE_CORESYSTEM
  865. [SecurityCritical]
  866. #endif
  867. private static unsafe int FindSubjectKeyIdentifierCallback(SafeCertContextHandle safeCertContextHandle, object pvCallbackData) {
  868. SafeLocalAllocHandle ptr = SafeLocalAllocHandle.InvalidHandle;
  869. // We look for the Key Id extended property
  870. // this will first look if there is a V3 SKI extension
  871. // and then if that fails, It will return the Key Id extended property.
  872. uint cbData = 0;
  873. if (!CAPI.CertGetCertificateContextProperty(safeCertContextHandle,
  874. CAPI.CERT_KEY_IDENTIFIER_PROP_ID,
  875. ptr,
  876. ref cbData))
  877. return CAPI.S_FALSE;
  878. ptr = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbData));
  879. if (!CAPI.CertGetCertificateContextProperty(safeCertContextHandle,
  880. CAPI.CERT_KEY_IDENTIFIER_PROP_ID,
  881. ptr,
  882. ref cbData))
  883. return CAPI.S_FALSE;
  884. byte[] subjectKeyIdentifier = (byte[]) pvCallbackData;
  885. if (subjectKeyIdentifier.Length != cbData)
  886. return CAPI.S_FALSE;
  887. byte[] hex = new byte[cbData];
  888. Marshal.Copy(ptr.DangerousGetHandle(), hex, 0, hex.Length);
  889. ptr.Dispose();
  890. for (uint index = 0; index < cbData; index++) {
  891. if (subjectKeyIdentifier[index] != hex[index])
  892. return CAPI.S_FALSE;
  893. }
  894. return CAPI.S_OK;
  895. }
  896. private const uint X509_STORE_CONTENT_FLAGS =
  897. (CAPI.CERT_QUERY_CONTENT_FLAG_CERT |
  898. CAPI.CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT |
  899. CAPI.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  900. CAPI.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED |
  901. CAPI.CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED |
  902. CAPI.CERT_QUERY_CONTENT_FLAG_PFX |
  903. CAPI.CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE);
  904. #if FEATURE_CORESYSTEM
  905. [SecuritySafeCritical]
  906. #endif
  907. [ResourceExposure(ResourceScope.None)]
  908. #if !FEATURE_CORESYSTEM