internal static Microsoft.Win32.SafeHandles.SafeCspHandle AcquireCsp(string keyContainer, string providerName, ProviderType providerType, CryptAcquireContextFlags flags, bool throwPlatformException) { Contract.Ensures(Contract.Result <SafeCspHandle>() != null && !Contract.Result <SafeCspHandle>().IsInvalid&& !Contract.Result <SafeCspHandle>().IsClosed); Microsoft.Win32.SafeHandles.SafeCspHandle cspHandle = null; if (!UnsafeNativeMethods.CryptAcquireContext(out cspHandle, keyContainer, providerName, providerType, flags)) { // If the platform doesn't have the specified CSP, we'll either get a ProviderTypeNotDefined // or a KeysetNotDefined error depending on the CAPI version. int error = Marshal.GetLastWin32Error(); if (throwPlatformException && (error == (int)CapiNative.ErrorCode.ProviderTypeNotDefined || error == (int)CapiNative.ErrorCode.KeysetNotDefined)) { throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); } else { throw new CryptographicException(error); } } return(cspHandle); }
public AesCryptoServiceProvider () { Contract.Ensures(m_cspHandle != null && !m_cspHandle.IsInvalid && !m_cspHandle.IsClosed); // On Windows XP the AES CSP has the prototype name, but on newer operating systems it has the // standard name string providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAes; if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1) { providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAesPrototype; } m_cspHandle = CapiNative.AcquireCsp(null, providerName, CapiNative.ProviderType.RsaAes, CapiNative.CryptAcquireContextFlags.VerifyContext, true); // CAPI will not allow feedback sizes greater than 64 bits FeedbackSizeValue = 8; // Get the different AES key sizes supported by this platform, raising an error if there are no // supported key sizes. int defaultKeySize = 0; KeySizes[] keySizes = FindSupportedKeySizes(m_cspHandle, out defaultKeySize); if (keySizes.Length != 0) { Debug.Assert(defaultKeySize > 0, "defaultKeySize > 0"); KeySizeValue = defaultKeySize; } else { throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); } }
public SafeCspHandle Duplicate() { Contract.Requires(!IsInvalid && !IsClosed); // In the window between the call to CryptContextAddRef and when the raw handle value is assigned // into this safe handle, there's a second reference to the original safe handle that the CLR does // not know about, so we need to bump the reference count around this entire operation to ensure // that we don't have the original handle closed underneath us. bool acquired = false; RuntimeHelpers.PrepareConstrainedRegions(); try { DangerousAddRef(ref acquired); IntPtr originalHandle = DangerousGetHandle(); int error = (int)CapiNative.ErrorCode.Success; SafeCspHandle duplicate = new SafeCspHandle(); // A successful call to CryptContextAddRef and an assignment of the handle value to the duplicate // SafeHandle need to happen atomically, so we contain them within a CER. RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (!CryptContextAddRef(this, IntPtr.Zero, 0)) { error = Marshal.GetLastWin32Error(); } else { duplicate.SetHandle(originalHandle); } } // If we could not call CryptContextAddRef succesfully, then throw the error here otherwise // we should be in a valid state at this point. if (error != (int)CapiNative.ErrorCode.Success) { duplicate.Dispose(); throw new CryptographicException(error); } else { Debug.Assert(!duplicate.IsInvalid, "Failed to duplicate handle successfully"); } return(duplicate); } finally { if (acquired) { DangerousRelease(); } } }
internal static T GetProviderParameterStruct <T>(Microsoft.Win32.SafeHandles.SafeCspHandle provider, ProviderParameter parameter, ProviderParameterFlags flags) where T : struct { Contract.Requires(provider != null); Contract.Requires(parameter == ProviderParameter.EnumerateAlgorithms); // Figure out how big the parameter is int bufferSize = 0; IntPtr buffer = IntPtr.Zero; if (!UnsafeNativeMethods.CryptGetProvParam(provider, parameter, buffer, ref bufferSize, flags)) { int errorCode = Marshal.GetLastWin32Error(); // NoMoreItems means that we've finished the enumeration we're currently working on, this is // not a real error, so return an empty structure to mark the end. if (errorCode == (int)ErrorCode.NoMoreItems) { return(new T()); } else if (errorCode != (int)ErrorCode.MoreData) { throw new CryptographicException(errorCode); } } Debug.Assert(Marshal.SizeOf(typeof(T)) <= bufferSize, "Buffer size does not match structure size"); // // Pull the parameter back and marshal it into the return structure // RuntimeHelpers.PrepareConstrainedRegions(); try { // Allocate in a CER because we could fail between the alloc and the assignment RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { buffer = Marshal.AllocCoTaskMem(bufferSize); } if (!UnsafeNativeMethods.CryptGetProvParam(provider, parameter, buffer, ref bufferSize, flags)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } return((T)Marshal.PtrToStructure(buffer, typeof(T))); } finally { if (buffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(buffer); } } }
// SafeCritical - we're not exposing out anything that we want to prevent untrusted code from getting at public CapiHashAlgorithm(string provider, CapiNative.ProviderType providerType, CapiNative.AlgorithmId algorithm) { Contract.Requires(!String.IsNullOrEmpty(provider)); Contract.Requires((CapiNative.AlgorithmClass)((uint)algorithm & (uint)CapiNative.AlgorithmClass.Hash) == CapiNative.AlgorithmClass.Hash); Contract.Ensures(m_cspHandle != null && !m_cspHandle.IsInvalid && !m_cspHandle.IsClosed); Contract.Ensures(m_hashHandle != null && !m_hashHandle.IsInvalid && !m_hashHandle.IsClosed); m_algorithmId = algorithm; m_cspHandle = CapiNative.AcquireCsp(null, provider, providerType, CapiNative.CryptAcquireContextFlags.VerifyContext, true); Initialize(); }
internal void SetParentCsp(SafeCspHandle parentCsp) { bool addedRef = false; RuntimeHelpers.PrepareConstrainedRegions(); try { parentCsp.DangerousAddRef(ref addedRef); IntPtr rawParentHandle = parentCsp.DangerousGetHandle(); ParentCsp = rawParentHandle; } finally { if (addedRef) { parentCsp.DangerousRelease(); } } }
public SafeCspHandle Duplicate() { SafeCspHandle handle2; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { base.DangerousAddRef(ref success); IntPtr ptr = base.DangerousGetHandle(); int hr = 0; SafeCspHandle handle = new SafeCspHandle(); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (!CryptContextAddRef(this, IntPtr.Zero, 0)) { hr = Marshal.GetLastWin32Error(); } else { handle.SetHandle(ptr); } } if (hr != 0) { handle.Dispose(); throw new CryptographicException(hr); } handle2 = handle; } finally { if (success) { base.DangerousRelease(); } } return handle2; }
public CapiSymmetricAlgorithm(int blockSize, int feedbackSize, Microsoft.Win32.SafeHandles.SafeCspHandle provider, SafeCapiKeyHandle key, byte[] iv, CipherMode cipherMode, PaddingMode paddingMode, EncryptionMode encryptionMode) { Contract.Requires(0 < blockSize && blockSize % 8 == 0); Contract.Requires(0 <= feedbackSize); Contract.Requires(provider != null && !provider.IsInvalid && !provider.IsClosed); Contract.Requires(key != null && !key.IsInvalid && !key.IsClosed); Contract.Ensures(m_provider != null && !m_provider.IsInvalid && !m_provider.IsClosed); m_blockSize = blockSize; m_encryptionMode = encryptionMode; m_paddingMode = paddingMode; m_provider = provider.Duplicate(); m_key = SetupKey(key, ProcessIV(iv, blockSize, cipherMode), cipherMode, feedbackSize); }
public AesCryptoServiceProvider() { Contract.Ensures(m_cspHandle != null && !m_cspHandle.IsInvalid && !m_cspHandle.IsClosed); // On Windows XP the AES CSP has the prototype name, but on newer operating systems it has the // standard name string providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAes; if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1) { providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAesPrototype; } m_cspHandle = CapiNative.AcquireCsp(null, providerName, CapiNative.ProviderType.RsaAes, CapiNative.CryptAcquireContextFlags.VerifyContext, true); // CAPI will not allow feedback sizes greater than 64 bits FeedbackSizeValue = 8; // Get the different AES key sizes supported by this platform, raising an error if there are no // supported key sizes. int defaultKeySize = 0; KeySizes[] keySizes = FindSupportedKeySizes(m_cspHandle, out defaultKeySize); if (keySizes.Length != 0) { Debug.Assert(defaultKeySize > 0, "defaultKeySize > 0"); KeySizeValue = defaultKeySize; } else { throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); } }
public static extern bool CryptImportKey(Microsoft.Win32.SafeHandles.SafeCspHandle hProv, [MarshalAs(UnmanagedType.LPArray)] byte[] pbData, int dwDataLen, SafeCapiKeyHandle hPubKey, KeyFlags dwFlags, [Out] out SafeCapiKeyHandle phKey);
public static extern bool CryptGetProvParam(Microsoft.Win32.SafeHandles.SafeCspHandle hProv, ProviderParameter dwParam, IntPtr pbData, [In, Out] ref int pdwDataLen, ProviderParameterFlags dwFlags);
public static extern bool CryptGenRandom(Microsoft.Win32.SafeHandles.SafeCspHandle hProv, int dwLen, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbBuffer);
public static extern bool CryptGenKey(Microsoft.Win32.SafeHandles.SafeCspHandle hProv, AlgorithmId Algid, KeyFlags dwFlags, [Out] out SafeCapiKeyHandle phKey);
public static extern bool CryptCreateHash(Microsoft.Win32.SafeHandles.SafeCspHandle hProv, AlgorithmId Algid, SafeCapiKeyHandle hKey, int dwFlags, [Out] out SafeCapiHashHandle phHash);
internal static SafeCapiKeyHandle ImportSymmetricKey(Microsoft.Win32.SafeHandles.SafeCspHandle provider, AlgorithmId algorithm, byte[] key) { Contract.Requires(provider != null); Contract.Requires(((int)algorithm & (int)AlgorithmClass.DataEncryption) == (int)AlgorithmClass.DataEncryption); Contract.Requires(key != null); Contract.Ensures(Contract.Result <SafeCapiKeyHandle>() != null && !Contract.Result <SafeCapiKeyHandle>().IsInvalid&& !Contract.Result <SafeCapiKeyHandle>().IsClosed); // // Setup a PLAINTEXTKEYBLOB (v2) which has the following format: // BLOBHEADER hdr // DWORD cbKeySize // BYTE rbgKeyData[] // int blobSize = Marshal.SizeOf(typeof(BLOBHEADER)) + Marshal.SizeOf(typeof(int)) + key.Length; byte[] keyBlob = new byte[blobSize]; unsafe { fixed(byte *pBlob = keyBlob) { BLOBHEADER *pHeader = (BLOBHEADER *)pBlob; pHeader->bType = KeyBlobType.PlainText; pHeader->bVersion = 2; pHeader->reserved = 0; pHeader->aiKeyAlg = algorithm; int *pSize = (int *)(pBlob + Marshal.SizeOf(*pHeader)); *pSize = key.Length; } } Buffer.BlockCopy(key, 0, keyBlob, Marshal.SizeOf(typeof(BLOBHEADER)) + Marshal.SizeOf(typeof(int)), key.Length); // Import the PLAINTEXTKEYBLOB into the CSP SafeCapiKeyHandle importedKey = null; RuntimeHelpers.PrepareConstrainedRegions(); try { if (!UnsafeNativeMethods.CryptImportKey(provider, keyBlob, keyBlob.Length, SafeCapiKeyHandle.InvalidHandle, KeyFlags.Exportable, out importedKey)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } finally { if (importedKey != null && !importedKey.IsInvalid) { importedKey.SetParentCsp(provider); } } return(importedKey); }
private static extern bool CryptContextAddRef(SafeCspHandle hProv, IntPtr pdwReserved, int dwFlags);
public static extern bool CryptAcquireContext([Out] out Microsoft.Win32.SafeHandles.SafeCspHandle phProv, string pszContainer, string pszProvider, ProviderType dwProvType, CryptAcquireContextFlags dwFlags);
private static KeySizes[] FindSupportedKeySizes(Microsoft.Win32.SafeHandles.SafeCspHandle csp, out int defaultKeySize) { Contract.Requires(csp != null); Contract.Ensures(Contract.Result <KeySizes[]>() != null); // If this platform has any supported algorithm sizes, then the default key size should be set to a // reasonable value. Contract.Ensures(Contract.Result <KeySizes[]>().Length == 0 || (Contract.ValueAtReturn <int>(out defaultKeySize) > 0 && Contract.ValueAtReturn <int>(out defaultKeySize) % 8 == 0)); if (s_supportedKeySizes == null) { List <KeySizes> keySizes = new List <KeySizes>(); int maxKeySize = 0; // // Enumerate the CSP's supported algorithms to see what key sizes it supports for AES // CapiNative.PROV_ENUMALGS algorithm = CapiNative.GetProviderParameterStruct <CapiNative.PROV_ENUMALGS>(csp, CapiNative.ProviderParameter.EnumerateAlgorithms, CapiNative.ProviderParameterFlags.RestartEnumeration); // Translate between CAPI AES algorithm IDs and supported key sizes while (algorithm.aiAlgId != CapiNative.AlgorithmId.None) { switch (algorithm.aiAlgId) { case CapiNative.AlgorithmId.Aes128: keySizes.Add(new KeySizes(128, 128, 0)); if (128 > maxKeySize) { maxKeySize = 128; } break; case CapiNative.AlgorithmId.Aes192: keySizes.Add(new KeySizes(192, 192, 0)); if (192 > maxKeySize) { maxKeySize = 192; } break; case CapiNative.AlgorithmId.Aes256: keySizes.Add(new KeySizes(256, 256, 0)); if (256 > maxKeySize) { maxKeySize = 256; } break; default: break; } algorithm = CapiNative.GetProviderParameterStruct <CapiNative.PROV_ENUMALGS>(csp, CapiNative.ProviderParameter.EnumerateAlgorithms, CapiNative.ProviderParameterFlags.None); } s_supportedKeySizes = keySizes.ToArray(); s_defaultKeySize = maxKeySize; } defaultKeySize = s_defaultKeySize; return(s_supportedKeySizes); }