Skip to content

Commit 544c7e6

Browse files
committed
Merge in 'release/7.0' changes
2 parents e963835 + 0d59506 commit 544c7e6

File tree

2 files changed

+109
-2
lines changed
  • src/libraries

2 files changed

+109
-2
lines changed

src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ internal static bool TrySecKeyCopyExternalRepresentation(
127127
{
128128
const int errSecPassphraseRequired = -25260;
129129

130+
// macOS Sonoma 14.4 started returning errSecInvalidKeyAttributeMask when a key could not be exported
131+
// because it must be exported with a password.
132+
const int errSecInvalidKeyAttributeMask = -67738;
133+
130134
int result = AppleCryptoNative_SecKeyCopyExternalRepresentation(
131135
key,
132136
out SafeCFDataHandle data,
@@ -141,7 +145,7 @@ internal static bool TrySecKeyCopyExternalRepresentation(
141145
externalRepresentation = CoreFoundation.CFGetData(data);
142146
return true;
143147
case kErrorSeeError:
144-
if (Interop.CoreFoundation.GetErrorCode(errorHandle) == errSecPassphraseRequired)
148+
if (Interop.CoreFoundation.GetErrorCode(errorHandle) is errSecPassphraseRequired or errSecInvalidKeyAttributeMask)
145149
{
146150
externalRepresentation = Array.Empty<byte>();
147151
return false;

src/libraries/System.Security.Cryptography.X509Certificates/tests/CertTests.cs

+104-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using System.IO;
66
using System.Runtime.InteropServices;
7+
using System.Security.Cryptography.X509Certificates.Tests.CertificateCreation;
78
using System.Threading;
89
using Microsoft.DotNet.XUnitExtensions;
910
using Test.Cryptography;
@@ -24,6 +25,108 @@ public CertTests(ITestOutputHelper output)
2425
_log = output;
2526
}
2627

28+
[Fact]
29+
public static void PrivateKey_FromCertificate_CanExportPrivate_ECDsa()
30+
{
31+
using (ECDsa ca = ECDsa.Create(ECCurve.NamedCurves.nistP256))
32+
{
33+
CertificateRequest req = new("CN=potatos", ca, HashAlgorithmName.SHA256);
34+
35+
using (X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddDays(3)))
36+
using (ECDsa certKey = cert.GetECDsaPrivateKey())
37+
{
38+
ECParameters certParameters = certKey.ExportParameters(true);
39+
ECParameters originalParameters = ca.ExportParameters(true);
40+
AssertExtensions.SequenceEqual(originalParameters.D, certParameters.D);
41+
}
42+
}
43+
}
44+
45+
[Fact]
46+
public static void PrivateKey_FromCertificate_CanExportPrivate_RSA()
47+
{
48+
using (RSA ca = RSA.Create(2048))
49+
{
50+
CertificateRequest req = new("CN=potatos", ca, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
51+
52+
using (X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddDays(3)))
53+
using (RSA certKey = cert.GetRSAPrivateKey())
54+
{
55+
RSAParameters certParameters = certKey.ExportParameters(true);
56+
RSAParameters originalParameters = ca.ExportParameters(true);
57+
AssertExtensions.SequenceEqual(originalParameters.P, certParameters.P);
58+
AssertExtensions.SequenceEqual(originalParameters.Q, certParameters.Q);
59+
}
60+
}
61+
}
62+
63+
[Fact]
64+
[SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")]
65+
public static void PrivateKey_FromCertificate_CanExportPrivate_DSA()
66+
{
67+
DSAParameters originalParameters = TestData.GetDSA1024Params();
68+
69+
using (DSA ca = DSA.Create())
70+
{
71+
ca.ImportParameters(originalParameters);
72+
DSAX509SignatureGenerator gen = new DSAX509SignatureGenerator(ca);
73+
X500DistinguishedName dn = new X500DistinguishedName("CN=potatos");
74+
75+
CertificateRequest req = new CertificateRequest(
76+
dn,
77+
gen.PublicKey,
78+
HashAlgorithmName.SHA1);
79+
80+
using (X509Certificate2 cert = req.Create(dn, gen, DateTimeOffset.Now, DateTimeOffset.Now.AddDays(3), new byte[] { 1, 2, 3 }))
81+
using (X509Certificate2 certWithKey = cert.CopyWithPrivateKey(ca))
82+
using (DSA certKey = certWithKey.GetDSAPrivateKey())
83+
{
84+
DSAParameters certParameters = certKey.ExportParameters(true);
85+
AssertExtensions.SequenceEqual(originalParameters.X, certParameters.X);
86+
}
87+
}
88+
}
89+
90+
[Fact]
91+
public static void PrivateKey_FromCertificate_CanExportPrivate_ECDiffieHellman()
92+
{
93+
using (ECDsa ca = ECDsa.Create(ECCurve.NamedCurves.nistP256))
94+
using (ECDiffieHellman ecdh = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256))
95+
{
96+
CertificateRequest issuerRequest = new CertificateRequest(
97+
new X500DistinguishedName("CN=root"),
98+
ca,
99+
HashAlgorithmName.SHA256);
100+
101+
issuerRequest.CertificateExtensions.Add(
102+
new X509BasicConstraintsExtension(true, false, 0, true));
103+
104+
CertificateRequest request = new CertificateRequest(
105+
new X500DistinguishedName("CN=potato"),
106+
new PublicKey(ecdh),
107+
HashAlgorithmName.SHA256);
108+
109+
request.CertificateExtensions.Add(
110+
new X509BasicConstraintsExtension(false, false, 0, true));
111+
request.CertificateExtensions.Add(
112+
new X509KeyUsageExtension(X509KeyUsageFlags.KeyAgreement, true));
113+
114+
DateTimeOffset notBefore = DateTimeOffset.UtcNow;
115+
DateTimeOffset notAfter = notBefore.AddDays(30);
116+
byte[] serial = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
117+
118+
using (X509Certificate2 issuer = issuerRequest.CreateSelfSigned(notBefore, notAfter))
119+
using (X509Certificate2 cert = request.Create(issuer, notBefore, notAfter, serial))
120+
using (X509Certificate2 certWithKey = cert.CopyWithPrivateKey(ecdh))
121+
using (ECDiffieHellman certKey = certWithKey.GetECDiffieHellmanPrivateKey())
122+
{
123+
ECParameters certParameters = certKey.ExportParameters(true);
124+
ECParameters originalParameters = ecdh.ExportParameters(true);
125+
AssertExtensions.SequenceEqual(originalParameters.D, certParameters.D);
126+
}
127+
}
128+
}
129+
27130
[Fact]
28131
public static void RaceUseAndDisposeDoesNotCrash()
29132
{
@@ -79,7 +182,7 @@ public static void X509CertTest()
79182
// GetSerialNumber() returns in little-endian order.
80183
Array.Reverse(expectedSerial);
81184
AssertExtensions.SequenceEqual(expectedSerial, serial1);
82-
185+
83186
Assert.Equal("1.2.840.113549.1.1.1", cert.GetKeyAlgorithm());
84187

85188
int pklen = cert.GetPublicKey().Length;

0 commit comments

Comments
 (0)