| File: RegistryPolicyResolver.cs | Web Access |
| Project: src\aspnetcore\src\DataProtection\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj (Microsoft.AspNetCore.DataProtection) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.Versioning; using Microsoft.AspNetCore.Cryptography; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNetCore.DataProtection.Internal; using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.Win32; namespace Microsoft.AspNetCore.DataProtection; /// <summary> /// A type which allows reading policy from the system registry. /// </summary> [SupportedOSPlatform("windows")] internal sealed class RegistryPolicyResolver : IRegistryPolicyResolver { private readonly Func<RegistryKey?> _getPolicyRegKey; private readonly IActivator _activator; public RegistryPolicyResolver(IActivator activator) { _getPolicyRegKey = () => Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\DotNetPackages\Microsoft.AspNetCore.DataProtection"); _activator = activator; } internal RegistryPolicyResolver(RegistryKey policyRegKey, IActivator activator) { _getPolicyRegKey = () => policyRegKey; _activator = activator; } private static List<string> ReadKeyEscrowSinks(RegistryKey key) { var sinks = new List<string>(); // The format of this key is "type1; type2; ...". // We call Type.GetType to perform an eager check that the type exists. var sinksFromRegistry = (string?)key.GetValue("KeyEscrowSinks"); if (sinksFromRegistry != null) { foreach (string sinkFromRegistry in sinksFromRegistry.Split(';')) { var candidate = sinkFromRegistry.Trim(); if (!string.IsNullOrEmpty(candidate)) { typeof(IKeyEscrowSink).AssertIsAssignableFrom(TypeExtensions.GetTypeWithTrimFriendlyErrorMessage(candidate)); sinks.Add(candidate); } } } return sinks; } public RegistryPolicy? ResolvePolicy() { using (var registryKey = _getPolicyRegKey()) { return ResolvePolicyCore(registryKey); // fully evaluate enumeration while the reg key is open } } private RegistryPolicy? ResolvePolicyCore(RegistryKey? policyRegKey) { if (policyRegKey == null) { return null; } // Read the encryption options type: CNG-CBC, CNG-GCM, Managed AlgorithmConfiguration? configuration = null; var encryptionType = (string?)policyRegKey.GetValue("EncryptionType"); if (string.Equals(encryptionType, "CNG-CBC", StringComparison.OrdinalIgnoreCase)) { configuration = GetCngCbcAuthenticatedEncryptorConfiguration(policyRegKey); } else if (string.Equals(encryptionType, "CNG-GCM", StringComparison.OrdinalIgnoreCase)) { configuration = GetCngGcmAuthenticatedEncryptorConfiguration(policyRegKey); } else if (string.Equals(encryptionType, "Managed", StringComparison.OrdinalIgnoreCase)) { configuration = GetManagedAuthenticatedEncryptorConfiguration(policyRegKey); } else if (!string.IsNullOrEmpty(encryptionType)) { throw CryptoUtil.Fail("Unrecognized EncryptionType: " + encryptionType); } // Read ancillary data var defaultKeyLifetime = (int?)policyRegKey.GetValue("DefaultKeyLifetime"); var escrowSinks = ReadKeyEscrowSinks(policyRegKey); var keyEscrowSinks = escrowSinks.Count is 0 ? Array.Empty<IKeyEscrowSink>() : new IKeyEscrowSink[escrowSinks.Count]; for (var i = 0; i < keyEscrowSinks.Length; i++) { keyEscrowSinks[i] = _activator.CreateInstance<IKeyEscrowSink>(escrowSinks[i]); } return new RegistryPolicy(configuration, keyEscrowSinks, defaultKeyLifetime); } private static CngCbcAuthenticatedEncryptorConfiguration GetCngCbcAuthenticatedEncryptorConfiguration(RegistryKey key) { var options = new CngCbcAuthenticatedEncryptorConfiguration(); var valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm)); if (valueFromRegistry != null) { options.EncryptionAlgorithm = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!; } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider)); if (valueFromRegistry != null) { options.EncryptionAlgorithmProvider = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!; } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize)); if (valueFromRegistry != null) { options.EncryptionAlgorithmKeySize = Convert.ToInt32(valueFromRegistry, CultureInfo.InvariantCulture); } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm)); if (valueFromRegistry != null) { options.HashAlgorithm = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!; } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider)); if (valueFromRegistry != null) { options.HashAlgorithmProvider = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture); } return options; } private static CngGcmAuthenticatedEncryptorConfiguration GetCngGcmAuthenticatedEncryptorConfiguration(RegistryKey key) { var options = new CngGcmAuthenticatedEncryptorConfiguration(); var valueFromRegistry = key.GetValue(nameof(CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm)); if (valueFromRegistry != null) { options.EncryptionAlgorithm = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!; } valueFromRegistry = key.GetValue(nameof(CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider)); if (valueFromRegistry != null) { options.EncryptionAlgorithmProvider = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!; } valueFromRegistry = key.GetValue(nameof(CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize)); if (valueFromRegistry != null) { options.EncryptionAlgorithmKeySize = Convert.ToInt32(valueFromRegistry, CultureInfo.InvariantCulture); } return options; } private static ManagedAuthenticatedEncryptorConfiguration GetManagedAuthenticatedEncryptorConfiguration(RegistryKey key) { var options = new ManagedAuthenticatedEncryptorConfiguration(); var valueFromRegistry = key.GetValue(nameof(ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType)); if (valueFromRegistry != null) { options.EncryptionAlgorithmType = ManagedAlgorithmHelpers.FriendlyNameToType(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!); } valueFromRegistry = key.GetValue(nameof(ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize)); if (valueFromRegistry != null) { options.EncryptionAlgorithmKeySize = Convert.ToInt32(valueFromRegistry, CultureInfo.InvariantCulture); } valueFromRegistry = key.GetValue(nameof(ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType)); if (valueFromRegistry != null) { options.ValidationAlgorithmType = ManagedAlgorithmHelpers.FriendlyNameToType(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!); } return options; } }