| File: System\Security\Cryptography\CspKeyContainerInfo.Windows.cs | Web Access |
| Project: src\runtime\src\libraries\System.Security.Cryptography\src\System.Security.Cryptography.csproj (System.Security.Cryptography) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.Versioning; namespace System.Security.Cryptography { [SupportedOSPlatform("windows")] public sealed class CspKeyContainerInfo { private readonly CspParameters _parameters; private readonly bool _randomKeyContainer; //Public Constructor will call internal constructor. public CspKeyContainerInfo(CspParameters parameters) : this(parameters, false) { } /// <summary> ///Internal constructor for creating the CspKeyContainerInfo object /// </summary> /// <param name="parameters">CSP parameters</param> /// <param name="randomKeyContainer">Is it random container</param> internal CspKeyContainerInfo(CspParameters parameters, bool randomKeyContainer) { _parameters = new CspParameters(parameters); if (_parameters.KeyNumber == -1) { if (_parameters.ProviderType == (int)CapiHelper.ProviderType.PROV_RSA_FULL || _parameters.ProviderType == (int)CapiHelper.ProviderType.PROV_RSA_AES) { _parameters.KeyNumber = (int)KeyNumber.Exchange; } else if (_parameters.ProviderType == (int)CapiHelper.ProviderType.PROV_DSS_DH) { _parameters.KeyNumber = (int)KeyNumber.Signature; } } _randomKeyContainer = randomKeyContainer; } /// <summary> /// Check the key is accessible /// </summary> public bool Accessible { get { object? retVal = ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_ACCESSIBLE, throwOnNotFound: false); if (retVal == null) { // The key wasn't found, so consider it to be not accessible. return false; } return (bool)retVal; } } /// <summary> /// Check the key is exportable /// </summary> public bool Exportable { get { // Assume hardware keys are not exportable. if (HardwareDevice) { return false; } return (bool)ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_EXPORTABLE)!; } } /// <summary> /// Check if device with key is HW device /// </summary> public bool HardwareDevice { get { return (bool)ReadDeviceParameterVerifyContext(CapiHelper.ClrPropertyId.CLR_HARDWARE); } } /// <summary> /// Get Key container Name /// </summary> public string? KeyContainerName { get { return _parameters.KeyContainerName; } } /// <summary> /// Get the key number /// </summary> public KeyNumber KeyNumber { get { return (KeyNumber)_parameters.KeyNumber; } } /// <summary> /// Check if machine key store is in flag or not /// </summary> public bool MachineKeyStore { get { return CapiHelper.IsFlagBitSet((uint)_parameters.Flags, (uint)CspProviderFlags.UseMachineKeyStore); } } /// <summary> /// Check if key is protected /// </summary> public bool Protected { get { // Assume hardware keys are protected. if (HardwareDevice) { return true; } return (bool)ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_PROTECTED)!; } } /// <summary> /// Gets the provider name /// </summary> public string? ProviderName { get { return _parameters.ProviderName; } } /// <summary> /// Gets the provider type /// </summary> public int ProviderType { get { return _parameters.ProviderType; } } /// <summary> /// Check if key container is randomly generated /// </summary> public bool RandomlyGenerated { get { return _randomKeyContainer; } } /// <summary> /// Check if container is removable /// </summary> public bool Removable { get { return (bool)ReadDeviceParameterVerifyContext(CapiHelper.ClrPropertyId.CLR_REMOVABLE); } } /// <summary> /// Get the container name /// </summary> public string UniqueKeyContainerName { get { return (string)ReadKeyParameterSilent(CapiHelper.ClrPropertyId.CLR_UNIQUE_CONTAINER)!; } } /// <summary> /// Read a parameter from the current key using CRYPT_SILENT, to avoid any potential UI prompts. /// </summary> private object? ReadKeyParameterSilent(CapiHelper.ClrPropertyId keyParam, bool throwOnNotFound = true) { const uint SilentFlags = (uint)Interop.Advapi32.CryptAcquireContextFlags.CRYPT_SILENT; SafeProvHandle safeProvHandle; int hr = CapiHelper.OpenCSP(_parameters, SilentFlags, out safeProvHandle); using (safeProvHandle) { if (hr != CapiHelper.S_OK) { if (throwOnNotFound) { throw new CryptographicException(SR.Cryptography_CSP_NotFound); } return null; } object retVal = CapiHelper.GetProviderParameter(safeProvHandle, _parameters.KeyNumber, keyParam); return retVal; } } /// <summary> /// Read a parameter using VERIFY_CONTEXT to read from the device being targeted by _parameters /// </summary> private object ReadDeviceParameterVerifyContext(CapiHelper.ClrPropertyId keyParam) { CspParameters parameters = new CspParameters(_parameters); // We're asking questions of the device container, the only flag that makes sense is Machine vs User. parameters.Flags &= CspProviderFlags.UseMachineKeyStore; // In order to ask about the device, instead of a key, we need to ensure that no key is named. parameters.KeyContainerName = null; const uint OpenDeviceFlags = (uint)Interop.Advapi32.CryptAcquireContextFlags.CRYPT_VERIFYCONTEXT; SafeProvHandle safeProvHandle; int hr = CapiHelper.OpenCSP(parameters, OpenDeviceFlags, out safeProvHandle); using (safeProvHandle) { if (hr != CapiHelper.S_OK) { throw new CryptographicException(SR.Cryptography_CSP_NotFound); } object retVal = CapiHelper.GetProviderParameter(safeProvHandle, parameters.KeyNumber, keyParam); return retVal; } } } }