private unsafe static Cryptography.SafeCertStoreHandle FindCertInStore(Cryptography.SafeCertStoreHandle safeSourceStoreHandle, X509FindType findType, Object findValue, bool validOnly) { if (findValue == null) throw new ArgumentNullException("findValue"); IntPtr pvFindPara = IntPtr.Zero; object pvCallbackData1 = null; object pvCallbackData2 = null; FindProcDelegate pfnCertCallback1 = null; FindProcDelegate pfnCertCallback2 = null; uint dwFindType = CAPI.CERT_FIND_ANY; string subject, issuer; CAPI.CRYPTOAPI_BLOB HashBlob = new CAPI.CRYPTOAPI_BLOB(); SafeLocalAllocHandle pb = SafeLocalAllocHandle.InvalidHandle; _FILETIME ft = new _FILETIME(); string oidValue = null; switch(findType) { case X509FindType.FindByThumbprint: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); byte[] hex = X509Utils.DecodeHexString((string) findValue); pb = X509Utils.ByteToPtr(hex); HashBlob.pbData = pb.DangerousGetHandle(); HashBlob.cbData = (uint) hex.Length; dwFindType = CAPI.CERT_FIND_HASH; pvFindPara = new IntPtr(&HashBlob); break; case X509FindType.FindBySubjectName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); subject = (string) findValue; dwFindType = CAPI.CERT_FIND_SUBJECT_STR; pb = X509Utils.StringToUniPtr(subject); pvFindPara = pb.DangerousGetHandle(); break; case X509FindType.FindBySubjectDistinguishedName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); subject = (string) findValue; pfnCertCallback1 = new FindProcDelegate(FindSubjectDistinguishedNameCallback); pvCallbackData1 = subject; break; case X509FindType.FindByIssuerName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); issuer = (string) findValue; dwFindType = CAPI.CERT_FIND_ISSUER_STR; pb = X509Utils.StringToUniPtr(issuer); pvFindPara = pb.DangerousGetHandle(); break; case X509FindType.FindByIssuerDistinguishedName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); issuer = (string) findValue; pfnCertCallback1 = new FindProcDelegate(FindIssuerDistinguishedNameCallback); pvCallbackData1 = issuer; break; case X509FindType.FindBySerialNumber: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); pfnCertCallback1 = new FindProcDelegate(FindSerialNumberCallback); pfnCertCallback2 = new FindProcDelegate(FindSerialNumberCallback); BigInt h = new BigInt(); h.FromHexadecimal((string) findValue); pvCallbackData1 = (byte[]) h.ToByteArray(); h.FromDecimal((string) findValue); pvCallbackData2 = (byte[]) h.ToByteArray(); break; case X509FindType.FindByTimeValid: if (findValue.GetType() != typeof(DateTime)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); *((long*) &ft) = ((DateTime) findValue).ToFileTime(); pfnCertCallback1 = new FindProcDelegate(FindTimeValidCallback); pvCallbackData1 = ft; break; case X509FindType.FindByTimeNotYetValid: if (findValue.GetType() != typeof(DateTime)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); *((long*) &ft) = ((DateTime) findValue).ToFileTime(); pfnCertCallback1 = new FindProcDelegate(FindTimeNotBeforeCallback); pvCallbackData1 = ft; break; case X509FindType.FindByTimeExpired: if (findValue.GetType() != typeof(DateTime)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); *((long*) &ft) = ((DateTime) findValue).ToFileTime(); pfnCertCallback1 = new FindProcDelegate(FindTimeNotAfterCallback); pvCallbackData1 = ft; break; case X509FindType.FindByTemplateName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); pvCallbackData1 = (string) findValue; pfnCertCallback1 = new FindProcDelegate(FindTemplateNameCallback); break; case X509FindType.FindByApplicationPolicy: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); // If we were passed the friendly name, retrieve the value string. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string) findValue, Cryptography.OidGroup.Policy); if (oidValue == null) { oidValue = (string) findValue; X509Utils.ValidateOidValue(oidValue); } pvCallbackData1 = oidValue; pfnCertCallback1 = new FindProcDelegate(FindApplicationPolicyCallback); break; case X509FindType.FindByCertificatePolicy: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); // If we were passed the friendly name, retrieve the value string. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)findValue, Cryptography.OidGroup.Policy); if (oidValue == null) { oidValue = (string) findValue; X509Utils.ValidateOidValue(oidValue); } pvCallbackData1 = oidValue; pfnCertCallback1 = new FindProcDelegate(FindCertificatePolicyCallback); break; case X509FindType.FindByExtension: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); // If we were passed the friendly name, retrieve the value string. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)findValue, Cryptography.OidGroup.ExtensionOrAttribute); if (oidValue == null) { oidValue = (string) findValue; X509Utils.ValidateOidValue(oidValue); } pvCallbackData1 = oidValue; pfnCertCallback1 = new FindProcDelegate(FindExtensionCallback); break; case X509FindType.FindByKeyUsage: // The findValue object can be either a friendly name, a X509KeyUsageFlags enum or an integer. if (findValue.GetType() == typeof(string)) { CAPI.KEY_USAGE_STRUCT[] KeyUsages = new CAPI.KEY_USAGE_STRUCT[] { new CAPI.KEY_USAGE_STRUCT("DigitalSignature", CAPI.CERT_DIGITAL_SIGNATURE_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("NonRepudiation", CAPI.CERT_NON_REPUDIATION_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("KeyEncipherment", CAPI.CERT_KEY_ENCIPHERMENT_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("DataEncipherment", CAPI.CERT_DATA_ENCIPHERMENT_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("KeyAgreement", CAPI.CERT_KEY_AGREEMENT_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("KeyCertSign", CAPI.CERT_KEY_CERT_SIGN_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("CrlSign", CAPI.CERT_CRL_SIGN_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("EncipherOnly", CAPI.CERT_ENCIPHER_ONLY_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("DecipherOnly", CAPI.CERT_DECIPHER_ONLY_KEY_USAGE) }; for (uint index = 0; index < KeyUsages.Length; index++) { if (String.Compare(KeyUsages[index].pwszKeyUsage, (string) findValue, StringComparison.OrdinalIgnoreCase) == 0) { pvCallbackData1 = KeyUsages[index].dwKeyUsageBit; break; } } if (pvCallbackData1 == null) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType)); } else if (findValue.GetType() == typeof(X509KeyUsageFlags)) { pvCallbackData1 = findValue; } else if (findValue.GetType() == typeof(uint) || findValue.GetType() == typeof(int)) { // We got the actual DWORD pvCallbackData1 = findValue; } else throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType)); pfnCertCallback1 = new FindProcDelegate(FindKeyUsageCallback); break; case X509FindType.FindBySubjectKeyIdentifier: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); pvCallbackData1 = (byte[]) X509Utils.DecodeHexString((string) findValue); pfnCertCallback1 = new FindProcDelegate(FindSubjectKeyIdentifierCallback); break; default: throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType)); } // First, create a memory store Cryptography.SafeCertStoreHandle safeTargetStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (safeTargetStoreHandle == null || safeTargetStoreHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); // FindByCert will throw an exception in case of failures. FindByCert(safeSourceStoreHandle, dwFindType, pvFindPara, validOnly, pfnCertCallback1, pfnCertCallback2, pvCallbackData1, pvCallbackData2, safeTargetStoreHandle); pb.Dispose(); return safeTargetStoreHandle; }
SafeCertStoreHandle PFXImportCertStore( [In] uint dwObjectType, [In] object pvObject, [In] string szPassword, [In] uint dwFlags, [In] bool persistKeyContainers) { if (pvObject == null) throw new ArgumentNullException("pvObject"); byte[] pbData = null; if (dwObjectType == CERT_QUERY_OBJECT_FILE) { pbData = File.ReadAllBytes((string)pvObject); } else { pbData = (byte[]) pvObject; } #if !FEATURE_CORESYSTEM if (persistKeyContainers) { // // Right now, we always demand KeyContainerPermission regardless of whether the PFX contains a private key or not. // We could avoid that by looping through the certs in the store and find out whether there are actually private keys. // if (!CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) { KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.Create); kp.Demand(); } } #endif SafeCertStoreHandle safeCertStoreHandle = SafeCertStoreHandle.InvalidHandle; GCHandle handle = GCHandle.Alloc(pbData, GCHandleType.Pinned); IntPtr ptr = handle.AddrOfPinnedObject(); try { CRYPTOAPI_BLOB certBlob; certBlob.cbData = (uint) pbData.Length; certBlob.pbData = ptr; safeCertStoreHandle = CAPIMethods.PFXImportCertStore(new IntPtr(&certBlob), szPassword, dwFlags); } finally { if (handle.IsAllocated) handle.Free(); } if (!safeCertStoreHandle.IsInvalid) { // // If the user did not want us to persist private keys, then we should loop through all // the certificates in the collection and set our custom CERT_DELETE_KEYSET_PROP_ID property // so the key container will be deleted when the cert contexts will go away. // if (persistKeyContainers == false) { IntPtr pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, IntPtr.Zero); while (pEnumContext != IntPtr.Zero) { CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB(); if (!CAPI.CertSetCertificateContextProperty(pEnumContext, CERT_DELETE_KEYSET_PROP_ID, CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG, // we don't want this property to be persisted. new IntPtr(&blob))) throw new CryptographicException(Marshal.GetLastWin32Error()); pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, pEnumContext); } } } return safeCertStoreHandle; }
private unsafe static byte[] ExportCertificatesToBlob(Cryptography.SafeCertStoreHandle safeCertStoreHandle, X509ContentType contentType, string password) { Cryptography.SafeCertContextHandle safeCertContextHandle = Cryptography.SafeCertContextHandle.InvalidHandle; uint dwSaveAs = CAPI.CERT_STORE_SAVE_AS_PKCS7; byte[] pbBlob = null; CAPI.CRYPTOAPI_BLOB DataBlob = new CAPI.CRYPTOAPI_BLOB(); SafeLocalAllocHandle pbEncoded = SafeLocalAllocHandle.InvalidHandle; switch(contentType) { case X509ContentType.Cert: safeCertContextHandle = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, safeCertContextHandle); if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle()); pbBlob = new byte[pCertContext.cbCertEncoded]; Marshal.Copy(pCertContext.pbCertEncoded, pbBlob, 0, pbBlob.Length); } break; case X509ContentType.SerializedCert: safeCertContextHandle = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, safeCertContextHandle); uint cbEncoded = 0; if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { if (!CAPI.CertSerializeCertificateStoreElement(safeCertContextHandle, 0, pbEncoded, new IntPtr(&cbEncoded))) throw new CryptographicException(Marshal.GetLastWin32Error()); pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbEncoded)); if (!CAPI.CertSerializeCertificateStoreElement(safeCertContextHandle, 0, pbEncoded, new IntPtr(&cbEncoded))) throw new CryptographicException(Marshal.GetLastWin32Error()); pbBlob = new byte[cbEncoded]; Marshal.Copy(pbEncoded.DangerousGetHandle(), pbBlob, 0, pbBlob.Length); } break; case X509ContentType.Pkcs12: if (!CAPI.PFXExportCertStore(safeCertStoreHandle, new IntPtr(&DataBlob), password, CAPI.EXPORT_PRIVATE_KEYS | CAPI.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(DataBlob.cbData)); DataBlob.pbData = pbEncoded.DangerousGetHandle(); if (!CAPI.PFXExportCertStore(safeCertStoreHandle, new IntPtr(&DataBlob), password, CAPI.EXPORT_PRIVATE_KEYS | CAPI.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbBlob = new byte[DataBlob.cbData]; Marshal.Copy(DataBlob.pbData, pbBlob, 0, pbBlob.Length); break; case X509ContentType.SerializedStore: // falling through case X509ContentType.Pkcs7: if (contentType == X509ContentType.SerializedStore) dwSaveAs = CAPI.CERT_STORE_SAVE_AS_STORE; // determine the required length if (!CAPI.CertSaveStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, dwSaveAs, CAPI.CERT_STORE_SAVE_TO_MEMORY, new IntPtr(&DataBlob), 0)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(DataBlob.cbData)); DataBlob.pbData = pbEncoded.DangerousGetHandle(); // now save the store to a memory blob if (!CAPI.CertSaveStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, dwSaveAs, CAPI.CERT_STORE_SAVE_TO_MEMORY, new IntPtr(&DataBlob), 0)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbBlob = new byte[DataBlob.cbData]; Marshal.Copy(DataBlob.pbData, pbBlob, 0, pbBlob.Length); break; default: throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidContentType)); } pbEncoded.Dispose(); safeCertContextHandle.Dispose(); return pbBlob; }
private static unsafe void SetFriendlyNameExtendedProperty (SafeCertContextHandle safeCertContextHandle, string name) { SafeLocalAllocHandle ptr = X509Utils.StringToUniPtr(name); using (ptr) { CAPI.CRYPTOAPI_BLOB DataBlob = new CAPI.CRYPTOAPI_BLOB(); DataBlob.cbData = 2 * ((uint) name.Length + 1); DataBlob.pbData = ptr.DangerousGetHandle(); if (!CAPI.CertSetCertificateContextProperty(safeCertContextHandle, CAPI.CERT_FRIENDLY_NAME_PROP_ID, 0, new IntPtr(&DataBlob))) throw new CryptographicException(Marshal.GetLastWin32Error()); } }
private static unsafe byte[] EncodeExtension (byte[] subjectKeyIdentifier) { if (subjectKeyIdentifier == null) throw new ArgumentNullException("subjectKeyIdentifier"); if (subjectKeyIdentifier.Length == 0) throw new ArgumentException("subjectKeyIdentifier"); byte[] encodedSubjectKeyIdentifier = null; fixed (byte* pb = subjectKeyIdentifier) { CAPI.CRYPTOAPI_BLOB pSubjectKeyIdentifier = new CAPI.CRYPTOAPI_BLOB(); pSubjectKeyIdentifier.pbData = new IntPtr(pb); pSubjectKeyIdentifier.cbData = (uint) subjectKeyIdentifier.Length; if (!CAPI.EncodeObject(CAPI.szOID_SUBJECT_KEY_IDENTIFIER, new IntPtr(&pSubjectKeyIdentifier), out encodedSubjectKeyIdentifier)) throw new CryptographicException(Marshal.GetLastWin32Error()); } return encodedSubjectKeyIdentifier; }
public static byte[] Unprotect (byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope) { if (encryptedData == null) throw new ArgumentNullException("encryptedData"); if (Environment.OSVersion.Platform == PlatformID.Win32Windows) throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); GCHandle pbDataIn = new GCHandle(); GCHandle pOptionalEntropy = new GCHandle(); CAPI.CRYPTOAPI_BLOB userData = new CAPI.CRYPTOAPI_BLOB(); RuntimeHelpers.PrepareConstrainedRegions(); try { pbDataIn = GCHandle.Alloc(encryptedData, GCHandleType.Pinned); CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB(); dataIn.cbData = (uint) encryptedData.Length; dataIn.pbData = pbDataIn.AddrOfPinnedObject(); CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB(); if (optionalEntropy != null) { pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned); entropy.cbData = (uint) optionalEntropy.Length; entropy.pbData = pOptionalEntropy.AddrOfPinnedObject(); } uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN; if (scope == DataProtectionScope.LocalMachine) dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE; unsafe { if (!CAPI.CryptUnprotectData(new IntPtr(&dataIn), IntPtr.Zero, new IntPtr(&entropy), IntPtr.Zero, IntPtr.Zero, dwFlags, new IntPtr(&userData))) throw new CryptographicException(Marshal.GetLastWin32Error()); } // In some cases, the API would fail due to OOM but simply return a null pointer. if (userData.pbData == IntPtr.Zero) throw new OutOfMemoryException(); byte[] data = new byte[(int) userData.cbData]; Marshal.Copy(userData.pbData, data, 0, data.Length); return data; } catch (EntryPointNotFoundException) { throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); } finally { if (pbDataIn.IsAllocated) pbDataIn.Free(); if (pOptionalEntropy.IsAllocated) pOptionalEntropy.Free(); if (userData.pbData != IntPtr.Zero) { CAPI.CAPISafe.ZeroMemory(userData.pbData, userData.cbData); CAPI.CAPISafe.LocalFree(userData.pbData); } } }
public static byte[] Protect (byte[] userData, byte[] optionalEntropy, DataProtectionScope scope) { if (userData == null) throw new ArgumentNullException("userData"); if (Environment.OSVersion.Platform == PlatformID.Win32Windows) throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); GCHandle pbDataIn = new GCHandle(); GCHandle pOptionalEntropy = new GCHandle(); CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB(); RuntimeHelpers.PrepareConstrainedRegions(); try { pbDataIn = GCHandle.Alloc(userData, GCHandleType.Pinned); CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB(); dataIn.cbData = (uint) userData.Length; dataIn.pbData = pbDataIn.AddrOfPinnedObject(); CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB(); if (optionalEntropy != null) { pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned); entropy.cbData = (uint) optionalEntropy.Length; entropy.pbData = pOptionalEntropy.AddrOfPinnedObject(); } uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN; if (scope == DataProtectionScope.LocalMachine) dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE; unsafe { if (!CAPI.CryptProtectData(new IntPtr(&dataIn), String.Empty, new IntPtr(&entropy), IntPtr.Zero, IntPtr.Zero, dwFlags, new IntPtr(&blob))) { int lastWin32Error = Marshal.GetLastWin32Error(); // One of the most common reasons that DPAPI operations fail is that the user // profile is not loaded (for instance in the case of impersonation or running in a // service. In those cases, throw an exception that provides more specific details // about what happened. if (CAPI.ErrorMayBeCausedByUnloadedProfile(lastWin32Error)) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_ProfileMayNotBeLoaded")); } else { throw new CryptographicException(lastWin32Error); } } } // In some cases, the API would fail due to OOM but simply return a null pointer. if (blob.pbData == IntPtr.Zero) throw new OutOfMemoryException(); byte[] encryptedData = new byte[(int) blob.cbData]; Marshal.Copy(blob.pbData, encryptedData, 0, encryptedData.Length); return encryptedData; } catch (EntryPointNotFoundException) { throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); } finally { if (pbDataIn.IsAllocated) pbDataIn.Free(); if (pOptionalEntropy.IsAllocated) pOptionalEntropy.Free(); if (blob.pbData != IntPtr.Zero) { CAPI.CAPISafe.ZeroMemory(blob.pbData, blob.cbData); CAPI.CAPISafe.LocalFree(blob.pbData); } } }
internal static unsafe X509Certificate2 CreateDummyCertificate (CspParameters parameters) { SafeCertContextHandle handle = SafeCertContextHandle.InvalidHandle; // hProv SafeCryptProvHandle hProv = SafeCryptProvHandle.InvalidHandle; UInt32 dwFlags = 0; if (0 != (parameters.Flags & CspProviderFlags.UseMachineKeyStore)) { dwFlags |= CAPI.CRYPT_MACHINE_KEYSET; } if (0 != (parameters.Flags & CspProviderFlags.UseDefaultKeyContainer)) { dwFlags |= CAPI.CRYPT_VERIFYCONTEXT; } if (0 != (parameters.Flags & CspProviderFlags.NoPrompt)) { dwFlags |= CAPI.CRYPT_SILENT; } bool rc = CAPI.CryptAcquireContext(ref hProv, parameters.KeyContainerName, parameters.ProviderName, (uint)parameters.ProviderType, dwFlags); if (!rc) throw new CryptographicException(Marshal.GetLastWin32Error()); // pKeyProvInfo CAPI.CRYPT_KEY_PROV_INFO KeyProvInfo = new CAPI.CRYPT_KEY_PROV_INFO(); KeyProvInfo.pwszProvName = parameters.ProviderName; KeyProvInfo.pwszContainerName = parameters.KeyContainerName; KeyProvInfo.dwProvType = (uint)parameters.ProviderType; KeyProvInfo.dwKeySpec = (uint)parameters.KeyNumber ; KeyProvInfo.dwFlags = (uint)((parameters.Flags & CspProviderFlags.UseMachineKeyStore) == CspProviderFlags.UseMachineKeyStore ? CAPI.CRYPT_MACHINE_KEYSET : 0); SafeLocalAllocHandle pKeyProvInfo = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CRYPT_KEY_PROV_INFO)))); Marshal.StructureToPtr(KeyProvInfo, pKeyProvInfo.DangerousGetHandle(), false); // Signature CAPI.CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = new CAPI.CRYPT_ALGORITHM_IDENTIFIER(); SignatureAlgorithm.pszObjId = CAPI.szOID_OIWSEC_sha1RSASign; SafeLocalAllocHandle pSignatureAlgorithm = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr( Marshal.SizeOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER)))); Marshal.StructureToPtr(SignatureAlgorithm, pSignatureAlgorithm.DangerousGetHandle(), false); // pSubjectIssuerBlob X500DistinguishedName subjectName = new X500DistinguishedName("cn=CMS Signer Dummy Certificate"); fixed (byte * pbOctets = subjectName.RawData) { CAPI.CRYPTOAPI_BLOB SubjectIssuerBlob = new CAPI.CRYPTOAPI_BLOB(); SubjectIssuerBlob.cbData = (uint)subjectName.RawData.Length; SubjectIssuerBlob.pbData = new IntPtr(pbOctets); handle = CAPI.CAPIUnsafe.CertCreateSelfSignCertificate(hProv, new IntPtr(&SubjectIssuerBlob), 1, pKeyProvInfo.DangerousGetHandle(), pSignatureAlgorithm.DangerousGetHandle(), IntPtr.Zero, //StartTime IntPtr.Zero, //EndTime IntPtr.Zero); //Extensions } Marshal.DestroyStructure(pKeyProvInfo.DangerousGetHandle(), typeof(CAPI.CRYPT_KEY_PROV_INFO)); pKeyProvInfo.Dispose(); Marshal.DestroyStructure(pSignatureAlgorithm.DangerousGetHandle(), typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER)); pSignatureAlgorithm.Dispose(); if (handle == null || handle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); X509Certificate2 certificate = new X509Certificate2(handle.DangerousGetHandle()); handle.Dispose(); return certificate; }
internal static unsafe uint AddCertsToMessage (SafeCryptMsgHandle safeCryptMsgHandle, X509Certificate2Collection bagOfCerts, X509Certificate2Collection chainOfCerts) { uint certsAdded = 0; foreach (X509Certificate2 certificate in chainOfCerts) { // Skip it if already in the bag of certs. X509Certificate2Collection foundCerts = bagOfCerts.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false); if (foundCerts.Count == 0) { SafeCertContextHandle safeCertContextHandle = X509Utils.GetCertContext(certificate); CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle()); CAPI.CRYPTOAPI_BLOB certBlob = new CAPI.CRYPTOAPI_BLOB(); certBlob.cbData = pCertContext.cbCertEncoded; certBlob.pbData = pCertContext.pbCertEncoded; if (!CAPI.CryptMsgControl(safeCryptMsgHandle, 0, CAPI.CMSG_CTRL_ADD_CERT, new IntPtr((long) &certBlob))) throw new CryptographicException(Marshal.GetLastWin32Error()); certsAdded++; } } return certsAdded; }
internal static unsafe byte[] EncodeOctetString (byte[] octets) { fixed (byte * pbOctets = octets) { CAPI.CRYPTOAPI_BLOB octetsBlob = new CAPI.CRYPTOAPI_BLOB(); octetsBlob.cbData = (uint) octets.Length; octetsBlob.pbData = new IntPtr(pbOctets); // Encode data. byte[] encodedOctets = new byte[0]; if (!CAPI.EncodeObject(new IntPtr((long) CAPI.X509_OCTET_STRING), new IntPtr((long) &octetsBlob), out encodedOctets)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } return encodedOctets; } }
private unsafe void EncryptContent (CmsRecipientCollection recipients) { CMSG_ENCRYPT_PARAM encryptParam = new CMSG_ENCRYPT_PARAM(); if (recipients.Count < 1) throw new CryptographicException(CAPI.CRYPT_E_RECIPIENT_NOT_FOUND); foreach (CmsRecipient recipient in recipients) { if (recipient.Certificate == null) throw new ArgumentNullException(SecurityResources.GetResourceString("Cryptography_Cms_RecipientCertificateNotFound")); if ((PkcsUtils.GetRecipientInfoType(recipient.Certificate) == RecipientInfoType.KeyAgreement) || (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)) encryptParam.useCms = true; } if (!encryptParam.useCms) { if (this.Certificates.Count > 0 || this.UnprotectedAttributes.Count > 0) { encryptParam.useCms = true; } } if (encryptParam.useCms && !PkcsUtils.CmsSupported()) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Not_Supported")); } CAPI.CMSG_ENVELOPED_ENCODE_INFO encodeInfo = new CAPI.CMSG_ENVELOPED_ENCODE_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO))); SafeLocalAllocHandle ceei = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO)))); SetCspParams(this.ContentEncryptionAlgorithm, ref encryptParam); encodeInfo.ContentEncryptionAlgorithm.pszObjId = this.ContentEncryptionAlgorithm.Oid.Value; //encodeInfo.hCryptProv = encryptParam.safeCryptProvHandle.DangerousGetHandle(); if (encryptParam.pvEncryptionAuxInfo != null && !encryptParam.pvEncryptionAuxInfo.IsInvalid) { encodeInfo.pvEncryptionAuxInfo = encryptParam.pvEncryptionAuxInfo.DangerousGetHandle(); } encodeInfo.cRecipients = (uint) recipients.Count; List<SafeCertContextHandle> certContexts = null; if (encryptParam.useCms) { SetCmsRecipientParams(recipients, this.Certificates, this.UnprotectedAttributes, this.ContentEncryptionAlgorithm, ref encryptParam); encodeInfo.rgCmsRecipients = encryptParam.rgpRecipients.DangerousGetHandle(); if (encryptParam.rgCertEncoded != null && !encryptParam.rgCertEncoded.IsInvalid) { encodeInfo.cCertEncoded = (uint) this.Certificates.Count; encodeInfo.rgCertEncoded = encryptParam.rgCertEncoded.DangerousGetHandle(); } if (encryptParam.rgUnprotectedAttr != null && !encryptParam.rgUnprotectedAttr.IsInvalid) { encodeInfo.cUnprotectedAttr = (uint) this.UnprotectedAttributes.Count; encodeInfo.rgUnprotectedAttr = encryptParam.rgUnprotectedAttr.DangerousGetHandle(); } } else { SetPkcs7RecipientParams(recipients, ref encryptParam, out certContexts); encodeInfo.rgpRecipients = encryptParam.rgpRecipients.DangerousGetHandle(); } Marshal.StructureToPtr(encodeInfo, ceei.DangerousGetHandle(), false); try { SafeCryptMsgHandle safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, CAPI.CMSG_ENVELOPED, ceei.DangerousGetHandle(), this.ContentInfo.ContentType.Value, IntPtr.Zero); if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) { m_safeCryptMsgHandle.Dispose(); } m_safeCryptMsgHandle = safeCryptMsgHandle; } finally { Marshal.DestroyStructure(ceei.DangerousGetHandle(), typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO)); ceei.Dispose(); } byte[] encodedContent = new byte[0]; if (String.Compare(this.ContentInfo.ContentType.Value, CAPI.szOID_RSA_data, StringComparison.OrdinalIgnoreCase) == 0) { byte[] content = this.ContentInfo.Content; fixed (byte * pbContent = content) { CAPI.CRYPTOAPI_BLOB dataBlob = new CAPI.CRYPTOAPI_BLOB(); dataBlob.cbData = (uint) content.Length; dataBlob.pbData = new IntPtr(pbContent); if (!CAPI.EncodeObject(new IntPtr(CAPI.X509_OCTET_STRING), new IntPtr(&dataBlob), out encodedContent)) throw new CryptographicException(Marshal.GetLastWin32Error()); } } else { encodedContent = this.ContentInfo.Content; } if (encodedContent.Length > 0) { if (!CAPI.CAPISafe.CryptMsgUpdate(m_safeCryptMsgHandle, encodedContent, (uint) encodedContent.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); } // Keep alive GC.KeepAlive(encryptParam); GC.KeepAlive(recipients); GC.KeepAlive(certContexts); }
public X509Certificate2Collection Find(X509FindType findType, object findValue, bool validOnly) { DiagnosticUtility.DebugAssert(!this.certStoreHandle.IsInvalid, ""); uint dwFindType; SafeHGlobalHandle pvFindPara = SafeHGlobalHandle.InvalidHandle; SafeCertContextHandle pCertContext = SafeCertContextHandle.InvalidHandle; X509Certificate2Collection result = new X509Certificate2Collection(); SafeHGlobalHandle pvTemp = SafeHGlobalHandle.InvalidHandle; string strFindValue; byte[] bytes; try { switch (findType) { case X509FindType.FindBySubjectName: strFindValue = findValue as string; if (strFindValue == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType()))); dwFindType = CAPI.CERT_FIND_SUBJECT_STR; pvFindPara = SafeHGlobalHandle.AllocHGlobal(strFindValue); break; case X509FindType.FindByThumbprint: bytes = findValue as byte[]; if (bytes == null) { strFindValue = findValue as string; if (strFindValue == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType()))); bytes = SecurityUtils.DecodeHexString(strFindValue); } CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB(); pvTemp = SafeHGlobalHandle.AllocHGlobal(bytes); blob.pbData = pvTemp.DangerousGetHandle(); blob.cbData = (uint)bytes.Length; dwFindType = CAPI.CERT_FIND_HASH; pvFindPara = SafeHGlobalHandle.AllocHGlobal(CAPI.CRYPTOAPI_BLOB.Size); Marshal.StructureToPtr(blob, pvFindPara.DangerousGetHandle(), false); break; case X509FindType.FindBySubjectDistinguishedName: if (!(findValue is string)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType()))); dwFindType = CAPI.CERT_FIND_ANY; break; case X509FindType.FindByIssuerName: strFindValue = findValue as string; if (strFindValue == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType()))); dwFindType = CAPI.CERT_FIND_ISSUER_STR; pvFindPara = SafeHGlobalHandle.AllocHGlobal(strFindValue); break; case X509FindType.FindByIssuerDistinguishedName: if (!(findValue is string)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatch, findType, typeof(string), findValue.GetType()))); dwFindType = CAPI.CERT_FIND_ANY; break; case X509FindType.FindBySerialNumber: bytes = findValue as byte[]; if (bytes == null) { strFindValue = findValue as string; if (strFindValue == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType()))); bytes = SecurityUtils.DecodeHexString(strFindValue); // reverse bits int len = bytes.Length; for (int i = 0, j = len - 1; i < bytes.Length / 2; ++i, --j) { byte tmp = bytes[i]; bytes[i] = bytes[j]; bytes[j] = tmp; } } findValue = bytes; dwFindType = CAPI.CERT_FIND_ANY; break; case X509FindType.FindBySubjectKeyIdentifier: bytes = findValue as byte[]; if (bytes == null) { strFindValue = findValue as string; if (strFindValue == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.X509FindValueMismatchMulti, findType, typeof(string), typeof(byte[]), findValue.GetType()))); bytes = SecurityUtils.DecodeHexString(strFindValue); } findValue = bytes; dwFindType = CAPI.CERT_FIND_ANY; break; default: // Fallback to CLR implementation X509Store store = new X509Store(this.certStoreHandle.DangerousGetHandle()); try { return store.Certificates.Find(findType, findValue, validOnly); } finally { store.Close(); } } #pragma warning suppress 56523 // We are not interested in CRYPT_E_NOT_FOUND error, it return null anyway. pCertContext = CAPI.CertFindCertificateInStore(this.certStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, dwFindType, pvFindPara, pCertContext); while (pCertContext != null && !pCertContext.IsInvalid) { X509Certificate2 cert; if (TryGetMatchingX509Certificate(pCertContext.DangerousGetHandle(), findType, dwFindType, findValue, validOnly, out cert)) { result.Add(cert); } // CER RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { // Suppress the finalizer #pragma warning suppress 56508 // CertFindCertificateInStore will release the prev one. GC.SuppressFinalize(pCertContext); #pragma warning suppress 56523 // We are not interested in CRYPT_E_NOT_FOUND error, it return null anyway. pCertContext = CAPI.CertFindCertificateInStore(this.certStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, dwFindType, pvFindPara, pCertContext); } } } finally { if (pCertContext != null) { pCertContext.Close(); } pvFindPara.Close(); pvTemp.Close(); } return result; }