Skip to content

Commit

Permalink
Merge in 'release/7.0' changes
Browse files Browse the repository at this point in the history
  • Loading branch information
dotnet-bot committed Mar 19, 2024
2 parents e963835 + 0d59506 commit 544c7e6
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ internal static bool TrySecKeyCopyExternalRepresentation(
{
const int errSecPassphraseRequired = -25260;

// macOS Sonoma 14.4 started returning errSecInvalidKeyAttributeMask when a key could not be exported
// because it must be exported with a password.
const int errSecInvalidKeyAttributeMask = -67738;

int result = AppleCryptoNative_SecKeyCopyExternalRepresentation(
key,
out SafeCFDataHandle data,
Expand All @@ -141,7 +145,7 @@ internal static bool TrySecKeyCopyExternalRepresentation(
externalRepresentation = CoreFoundation.CFGetData(data);
return true;
case kErrorSeeError:
if (Interop.CoreFoundation.GetErrorCode(errorHandle) == errSecPassphraseRequired)
if (Interop.CoreFoundation.GetErrorCode(errorHandle) is errSecPassphraseRequired or errSecInvalidKeyAttributeMask)
{
externalRepresentation = Array.Empty<byte>();
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates.Tests.CertificateCreation;
using System.Threading;
using Microsoft.DotNet.XUnitExtensions;
using Test.Cryptography;
Expand All @@ -24,6 +25,108 @@ public CertTests(ITestOutputHelper output)
_log = output;
}

[Fact]
public static void PrivateKey_FromCertificate_CanExportPrivate_ECDsa()
{
using (ECDsa ca = ECDsa.Create(ECCurve.NamedCurves.nistP256))
{
CertificateRequest req = new("CN=potatos", ca, HashAlgorithmName.SHA256);

using (X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddDays(3)))
using (ECDsa certKey = cert.GetECDsaPrivateKey())
{
ECParameters certParameters = certKey.ExportParameters(true);
ECParameters originalParameters = ca.ExportParameters(true);
AssertExtensions.SequenceEqual(originalParameters.D, certParameters.D);
}
}
}

[Fact]
public static void PrivateKey_FromCertificate_CanExportPrivate_RSA()
{
using (RSA ca = RSA.Create(2048))
{
CertificateRequest req = new("CN=potatos", ca, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

using (X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddDays(3)))
using (RSA certKey = cert.GetRSAPrivateKey())
{
RSAParameters certParameters = certKey.ExportParameters(true);
RSAParameters originalParameters = ca.ExportParameters(true);
AssertExtensions.SequenceEqual(originalParameters.P, certParameters.P);
AssertExtensions.SequenceEqual(originalParameters.Q, certParameters.Q);
}
}
}

[Fact]
[SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "DSA is not available")]
public static void PrivateKey_FromCertificate_CanExportPrivate_DSA()
{
DSAParameters originalParameters = TestData.GetDSA1024Params();

using (DSA ca = DSA.Create())
{
ca.ImportParameters(originalParameters);
DSAX509SignatureGenerator gen = new DSAX509SignatureGenerator(ca);
X500DistinguishedName dn = new X500DistinguishedName("CN=potatos");

CertificateRequest req = new CertificateRequest(
dn,
gen.PublicKey,
HashAlgorithmName.SHA1);

using (X509Certificate2 cert = req.Create(dn, gen, DateTimeOffset.Now, DateTimeOffset.Now.AddDays(3), new byte[] { 1, 2, 3 }))
using (X509Certificate2 certWithKey = cert.CopyWithPrivateKey(ca))
using (DSA certKey = certWithKey.GetDSAPrivateKey())
{
DSAParameters certParameters = certKey.ExportParameters(true);
AssertExtensions.SequenceEqual(originalParameters.X, certParameters.X);
}
}
}

[Fact]
public static void PrivateKey_FromCertificate_CanExportPrivate_ECDiffieHellman()
{
using (ECDsa ca = ECDsa.Create(ECCurve.NamedCurves.nistP256))
using (ECDiffieHellman ecdh = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256))
{
CertificateRequest issuerRequest = new CertificateRequest(
new X500DistinguishedName("CN=root"),
ca,
HashAlgorithmName.SHA256);

issuerRequest.CertificateExtensions.Add(
new X509BasicConstraintsExtension(true, false, 0, true));

CertificateRequest request = new CertificateRequest(
new X500DistinguishedName("CN=potato"),
new PublicKey(ecdh),
HashAlgorithmName.SHA256);

request.CertificateExtensions.Add(
new X509BasicConstraintsExtension(false, false, 0, true));
request.CertificateExtensions.Add(
new X509KeyUsageExtension(X509KeyUsageFlags.KeyAgreement, true));

DateTimeOffset notBefore = DateTimeOffset.UtcNow;
DateTimeOffset notAfter = notBefore.AddDays(30);
byte[] serial = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

using (X509Certificate2 issuer = issuerRequest.CreateSelfSigned(notBefore, notAfter))
using (X509Certificate2 cert = request.Create(issuer, notBefore, notAfter, serial))
using (X509Certificate2 certWithKey = cert.CopyWithPrivateKey(ecdh))
using (ECDiffieHellman certKey = certWithKey.GetECDiffieHellmanPrivateKey())
{
ECParameters certParameters = certKey.ExportParameters(true);
ECParameters originalParameters = ecdh.ExportParameters(true);
AssertExtensions.SequenceEqual(originalParameters.D, certParameters.D);
}
}
}

[Fact]
public static void RaceUseAndDisposeDoesNotCrash()
{
Expand Down Expand Up @@ -79,7 +182,7 @@ public static void X509CertTest()
// GetSerialNumber() returns in little-endian order.
Array.Reverse(expectedSerial);
AssertExtensions.SequenceEqual(expectedSerial, serial1);

Assert.Equal("1.2.840.113549.1.1.1", cert.GetKeyAlgorithm());

int pklen = cert.GetPublicKey().Length;
Expand Down

0 comments on commit 544c7e6

Please sign in to comment.