Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor DataProtection trimming #41650

Merged
merged 4 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ public static IDataProtector GetDataProtector(this IServiceProvider services, st
/// <param name="protector">The data protector to use for this operation.</param>
/// <param name="plaintext">The plaintext data to protect.</param>
/// <returns>The protected form of the plaintext data.</returns>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public static string Protect(this IDataProtector protector, string plaintext)
{
if (protector == null)
Expand Down Expand Up @@ -218,7 +217,6 @@ public static string Protect(this IDataProtector protector, string plaintext)
/// <exception cref="System.Security.Cryptography.CryptographicException">
/// Thrown if <paramref name="protectedData"/> is invalid or malformed.
/// </exception>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public static string Unprotect(this IDataProtector protector, string protectedData)
{
if (protector == null)
Expand Down
2 changes: 0 additions & 2 deletions src/DataProtection/Abstractions/src/IDataProtector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public interface IDataProtector : IDataProtectionProvider
/// </summary>
/// <param name="plaintext">The plaintext data to protect.</param>
/// <returns>The protected form of the plaintext data.</returns>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
byte[] Protect(byte[] plaintext);

/// <summary>
Expand All @@ -26,6 +25,5 @@ public interface IDataProtector : IDataProtectionProvider
/// <exception cref="System.Security.Cryptography.CryptographicException">
/// Thrown if the protected data is invalid or malformed.
/// </exception>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
byte[] Unprotect(byte[] protectedData);
}
3 changes: 1 addition & 2 deletions src/DataProtection/DataProtection/src/ActivatorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ internal static class ActivatorExtensions
/// Creates an instance of <paramref name="implementationTypeName"/> and ensures
/// that it is assignable to <typeparamref name="T"/>.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public static T CreateInstance<T>(this IActivator activator, string implementationTypeName)
public static T CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(this IActivator activator, string implementationTypeName)
where T : class
{
if (implementationTypeName == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public sealed class AuthenticatedEncryptorDescriptorDeserializer : IAuthenticate
/// <summary>
/// Imports the <see cref="AuthenticatedEncryptorDescriptor"/> from serialized XML.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element)
{
if (element == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public sealed class CngCbcAuthenticatedEncryptorDescriptorDeserializer : IAuthen
/// <summary>
/// Imports the <see cref="CngCbcAuthenticatedEncryptorDescriptor"/> from serialized XML.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element)
{
if (element == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public sealed class CngGcmAuthenticatedEncryptorDescriptorDeserializer : IAuthen
/// <summary>
/// Imports the <see cref="CngCbcAuthenticatedEncryptorDescriptor"/> from serialized XML.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element)
{
if (element == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ public interface IAuthenticatedEncryptorDescriptorDeserializer
/// </summary>
/// <param name="element">The element to deserialize.</param>
/// <returns>The <see cref="IAuthenticatedEncryptorDescriptor"/> represented by <paramref name="element"/>.</returns>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public sealed class ManagedAuthenticatedEncryptorDescriptorDeserializer : IAuthe
/// <summary>
/// Imports the <see cref="ManagedAuthenticatedEncryptorDescriptor"/> from serialized XML.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element)
{
if (element == null)
Expand Down Expand Up @@ -48,7 +47,6 @@ public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element)

// Any changes to this method should also be be reflected
// in ManagedAuthenticatedEncryptorDescriptor.TypeToFriendlyName.
[RequiresUnreferencedCode(TrimmerWarning.Message)]
private static Type FriendlyNameToType(string typeName)
{
if (typeName == nameof(Aes))
Expand All @@ -73,7 +71,7 @@ private static Type FriendlyNameToType(string typeName)
}
else
{
return Type.GetType(typeName, throwOnError: true)!;
return TypeExtensions.GetTypeWithTrimFriendlyErrorMessage(typeName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ public EphemeralKeyRing(ILoggerFactory loggerFactory)
return (keyId == default(Guid)) ? DefaultAuthenticatedEncryptor : null;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
public IKeyRing GetCurrentKeyRing()
{
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,5 @@ public interface IPersistedDataProtector : IDataProtector
/// Implementations should throw CryptographicException if the protected data is
/// invalid or malformed.
/// </remarks>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ namespace Microsoft.AspNetCore.DataProtection;
// even if it was not registered causing problems crossplat
internal interface IRegistryPolicyResolver
{
[RequiresUnreferencedCode(TrimmerWarning.Message)]
RegistryPolicy? ResolvePolicy();
}
3 changes: 1 addition & 2 deletions src/DataProtection/DataProtection/src/Internal/IActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ public interface IActivator
/// Creates an instance of <paramref name="implementationTypeName"/> and ensures
/// that it is assignable to <paramref name="expectedBaseType"/>.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
object CreateInstance(Type expectedBaseType, string implementationTypeName);
object CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type expectedBaseType, string implementationTypeName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement;
/// </summary>
internal sealed class DeferredKey : KeyBase
{
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public DeferredKey(
Guid keyId,
DateTimeOffset creationDate,
Expand All @@ -36,7 +35,6 @@ public DeferredKey(
{
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
private static Func<IAuthenticatedEncryptorDescriptor> GetLazyDescriptorDelegate(IInternalXmlKeyManager keyManager, XElement keyElement)
{
// The <key> element will be held around in memory for a potentially lengthy period
Expand All @@ -54,7 +52,6 @@ private static Func<IAuthenticatedEncryptorDescriptor> GetLazyDescriptorDelegate
keyElement = null!;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
IAuthenticatedEncryptorDescriptor GetLazyDescriptorDelegate()
{
return keyManager.DeserializeDescriptorFromKeyElement(encryptedKeyElement.ToXElement());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public interface IKeyManager
/// Fetches all keys from the underlying repository.
/// </summary>
/// <returns>The collection of all keys.</returns>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
IReadOnlyCollection<IKey> GetAllKeys();

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ public interface ICacheableKeyRingProvider
/// This API supports infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
CacheableKeyRing GetCacheableKeyRing(DateTimeOffset now);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public interface IInternalXmlKeyManager
/// This API supports infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
IAuthenticatedEncryptorDescriptor DeserializeDescriptorFromKeyElement(XElement keyElement);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ public interface IKeyRingProvider
/// This API supports infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
IKeyRing GetCurrentKeyRing();
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ private static string JoinPurposesForLog(IEnumerable<string> purposes)
}

// allows decrypting payloads whose keys have been revoked
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked)
{
// argument & state checking
Expand All @@ -92,7 +91,6 @@ public byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErro
return retVal;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
public byte[] Protect(byte[] plaintext)
{
if (plaintext == null)
Expand Down Expand Up @@ -182,7 +180,6 @@ private static bool TryGetVersionFromMagicHeader(uint magicHeader, out int versi
}
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
public byte[] Unprotect(byte[] protectedData)
{
if (protectedData == null)
Expand All @@ -197,7 +194,6 @@ public byte[] Unprotect(byte[] protectedData)
wasRevoked: out _);
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
private byte[] UnprotectCore(byte[] protectedData, bool allowOperationsOnRevokedKeys, out UnprotectStatus status)
{
Debug.Assert(protectedData != null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ public KeyRingProvider(

internal bool InAutoRefreshWindow() => DateTime.UtcNow < AutoRefreshWindowEnd;

[RequiresUnreferencedCode(TrimmerWarning.Message)]
private CacheableKeyRing CreateCacheableKeyRingCore(DateTimeOffset now, IKey? keyJustAdded)
{
// Refresh the list of all keys
Expand Down Expand Up @@ -146,19 +145,16 @@ private CacheableKeyRing CreateCacheableKeyRingCoreStep2(DateTimeOffset now, Can
allKeys: allKeys);
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
public IKeyRing GetCurrentKeyRing()
{
return GetCurrentKeyRingCore(DateTime.UtcNow);
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
internal IKeyRing RefreshCurrentKeyRing()
{
return GetCurrentKeyRingCore(DateTime.UtcNow, forceRefresh: true);
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
internal IKeyRing GetCurrentKeyRingCore(DateTime utcNow, bool forceRefresh = false)
{
Debug.Assert(utcNow.Kind == DateTimeKind.Utc);
Expand Down Expand Up @@ -277,7 +273,6 @@ private static DateTimeOffset Min(DateTimeOffset a, DateTimeOffset b)
return (a < b) ? a : b;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
CacheableKeyRing ICacheableKeyRingProvider.GetCacheableKeyRing(DateTimeOffset now)
{
// the entry point allows one recursive call
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ private static string DateTimeOffsetToFilenameSafeString(DateTimeOffset dateTime
}

/// <inheritdoc/>
[RequiresUnreferencedCode(TrimmerWarning.Message)]
public IReadOnlyCollection<IKey> GetAllKeys()
{
var allElements = KeyRepository.GetAllElements();
Expand Down Expand Up @@ -257,7 +256,6 @@ public CancellationToken GetCacheExpirationToken()
return Interlocked.CompareExchange<CancellationTokenSource?>(ref _cacheExpirationTokenSource, null, null).Token;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
private KeyBase? ProcessKeyElement(XElement keyElement)
{
Debug.Assert(keyElement.Name == KeyElementName);
Expand Down Expand Up @@ -444,7 +442,6 @@ IKey IInternalXmlKeyManager.CreateNewKey(Guid keyId, DateTimeOffset creationDate
encryptorFactories: _encryptorFactories);
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
IAuthenticatedEncryptorDescriptor IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement)
{
try
Expand All @@ -455,7 +452,8 @@ IAuthenticatedEncryptorDescriptor IInternalXmlKeyManager.DeserializeDescriptorFr

// Decrypt the descriptor element and pass it to the descriptor for consumption
var unencryptedInputToDeserializer = descriptorElement.Elements().Single().DecryptElement(_activator);
var deserializerInstance = _activator.CreateInstance<IAuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName);

var deserializerInstance = CreateDeserializer(descriptorDeserializerTypeName);
var descriptorInstance = deserializerInstance.ImportFromXml(unencryptedInputToDeserializer);

return descriptorInstance ?? CryptoUtil.Fail<IAuthenticatedEncryptorDescriptor>("ImportFromXml returned null.");
Expand All @@ -467,6 +465,34 @@ IAuthenticatedEncryptorDescriptor IInternalXmlKeyManager.DeserializeDescriptorFr
}
}

[UnconditionalSuppressMessage("Trimmer", "IL2057", Justification = "Type.GetType result is only useful with types that are referenced by DataProtection assembly.")]
private IAuthenticatedEncryptorDescriptorDeserializer CreateDeserializer(string descriptorDeserializerTypeName)
{
var resolvedTypeName = TypeForwardingActivator.TryForwardTypeName(descriptorDeserializerTypeName, out var forwardedTypeName)
? forwardedTypeName
: descriptorDeserializerTypeName;
var type = Type.GetType(resolvedTypeName, throwOnError: false);

if (type == typeof(AuthenticatedEncryptorDescriptorDeserializer))
{
return _activator.CreateInstance<AuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName);
}
else if (type == typeof(CngCbcAuthenticatedEncryptorDescriptorDeserializer) && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return _activator.CreateInstance<CngCbcAuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName);
}
else if (type == typeof(CngGcmAuthenticatedEncryptorDescriptorDeserializer) && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return _activator.CreateInstance<CngGcmAuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName);
}
else if (type == typeof(ManagedAuthenticatedEncryptorDescriptorDeserializer))
{
return _activator.CreateInstance<ManagedAuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName);
}

return _activator.CreateInstance<IAuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName);
}

void IInternalXmlKeyManager.RevokeSingleKey(Guid keyId, DateTimeOffset revocationDate, string? reason)
{
// <revocation version="1">
Expand Down
10 changes: 3 additions & 7 deletions src/DataProtection/DataProtection/src/RegistryPolicyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ internal RegistryPolicyResolver(RegistryKey policyRegKey, IActivator activator)
_activator = activator;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
private static List<string> ReadKeyEscrowSinks(RegistryKey key)
{
var sinks = new List<string>();
Expand All @@ -52,7 +51,7 @@ private static List<string> ReadKeyEscrowSinks(RegistryKey key)
var candidate = sinkFromRegistry.Trim();
if (!string.IsNullOrEmpty(candidate))
{
typeof(IKeyEscrowSink).AssertIsAssignableFrom(Type.GetType(candidate, throwOnError: true)!);
typeof(IKeyEscrowSink).AssertIsAssignableFrom(TypeExtensions.GetTypeWithTrimFriendlyErrorMessage(candidate));
sinks.Add(candidate);
}
}
Expand All @@ -61,7 +60,6 @@ private static List<string> ReadKeyEscrowSinks(RegistryKey key)
return sinks;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
public RegistryPolicy? ResolvePolicy()
{
using (var registryKey = _getPolicyRegKey())
Expand All @@ -70,7 +68,6 @@ private static List<string> ReadKeyEscrowSinks(RegistryKey key)
}
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
private RegistryPolicy? ResolvePolicyCore(RegistryKey? policyRegKey)
{
if (policyRegKey == null)
Expand Down Expand Up @@ -174,14 +171,13 @@ private static CngGcmAuthenticatedEncryptorConfiguration GetCngGcmAuthenticatedE
return options;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
private static ManagedAuthenticatedEncryptorConfiguration GetManagedAuthenticatedEncryptorConfiguration(RegistryKey key)
{
var options = new ManagedAuthenticatedEncryptorConfiguration();
var valueFromRegistry = key.GetValue(nameof(ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmType));
if (valueFromRegistry != null)
{
options.EncryptionAlgorithmType = Type.GetType(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!, throwOnError: true)!;
options.EncryptionAlgorithmType = TypeExtensions.GetTypeWithTrimFriendlyErrorMessage(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!);
}

valueFromRegistry = key.GetValue(nameof(ManagedAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize));
Expand All @@ -193,7 +189,7 @@ private static ManagedAuthenticatedEncryptorConfiguration GetManagedAuthenticate
valueFromRegistry = key.GetValue(nameof(ManagedAuthenticatedEncryptorConfiguration.ValidationAlgorithmType));
if (valueFromRegistry != null)
{
options.ValidationAlgorithmType = Type.GetType(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!, throwOnError: true)!;
options.ValidationAlgorithmType = TypeExtensions.GetTypeWithTrimFriendlyErrorMessage(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!);
}

return options;
Expand Down
7 changes: 4 additions & 3 deletions src/DataProtection/DataProtection/src/SimpleActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ public SimpleActivator(IServiceProvider? services)
_services = services;
}

[RequiresUnreferencedCode(TrimmerWarning.Message)]
public virtual object CreateInstance(Type expectedBaseType, string implementationTypeName)
[UnconditionalSuppressMessage("Trimmer", "IL2072", Justification = "Unknown type names are rarely used by apps. Handle trimmed types by providing a useful error message.")]
[UnconditionalSuppressMessage("Trimmer", "IL2075", Justification = "Unknown type names are rarely used by apps. Handle trimmed types by providing a useful error message.")]
public virtual object CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type expectedBaseType, string implementationTypeName)
{
// Would the assignment even work?
var implementationType = Type.GetType(implementationTypeName, throwOnError: true)!;
var implementationType = TypeExtensions.GetTypeWithTrimFriendlyErrorMessage(implementationTypeName);
expectedBaseType.AssertIsAssignableFrom(implementationType);

// If no IServiceProvider was specified, prefer .ctor() [if it exists]
Expand Down
Loading