Skip to content

Commit 0e1368f

Browse files
Add more logic before PNSE where possible
1 parent 3655a7b commit 0e1368f

File tree

7 files changed

+153
-9
lines changed

7 files changed

+153
-9
lines changed

src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateKeyAccessors.cs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,28 @@ public static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certific
416416
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
417417
public static CompositeMLDsa? GetCompositeMLDsaPublicKey(this X509Certificate2 certificate)
418418
{
419-
throw new PlatformNotSupportedException();
419+
ArgumentNullException.ThrowIfNull(certificate);
420+
421+
#if NET10_0_OR_GREATER
422+
return certificate.GetCompositeMLDsaPublicKey();
423+
#else
424+
if (CompositeMLDsaAlgorithm.GetAlgorithmFromOid(certificate.GetKeyAlgorithm()) is null)
425+
{
426+
return null;
427+
}
428+
429+
ArraySegment<byte> encoded = GetCertificateSubjectPublicKeyInfo(certificate);
430+
431+
try
432+
{
433+
return CompositeMLDsa.ImportSubjectPublicKeyInfo(encoded);
434+
}
435+
finally
436+
{
437+
// SubjectPublicKeyInfo does not need to clear since it's public
438+
CryptoPool.Return(encoded, clearSize: 0);
439+
}
440+
#endif
420441
}
421442

422443
/// <summary>
@@ -440,7 +461,18 @@ public static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certific
440461
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
441462
public static CompositeMLDsa? GetCompositeMLDsaPrivateKey(this X509Certificate2 certificate)
442463
{
464+
ArgumentNullException.ThrowIfNull(certificate);
465+
466+
#if NET10_0_OR_GREATER
467+
return certificate.GetCompositeMLDsaPrivateKey();
468+
#else
469+
if (CompositeMLDsaAlgorithm.GetAlgorithmFromOid(certificate.GetKeyAlgorithm()) is null)
470+
{
471+
return null;
472+
}
473+
443474
throw new PlatformNotSupportedException();
475+
#endif
444476
}
445477

446478
/// <summary>
@@ -472,7 +504,43 @@ public static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certific
472504
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
473505
public static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certificate, CompositeMLDsa privateKey)
474506
{
507+
ArgumentNullException.ThrowIfNull(certificate);
508+
ArgumentNullException.ThrowIfNull(privateKey);
509+
510+
#if NET10_0_OR_GREATER
511+
return certificate.CopyWithPrivateKey(privateKey);
512+
#elif NETSTANDARD
513+
throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_AlgorithmNotSupported, nameof(CompositeMLDsa)));
514+
#else
515+
if (!Helpers.IsOSPlatformWindows)
516+
throw new PlatformNotSupportedException();
517+
518+
if (certificate.HasPrivateKey)
519+
throw new InvalidOperationException(SR.Cryptography_Cert_AlreadyHasPrivateKey);
520+
521+
using (CompositeMLDsa? publicKey = GetCompositeMLDsaPublicKey(certificate))
522+
{
523+
if (publicKey is null)
524+
{
525+
throw new ArgumentException(SR.Cryptography_PrivateKey_WrongAlgorithm);
526+
}
527+
528+
if (publicKey.Algorithm != privateKey.Algorithm)
529+
{
530+
throw new ArgumentException(SR.Cryptography_PrivateKey_DoesNotMatch, nameof(privateKey));
531+
}
532+
533+
byte[] pk1 = publicKey.ExportCompositeMLDsaPublicKey();
534+
byte[] pk2 = privateKey.ExportCompositeMLDsaPublicKey();
535+
536+
if (!pk1.SequenceEqual(pk2))
537+
{
538+
throw new ArgumentException(SR.Cryptography_PrivateKey_DoesNotMatch, nameof(privateKey));
539+
}
540+
}
541+
475542
throw new PlatformNotSupportedException();
543+
#endif
476544
}
477545

478546
#if !NET10_0_OR_GREATER

