diff --git a/eng/TrimmableProjects.props b/eng/TrimmableProjects.props index c2dc91c7263d..2721673fb8db 100644 --- a/eng/TrimmableProjects.props +++ b/eng/TrimmableProjects.props @@ -7,6 +7,13 @@ --> + + + + + + + diff --git a/src/DataProtection/Abstractions/src/DataProtectionCommonExtensions.cs b/src/DataProtection/Abstractions/src/DataProtectionCommonExtensions.cs index 7dd8314da598..53bc26e9bdd7 100644 --- a/src/DataProtection/Abstractions/src/DataProtectionCommonExtensions.cs +++ b/src/DataProtection/Abstractions/src/DataProtectionCommonExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.DataProtection.Abstractions; using Microsoft.Extensions.Internal; @@ -182,6 +183,7 @@ public static IDataProtector GetDataProtector(this IServiceProvider services, st /// The data protector to use for this operation. /// The plaintext data to protect. /// The protected form of the plaintext data. + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static string Protect(this IDataProtector protector, string plaintext) { if (protector == null) @@ -216,6 +218,7 @@ public static string Protect(this IDataProtector protector, string plaintext) /// /// Thrown if is invalid or malformed. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static string Unprotect(this IDataProtector protector, string protectedData) { if (protector == null) diff --git a/src/DataProtection/Abstractions/src/IDataProtector.cs b/src/DataProtection/Abstractions/src/IDataProtector.cs index 160226ff5997..166535756f4d 100644 --- a/src/DataProtection/Abstractions/src/IDataProtector.cs +++ b/src/DataProtection/Abstractions/src/IDataProtector.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.AspNetCore.DataProtection; /// @@ -13,6 +15,7 @@ public interface IDataProtector : IDataProtectionProvider /// /// The plaintext data to protect. /// The protected form of the plaintext data. + [RequiresUnreferencedCode(TrimmerWarning.Message)] byte[] Protect(byte[] plaintext); /// @@ -23,5 +26,6 @@ public interface IDataProtector : IDataProtectionProvider /// /// Thrown if the protected data is invalid or malformed. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] byte[] Unprotect(byte[] protectedData); } diff --git a/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj b/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj index c2983188e440..821888b21efc 100644 --- a/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj +++ b/src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core data protection abstractions. @@ -10,12 +10,14 @@ Microsoft.AspNetCore.DataProtection.IDataProtector true true aspnetcore;dataprotection - enable + true - + + diff --git a/src/DataProtection/Cryptography.Internal/src/Microsoft.AspNetCore.Cryptography.Internal.csproj b/src/DataProtection/Cryptography.Internal/src/Microsoft.AspNetCore.Cryptography.Internal.csproj index 58225401c5b6..c4acc321dd18 100644 --- a/src/DataProtection/Cryptography.Internal/src/Microsoft.AspNetCore.Cryptography.Internal.csproj +++ b/src/DataProtection/Cryptography.Internal/src/Microsoft.AspNetCore.Cryptography.Internal.csproj @@ -7,7 +7,7 @@ true true aspnetcore;dataprotection - enable + true diff --git a/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj b/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj index 6d36d60b5a5c..ef7e1273a70a 100644 --- a/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj +++ b/src/DataProtection/Cryptography.KeyDerivation/src/Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj @@ -7,7 +7,7 @@ true true aspnetcore;dataprotection - enable + true annotations diff --git a/src/DataProtection/DataProtection/src/ActivatorExtensions.cs b/src/DataProtection/DataProtection/src/ActivatorExtensions.cs index f4ec8b7186de..d1136db9ba9c 100644 --- a/src/DataProtection/DataProtection/src/ActivatorExtensions.cs +++ b/src/DataProtection/DataProtection/src/ActivatorExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Cryptography; using Microsoft.AspNetCore.DataProtection.Internal; using Microsoft.Extensions.DependencyInjection; @@ -17,6 +18,7 @@ internal static class ActivatorExtensions /// Creates an instance of and ensures /// that it is assignable to . /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static T CreateInstance(this IActivator activator, string implementationTypeName) where T : class { diff --git a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs index ad05963e59bf..dc103ed5b96e 100644 --- a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Xml.Linq; @@ -16,6 +17,7 @@ public sealed class AuthenticatedEncryptorDescriptorDeserializer : IAuthenticate /// /// Imports the from serialized XML. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) { if (element == null) diff --git a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs index 9522e6b0e10b..09efbf55ea89 100644 --- a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; using System.Xml.Linq; @@ -17,6 +18,7 @@ public sealed class CngCbcAuthenticatedEncryptorDescriptorDeserializer : IAuthen /// /// Imports the from serialized XML. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) { if (element == null) diff --git a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs index a26531fc10ce..1222ea189729 100644 --- a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; using System.Xml.Linq; @@ -17,6 +18,7 @@ public sealed class CngGcmAuthenticatedEncryptorDescriptorDeserializer : IAuthen /// /// Imports the from serialized XML. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) { if (element == null) diff --git a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptorDeserializer.cs index 6f9865b74bf2..c0e4c7e37994 100644 --- a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/IAuthenticatedEncryptorDescriptorDeserializer.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Xml.Linq; namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; @@ -15,5 +16,6 @@ public interface IAuthenticatedEncryptorDescriptorDeserializer /// /// The element to deserialize. /// The represented by . + [RequiresUnreferencedCode(TrimmerWarning.Message)] IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element); } diff --git a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs index 7bae58122aa8..67de02c8368d 100644 --- a/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/DataProtection/DataProtection/src/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; using System.Xml.Linq; @@ -16,6 +17,7 @@ public sealed class ManagedAuthenticatedEncryptorDescriptorDeserializer : IAuthe /// /// Imports the from serialized XML. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) { if (element == null) @@ -46,6 +48,7 @@ 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)) diff --git a/src/DataProtection/DataProtection/src/EphemeralDataProtectionProvider.cs b/src/DataProtection/DataProtection/src/EphemeralDataProtectionProvider.cs index 429f7164a78b..57e4dba965b6 100644 --- a/src/DataProtection/DataProtection/src/EphemeralDataProtectionProvider.cs +++ b/src/DataProtection/DataProtection/src/EphemeralDataProtectionProvider.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using Microsoft.AspNetCore.Cryptography.Cng; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; @@ -94,6 +95,7 @@ public EphemeralKeyRing(ILoggerFactory loggerFactory) return (keyId == default(Guid)) ? DefaultAuthenticatedEncryptor : null; } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public IKeyRing GetCurrentKeyRing() { return this; diff --git a/src/DataProtection/DataProtection/src/IPersistedDataProtector.cs b/src/DataProtection/DataProtection/src/IPersistedDataProtector.cs index 746ebc8dba65..4690b92c6f28 100644 --- a/src/DataProtection/DataProtection/src/IPersistedDataProtector.cs +++ b/src/DataProtection/DataProtection/src/IPersistedDataProtector.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.AspNetCore.DataProtection; /// @@ -29,5 +31,6 @@ public interface IPersistedDataProtector : IDataProtector /// Implementations should throw CryptographicException if the protected data is /// invalid or malformed. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked); } diff --git a/src/DataProtection/DataProtection/src/IRegistryPolicyResolver.cs b/src/DataProtection/DataProtection/src/IRegistryPolicyResolver.cs index 4d609db44594..e8d4bbf32693 100644 --- a/src/DataProtection/DataProtection/src/IRegistryPolicyResolver.cs +++ b/src/DataProtection/DataProtection/src/IRegistryPolicyResolver.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.AspNetCore.DataProtection; // Single implementation of this interface is conditionally added to DI on Windows @@ -8,5 +10,6 @@ namespace Microsoft.AspNetCore.DataProtection; // even if it was not registered causing problems crossplat internal interface IRegistryPolicyResolver { + [RequiresUnreferencedCode(TrimmerWarning.Message)] RegistryPolicy? ResolvePolicy(); } diff --git a/src/DataProtection/DataProtection/src/Internal/IActivator.cs b/src/DataProtection/DataProtection/src/Internal/IActivator.cs index d3210cfae06c..058e85978b51 100644 --- a/src/DataProtection/DataProtection/src/Internal/IActivator.cs +++ b/src/DataProtection/DataProtection/src/Internal/IActivator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.DataProtection.Internal; @@ -15,5 +16,6 @@ public interface IActivator /// Creates an instance of and ensures /// that it is assignable to . /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] object CreateInstance(Type expectedBaseType, string implementationTypeName); } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/DeferredKey.cs b/src/DataProtection/DataProtection/src/KeyManagement/DeferredKey.cs index 0bfa77f66666..748c7da775d8 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/DeferredKey.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/DeferredKey.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Xml.Linq; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; @@ -17,6 +18,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement; /// internal sealed class DeferredKey : KeyBase { + [RequiresUnreferencedCode(TrimmerWarning.Message)] public DeferredKey( Guid keyId, DateTimeOffset creationDate, @@ -34,6 +36,7 @@ public DeferredKey( { } + [RequiresUnreferencedCode(TrimmerWarning.Message)] private static Func GetLazyDescriptorDelegate(IInternalXmlKeyManager keyManager, XElement keyElement) { // The element will be held around in memory for a potentially lengthy period @@ -42,7 +45,7 @@ private static Func GetLazyDescriptorDelegate try { - return () => keyManager.DeserializeDescriptorFromKeyElement(encryptedKeyElement.ToXElement()); + return GetLazyDescriptorDelegate; } finally { @@ -50,5 +53,11 @@ private static Func GetLazyDescriptorDelegate // helps us detect if we've done this by causing a null ref at runtime. keyElement = null!; } + + [RequiresUnreferencedCode(TrimmerWarning.Message)] + IAuthenticatedEncryptorDescriptor GetLazyDescriptorDelegate() + { + return keyManager.DeserializeDescriptorFromKeyElement(encryptedKeyElement.ToXElement()); + } } } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs index d6a8686e7866..ab413fe106bb 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/IKeyManager.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading; namespace Microsoft.AspNetCore.DataProtection.KeyManagement; @@ -28,6 +29,7 @@ public interface IKeyManager /// Fetches all keys from the underlying repository. /// /// The collection of all keys. + [RequiresUnreferencedCode(TrimmerWarning.Message)] IReadOnlyCollection GetAllKeys(); /// diff --git a/src/DataProtection/DataProtection/src/KeyManagement/Internal/ICacheableKeyRingProvider.cs b/src/DataProtection/DataProtection/src/KeyManagement/Internal/ICacheableKeyRingProvider.cs index 69f529241539..c3af365d0404 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/Internal/ICacheableKeyRingProvider.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/Internal/ICacheableKeyRingProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; @@ -15,5 +16,6 @@ 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. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] CacheableKeyRing GetCacheableKeyRing(DateTimeOffset now); } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/Internal/IInternalXmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/Internal/IInternalXmlKeyManager.cs index 299012173368..94ff1a313534 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/Internal/IInternalXmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/Internal/IInternalXmlKeyManager.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Xml.Linq; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; @@ -23,6 +24,7 @@ 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. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] IAuthenticatedEncryptorDescriptor DeserializeDescriptorFromKeyElement(XElement keyElement); /// diff --git a/src/DataProtection/DataProtection/src/KeyManagement/Internal/IKeyRingProvider.cs b/src/DataProtection/DataProtection/src/KeyManagement/Internal/IKeyRingProvider.cs index 30fd4c7a2a4f..ffcd3ac8a574 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/Internal/IKeyRingProvider.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/Internal/IKeyRingProvider.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; /// @@ -13,5 +15,6 @@ 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. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] IKeyRing GetCurrentKeyRing(); } diff --git a/src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedDataProtector.cs b/src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedDataProtector.cs index 00f2ac1de608..7816b61b7480 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedDataProtector.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/KeyRingBasedDataProtector.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -75,6 +76,7 @@ private static string JoinPurposesForLog(IEnumerable 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 @@ -90,6 +92,7 @@ public byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErro return retVal; } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public byte[] Protect(byte[] plaintext) { if (plaintext == null) @@ -179,6 +182,7 @@ private static bool TryGetVersionFromMagicHeader(uint magicHeader, out int versi } } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public byte[] Unprotect(byte[] protectedData) { if (protectedData == null) @@ -193,6 +197,7 @@ public byte[] Unprotect(byte[] protectedData) wasRevoked: out _); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] private byte[] UnprotectCore(byte[] protectedData, bool allowOperationsOnRevokedKeys, out UnprotectStatus status) { Debug.Assert(protectedData != null); diff --git a/src/DataProtection/DataProtection/src/KeyManagement/KeyRingProvider.cs b/src/DataProtection/DataProtection/src/KeyManagement/KeyRingProvider.cs index 5103bc8126a8..917257425d9c 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/KeyRingProvider.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/KeyRingProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.AspNetCore.Cryptography; using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; @@ -57,6 +58,7 @@ public KeyRingProvider( internal bool InAutoRefreshWindow() => DateTime.UtcNow < AutoRefreshWindowEnd; + [RequiresUnreferencedCode(TrimmerWarning.Message)] private CacheableKeyRing CreateCacheableKeyRingCore(DateTimeOffset now, IKey? keyJustAdded) { // Refresh the list of all keys @@ -144,16 +146,19 @@ 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); @@ -272,6 +277,7 @@ 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 diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index e6f54cefdd3e..edb3ab131f86 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; @@ -153,6 +154,7 @@ private static string DateTimeOffsetToFilenameSafeString(DateTimeOffset dateTime } /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public IReadOnlyCollection GetAllKeys() { var allElements = KeyRepository.GetAllElements(); @@ -255,6 +257,7 @@ public CancellationToken GetCacheExpirationToken() return Interlocked.CompareExchange(ref _cacheExpirationTokenSource, null, null).Token; } + [RequiresUnreferencedCode(TrimmerWarning.Message)] private KeyBase? ProcessKeyElement(XElement keyElement) { Debug.Assert(keyElement.Name == KeyElementName); @@ -441,6 +444,7 @@ IKey IInternalXmlKeyManager.CreateNewKey(Guid keyId, DateTimeOffset creationDate encryptorFactories: _encryptorFactories); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] IAuthenticatedEncryptorDescriptor IInternalXmlKeyManager.DeserializeDescriptorFromKeyElement(XElement keyElement) { try diff --git a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.WarningSuppressions.xml b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.WarningSuppressions.xml new file mode 100644 index 000000000000..2c4a3e9144dc --- /dev/null +++ b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.WarningSuppressions.xml @@ -0,0 +1,17 @@ + + + + + ILLink + IL2026 + member + M:Microsoft.AspNetCore.DataProtection.Internal.DataProtectionHostedService.StartAsync(System.Threading.CancellationToken) + + + ILLink + IL2026 + member + M:Microsoft.AspNetCore.DataProtection.Internal.KeyManagementOptionsSetup.Configure(Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions) + + + \ No newline at end of file diff --git a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj index 39c5886edb88..70d67fb9ee39 100644 --- a/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj +++ b/src/DataProtection/DataProtection/src/Microsoft.AspNetCore.DataProtection.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core logic to protect and unprotect data, similar to DPAPI. @@ -11,11 +11,14 @@ true annotations enable + true - - + + diff --git a/src/DataProtection/DataProtection/src/RegistryPolicyResolver.cs b/src/DataProtection/DataProtection/src/RegistryPolicyResolver.cs index 1ca32f6b0979..a9aee3189a20 100644 --- a/src/DataProtection/DataProtection/src/RegistryPolicyResolver.cs +++ b/src/DataProtection/DataProtection/src/RegistryPolicyResolver.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; @@ -36,37 +37,7 @@ internal RegistryPolicyResolver(RegistryKey policyRegKey, IActivator activator) _activator = activator; } - // populates an options object from values stored in the registry - private static void PopulateOptions(object options, RegistryKey key) - { - foreach (PropertyInfo propInfo in options.GetType().GetProperties()) - { - if (propInfo.IsDefined(typeof(ApplyPolicyAttribute))) - { - var valueFromRegistry = key.GetValue(propInfo.Name); - if (valueFromRegistry != null) - { - if (propInfo.PropertyType == typeof(string)) - { - propInfo.SetValue(options, Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)); - } - else if (propInfo.PropertyType == typeof(int)) - { - propInfo.SetValue(options, Convert.ToInt32(valueFromRegistry, CultureInfo.InvariantCulture)); - } - else if (propInfo.PropertyType == typeof(Type)) - { - propInfo.SetValue(options, Type.GetType(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!, throwOnError: true)); - } - else - { - throw CryptoUtil.Fail("Unexpected type on property: " + propInfo.Name); - } - } - } - } - } - + [RequiresUnreferencedCode(TrimmerWarning.Message)] private static List ReadKeyEscrowSinks(RegistryKey key) { var sinks = new List(); @@ -79,7 +50,7 @@ private static List ReadKeyEscrowSinks(RegistryKey key) foreach (string sinkFromRegistry in sinksFromRegistry.Split(';')) { var candidate = sinkFromRegistry.Trim(); - if (!String.IsNullOrEmpty(candidate)) + if (!string.IsNullOrEmpty(candidate)) { typeof(IKeyEscrowSink).AssertIsAssignableFrom(Type.GetType(candidate, throwOnError: true)!); sinks.Add(candidate); @@ -90,6 +61,7 @@ private static List ReadKeyEscrowSinks(RegistryKey key) return sinks; } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public RegistryPolicy? ResolvePolicy() { using (var registryKey = _getPolicyRegKey()) @@ -98,6 +70,7 @@ private static List ReadKeyEscrowSinks(RegistryKey key) } } + [RequiresUnreferencedCode(TrimmerWarning.Message)] private RegistryPolicy? ResolvePolicyCore(RegistryKey? policyRegKey) { if (policyRegKey == null) @@ -109,33 +82,120 @@ private static List ReadKeyEscrowSinks(RegistryKey key) AlgorithmConfiguration? configuration = null; var encryptionType = (string?)policyRegKey.GetValue("EncryptionType"); - if (String.Equals(encryptionType, "CNG-CBC", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(encryptionType, "CNG-CBC", StringComparison.OrdinalIgnoreCase)) { - configuration = new CngCbcAuthenticatedEncryptorConfiguration(); + configuration = GetCngCbcAuthenticatedEncryptorConfiguration(policyRegKey); } - else if (String.Equals(encryptionType, "CNG-GCM", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(encryptionType, "CNG-GCM", StringComparison.OrdinalIgnoreCase)) { - configuration = new CngGcmAuthenticatedEncryptorConfiguration(); + configuration = GetCngGcmAuthenticatedEncryptorConfiguration(policyRegKey); } - else if (String.Equals(encryptionType, "Managed", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(encryptionType, "Managed", StringComparison.OrdinalIgnoreCase)) { - configuration = new ManagedAuthenticatedEncryptorConfiguration(); + configuration = GetManagedAuthenticatedEncryptorConfiguration(policyRegKey); } - else if (!String.IsNullOrEmpty(encryptionType)) + else if (!string.IsNullOrEmpty(encryptionType)) { throw CryptoUtil.Fail("Unrecognized EncryptionType: " + encryptionType); } - if (configuration != null) - { - PopulateOptions(configuration, policyRegKey); - } // Read ancillary data var defaultKeyLifetime = (int?)policyRegKey.GetValue("DefaultKeyLifetime"); - - var keyEscrowSinks = ReadKeyEscrowSinks(policyRegKey).Select(item => _activator.CreateInstance(item)); + var escrowSinks = ReadKeyEscrowSinks(policyRegKey); + var keyEscrowSinks = escrowSinks.Count is 0 ? + Array.Empty() : + new IKeyEscrowSink[escrowSinks.Count]; + for (var i = 0; i < keyEscrowSinks.Length; i++) + { + keyEscrowSinks[i] = _activator.CreateInstance(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; + } + + [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)!; + } + + 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 = Type.GetType(Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture)!, throwOnError: true)!; + } + + return options; + } } diff --git a/src/DataProtection/DataProtection/src/SimpleActivator.cs b/src/DataProtection/DataProtection/src/SimpleActivator.cs index 06e7aefba733..f51c757c578e 100644 --- a/src/DataProtection/DataProtection/src/SimpleActivator.cs +++ b/src/DataProtection/DataProtection/src/SimpleActivator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.DataProtection.Internal; namespace Microsoft.AspNetCore.DataProtection; @@ -26,6 +27,7 @@ public SimpleActivator(IServiceProvider? services) _services = services; } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public virtual object CreateInstance(Type expectedBaseType, string implementationTypeName) { // Would the assignment even work? diff --git a/src/DataProtection/DataProtection/src/TypeForwardingActivator.cs b/src/DataProtection/DataProtection/src/TypeForwardingActivator.cs index 86bd74ccf727..bfa537187dfb 100644 --- a/src/DataProtection/DataProtection/src/TypeForwardingActivator.cs +++ b/src/DataProtection/DataProtection/src/TypeForwardingActivator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -24,10 +25,12 @@ public TypeForwardingActivator(IServiceProvider services, ILoggerFactory loggerF _logger = loggerFactory.CreateLogger(typeof(TypeForwardingActivator)); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public override object CreateInstance(Type expectedBaseType, string originalTypeName) => CreateInstance(expectedBaseType, originalTypeName, out var _); // for testing + [RequiresUnreferencedCode(TrimmerWarning.Message)] internal object CreateInstance(Type expectedBaseType, string originalTypeName, out bool forwarded) { var forwardedTypeName = originalTypeName; diff --git a/src/DataProtection/DataProtection/src/XmlEncryption/XmlEncryptionExtensions.cs b/src/DataProtection/DataProtection/src/XmlEncryption/XmlEncryptionExtensions.cs index 3b22fc8f529c..1cf4c264a509 100644 --- a/src/DataProtection/DataProtection/src/XmlEncryption/XmlEncryptionExtensions.cs +++ b/src/DataProtection/DataProtection/src/XmlEncryption/XmlEncryptionExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Xml.Linq; @@ -15,6 +16,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption; internal static unsafe class XmlEncryptionExtensions { + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static XElement DecryptElement(this XElement element, IActivator activator) { // If no decryption necessary, return original element. diff --git a/src/DataProtection/EntityFrameworkCore/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj b/src/DataProtection/EntityFrameworkCore/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj index d8f002d7d0af..df26a331d532 100644 --- a/src/DataProtection/EntityFrameworkCore/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj +++ b/src/DataProtection/EntityFrameworkCore/src/Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj @@ -6,7 +6,7 @@ true true aspnetcore;dataprotection;entityframeworkcore - enable + true diff --git a/src/DataProtection/Extensions/src/DataProtectionAdvancedExtensions.cs b/src/DataProtection/Extensions/src/DataProtectionAdvancedExtensions.cs index 9d3214bd6543..520b0901fd51 100644 --- a/src/DataProtection/Extensions/src/DataProtectionAdvancedExtensions.cs +++ b/src/DataProtection/Extensions/src/DataProtectionAdvancedExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.DataProtection; @@ -18,6 +19,7 @@ public static class DataProtectionAdvancedExtensions /// The plaintext data to protect. /// The amount of time after which the payload should no longer be unprotectable. /// The protected form of the plaintext data. + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static byte[] Protect(this ITimeLimitedDataProtector protector, byte[] plaintext, TimeSpan lifetime) { if (protector == null) @@ -41,6 +43,7 @@ public static byte[] Protect(this ITimeLimitedDataProtector protector, byte[] pl /// The plaintext data to protect. /// The time when this payload should expire. /// The protected form of the plaintext data. + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static string Protect(this ITimeLimitedDataProtector protector, string plaintext, DateTimeOffset expiration) { if (protector == null) @@ -65,6 +68,7 @@ public static string Protect(this ITimeLimitedDataProtector protector, string pl /// The plaintext data to protect. /// The amount of time after which the payload should no longer be unprotectable. /// The protected form of the plaintext data. + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static string Protect(this ITimeLimitedDataProtector protector, string plaintext, TimeSpan lifetime) { if (protector == null) @@ -107,6 +111,7 @@ public static ITimeLimitedDataProtector ToTimeLimitedDataProtector(this IDataPro /// /// Thrown if is invalid, malformed, or expired. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] public static string Unprotect(this ITimeLimitedDataProtector protector, string protectedData, out DateTimeOffset expiration) { if (protector == null) @@ -145,6 +150,7 @@ public IDataProtector CreateProtector(string purpose) throw new NotImplementedException(); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public byte[] Protect(byte[] plaintext) { if (plaintext == null) @@ -155,6 +161,7 @@ public byte[] Protect(byte[] plaintext) return _innerProtector.Protect(plaintext, Expiration); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public byte[] Unprotect(byte[] protectedData) { if (protectedData == null) diff --git a/src/DataProtection/Extensions/src/ITimeLimitedDataProtector.cs b/src/DataProtection/Extensions/src/ITimeLimitedDataProtector.cs index 5632b227c64a..04aa0b273621 100644 --- a/src/DataProtection/Extensions/src/ITimeLimitedDataProtector.cs +++ b/src/DataProtection/Extensions/src/ITimeLimitedDataProtector.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.DataProtection; @@ -38,6 +39,7 @@ public interface ITimeLimitedDataProtector : IDataProtector /// The plaintext data to protect. /// The time when this payload should expire. /// The protected form of the plaintext data. + [RequiresUnreferencedCode(TrimmerWarning.Message)] byte[] Protect(byte[] plaintext, DateTimeOffset expiration); /// @@ -50,5 +52,6 @@ public interface ITimeLimitedDataProtector : IDataProtector /// /// Thrown if is invalid, malformed, or expired. /// + [RequiresUnreferencedCode(TrimmerWarning.Message)] byte[] Unprotect(byte[] protectedData, out DateTimeOffset expiration); } diff --git a/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj b/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj index 35624976d7ad..d050a6d3a4c6 100644 --- a/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj +++ b/src/DataProtection/Extensions/src/Microsoft.AspNetCore.DataProtection.Extensions.csproj @@ -7,11 +7,13 @@ true true aspnetcore;dataprotection - enable + true - + + diff --git a/src/DataProtection/Extensions/src/TimeLimitedDataProtector.cs b/src/DataProtection/Extensions/src/TimeLimitedDataProtector.cs index b4989d089399..d3514d3eeaaa 100644 --- a/src/DataProtection/Extensions/src/TimeLimitedDataProtector.cs +++ b/src/DataProtection/Extensions/src/TimeLimitedDataProtector.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; using System.Threading; using Microsoft.AspNetCore.DataProtection.Extensions; @@ -46,6 +47,7 @@ private IDataProtector GetInnerProtectorWithTimeLimitedPurpose() return retVal; } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public byte[] Protect(byte[] plaintext, DateTimeOffset expiration) { if (plaintext == null) @@ -61,6 +63,7 @@ public byte[] Protect(byte[] plaintext, DateTimeOffset expiration) return GetInnerProtectorWithTimeLimitedPurpose().Protect(plaintextWithHeader); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] public byte[] Unprotect(byte[] protectedData, out DateTimeOffset expiration) { if (protectedData == null) @@ -71,6 +74,7 @@ public byte[] Unprotect(byte[] protectedData, out DateTimeOffset expiration) return UnprotectCore(protectedData, DateTimeOffset.UtcNow, out expiration); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] internal byte[] UnprotectCore(byte[] protectedData, DateTimeOffset now, out DateTimeOffset expiration) { if (protectedData == null) @@ -124,6 +128,7 @@ IDataProtector IDataProtectionProvider.CreateProtector(string purpose) return CreateProtector(purpose); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] byte[] IDataProtector.Protect(byte[] plaintext) { if (plaintext == null) @@ -135,6 +140,7 @@ byte[] IDataProtector.Protect(byte[] plaintext) return Protect(plaintext, DateTimeOffset.MaxValue); } + [RequiresUnreferencedCode(TrimmerWarning.Message)] byte[] IDataProtector.Unprotect(byte[] protectedData) { if (protectedData == null) diff --git a/src/DataProtection/StackExchangeRedis/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj b/src/DataProtection/StackExchangeRedis/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj index f1a88a9f673a..8e2eabffec2f 100644 --- a/src/DataProtection/StackExchangeRedis/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj +++ b/src/DataProtection/StackExchangeRedis/src/Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj @@ -6,7 +6,7 @@ true true aspnetcore;dataprotection;redis - enable + true diff --git a/src/DataProtection/shared/src/TrimmerWarning.cs b/src/DataProtection/shared/src/TrimmerWarning.cs new file mode 100644 index 000000000000..b047e4d8b20a --- /dev/null +++ b/src/DataProtection/shared/src/TrimmerWarning.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.DataProtection; + +internal static class TrimmerWarning +{ + public const string Message = "Data Protection may attempt to load types in a way that cannot be statically analyzed. Ensure all required types are preserved."; +} diff --git a/src/Shared/TrimmingAttributes.cs b/src/Shared/TrimmingAttributes.cs new file mode 100644 index 000000000000..c4b5bc0c6505 --- /dev/null +++ b/src/Shared/TrimmingAttributes.cs @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +namespace System.Diagnostics.CodeAnalysis; + +/// +/// Indicates that the specified method requires dynamic access to code that is not referenced +/// statically, for example through . +/// +/// +/// This allows tools to understand which methods are unsafe to call when removing unreferenced +/// code from an application. +/// +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] +internal sealed class RequiresUnreferencedCodeAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of unreferenced code. + /// + public RequiresUnreferencedCodeAttribute(string message) + { + Message = message; + } + + /// + /// Gets a message that contains information about the usage of unreferenced code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requires unreferenced code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } +} + +/// +/// Suppresses reporting of a specific rule violation, allowing multiple suppressions on a +/// single code artifact. +/// +/// +/// is different than +/// in that it doesn't have a +/// . So it is always preserved in the compiled assembly. +/// +[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] +internal sealed class UnconditionalSuppressMessageAttribute : Attribute +{ + /// + /// Initializes a new instance of the + /// class, specifying the category of the tool and the identifier for an analysis rule. + /// + /// The category for the attribute. + /// The identifier of the analysis rule the attribute applies to. + public UnconditionalSuppressMessageAttribute(string category, string checkId) + { + Category = category; + CheckId = checkId; + } + + /// + /// Gets the category identifying the classification of the attribute. + /// + /// + /// The property describes the tool or tool analysis category + /// for which a message suppression attribute applies. + /// + public string Category { get; } + + /// + /// Gets the identifier of the analysis tool rule to be suppressed. + /// + /// + /// Concatenated together, the and + /// properties form a unique check identifier. + /// + public string CheckId { get; } + + /// + /// Gets or sets the scope of the code that is relevant for the attribute. + /// + /// + /// The Scope property is an optional argument that specifies the metadata scope for which + /// the attribute is relevant. + /// + public string? Scope { get; set; } + + /// + /// Gets or sets a fully qualified path that represents the target of the attribute. + /// + /// + /// The property is an optional argument identifying the analysis target + /// of the attribute. An example value is "System.IO.Stream.ctor():System.Void". + /// Because it is fully qualified, it can be long, particularly for targets such as parameters. + /// The analysis tool user interface should be capable of automatically formatting the parameter. + /// + public string? Target { get; set; } + + /// + /// Gets or sets an optional argument expanding on exclusion criteria. + /// + /// + /// The property is an optional argument that specifies additional + /// exclusion where the literal metadata target is not sufficiently precise. For example, + /// the cannot be applied within a method, + /// and it may be desirable to suppress a violation against a statement in the method that will + /// give a rule violation, but not against all statements in the method. + /// + public string? MessageId { get; set; } + + /// + /// Gets or sets the justification for suppressing the code analysis message. + /// + public string? Justification { get; set; } +} diff --git a/src/Tools/Tools.slnf b/src/Tools/Tools.slnf index b419c1d28c6e..9e1a35eff802 100644 --- a/src/Tools/Tools.slnf +++ b/src/Tools/Tools.slnf @@ -10,7 +10,16 @@ "src\\Components\\WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj", "src\\Components\\WebAssembly\\WebAssembly\\src\\Microsoft.AspNetCore.Components.WebAssembly.csproj", "src\\Components\\Web\\src\\Microsoft.AspNetCore.Components.Web.csproj", + "src\\DataProtection\\Abstractions\\src\\Microsoft.AspNetCore.DataProtection.Abstractions.csproj", + "src\\DataProtection\\Cryptography.Internal\\src\\Microsoft.AspNetCore.Cryptography.Internal.csproj", + "src\\DataProtection\\Cryptography.KeyDerivation\\src\\Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj", + "src\\DataProtection\\DataProtection\\src\\Microsoft.AspNetCore.DataProtection.csproj", + "src\\DataProtection\\EntityFrameworkCore\\src\\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj", + "src\\DataProtection\\Extensions\\src\\Microsoft.AspNetCore.DataProtection.Extensions.csproj", + "src\\DataProtection\\StackExchangeRedis\\src\\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj", "src\\Extensions\\Features\\src\\Microsoft.Extensions.Features.csproj", + "src\\HealthChecks\\Abstractions\\src\\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj", + "src\\HealthChecks\\HealthChecks\\src\\Microsoft.Extensions.Diagnostics.HealthChecks.csproj", "src\\Hosting\\Abstractions\\src\\Microsoft.AspNetCore.Hosting.Abstractions.csproj", "src\\Hosting\\Hosting\\src\\Microsoft.AspNetCore.Hosting.csproj", "src\\Hosting\\Server.Abstractions\\src\\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj", @@ -26,7 +35,28 @@ "src\\Http\\Routing\\src\\Microsoft.AspNetCore.Routing.csproj", "src\\Http\\WebUtilities\\src\\Microsoft.AspNetCore.WebUtilities.csproj", "src\\JSInterop\\Microsoft.JSInterop\\src\\Microsoft.JSInterop.csproj", + "src\\Middleware\\CORS\\src\\Microsoft.AspNetCore.Cors.csproj", + "src\\Middleware\\ConcurrencyLimiter\\src\\Microsoft.AspNetCore.ConcurrencyLimiter.csproj", + "src\\Middleware\\Diagnostics.Abstractions\\src\\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj", + "src\\Middleware\\Diagnostics.EntityFrameworkCore\\src\\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj", + "src\\Middleware\\Diagnostics\\src\\Microsoft.AspNetCore.Diagnostics.csproj", + "src\\Middleware\\HeaderPropagation\\src\\Microsoft.AspNetCore.HeaderPropagation.csproj", + "src\\Middleware\\HealthChecks.EntityFrameworkCore\\src\\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.csproj", + "src\\Middleware\\HealthChecks\\src\\Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj", + "src\\Middleware\\HostFiltering\\src\\Microsoft.AspNetCore.HostFiltering.csproj", + "src\\Middleware\\HttpLogging\\src\\Microsoft.AspNetCore.HttpLogging.csproj", "src\\Middleware\\HttpOverrides\\src\\Microsoft.AspNetCore.HttpOverrides.csproj", + "src\\Middleware\\HttpsPolicy\\src\\Microsoft.AspNetCore.HttpsPolicy.csproj", + "src\\Middleware\\Localization.Routing\\src\\Microsoft.AspNetCore.Localization.Routing.csproj", + "src\\Middleware\\Localization\\src\\Microsoft.AspNetCore.Localization.csproj", + "src\\Middleware\\MiddlewareAnalysis\\src\\Microsoft.AspNetCore.MiddlewareAnalysis.csproj", + "src\\Middleware\\ResponseCaching.Abstractions\\src\\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj", + "src\\Middleware\\ResponseCaching\\src\\Microsoft.AspNetCore.ResponseCaching.csproj", + "src\\Middleware\\ResponseCompression\\src\\Microsoft.AspNetCore.ResponseCompression.csproj", + "src\\Middleware\\Rewrite\\src\\Microsoft.AspNetCore.Rewrite.csproj", + "src\\Middleware\\Session\\src\\Microsoft.AspNetCore.Session.csproj", + "src\\Middleware\\StaticFiles\\src\\Microsoft.AspNetCore.StaticFiles.csproj", + "src\\Middleware\\WebSockets\\src\\Microsoft.AspNetCore.WebSockets.csproj", "src\\ObjectPool\\src\\Microsoft.Extensions.ObjectPool.csproj", "src\\Security\\Authorization\\Core\\src\\Microsoft.AspNetCore.Authorization.csproj", "src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",