X25519: Handle zero peer keys on downlevel Windows platforms - #134535
Conversation
Add the Wycheproof all-zero public-key vector to each raw secret agreement overload. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run runtime |
|
Draft and NO-REVIEW because this PR does not contain the fix, yet. I want to see the tests fail in CI before pushing the fix. |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @bartonjs, @vcsjones, @dotnet/area-system-security |
|
/azp run runtime-coreclr libraries-jitstress |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Confirmed in jitstress test run https://helixr1107v0xdcypoyl9e7f.blob.core.windows.net/dotnet-runtime-refs-pull-134535-merge-73a894a0113b416799/System.Security.Cryptography.Tests/1/console.72dee97e.log?helixlogtype=result Assert.ThrowsAny() Failure: No exception was thrown Expected: typeof(System.Security.Cryptography.CryptographicException) Stack Trace: /_/src/libraries/Common/tests/System/Security/Cryptography/X25519DiffieHellmanBaseTests.cs(306,0): at System.Security.Cryptography.Tests.X25519DiffieHellmanBaseTests.DeriveRawSecretAgreement_Bytes_ZeroSharedSecret_Throws(String peerPublicKeyHex) at InvokeStub_X25519DiffieHellmanBaseTests.DeriveRawSecretAgreement_Bytes_ZeroSharedSecret_Throws(Object, Span`1) /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs(95,0): at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) |
Detect peer public keys that reduce to zero before invoking downlevel Windows CNG implementations that can return an incorrect nonzero shared secret. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run runtime-coreclr libraries-jitstress |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
One or more issues must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Fixes Windows X25519 agreement with all-zero peer keys by rejecting reduced-zero public keys before deriving a secret.
Changes:
- Added zero-key coverage across raw agreement overloads.
- Added reduced-zero detection to both Windows X25519 implementations.
| File | Description |
|---|---|
| src/libraries/Common/tests/System/Security/Cryptography/X25519DiffieHellmanBaseTests.cs | Updated as part of this pull request. |
| src/libraries/Common/src/System/Security/Cryptography/X25519DiffieHellmanImplementation.Windows.cs | Updated as part of this pull request. |
| src/libraries/Common/src/System/Security/Cryptography/X25519DiffieHellmanCng.Windows.cs | Updated as part of this pull request. |
|
/azp run runtime-coreclr libraries-jitstress |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Continue testing reduced-zero peer values through raw-byte APIs on all Windows versions while limiting CngKey object round-trip coverage to Windows 11 and newer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run runtime-coreclr libraries-jitstress |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Caller-supplied CngKey objects may reject or transform reduced-zero public values during provider import, so retain this coverage through the raw-byte APIs instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run runtime-coreclr libraries-jitstress |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
/azp run runtime-coreclr libraries-jitstress |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
/backport to release/11.0 |
|
Started backporting to |

An all-zero peer (public) key should always produce a zero shared secret, which should get rejected during key agreement.
Windows normally rejects this during importation time, but that is not enabled because Windows would also eagerly reject off-twist public keys which should work. With this change, when a "zero" public key is imported (either by naturally being zero or reduced to zero) we skip importing it into bcrypt and retain "This was a zero key". During derivation we throw since that would produce a zero shared secret. This keeps Windows consistent with other platforms, where import is not the protected path, but derivation is.
For X25519DHCng (ncrypt) its not possible to really gate this when the peer key is zero. However that responsibility falls to the person creating the public key handle, and the handle is external in this case.
This was discovered with HPKE tests in #134528.