src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ internal CompositeMLDsaAlgorithm() { }
646646
public static bool operator !=(System.Security.Cryptography.CompositeMLDsaAlgorithm? left, System.Security.Cryptography.CompositeMLDsaAlgorithm? right) { throw null; }
647647
public override string ToString() { throw null; }
648648
}
649-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
649+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
650650
public sealed partial class CompositeMLDsaCng : System.Security.Cryptography.CompositeMLDsa
651651
{
652652
[System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")]
@@ -3362,7 +3362,7 @@ namespace System.Security.Cryptography.X509Certificates
33623362
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
33633363
public sealed partial class CertificateRequest
33643364
{
3365-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
3365+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
33663366
public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.CompositeMLDsa key) { }
33673367
public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { }
33683368
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
@@ -3479,7 +3479,7 @@ public Pkcs12LoadLimitExceededException(string propertyName) { }
34793479
public sealed partial class PublicKey
34803480
{
34813481
public PublicKey(System.Security.Cryptography.AsymmetricAlgorithm key) { }
3482-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006")]
3482+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006")]
34833483
public PublicKey(System.Security.Cryptography.CompositeMLDsa key) { }
34843484
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006")]
34853485
public PublicKey(System.Security.Cryptography.MLDsa key) { }
@@ -3495,6 +3495,9 @@ public PublicKey(System.Security.Cryptography.SlhDsa key) { }
34953495
public System.Security.Cryptography.Oid Oid { get { throw null; } }
34963496
public static System.Security.Cryptography.X509Certificates.PublicKey CreateFromSubjectPublicKeyInfo(System.ReadOnlySpan<byte> source, out int bytesRead) { throw null; }
34973497
public byte[] ExportSubjectPublicKeyInfo() { throw null; }
3498+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
3499+
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
3500+
public System.Security.Cryptography.CompositeMLDsa? GetCompositeMLDsaPublicKey() { throw null; }
34983501
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
34993502
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
35003503
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
@@ -3822,7 +3825,7 @@ public X509Certificate2(string fileName, string? password, System.Security.Crypt
38223825
public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get { throw null; } }
38233826
public string Thumbprint { get { throw null; } }
38243827
public int Version { get { throw null; } }
3825-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
3828+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
38263829
public System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(System.Security.Cryptography.CompositeMLDsa privateKey) { throw null; }
38273830
public System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(System.Security.Cryptography.ECDiffieHellman privateKey) { throw null; }
38283831
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
@@ -4254,7 +4257,7 @@ public abstract partial class X509SignatureGenerator
42544257
protected X509SignatureGenerator() { }
42554258
public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } }
42564259
protected abstract System.Security.Cryptography.X509Certificates.PublicKey BuildPublicKey();
4257-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
4260+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
42584261
public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForCompositeMLDsa(System.Security.Cryptography.CompositeMLDsa key) { throw null; }
42594262
public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForECDsa(System.Security.Cryptography.ECDsa key) { throw null; }
42604263
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]

src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-browser;$(NetCoreAppCurrent)</TargetFrameworks>

src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificateRequest.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ public CertificateRequest(
309309
string subjectName,
310310
CompositeMLDsa key)
311311
{
312+
ArgumentNullException.ThrowIfNull(subjectName);
313+
ArgumentNullException.ThrowIfNull(key);
314+
312315
throw new PlatformNotSupportedException();
313316
}
314317

@@ -330,6 +333,9 @@ public CertificateRequest(
330333
X500DistinguishedName subjectName,
331334
CompositeMLDsa key)
332335
{
336+
ArgumentNullException.ThrowIfNull(subjectName);
337+
ArgumentNullException.ThrowIfNull(key);
338+
333339
throw new PlatformNotSupportedException();
334340
}
335341

src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/PublicKey.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ public PublicKey(SlhDsa key) : this(key.ExportSubjectPublicKeyInfo())
123123
[Experimental(Experimentals.PostQuantumCryptographyDiagId)]
124124
public PublicKey(CompositeMLDsa key) : this(key.ExportSubjectPublicKeyInfo())
125125
{
126-
throw new PlatformNotSupportedException();
127126
}
128127

