Skip to content

Commit

Permalink
Refactor DataProtection trimming (#41650)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK committed May 13, 2022
1 parent 1230a1a commit 2c2074b
Show file tree
Hide file tree
Showing 30 changed files with 125 additions and 91 deletions.
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

0 comments on commit 2c2074b

Please sign in to comment.