runtime: Annotate unsupported APIs in System.Security.*
As part of https://github.com/dotnet/runtime/issues/47228 i am running an analyzer to detect APIs throwing PNSE but not annotated with Obsolete/SupportedOSPlatform/UnsupportedOSPlatform attributes, we need to annotate them so that developers get warnings when they use them unexpectedly
For now, I have results only for cross-platform builds, analysis of targeted builds are coming soon where more APIs could be detected
API | Comment | Suggestion | Location |
---|---|---|---|
‘SecurityContext.Capture()’ | throws unconditionally | All APIs throws [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(11,51) |
‘SecurityContext.CreateCopy()’ | throws unconditionally | [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(12,47) |
‘SecurityContext.Dispose()’ | throws unconditionally | [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(13,33) |
‘SecurityContext.IsFlowSuppressed()’ | throws unconditionally | [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(14,49) |
‘SecurityContext.IsWindowsIdentityFlowSuppressed()’ | throws unconditionally | [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(15,64) |
‘SecurityContext.RestoreFlow()’ | throws unconditionally | [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(16,44) |
‘SecurityContext.Run(SecurityContext, ContextCallback, object)’ | throws unconditionally | [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(17,107) |
‘SecurityContext.SuppressFlow()’ | throws unconditionally | [Obsolete] the type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(18,57) |
‘SecurityContext.SuppressFlowWindowsIdentity()’ | throws unconditionally | [Obsolete] entire type | libraries\System.Security.Permissions\src\System\Security\SecurityContext.cs(19,72) |
EDIT: Adding APIs found for netstandard
targeted builds
API | Comment | Suggestion | Location |
---|---|---|---|
‘ECDiffieHellmanCng.FromXmlString(string, ECKeyXmlFormat)’ | Uncondidionally throws | obsolete | libraries\System.Security.Cryptography.Cng\src\System\Security\Cryptography\ECDiffieHellmanCng.Xml.cs(10,13) |
‘ECDiffieHellmanCng.ToXmlString(ECKeyXmlFormat)’ | Uncondidionally throws | obsolete | libraries\System.Security.Cryptography.Cng\src\System\Security\Cryptography\ECDiffieHellmanCng.Xml.cs(15,13) |
‘ECDiffieHellmanCngPublicKey.ToXmlString()’ | Uncondidionally throws | obsolete | libraries\System.Security.Cryptography.Cng\src\System\Security\Cryptography\ECDiffieHellmanCngPublicKey.cs(37,13) |
‘ECDiffieHellmanCngPublicKey.FromXmlString(string)’ | Uncondidionally throws | obsolete | libraries\System.Security.Cryptography.Cng\src\System\Security\Cryptography\ECDiffieHellmanCngPublicKey.cs(42,13) |
‘ECDsaCng.FromXmlString(string, ECKeyXmlFormat)’ | Uncondidionally throws | obsolete | libraries\System.Security.Cryptography.Cng\src\System\Security\Cryptography\ECDsaCng.cs(131,16) |
‘ECDsaCng.ToXmlString(ECKeyXmlFormat)’ | Uncondidionally throws | obsolete | libraries\System.Security.Cryptography.Cng\src\System\Security\Cryptography\ECDsaCng.cs(143,16) |
‘ECDiffieHellmanOpenSslPublicKey.ToXmlString()’ | Internal API, unconditionally throwing | obsolet if referenced in public API | libraries\Common\src\System\Security\Cryptography\ECDiffieHellmanOpenSslPublicKey.cs(42,17) |
‘ECDiffieHellmanOpenSslPublicKey.ToByteArray()’ | Internal API, unconditionally throwing | obsolete if referenced in public API | libraries\Common\src\System\Security\Cryptography\ECDiffieHellmanOpenSslPublicKey.cs(47,17) |
‘CmsSigner.CmsSigner(CspParameters)’ | It has comment possibly adding windows support | but no issue attached, obsolete | libraries\System.Security.Cryptography.Pkcs\src\System\Security\Cryptography\Pkcs\CmsSigner.cs(63,55) |
‘SignerInfo.ComputeCounterSignature()’ | Uncondidionally throws | obsolete | libraries\System.Security.Cryptography.Pkcs\src\System\Security\Cryptography\Pkcs\SignerInfo.cs(296,13) |
‘PermissionSet.PermitOnly()’ | Uncondidionally throws | it has ifdef-ed obsolete | libraries\System.Private.CoreLib\src\System\Security\PermissionSet.cs(43,36) |
‘CodeAccessPermission.PermitOnly()’ | Uncondidionally throws | it has ifdef-ed obsolete | libraries\System.Security.Permissions\src\System\Security\CodeAccessPermission.cs(22,36) |
Note: We are suggesting to add [Obsolete] for the APIs only supported in .Net framework but not supported in .NetCore, with the corresponding Message, DiagnosticId, and UrlFormat https://github.com/dotnet/runtime/blob/cecc76a29a8b6c1fca181a38f076b4d949081746/src/libraries/System.Net.Requests/src/System/Net/AuthenticationManager.cs#L17 You can claim the next available DiagnosticId from Obsoletions.cs .
If it is only supported on a specific platform(s) consider adding [SupportedOSPlatform(“platformName”)] or if it is unsupported on a specific platform(s) [UnsupportedOSPlatform(“platformName”)] attribute instead
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 38 (36 by maintainers)
Yeah. But then it feels weird to have a constructor that takes the key blob and no not-obsolete way to do anything with it.
Since it’s a protected constructor on a class that no one is deriving from I would wager we could take a swing at obsoleting it with less than perfect wording.
OK, the landscape here is complicated, but in general it looks like @bartonjs’s wager holds up, particularly through the lens of “ecosystem code exposed to such a change”. I definitely found types that inherit from System.Security.Cryptography.ECDiffieHellmanPublicKey, but almost universally these are types in our own shipped assemblies (System.Core, System.Security.Cng/Algorithms/OpenSsl). These assemblies are in our own packages, as well as redistributed in other packages at a pretty high rate. None of those really represent problematic scenarios WRT deprecation. The few that were genuinely non-product types are in assemblies that are not published on NuGet.org, and instead come from other locations like internal test trees/tools.
Had there been an actual “eat my hat” type consequence I definitely would have thrown in a disclaimer like “(offer valid only for non-prerelease packages already present on nuget.org at the original time of this post)”. I may not be smart enough to remember to look in partial files, but I’m not that naive 😄.
I’ll tackle the rest of these over the next day or two.
For RC2-browser we seem to have marked the whole type, which was probably a bit of an overreach, because someone /could/ provide a working implementation of RC2. RC2.Create() on android I’m pretty sure succeeds, but returns an object that fails if you try to actually use it. Part of me thinks it’d be better to just put the PNSE there, but maybe there’s a legit use case I can think of for the dummy RC2 instance.
So… yeah, marking RC2.Create as Unsupported-android is probably right. With a comment that says a more formal version of “yeah, it returns, but the object is going to throw if you call CreateEncryptor or CreateDecryptor… so it’s the same as not working”
As for other things in @buyaa-n 's tables:
I think that only leaves ECDiffieHellmanPublicKey.ToByteArray and ECDiffieHellmanPublicKey…ctor(byte[]). I’d support Obsoleting these. I… thought… we had added SPKI export on this type, but I don’t see it. So maybe we need to hold this one back one release. Using inbox types the ToByteArray only works on Windows, but since it’s a virtual I don’t like putting a SupportedOSAttribute on it.
Just to summarize findings that I think are actionable:
Rfc2898DeriveBytes.CryptDeriveKey
obsolete: https://github.com/dotnet/runtime/pull/57002System.Security.SecurityContext
obsolete https://github.com/dotnet/runtime/pull/57035CmsSigner.CmsSigner(CspParameters)
obsolete https://github.com/dotnet/runtime/pull/57301SignerInfo.ComputeCounterSignature()
obsolete https://github.com/dotnet/runtime/pull/57301RC2.Create()
add[UnsupportedOSPlatform(“android”)]
https://github.com/dotnet/runtime/pull/57289It would still be useful to have someone else validate this.
We could take these 3 obsoletions without going through API Review–just code review from @bartonjs and @GrabYourPitchforks. I’m comfortable taking them before the August 17th cutoff for .NET 6, especially since it’s not a breaking change.
I’m not sure adding an
UnsupportedOSPlatform
here would be ergonomic. The issue is that the public APIExportExplicitParameters
is accessible via the virtualECDsa.ExportExplicitParameters
. We would have to decorate the virtual with the UOSP attribute, which would not interact well with derived classes (our own or developers’ own). To illustrate:Similar concerns lie with
ToXmlString
,FromXmlString
, andToByteArray
. It seems a little odd to obsolete anoverride
when a user derived type could override one of these from the base class and implement it.Some of these do make sense to me to obsolete:
Rfc2898DeriveBytes.CryptDeriveKey
- it’s unimplemented and can’t be implemented xplat since it’s a Windows thing. I’m unaware of demand to bring it back.CmsSigner.CmsSigner(CspParameters)
seems weird. It manufactures a certificate on the fly based on those CspParameters. It makes sense to obsolete since it can only be implemented on Windows. If we really, really wanted “make me a cert on the fly” behavior, it probably makes sense to implement a new API that accepted anAsymmetricAlgorithm
or something.SignerInfo.ComputeCounterSignature()
There’s an overload that accepts theCmsSigner
, so I think it makes sense to obsolete.I don’t see any immediately actionable things for 6.0. Presumably the obsoletions need to go through API review, and I don’t know if we’re taking any more obsoletions for 6.0 (granted all of them
throw
, so it’s not exactly a breaking change).The public entry,
Create
is already marked withUnsupportedOSPlatform
:https://github.com/dotnet/runtime/blob/a2f2a629328a136c2cd18f2cd729e3854de2aeb4/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs#L38
So I think that one is already taken care of.
Some of these APIs that “unconditionally throw” are virtual and are expected to be overridden in derived classes, so while the base class throws, they aren’t necessarily obsolete because derived classes override them and some functionality depend on these classes. I think this would be the case for all of the methods on the
HMAC
class. So I do not think those should be obsolete or otherwise annotated.