129128
private PublicKey(byte[] subjectPublicKeyInfo)
@@ -412,6 +411,29 @@ public static PublicKey CreateFromSubjectPublicKeyInfo(ReadOnlySpan<byte> source
412411
? EncodeSubjectPublicKeyInfo().Encode(SlhDsa.ImportSubjectPublicKeyInfo)
413412
: null;
414413

414+
/// <summary>
415+
/// Gets the <see cref="CompositeMLDsa"/> public key, or <see langword="null" />
416+
/// if the key is not a Composite ML-DSA key.
417+
/// </summary>
418+
/// <returns>
419+
/// The public key, or <see langword="null"/> if the key is not a Composite ML-DSA key.
420+
/// </returns>
421+
/// <exception cref="PlatformNotSupportedException">
422+
/// The object represents a Composite ML-DSA public key, but the platform does not support the algorithm.
423+
/// </exception>
424+
/// <exception cref="CryptographicException">
425+
/// The key contents are corrupt or could not be read successfully.
426+
/// </exception>
427+
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
428+
[UnsupportedOSPlatform("browser")]
429+
public CompositeMLDsa? GetCompositeMLDsaPublicKey()
430+
{
431+
if (CompositeMLDsaAlgorithm.GetAlgorithmFromOid(_oid.Value) is null)
432+
return null;
433+
434+
return EncodeSubjectPublicKeyInfo().Encode(CompositeMLDsa.ImportSubjectPublicKeyInfo);
435+
}
436+
415437
internal AsnWriter EncodeSubjectPublicKeyInfo()
416438
{
417439
SubjectPublicKeyInfoAsn spki = new SubjectPublicKeyInfoAsn

src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2.cs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,13 @@ public X509Certificate2 CopyWithPrivateKey(SlhDsa privateKey)
11011101
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
11021102
public CompositeMLDsa? GetCompositeMLDsaPublicKey()
11031103
{
1104-
throw new PlatformNotSupportedException();
1104+
if (CompositeMLDsaAlgorithm.GetAlgorithmFromOid(GetKeyAlgorithm()) is null)
1105+
{
1106+
return null;
1107+
}
1108+
1109+
Debug.Assert(!OperatingSystem.IsBrowser());
1110+
return PublicKey.GetCompositeMLDsaPublicKey();
11051111
}
11061112

11071113
/// <summary>
@@ -1110,12 +1116,20 @@ public X509Certificate2 CopyWithPrivateKey(SlhDsa privateKey)
11101116
/// <returns>
11111117
/// The private key, or <see langword="null"/> if this certificate does not have a Composite ML-DSA private key.
11121118
/// </returns>
1119+
/// <exception cref="PlatformNotSupportedException">
1120+
/// Retrieving a Composite ML-DSA private key from a certificate is not supported on this platform.
1121+
/// </exception>
11131122
/// <exception cref="CryptographicException">
11141123
/// An error occurred accessing the private key.
11151124
/// </exception>
11161125
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
11171126
public CompositeMLDsa? GetCompositeMLDsaPrivateKey()
11181127
{
1128+
if (CompositeMLDsaAlgorithm.GetAlgorithmFromOid(GetKeyAlgorithm()) is null)
1129+
{
1130+
return null;
1131+
}
1132+
11191133
throw new PlatformNotSupportedException();
11201134
}
11211135

@@ -1139,9 +1153,38 @@ public X509Certificate2 CopyWithPrivateKey(SlhDsa privateKey)
11391153
/// <exception cref="InvalidOperationException">
11401154
/// The certificate already has an associated private key.
11411155
/// </exception>
1156+
/// <exception cref="PlatformNotSupportedException">
1157+
/// Combining a certificate and a Composite ML-DSA private key is not supported on this platform.
1158+
/// </exception>
11421159
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
11431160
public X509Certificate2 CopyWithPrivateKey(CompositeMLDsa privateKey)
11441161
{
1162+
ArgumentNullException.ThrowIfNull(privateKey);
1163+
1164+
if (HasPrivateKey)
1165+
throw new InvalidOperationException(SR.Cryptography_Cert_AlreadyHasPrivateKey);
1166+
1167+
using (CompositeMLDsa? publicKey = GetCompositeMLDsaPublicKey())
1168+
{
1169+
if (publicKey is null)
1170+
{
1171+
throw new ArgumentException(SR.Cryptography_PrivateKey_WrongAlgorithm);
1172+
}
1173+
1174+
if (publicKey.Algorithm != privateKey.Algorithm)
1175+
{
1176+
throw new ArgumentException(SR.Cryptography_PrivateKey_DoesNotMatch, nameof(privateKey));
1177+
}
1178+
1179+
byte[] pk1 = publicKey.ExportCompositeMLDsaPublicKey();
1180+
byte[] pk2 = privateKey.ExportCompositeMLDsaPublicKey();
1181+
1182+
if (!pk1.SequenceEqual(pk2))
1183+
{
1184+
throw new ArgumentException(SR.Cryptography_PrivateKey_DoesNotMatch, nameof(privateKey));
1185+
}
1186+
}
1187+
11451188
throw new PlatformNotSupportedException();
11461189
}
11471190

src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509SignatureGenerator.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public static X509SignatureGenerator CreateForSlhDsa(SlhDsa key)
9090
[Experimental(Experimentals.PostQuantumCryptographyDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
9191
public static X509SignatureGenerator CreateForCompositeMLDsa(CompositeMLDsa key)
9292
{
93+
ArgumentNullException.ThrowIfNull(key);
94+
9395
throw new PlatformNotSupportedException();
9496
}
9597
}

0 commit comments

Comments
 (0)