/// <summary> /// Wrap an existing key handle with a CngKey object /// </summary> public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { if (keyHandle == null) throw new ArgumentNullException("keyHandle"); if (keyHandle.IsClosed || keyHandle.IsInvalid) throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, "keyHandle"); SafeNCryptKeyHandle keyHandleCopy = keyHandle.Duplicate(); // Get a handle to the key's provider. SafeNCryptProviderHandle providerHandle = new SafeNCryptProviderHandle(); IntPtr rawProviderHandle = keyHandle.GetPropertyAsIntPtr(KeyPropertyName.ProviderHandle, CngPropertyOptions.None); providerHandle.SetHandleValue(rawProviderHandle); // Set up a key object wrapping the handle CngKey key = null; try { key = new CngKey(providerHandle, keyHandleCopy); bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey; // // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is // set up to return true. In the case that the handle is for an ephemeral key that was created // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already // be setup. However, if the key was created outside of the CLR we will need to setup our // ephemeral detection property. // // This enables consumers of CngKey objects to always be able to rely on the result of // calling IsEphemeral, and also allows them to safely access the Name property. // // Finally, if we detect that this is an ephemeral key that the CLR created but we were not // told that it was an ephemeral key we'll throw an exception. This prevents us from having // to decide who to believe -- the key property or the caller of the API. Since other code // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we // need to reject the case that we suspect that the flag is incorrect. // if (!key.IsEphemeral && openingEphemeralKey) { key.IsEphemeral = true; } else if (key.IsEphemeral && !openingEphemeralKey) { throw new ArgumentException(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag, "keyHandleOpenOptions"); } } catch { // Make sure that we don't leak the handle the CngKey duplicated if (key != null) key.Dispose(); throw; } return key; }
public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { ArgumentNullException.ThrowIfNull(keyHandle); if (keyHandle.IsClosed || keyHandle.IsInvalid) { throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, nameof(keyHandle)); } return(OpenNoDuplicate(keyHandle.Duplicate(), keyHandleOpenOptions)); }
internal static CngKey OpenNoDuplicate(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { SafeNCryptProviderHandle?providerHandle = null; try { // Get a handle to the key's provider. providerHandle = new SafeNCryptProviderHandle(); IntPtr rawProviderHandle = keyHandle.GetPropertyAsIntPtr(KeyPropertyName.ProviderHandle, CngPropertyOptions.None); Marshal.InitHandle(providerHandle, rawProviderHandle); // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is // set up to return true. In the case that the handle is for an ephemeral key that was created // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already // be setup. However, if the key was created outside of the CLR we will need to setup our // ephemeral detection property. // // This enables consumers of CngKey objects to always be able to rely on the result of // calling IsEphemeral, and also allows them to safely access the Name property. // // Finally, if we detect that this is an ephemeral key that the CLR created but we were not // told that it was an ephemeral key we'll throw an exception. This prevents us from having // to decide who to believe -- the key property or the caller of the API. Since other code // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we // need to reject the case that we suspect that the flag is incorrect. var key = new CngKey(providerHandle, keyHandle); bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey; if (!key.IsEphemeral) { if (openingEphemeralKey) { key.IsEphemeral = true; } } else if (!openingEphemeralKey) { throw new ArgumentException(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag, nameof(keyHandleOpenOptions)); } return(key); } catch { // Make sure that we don't leak the handles providerHandle?.Dispose(); keyHandle.Dispose(); throw; } }
public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { if (keyHandle == null) { throw new ArgumentNullException("keyHandle"); } if (keyHandle.IsClosed || keyHandle.IsInvalid) { throw new ArgumentException(System.SR.GetString("Cryptography_OpenInvalidHandle"), "keyHandle"); } SafeNCryptKeyHandle handle = keyHandle.Duplicate(); SafeNCryptProviderHandle kspHandle = new SafeNCryptProviderHandle(); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { IntPtr newHandleValue = NCryptNative.GetPropertyAsIntPtr(keyHandle, "Provider Handle", CngPropertyOptions.None); kspHandle.SetHandleValue(newHandleValue); } CngKey key = null; bool flag = false; try { key = new CngKey(kspHandle, handle); bool flag2 = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey; if (!key.IsEphemeral && flag2) { key.IsEphemeral = true; } else if (key.IsEphemeral && !flag2) { throw new ArgumentException(System.SR.GetString("Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag"), "keyHandleOpenOptions"); } flag = true; } finally { if (!flag && (key != null)) { key.Dispose(); } } return(key); }
private static SafeNCryptKeyHandle TryAcquireCngPrivateKey( SafeCertContextHandle certificateContext, out CngKeyHandleOpenOptions handleOptions) { Debug.Assert(certificateContext != null, "certificateContext != null"); Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid, "!certificateContext.IsClosed && !certificateContext.IsInvalid"); IntPtr privateKeyPtr; // If the certificate has a key handle instead of a key prov info, return the // ephemeral key { int cbData = IntPtr.Size; if (Interop.crypt32.CertGetCertificateContextProperty( certificateContext, CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID, out privateKeyPtr, ref cbData)) { handleOptions = CngKeyHandleOpenOptions.EphemeralKey; return(new SafeNCryptKeyHandle(privateKeyPtr, certificateContext)); } } bool freeKey = true; SafeNCryptKeyHandle privateKey = null; handleOptions = CngKeyHandleOpenOptions.None; try { int keySpec = 0; if (!Interop.crypt32.CryptAcquireCertificatePrivateKey( certificateContext, CryptAcquireFlags.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG, IntPtr.Zero, out privateKey, out keySpec, out freeKey)) { int dwErrorCode = Marshal.GetLastWin32Error(); // The documentation for CryptAcquireCertificatePrivateKey says that freeKey // should already be false if "key acquisition fails", and it can be presumed // that privateKey was set to 0. But, just in case: freeKey = false; privateKey?.SetHandleAsInvalid(); return(null); } // It is very unlikely that Windows will tell us !freeKey other than when reporting failure, // because we set neither CRYPT_ACQUIRE_CACHE_FLAG nor CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, which are // currently the only two success situations documented. However, any !freeKey response means the // key's lifetime is tied to that of the certificate, so re-register the handle as a child handle // of the certificate. if (!freeKey && privateKey != null && !privateKey.IsInvalid) { var newKeyHandle = new SafeNCryptKeyHandle(privateKey.DangerousGetHandle(), certificateContext); privateKey.SetHandleAsInvalid(); privateKey = newKeyHandle; freeKey = true; } return(privateKey); } catch { // If we aren't supposed to free the key, and we're not returning it, // just tell the SafeHandle to not free itself. if (privateKey != null && !freeKey) { privateKey.SetHandleAsInvalid(); } throw; } }
public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { throw new NotImplementedException(); }
public static CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { Contract.Ensures(Contract.Result<System.Security.Cryptography.CngKey>() != null); return default(CngKey); }
public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { throw new NotImplementedException (); }
private T GetPrivateKey <T>(X509Certificate2 certificate, bool silent, bool preferNCrypt) where T : AsymmetricAlgorithm { if (!certificate.HasPrivateKey) { return(null); } SafeProvOrNCryptKeyHandle handle = GetCertificatePrivateKey( certificate, silent, preferNCrypt, out CryptKeySpec keySpec, out Exception exception); using (handle) { if (handle == null || handle.IsInvalid) { if (exception != null) { throw exception; } return(null); } if (keySpec == CryptKeySpec.CERT_NCRYPT_KEY_SPEC) { using (SafeNCryptKeyHandle keyHandle = new SafeNCryptKeyHandle(handle.DangerousGetHandle(), handle)) { CngKeyHandleOpenOptions options = CngKeyHandleOpenOptions.None; byte clrIsEphemeral = 0; Interop.NCrypt.ErrorCode errorCode = Interop.NCrypt.NCryptGetByteProperty(keyHandle, "CLR IsEphemeral", ref clrIsEphemeral, CngPropertyOptions.CustomProperty); if (errorCode == Interop.NCrypt.ErrorCode.ERROR_SUCCESS && clrIsEphemeral == 1) { options |= CngKeyHandleOpenOptions.EphemeralKey; } using (CngKey cngKey = CngKey.Open(keyHandle, options)) { if (typeof(T) == typeof(RSA)) { return((T)(object)new RSACng(cngKey)); } if (typeof(T) == typeof(ECDsa)) { return((T)(object)new ECDsaCng(cngKey)); } if (typeof(T) == typeof(DSA)) { return((T)(object)new DSACng(cngKey)); } Debug.Fail($"Unknown CNG key type request: {typeof(T).FullName}"); return(null); } } } // The key handle is for CAPI. // Our CAPI types don't allow usage from a handle, so we have a few choices: // 1) Extract the information we need to re-open the key handle. // 2) Re-implement {R|D}SACryptoServiceProvider // 3) PNSE. // 4) Defer to cert.Get{R|D}SAPrivateKey if not silent, throw otherwise. CspParameters cspParams = handle.GetProvParameters(); Debug.Assert((cspParams.Flags & CspProviderFlags.UseExistingKey) != 0); cspParams.KeyNumber = (int)keySpec; if (silent) { cspParams.Flags |= CspProviderFlags.NoPrompt; } if (typeof(T) == typeof(RSA)) { return((T)(object)new RSACryptoServiceProvider(cspParams)); } if (typeof(T) == typeof(DSA)) { return((T)(object)new DSACryptoServiceProvider(cspParams)); } Debug.Fail($"Unknown CAPI key type request: {typeof(T).FullName}"); return(null); } }
public static CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { Contract.Ensures(Contract.Result <System.Security.Cryptography.CngKey>() != null); return(default(CngKey)); }
public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { if (keyHandle == null) { throw new ArgumentNullException("keyHandle"); } if (keyHandle.IsClosed || keyHandle.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Cryptography_OpenInvalidHandle), "keyHandle"); } SafeNCryptKeyHandle keyHandleCopy = keyHandle.Duplicate(); // Get a handle to the key's KSP SafeNCryptProviderHandle kspHandle = new SafeNCryptProviderHandle(); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { IntPtr rawHandle = NCryptNative.GetPropertyAsIntPtr(keyHandle, NCryptNative.KeyPropertyName.ProviderHandle, CngPropertyOptions.None); kspHandle.SetHandleValue(rawHandle); } // Setup a key object wrapping the handle CngKey key = null; bool keyFullySetup = false; try { key = new CngKey(kspHandle, keyHandleCopy); bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey; // // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is // setup to return true. In the case that the handle is for an ephemeral key that was created // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already // be setup. However, if the key was created outside of the CLR we will need to setup our // ephemeral detection property. // // This enables consumers of CngKey objects to always be able to rely on the result of // calling IsEphemeral, and also allows them to safely access the Name property. // // Finally, if we detect that this is an ephemeral key that the CLR created but we were not // told that it was an ephemeral key we'll throw an exception. This prevents us from having // to decide who to believe -- the key property or the caller of the API. Since other code // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we // need to reject the case that we suspect that the flag is incorrect. // if (!key.IsEphemeral && openingEphemeralKey) { key.IsEphemeral = true; } else if (key.IsEphemeral && !openingEphemeralKey) { throw new ArgumentException(SR.GetString(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag), "keyHandleOpenOptions"); } keyFullySetup = true; } finally { // Make sure that we don't leak the handle the CngKey duplicated if (!keyFullySetup && key != null) { key.Dispose(); } } return(key); }
#pragma warning disable CA2000 // Dispose objects before losing scope #pragma warning disable IDE0068 // Use recommended dispose pattern internal static SafeNCryptKeyHandle?TryAcquireCngPrivateKey( SafeCertContextHandle certificateContext, out CngKeyHandleOpenOptions openOptions) { Debug.Assert(certificateContext != null, "certificateContext != null"); Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid, "!certificateContext.IsClosed && !certificateContext.IsInvalid"); // If the certificate has a key handle instead of a key prov info, return the // ephemeral key { int cbData = IntPtr.Size; if (CertGetCertificateContextProperty( certificateContext, CertificateProperty.NCryptKeyHandle, out IntPtr privateKeyPtr, ref cbData)) { openOptions = CngKeyHandleOpenOptions.EphemeralKey; return(new SafeNCryptKeyHandle(privateKeyPtr, certificateContext)); } } openOptions = CngKeyHandleOpenOptions.None; bool freeKey = true; SafeNCryptKeyHandle?privateKey = null; RuntimeHelpers.PrepareConstrainedRegions(); try { if (!CryptAcquireCertificatePrivateKey( certificateContext, AcquireCertificateKeyOptions.AcquireOnlyNCryptKeys, IntPtr.Zero, out privateKey, out int keySpec, out freeKey)) { // The documentation for CryptAcquireCertificatePrivateKey says that freeKey // should already be false if "key acquisition fails", and it can be presumed // that privateKey was set to 0. But, just in case: freeKey = false; privateKey?.SetHandleAsInvalid(); return(null); } } finally { // It is very unlikely that Windows will tell us !freeKey other than when reporting failure, // because we set neither CRYPT_ACQUIRE_CACHE_FLAG nor CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, which are // currently the only two success situations documented. However, any !freeKey response means the // key's lifetime is tied to that of the certificate, so re-register the handle as a child handle // of the certificate. if (!freeKey && privateKey != null && !privateKey.IsInvalid) { SafeNCryptKeyHandle newKeyHandle = new SafeNCryptKeyHandle(privateKey.DangerousGetHandle(), certificateContext); privateKey.SetHandleAsInvalid(); privateKey = newKeyHandle; } } return(privateKey); }
/// this process runs in its own thread for the the full time of the hosting process. private void RunProcess(string keyName) { int threadID = Thread.GetCurrentProcessorId(); string whoami = Thread.CurrentPrincipal?.Identity?.ToString(); if (String.IsNullOrEmpty(whoami)) { whoami = Environment.GetEnvironmentVariable("USERNAME"); } _logger.LogInformation("Process Cred Store Service is runing on processor {0} and user {1}.", threadID, whoami); Thread.Sleep(200); // ensure the rest of the web server starts up bool bExists = CngKey.Exists(keyName); RSACng rsaKey; if (bExists) { CngKeyHandleOpenOptions ckhoo = new CngKeyHandleOpenOptions { }; cngKey = CngKey.Open(keyName); _logger.LogInformation("Found Key {0}.", keyName); X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine); certStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection certRes = certStore.Certificates.Find(X509FindType.FindBySubjectName, "Trustregistry", false); // X509Certificate2Enumerator certEnum = certRes.GetEnumerator(); foreach (X509Certificate2 x2 in certRes) { if (cert1 == null) { cert1 = x2; // TODO see if there are better choices than the first when i have some criteria } } certStore.Close(); } else { try { rsaKey = new RSACng(CngKey.Create(CngAlgorithm.Rsa, keyName, new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowExport })); cngKey = rsaKey.Key; RSAParameters rsaP = rsaKey.ExportParameters(true); X500DistinguishedName dn = new X500DistinguishedName("CN=Trustregistry.US", new X500DistinguishedNameFlags { }); CertificateRequest cr = new CertificateRequest(dn, rsaKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); _logger.LogInformation("Need to create a new Key named {0}.", keyName); } catch (Exception ex) { _logger.LogInformation("Exception trying to create a new Key named {0}, exception {1}.", keyName, ex.Message); } } if (cngKey != null) { try { keyType = cngKey.Algorithm; rsaKey = new RSACng(cngKey); X500DistinguishedName dnx = new X500DistinguishedName("CN=Trustregistry.US", new X500DistinguishedNameFlags { }); CertificateRequest crx = new CertificateRequest(dnx, rsaKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); X509Certificate2 cert2 = crx.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow + TimeSpan.FromHours(24 * 365.2 * 5)); // TODO get value from config IN HOURS // put that sert in the store X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine); certStore.Open(OpenFlags.ReadOnly); X509Certificate2Collection certRes = certStore.Certificates.Find(X509FindType.FindBySubjectName, "Trustregistry", false); // X509Certificate2Enumerator certEnum = certRes.GetEnumerator(); foreach (X509Certificate2 x2 in certRes) { if (cert1 == null) { cert1 = x2; // TODO see if there are better choices than the first when i have some criteria } } // certStore.Add(cert2); certStore.Close(); } catch (Exception ex) { _logger.LogInformation("Exception trying to create a new cert for key named {0}, exception {1}.", keyName, ex.Message); } } while (true) { if (busy) { } Thread.Sleep(60000); // TODO make this event driven _logger.LogInformation("Process Cred Store Service still runing."); } }
public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) { if (keyHandle == null) { throw new ArgumentNullException("keyHandle"); } if (keyHandle.IsClosed || keyHandle.IsInvalid) { throw new ArgumentException(System.SR.GetString("Cryptography_OpenInvalidHandle"), "keyHandle"); } SafeNCryptKeyHandle handle = keyHandle.Duplicate(); SafeNCryptProviderHandle kspHandle = new SafeNCryptProviderHandle(); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { IntPtr newHandleValue = NCryptNative.GetPropertyAsIntPtr(keyHandle, "Provider Handle", CngPropertyOptions.None); kspHandle.SetHandleValue(newHandleValue); } CngKey key = null; bool flag = false; try { key = new CngKey(kspHandle, handle); bool flag2 = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey; if (!key.IsEphemeral && flag2) { key.IsEphemeral = true; } else if (key.IsEphemeral && !flag2) { throw new ArgumentException(System.SR.GetString("Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag"), "keyHandleOpenOptions"); } flag = true; } finally { if (!flag && (key != null)) { key.Dispose(); } } return key; }