-
Notifications
You must be signed in to change notification settings - Fork 5.1k
104080 custom rsapss salt length #119255
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
base: main
Are you sure you want to change the base?
104080 custom rsapss salt length #119255
Conversation
…ation/generation with RSA keys. dotnet#104080
…lt customizations
…pported there) Updated reference code
Cose does not support custom salt lengths with PSS.
Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request adds support for custom PSS salt length for RSA-based signature operations. The implementation extends the RSASignaturePadding
class with a new CreatePss(int saltLength)
method and updates related cryptographic components to utilize custom salt lengths.
Key changes include:
- Extended
RSASignaturePadding
to support custom PSS salt lengths with new constants and factory method - Updated all RSA implementation backends (OpenSSL, CNG, BCrypt, etc.) to handle custom salt lengths
- Added comprehensive test coverage for various salt length scenarios
- Updated high-level APIs like
CmsSigner
andCertificateRequest
to support the new functionality
Reviewed Changes
Copilot reviewed 40 out of 41 changed files in this pull request and generated 5 comments.
Show a summary per file
File | Description |
---|---|
src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h | Added pssSaltLength parameter to RSA sign/verify functions |
src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey_rsa.c | Implemented custom salt length support in OpenSSL backend |
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSASignaturePadding.cs | Added CreatePss method, PssSaltLength property, and related constants |
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/RSAPssX509SignatureGenerator.cs | Updated to use custom salt lengths from padding configuration |
src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.cs | Modified PSS encoding/verification to accept custom salt lengths |
src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.DigestInfo.cs | Added salt length calculation logic and moved digest info constants |
src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs | Added comprehensive tests for custom PSS salt lengths |
src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs | Updated validation to accept any PSS mode padding |
src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/CoseSigner.cs | Added validation to prevent custom salt lengths in COSE |
src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.DigestInfo.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.Cng/tests/RSACngPkcs8TestsWithCustomPssSaltLength.cs
Outdated
Show resolved
Hide resolved
...rity.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestChainTests.cs
Outdated
Show resolved
Hide resolved
…tes/CertificateCreation/CertificateRequestChainTests.cs Co-authored-by: Copilot <[email protected]>
….Cryptography.cs Co-authored-by: Copilot <[email protected]>
…ngProcessor.DigestInfo.cs Co-authored-by: Copilot <[email protected]>
…s8TestsWithCustomPssSaltLength.cs Co-authored-by: Copilot <[email protected]>
…/henning-krause/runtime into 104080-custom-rsapss-salt-length
src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptSignHash.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptVerifySignature.cs
Outdated
Show resolved
Hide resolved
@@ -41,6 +41,9 @@ internal RSASignaturePadding GetSignaturePadding( | |||
HashAlgorithm.Algorithm)); | |||
} | |||
|
|||
#if NET10_0_OR_GREATER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is tricky. Right now, .NET 10 is "done". Technically this work will go in for .NET 11. However, the runtime and SDK are not "bumped" to .NET 11 yet so #if NET11_0_OR_GREATER
doesn't exist. We might need to wait for this work until #118583 is complete.
src/libraries/Common/src/System/Security/Cryptography/RSAAppleCrypto.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/System/Security/Cryptography/RSAAppleCrypto.cs
Outdated
Show resolved
Hide resolved
...braries/System.Security.Cryptography/src/System/Security/Cryptography/RSASignaturePadding.cs
Outdated
Show resolved
Hide resolved
...braries/System.Security.Cryptography/src/System/Security/Cryptography/RSASignaturePadding.cs
Outdated
Show resolved
Hide resolved
...braries/System.Security.Cryptography/src/System/Security/Cryptography/RSASignaturePadding.cs
Outdated
Show resolved
Hide resolved
...braries/System.Security.Cryptography/src/System/Security/Cryptography/RSASignaturePadding.cs
Outdated
Show resolved
Hide resolved
...rity.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made it about halfway, but have to disappear for a bit, so posting what I've already seen.
src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs
Outdated
Show resolved
Hide resolved
Debug.Assert(padding == RSASignaturePadding.Pss); | ||
if (padding.PssSaltLength < RSASignaturePadding.PssSaltLengthMax) | ||
{ | ||
throw PaddingModeNotSupported(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exception says the padding "mode" is invalid. Which isn't the case here. The "mode" is PSS, which is valid. So we probably want a new message for the salt size being gibberish (and yet a different one for "that doesn't work here")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, an assert here is fine given the throw there.
src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.DigestInfo.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.DigestInfo.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.DigestInfo.cs
Outdated
Show resolved
Hide resolved
...braries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.Cng/tests/RSACngPkcs8TestsPssSaltLength.cs
Outdated
Show resolved
Hide resolved
#if NET10_0_OR_GREATER | ||
if (signaturePadding.Mode == RSASignaturePaddingMode.Pss) | ||
{ | ||
if (signaturePadding.PssSaltLength != RSASignaturePadding.PssSaltLengthIsHashLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also allow a custom value that happens to match?
[InlineData(0)] | ||
[InlineData(17)] | ||
[InlineData(RSASignaturePadding.PssSaltLengthMax)] | ||
public void CoseSigner_PssPaddingWithInvalidSaltLength(int saltLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether we allow it, or not, there should be a test using 32
(matching SHA256).
[InlineData(Oids.Sha256, false, RSASignaturePadding.PssSaltLengthIsHashLength)] | ||
[InlineData(Oids.Sha384, false, RSASignaturePadding.PssSaltLengthIsHashLength)] | ||
[InlineData(Oids.Sha512, false, RSASignaturePadding.PssSaltLengthIsHashLength)] | ||
[InlineData(Oids.Sha1, false, RSASignaturePadding.PssSaltLengthIsHashLength)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit big for InlineData, probably should change to a MemberData using a couple of loops for enhanced legibility.
@@ -127,14 +127,14 @@ public static void ReadRsaPssDocument(bool fromSpan) | |||
Assert.Throws<CryptographicException>(() => signer.CheckHash()); | |||
|
|||
// At this time we cannot support the PSS parameters for this document. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment is out of date.
@@ -127,14 +127,14 @@ public static void ReadRsaPssDocument(bool fromSpan) | |||
Assert.Throws<CryptographicException>(() => signer.CheckHash()); | |||
|
|||
// At this time we cannot support the PSS parameters for this document. | |||
Assert.Throws<CryptographicException>(() => signer.CheckSignature(true)); | |||
signer.CheckSignature(true); | |||
|
|||
// Since there are no NoSignature signers the document CheckHash will succeed. | |||
// Assert.NotThrows | |||
cms.CheckHash(); | |||
|
|||
// Since at least one signer fails, the document signature will fail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment is out of date.
[InlineData("SHA256", 1)] | ||
[InlineData("SHA384", 1)] | ||
[InlineData("SHA512", 1)] | ||
//[InlineData("SHA1", 1)] // The current implementation for CertificateRequest does not support SHA-1 with PSS. If this is required, the RSASha1PssSignatureGenerator and the RSAPssX509SignatureGenerator class needs updates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SHA-1 used to be tested here. And the code doing it is still here. The coverage shouldn't be lost.
deterministicSignature: false); | ||
RSASignaturePadding.CreatePss(saltLength)), | ||
X509SignatureGenerator.CreateForRSA(key, RSASignaturePadding.CreatePss(saltLength)), | ||
deterministicSignature: saltLength == 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So why isn't 0 included in the InlineData then?
} | ||
|
||
|
||
[Theory] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: too many blank lines
} | |
[Theory] | |
} | |
[Theory] |
var data = new byte[] { 1, 2, 3, 4, 5 }; | ||
var signature = signatureGenerator.SignData(data, HashAlgorithmName.SHA256); | ||
var signatureAlgorithm = signatureGenerator.GetSignatureAlgorithmIdentifier(HashAlgorithmName.SHA256); | ||
|
||
var asnReader = new AsnReader(signatureAlgorithm, AsnEncodingRules.DER); | ||
var rootSequence = asnReader.ReadSequence(); | ||
Assert.Equal("1.2.840.113549.1.1.10", rootSequence.ReadObjectIdentifier()); // Make sure it's RSASSA-PSS | ||
var pssStructure = rootSequence.ReadSequence(); | ||
pssStructure.ReadEncodedValue(); // Ignore the hash algorithm OID | ||
pssStructure.ReadEncodedValue(); // Ignore the mask generation function OID | ||
var saltTag = new Asn1Tag(TagClass.ContextSpecific, 2, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many uses of var
here that are against style guidelines. If you want to keep them when it's permitted, you can, but I'd just change all of them to specify the type.
var saltTag = new Asn1Tag(TagClass.ContextSpecific, 2, true); | ||
if (pssStructure.HasData && pssStructure.PeekTag().HasSameClassAndValue(saltTag)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blank lines before control flow is preferred
var saltTag = new Asn1Tag(TagClass.ContextSpecific, 2, true); | |
if (pssStructure.HasData && pssStructure.PeekTag().HasSameClassAndValue(saltTag)) | |
var saltTag = new Asn1Tag(TagClass.ContextSpecific, 2, true); | |
if (pssStructure.HasData && pssStructure.PeekTag().HasSameClassAndValue(saltTag)) |
/// </remarks> | ||
public int PssSaltLength { get; } | ||
|
||
public static RSASignaturePadding CreatePss(int saltLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Public method requires documentation
Added support for custom PSS salt length for RSA based signature operations. Resolves #104080.
With this PR, I have extended the RsaSignaturePadding class with a custom salt length as discussed in #104080. I've also updated the CmsSigner and the CertificateRequest class to support this.
CoseSigner did not need functionality updates, because the spec does not support custom salt length. I have added checks to prevent this to be configured on the CoseSigner.
Tests where either added or updated to test the new functionality.
All RSA implementations which support this (MAC doesn't seem to support this) were updated.