From e2d5e8c9a2b360959bef928852b31ccdb517bba0 Mon Sep 17 00:00:00 2001 From: Jeremy Barton Date: Wed, 21 Sep 2022 17:05:50 -0700 Subject: [PATCH] Cache dynamically generated RSA keys in tests Many of our tests want to use generated keys to avoid any notion that the test pass/fail is tied to using a specific key, but they very rarely care that they're using a completely fresh key. With this change, the tests that don't involve mutating key objects (via Import*, Dispose, or calling set_KeySize), and otherwise were generating a new key every time, will now share keys across tests. OuterLoop for S.S.Cryptography.Tests drops from generating 2,039 RSA keys across the various sizes to generating only about 43 (the specific number will depend on concurrency). (For an inner-loop test run it's 189 dropping to the same 43 or so.) The change also lays infrastructure to pool ECDSA/etc keys, and for commonly-imported key values into pooled objects. In addition to doing a bit less of a stress-test on the key generator routines, this should speed up the tests a bit. On Windows, it shaves a couple of seconds off of the outer loop run (~160s -> ~155s). At this time the specific-type tests (S.S.C.Cng.Tests, etc) are not using pooling. --- .../RSA/EncryptDecrypt.cs | 57 ++-- .../RSA/EncryptDecrypt.netcoreapp.cs | 20 +- .../RSA/ImportExport.cs | 20 +- .../RSA/RSAFactory.cs | 33 ++ .../RSA/RSAKeyExchangeFormatter.cs | 14 +- .../RSA/RSAKeyFileTests.cs | 12 +- .../RSA/RSASignatureFormatter.cs | 20 +- .../AlgorithmImplementations/RSA/RSAXml.cs | 11 +- .../RSA/SignVerify.cs | 58 ++-- .../RSA/SignVerify.netcoreapp.cs | 7 +- .../System/Security/Cryptography/KeyPool.cs | 99 ++++++ .../Cryptography/RSAKeyPool.KnownKeys.cs | 21 ++ .../Security/Cryptography/RSAKeyPool.cs | 288 ++++++++++++++++++ .../X509Certificates/CertificateAuthority.cs | 15 +- .../System.Net.Http.Functional.Tests.csproj | 4 + .../System.Net.Quic.Functional.Tests.csproj | 2 + .../System.Net.Security.Tests.csproj | 4 + ...tem.Security.Cryptography.Cng.Tests.csproj | 4 + ...tem.Security.Cryptography.Csp.Tests.csproj | 4 + ...Security.Cryptography.OpenSsl.Tests.csproj | 4 + .../tests/DefaultRSAProvider.cs | 10 + .../tests/RSAKeyExchangeFormatterTests.cs | 12 +- .../System.Security.Cryptography.Tests.csproj | 6 + .../CertificateRequestApiTests.cs | 36 +-- .../CertificateRequestChainTests.cs | 42 ++- .../CertificateRequestLoadTests.cs | 25 +- .../CertificateRequestUsageTests.cs | 84 ++--- .../CertificateCreation/CrlBuilderTests.cs | 22 +- .../RSAPkcs1X509SignatureGeneratorTests.cs | 32 +- .../RSAPssX509SignatureGeneratorTests.cs | 32 +- .../X509Certificates/DynamicChainTests.cs | 16 +- .../HostnameMatchTests.Unix.cs | 5 +- .../tests/X509Certificates/PfxFormatTests.cs | 19 +- .../RevocationTests/DynamicRevocationTests.cs | 42 +-- .../X509Certificates/TestDataGenerator.cs | 28 +- 35 files changed, 777 insertions(+), 331 deletions(-) create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/KeyPool.cs create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.KnownKeys.cs create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.cs diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs index e72d42e87d2174..1ade7598c5ac4a 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Security.Cryptography.Tests; using Test.Cryptography; using Microsoft.DotNet.XUnitExtensions; using Xunit; @@ -18,8 +19,9 @@ protected override byte[] Decrypt(RSA rsa, byte[] data, RSAEncryptionPadding pad [Fact] public void NullArray_Throws() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; AssertExtensions.Throws("data", () => rsa.Encrypt(null, RSAEncryptionPadding.OaepSHA1)); AssertExtensions.Throws("data", () => rsa.Decrypt(null, RSAEncryptionPadding.OaepSHA1)); } @@ -37,8 +39,9 @@ public abstract class EncryptDecrypt [Fact] public void NullPadding_Throws() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; AssertExtensions.Throws("padding", () => Encrypt(rsa, TestData.HelloBytes, null)); AssertExtensions.Throws("padding", () => Decrypt(rsa, TestData.HelloBytes, null)); } @@ -87,9 +90,8 @@ public void DecryptSavedAnswer() byte[] output; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA1024Params)) { - rsa.ImportParameters(TestData.RSA1024Params); output = Decrypt(rsa, cipherBytes, RSAEncryptionPadding.OaepSHA1); } @@ -150,10 +152,8 @@ public void DecryptSavedAnswer_OaepSHA256() byte[] output; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); - if (RSAFactory.SupportsSha2Oaep) { output = Decrypt(rsa, cipherBytes, RSAEncryptionPadding.OaepSHA256); @@ -211,10 +211,8 @@ public void DecryptSavedAnswer_OaepSHA384() byte[] output; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); - if (RSAFactory.SupportsSha2Oaep) { output = Decrypt(rsa, cipherBytes, RSAEncryptionPadding.OaepSHA384); @@ -246,10 +244,8 @@ public void DecryptSavedAnswer_OaepSHA512() byte[] output; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); - if (RSAFactory.SupportsSha2Oaep) { output = Decrypt(rsa, cipherBytes, RSAEncryptionPadding.OaepSHA512); @@ -291,9 +287,8 @@ public void DecryptSavedAnswerUnusualExponent() byte[] output; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.UnusualExponentParameters)) { - rsa.ImportParameters(TestData.UnusualExponentParameters); output = Decrypt(rsa, cipherBytes, RSAEncryptionPadding.OaepSHA1); } @@ -320,18 +315,18 @@ private void RsaCryptRoundtrip(RSAEncryptionPadding paddingMode, bool expectSucc byte[] crypt; byte[] output; - using (RSA rsa = RSAFactory.Create(2048)) + using (RSALease lease= RSAFactory.CreateIdempotent(2048)) { if (!expectSuccess) { Assert.ThrowsAny( - () => Encrypt(rsa, TestData.HelloBytes, paddingMode)); + () => Encrypt(lease.Key, TestData.HelloBytes, paddingMode)); return; } - crypt = Encrypt(rsa, TestData.HelloBytes, paddingMode); - output = Decrypt(rsa, crypt, paddingMode); + crypt = Encrypt(lease.Key, TestData.HelloBytes, paddingMode); + output = Decrypt(lease.Key, crypt, paddingMode); } Assert.NotEqual(crypt, output); @@ -617,13 +612,13 @@ public void RsaDecryptAfterExport() { byte[] output; - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { - byte[] crypt = Encrypt(rsa, TestData.HelloBytes, RSAEncryptionPadding.OaepSHA1); + byte[] crypt = Encrypt(lease.Key, TestData.HelloBytes, RSAEncryptionPadding.OaepSHA1); // Export the key, this should not clear/destroy the key. - rsa.ExportParameters(true); - output = Decrypt(rsa, crypt, RSAEncryptionPadding.OaepSHA1); + lease.Key.ExportParameters(true); + output = Decrypt(lease.Key, crypt, RSAEncryptionPadding.OaepSHA1); } Assert.Equal(TestData.HelloBytes, output); @@ -662,10 +657,8 @@ public void UnusualExponentCryptRoundtrip() byte[] crypt; byte[] output; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.UnusualExponentParameters)) { - rsa.ImportParameters(TestData.UnusualExponentParameters); - crypt = Encrypt(rsa, TestData.HelloBytes, RSAEncryptionPadding.OaepSHA1); output = Decrypt(rsa, crypt, RSAEncryptionPadding.OaepSHA1); } @@ -681,10 +674,10 @@ public void NonPowerOfTwoKeySizeOaepRoundtrip(RSAEncryptionPadding oaepPaddingMo byte[] crypt; byte[] output; - using (RSA rsa = RSAFactory.Create(3072)) + using (RSALease lease = RSAFactory.CreateIdempotent(3072)) { - crypt = Encrypt(rsa, TestData.HelloBytes, oaepPaddingMode); - output = Decrypt(rsa, crypt, oaepPaddingMode); + crypt = Encrypt(lease.Key, TestData.HelloBytes, oaepPaddingMode); + output = Decrypt(lease.Key, crypt, oaepPaddingMode); } Assert.NotEqual(crypt, output); @@ -694,10 +687,10 @@ public void NonPowerOfTwoKeySizeOaepRoundtrip(RSAEncryptionPadding oaepPaddingMo [Fact] public void NotSupportedValueMethods() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { - Assert.Throws(() => rsa.DecryptValue(null)); - Assert.Throws(() => rsa.EncryptValue(null)); + Assert.Throws(() => lease.Key.DecryptValue(null)); + Assert.Throws(() => lease.Key.EncryptValue(null)); } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs index 6c926659ae4fd6..c14a95dfe0ab10 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Linq; +using System.Security.Cryptography.Tests; using Xunit; namespace System.Security.Cryptography.Rsa.Tests @@ -71,9 +72,8 @@ private static byte[] TryWithOutputArray(Func func) [Fact] public void Decrypt_VariousSizeSpans_Success() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA1024Params)) { - rsa.ImportParameters(TestData.RSA1024Params); byte[] cipherBytes = Encrypt(rsa, TestData.HelloBytes, RSAEncryptionPadding.OaepSHA1); byte[] actual; int bytesWritten; @@ -103,9 +103,8 @@ public void Decrypt_VariousSizeSpans_Success() [Fact] public void Encrypt_VariousSizeSpans_Success() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA1024Params)) { - rsa.ImportParameters(TestData.RSA1024Params); byte[] cipherBytes = Encrypt(rsa, TestData.HelloBytes, RSAEncryptionPadding.OaepSHA1); byte[] actual; int bytesWritten; @@ -148,8 +147,9 @@ public void Decrypt_WrongKey_OAEP_SHA256() [Fact] public static void EncryptDefaultSpan() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; byte[] dest = new byte[rsa.KeySize / 8]; Assert.True( @@ -166,11 +166,11 @@ public static void EncryptDefaultSpan() private static void Decrypt_WrongKey(RSAEncryptionPadding padding) { - using (RSA rsa1 = RSAFactory.Create()) - using (RSA rsa2 = RSAFactory.Create()) + using (RSALease rsa1 = RSAFactory.CreateIdempotent()) + using (RSALease rsa2 = RSAFactory.CreateIdempotent()) { byte[] input = TestData.HelloBytes; - byte[] encrypted = rsa1.Encrypt(input, padding); + byte[] encrypted = rsa1.Key.Encrypt(input, padding); byte[] buf = new byte[encrypted.Length]; buf.AsSpan().Fill(0xCA); @@ -196,7 +196,7 @@ private static void Decrypt_WrongKey(RSAEncryptionPadding padding) // false should never be returned. // // But if the padding doesn't work out (109384 out of 109385, see above) we'll throw. - bool decrypted = rsa2.TryDecrypt(encrypted, buf, padding, out bytesWritten); + bool decrypted = rsa2.Key.TryDecrypt(encrypted, buf, padding, out bytesWritten); Assert.True(decrypted, "Pkcs1 TryDecrypt succeeded with a large buffer"); // If bytesWritten != input.Length, we got back gibberish, which is good. @@ -211,7 +211,7 @@ private static void Decrypt_WrongKey(RSAEncryptionPadding padding) // // For RSA-1024 (less freedom) it's 1 in 5.363e19, so like 1.6 trillion years. - if (rsa2.TryDecrypt(encrypted, buf, padding, out bytesWritten) + if (rsa2.Key.TryDecrypt(encrypted, buf, padding, out bytesWritten) && bytesWritten == input.Length) { // We'll get -here- 1 in 111014 runs (RSA-2048 Pkcs1). diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs index ee608a62a30750..c3a47e8b014123 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs @@ -58,9 +58,8 @@ public static void PaddedExport() RSAParameters diminishedDPParameters = TestData.DiminishedDPParameters; RSAParameters exported; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(diminishedDPParameters)) { - rsa.ImportParameters(diminishedDPParameters); exported = rsa.ExportParameters(true); } @@ -111,9 +110,8 @@ public static void UnusualExponentImportExport() RSAParameters unusualExponentParameters = TestData.UnusualExponentParameters; RSAParameters exported; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(unusualExponentParameters)) { - rsa.ImportParameters(unusualExponentParameters); exported = rsa.ExportParameters(true); } @@ -129,9 +127,8 @@ public static void ImportExport1032() RSAParameters exported; RSAParameters exportedPublic; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(imported)) { - rsa.ImportParameters(imported); exported = rsa.ExportParameters(true); exportedPublic = rsa.ExportParameters(false); } @@ -178,10 +175,8 @@ public static void ImportPrivateExportPublic() { RSAParameters imported = TestData.RSA1024Params; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(imported)) { - rsa.ImportParameters(imported); - RSAParameters exportedPublic = rsa.ExportParameters(false); Assert.Equal(imported.Modulus, exportedPublic.Modulus); @@ -196,10 +191,8 @@ public static void MultiExport() { RSAParameters imported = TestData.RSA1024Params; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(imported)) { - rsa.ImportParameters(imported); - RSAParameters exportedPrivate = rsa.ExportParameters(true); RSAParameters exportedPrivate2 = rsa.ExportParameters(true); RSAParameters exportedPublic = rsa.ExportParameters(false); @@ -231,9 +224,8 @@ public static void PublicOnlyPrivateExport() Exponent = TestData.RSA1024Params.Exponent, }; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(imported)) { - rsa.ImportParameters(imported); Assert.ThrowsAny(() => rsa.ExportParameters(true)); } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs index 9a4b27348ab4a0..3bc44bd6465aea 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Security.Cryptography.Tests; + namespace System.Security.Cryptography.Rsa.Tests { public interface IRSAProvider @@ -33,6 +35,37 @@ public static RSA Create(RSAParameters rsaParameters) return rsa; } + internal static RSALease CreateIdempotent() + { + RSALease? lease = null; + CreateIdempotent(ref lease); + + if (lease != null) + { + return lease.Value; + } + + RSA key = Create(); + return new RSALease(key, key); + } + + internal static RSALease CreateIdempotent(int keySize) + { + RSALease? lease = null; + CreateIdempotent(keySize, ref lease); + + if (lease != null) + { + return lease.Value; + } + + RSA key = Create(keySize); + return new RSALease(key, key); + } + + static partial void CreateIdempotent(ref RSALease? lease); + static partial void CreateIdempotent(int keySize, ref RSALease? lease); + public static bool Supports384PrivateKey => s_provider.Supports384PrivateKey; public static bool SupportsLargeExponent => s_provider.SupportsLargeExponent; diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs index 3e9071c25c8bea..d354f23d400df7 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs @@ -13,10 +13,8 @@ public partial class RSAKeyExchangeFormatterTests [Fact] public static void VerifyDecryptKeyExchangeOaep() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); - var formatter = new RSAOAEPKeyExchangeFormatter(rsa); var deformatter = new RSAOAEPKeyExchangeDeformatter(rsa); VerifyDecryptKeyExchange(formatter, deformatter); @@ -26,10 +24,8 @@ public static void VerifyDecryptKeyExchangeOaep() [Fact] public static void VerifyDecryptKeyExchangePkcs1() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); - var formatter = new RSAPKCS1KeyExchangeFormatter(rsa); var deformatter = new RSAPKCS1KeyExchangeDeformatter(rsa); VerifyDecryptKeyExchange(formatter, deformatter); @@ -39,9 +35,8 @@ public static void VerifyDecryptKeyExchangePkcs1() [Fact] public static void TestKnownValueOaep() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA1024Params)) { - rsa.ImportParameters(TestData.RSA1024Params); byte[] encrypted = ( "19134ffba4025a1c651120ca07258a46e005a327c3927f615465060734dc0339114cabfd13803288883abf9329296a3e3a5cb1587927" + "a6e8a2e736f0a756e342b4adb0f1de5bba9ba5faee30456fb7409678eb71a70185606eda3303d9425fbeb730ab7803bea50e208b563f" @@ -56,9 +51,8 @@ public static void TestKnownValueOaep() [Fact] public static void TestKnownValuePkcs1() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA1024Params)) { - rsa.ImportParameters(TestData.RSA1024Params); byte[] encrypted = ( "7061adb87a8759f0a0dc6ece42f5b63bf186f845237c6b16bf824b303812486efbb8f5febb681902228a609d4330a6c21abf0fc0d271" + "ba63d1d0d9e486668270c2dbf73ab33055dfc0b797938557b99c0e9a535605c0a4bceefe5a37594732bb566ab026e4e8d5ce47d0967d" diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs index daa175dda47a93..0ec0a9206a9478 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Security.Cryptography.Encryption.RC2.Tests; +using System.Security.Cryptography.Tests; using System.Text; using Test.Cryptography; using Xunit; @@ -1116,8 +1117,10 @@ public static void NoPrivKeyFromPublicOnly() [Fact] public static void BadPbeParameters() { - using (RSA key = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA key = lease.Key; + Assert.ThrowsAny( () => key.ExportEncryptedPkcs8PrivateKey( ReadOnlySpan.Empty, @@ -1238,12 +1241,13 @@ public static void BadPbeParameters() [Fact] public static void DecryptPkcs12WithBytes() { - using (RSA key = RSAFactory.Create()) + using (RSALease lease = RSAKeyPool.Rent()) + using (RSA testKey = RSAFactory.Create()) { string charBased = "hello"; byte[] byteBased = Encoding.UTF8.GetBytes(charBased); - byte[] encrypted = key.ExportEncryptedPkcs8PrivateKey( + byte[] encrypted = lease.Key.ExportEncryptedPkcs8PrivateKey( charBased, new PbeParameters( PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, @@ -1251,7 +1255,7 @@ public static void DecryptPkcs12WithBytes() 123)); Assert.ThrowsAny( - () => key.ImportEncryptedPkcs8PrivateKey(byteBased, encrypted, out _)); + () => testKey.ImportEncryptedPkcs8PrivateKey(byteBased, encrypted, out _)); } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs index c1ce8e1754b87a..5269afca0c3888 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs @@ -13,10 +13,8 @@ public partial class RSASignatureFormatterTests : AsymmetricSignatureFormatterTe [ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha1Signatures))] public static void VerifySignature_SHA1() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); - var formatter = new RSAPKCS1SignatureFormatter(rsa); var deformatter = new RSAPKCS1SignatureDeformatter(rsa); @@ -31,10 +29,8 @@ public static void VerifySignature_SHA1() [Fact] public static void VerifySignature_SHA256() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); - var formatter = new RSAPKCS1SignatureFormatter(rsa); var deformatter = new RSAPKCS1SignatureDeformatter(rsa); @@ -49,10 +45,10 @@ public static void VerifySignature_SHA256() [Fact] public static void InvalidHashAlgorithm() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { - var formatter = new RSAPKCS1SignatureFormatter(rsa); - var deformatter = new RSAPKCS1SignatureDeformatter(rsa); + var formatter = new RSAPKCS1SignatureFormatter(lease.Key); + var deformatter = new RSAPKCS1SignatureDeformatter(lease.Key); // Exception is deferred until VerifySignature formatter.SetHashAlgorithm("INVALIDVALUE"); @@ -72,9 +68,8 @@ public static void VerifyKnownSignature() byte[] hash = "012d161304fa0c6321221516415813022320620c".HexToByteArray(); byte[] sig; - using (RSA key = RSAFactory.Create()) + using (RSA key = RSAFactory.Create(TestData.RSA1024Params)) { - key.ImportParameters(TestData.RSA1024Params); RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key); formatter.SetHashAlgorithm("SHA1"); sig = formatter.CreateSignature(hash); @@ -86,9 +81,8 @@ public static void VerifyKnownSignature() Assert.Equal(expectedSig, sig); } - using (RSA key = RSAFactory.Create()) // Test against a different instance + using (RSA key = RSAFactory.Create(TestData.RSA1024Params)) // Test against a different instance { - key.ImportParameters(TestData.RSA1024Params); RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key); deformatter.SetHashAlgorithm("SHA1"); bool verified = deformatter.VerifySignature(hash, sig); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs index 666f9bea3c4095..7aa9209153a9db 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Security.Cryptography.Tests; using System.Xml.Linq; using Xunit; @@ -984,13 +985,13 @@ public static void TestWriteUnusualExponentParameters(bool includePrivateParamet [Fact] public static void FromToXml() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { - RSAParameters pubOnly = rsa.ExportParameters(false); - RSAParameters pubPriv = rsa.ExportParameters(true); + RSAParameters pubOnly = lease.Key.ExportParameters(false); + RSAParameters pubPriv = lease.Key.ExportParameters(true); - string xmlPub = rsa.ToXmlString(false); - string xmlPriv = rsa.ToXmlString(true); + string xmlPub = lease.Key.ToXmlString(false); + string xmlPriv = lease.Key.ToXmlString(true); using (RSA rsaPub = RSAFactory.Create()) { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs index 0bbdd7db7372da..e2a6c41a3e42fe 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.Security.Cryptography.Tests; using Microsoft.DotNet.XUnitExtensions; using Test.Cryptography; using Test.IO.Streams; @@ -25,8 +26,9 @@ protected override bool VerifyHash(RSA rsa, byte[] hash, byte[] signature, HashA [Fact] public void NullArray_Throws() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; AssertExtensions.Throws("data", () => SignData(rsa, null, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); AssertExtensions.Throws("hash", () => SignHash(rsa, null, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); @@ -52,8 +54,9 @@ public abstract class SignVerify [Fact] public void InvalidHashAlgorithmName_Throws() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; var invalidName = new HashAlgorithmName(null); AssertExtensions.Throws("hashAlgorithm", () => SignData(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); AssertExtensions.Throws("hashAlgorithm", () => SignHash(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); @@ -71,8 +74,9 @@ public void InvalidHashAlgorithmName_Throws() [Fact] public void NullPadding_Throws() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; AssertExtensions.Throws("padding", () => SignData(rsa, new byte[1], HashAlgorithmName.SHA256, null)); AssertExtensions.Throws("padding", () => SignHash(rsa, new byte[1], HashAlgorithmName.SHA256, null)); AssertExtensions.Throws("padding", () => VerifyData(rsa, new byte[1], new byte[1], HashAlgorithmName.SHA256, null)); @@ -128,10 +132,10 @@ public void InvalidKeySize_DoesNotInvalidateKey() [Fact] public void PublicKey_CannotSign() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) using (RSA rsaPub = RSAFactory.Create()) { - rsaPub.ImportParameters(rsa.ExportParameters(false)); + rsaPub.ImportParameters(lease.Key.ExportParameters(false)); Assert.ThrowsAny( () => rsaPub.SignData(TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); @@ -141,10 +145,10 @@ public void PublicKey_CannotSign() [Fact] public void SignEmptyHash() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { Assert.ThrowsAny( - () => SignHash(rsa, Array.Empty(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); + () => SignHash(lease.Key, Array.Empty(), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); } } @@ -342,9 +346,8 @@ public void ExpectSignature_SHA256_1024_Stream() byte[] signature; using (Stream stream = new PositionValueStream(10)) - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA1024Params)) { - rsa.ImportParameters(TestData.RSA1024Params); signature = rsa.SignData(stream, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); } @@ -534,9 +537,8 @@ public static IEnumerable RoundTripTheories [Fact] public void NegativeVerify_WrongAlgorithm() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA384, RSASignaturePadding.Pkcs1); @@ -547,9 +549,8 @@ public void NegativeVerify_WrongAlgorithm() [Fact] public void NegativeVerify_WrongSignature() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); // Invalidate the signature. @@ -563,9 +564,8 @@ public void NegativeVerify_WrongSignature() [Fact] public void NegativeVerify_TamperedData() { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); byte[] signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); bool signatureMatched = VerifyData(rsa, Array.Empty(), signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); Assert.False(signatureMatched); @@ -577,15 +577,13 @@ public void NegativeVerify_BadKeysize() { byte[] signature; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { - rsa.ImportParameters(TestData.RSA2048Params); signature = SignData(rsa, TestData.HelloBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); } - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(TestData.RSA1024Params)) { - rsa.ImportParameters(TestData.RSA1024Params); bool signatureMatched = VerifyData(rsa, TestData.HelloBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); Assert.False(signatureMatched); @@ -897,12 +895,9 @@ public void PssRoundtrip(string hashAlgorithmName) Exponent = privateParameters.Exponent, }; - using (RSA privateKey = RSAFactory.Create()) - using (RSA publicKey = RSAFactory.Create()) + using (RSA privateKey = RSAFactory.Create(privateParameters)) + using (RSA publicKey = RSAFactory.Create(publicParameters)) { - privateKey.ImportParameters(privateParameters); - publicKey.ImportParameters(publicParameters); - byte[] data = TestData.RsaBigExponentParams.Modulus; HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); RSASignaturePadding padding = RSASignaturePadding.Pss; @@ -1228,9 +1223,8 @@ private void ExpectSignature( // the signature is deterministic, so we can safely verify it here. byte[] signature; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(rsaParameters)) { - rsa.ImportParameters(rsaParameters); signature = SignData(rsa, data, new HashAlgorithmName(hashAlgorithmName), RSASignaturePadding.Pkcs1); } @@ -1249,9 +1243,8 @@ private void ExpectHashSignature( // the signature is deterministic, so we can safely verify it here. byte[] signature; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(rsaParameters)) { - rsa.ImportParameters(rsaParameters); signature = SignHash(rsa, dataHash, new HashAlgorithmName(hashAlgorithmName), RSASignaturePadding.Pkcs1); } @@ -1272,9 +1265,8 @@ private void VerifySignature( bool signatureMatched; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(publicOnly)) { - rsa.ImportParameters(publicOnly); signatureMatched = VerifyData(rsa, data, signature, new HashAlgorithmName(hashAlgorithmName), RSASignaturePadding.Pkcs1); } @@ -1295,9 +1287,8 @@ private void VerifyHashSignature( bool signatureMatched; - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(publicOnly)) { - rsa.ImportParameters(publicOnly); signatureMatched = VerifyHash(rsa, dataHash, signature, new HashAlgorithmName(hashAlgorithmName), RSASignaturePadding.Pkcs1); } @@ -1306,9 +1297,8 @@ private void VerifyHashSignature( private void SignAndVerify(byte[] data, string hashAlgorithmName, RSAParameters rsaParameters) { - using (RSA rsa = RSAFactory.Create()) + using (RSA rsa = RSAFactory.Create(rsaParameters)) { - rsa.ImportParameters(rsaParameters); byte[] signature = SignData(rsa, data, new HashAlgorithmName(hashAlgorithmName), RSASignaturePadding.Pkcs1); bool signatureMatched = VerifyData(rsa, data, signature, new HashAlgorithmName(hashAlgorithmName), RSASignaturePadding.Pkcs1); Assert.True(signatureMatched); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.netcoreapp.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.netcoreapp.cs index 10ce40b962f8a4..3aeb50ef6849e8 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.netcoreapp.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.netcoreapp.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Security.Cryptography.Tests; using Xunit; namespace System.Security.Cryptography.Rsa.Tests @@ -85,8 +86,9 @@ private static byte[] TryWithOutputArray(Func func) [Fact] public static void SignDefaultSpanHash() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; byte[] signature = new byte[2048 / 8]; Assert.ThrowsAny( @@ -100,8 +102,9 @@ public static void SignDefaultSpanHash() [Fact] public static void VerifyDefaultSpanHash() { - using (RSA rsa = RSAFactory.Create()) + using (RSALease lease = RSAFactory.CreateIdempotent()) { + RSA rsa = lease.Key; byte[] signature = new byte[2048 / 8]; Assert.False( diff --git a/src/libraries/Common/tests/System/Security/Cryptography/KeyPool.cs b/src/libraries/Common/tests/System/Security/Cryptography/KeyPool.cs new file mode 100644 index 00000000000000..df05a38def0739 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/KeyPool.cs @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace System.Security.Cryptography.Tests +{ + internal class KeyPool where TKey : AsymmetricAlgorithm + { + private readonly List<(TDiscriminator Discriminator, ConcurrentStack Pool)> _pools = new(); + private readonly IEqualityComparer _comparer; + + internal KeyPool(IEqualityComparer? comparer = null) + { + _comparer = comparer ?? EqualityComparer.Default; + } + + private ConcurrentStack GetPool(TDiscriminator discriminator) + { + static ConcurrentStack? FindPool( + KeyPool pool, + TDiscriminator discriminator) + { + foreach ((TDiscriminator id, ConcurrentStack value) in pool._pools) + { + if (pool._comparer.Equals(discriminator, id)) + { + return value; + } + } + + return null; + } + + ConcurrentStack? pool = FindPool(this, discriminator); + + if (pool is null) + { + lock (_pools) + { + pool = FindPool(this, discriminator); + + if (pool is null) + { + pool = new ConcurrentStack(); + + _pools.Add((discriminator, pool)); + } + } + } + + return pool; + } + + internal KeyPoolLease Rent( + TDiscriminator discriminator, + Func creator) + { + ConcurrentStack pool = GetPool(discriminator); + + if (!pool.TryPop(out TKey rented)) + { + rented = creator(discriminator); + } + + return new KeyPoolLease(rented, discriminator, this); + } + + private void Return(TKey key, TDiscriminator discriminator) + { + GetPool(discriminator).Push(key); + } + + internal class KeyPoolLease : IDisposable + { + private readonly KeyPool _pool; + private readonly TDiscriminator _discriminator; + + internal TKey Key { get; private set; } + + internal KeyPoolLease( + TKey key, + TDiscriminator discriminator, + KeyPool pool) + { + Key = key; + _discriminator = discriminator; + _pool = pool; + } + + public void Dispose() + { + _pool.Return(Key, _discriminator); + Key = null!; + } + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.KnownKeys.cs b/src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.KnownKeys.cs new file mode 100644 index 00000000000000..cacbda94031d25 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.KnownKeys.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Security.Cryptography.Rsa.Tests; + +namespace System.Security.Cryptography.Tests +{ + internal static partial class RSAKeyPool + { + // Known keys can use the same pool as the generated keys, + // but have to avoid legal key sizes. + // + // Thankfully, the smallest size any provider has is 384, + // so 0-383 are automatically available. + internal static RSALease RentBigExponentKey() + { + return ShapeLease( + s_pool.Rent(0, ks => new IdempotentRSA(TestData.RsaBigExponentParams))); + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.cs b/src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.cs new file mode 100644 index 00000000000000..4cab82c0c2e428 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/RSAKeyPool.cs @@ -0,0 +1,288 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; + +namespace System.Security.Cryptography.Tests +{ + internal struct RSALease : IDisposable + { + private readonly IDisposable _lease; + public RSA Key { get; private set; } + + internal RSALease(RSA key, IDisposable lease) + { + _lease = lease; + Key = key; + } + + public void Dispose() + { + Key = null!; + _lease.Dispose(); + } + } + + internal static partial class RSAKeyPool + { + private static readonly KeyPool s_pool = new KeyPool(); + + public static RSALease Rent(int keySize = 2048) + { + // If a test is behaving oddly, pooling can be disabled (forcing every + // potentially-new-key to be an actually-new-key) by defining NO_RENTING. +#if NO_RENTING + RSA rsa = RSA.Create(keySize); + return new RSALease(rsa, rsa); +#else + return ShapeLease(s_pool.Rent(keySize, ks => new IdempotentRSA(ks))); +#endif + } + + private static RSALease ShapeLease(KeyPool.KeyPoolLease lease) + { + return new RSALease(lease.Key, lease); + } + + // An RSA wrapper type that does not support having the key replaced or disposed. + private sealed class IdempotentRSA : RSA + { + private readonly RSA _impl; + + internal IdempotentRSA(int keySize) + { + _impl = Create(keySize); + _impl.TryExportRSAPublicKey(Span.Empty, out _); + } + + public IdempotentRSA(RSAParameters rsaParameters) + { + _impl = Create(rsaParameters); + } + + public override void FromXmlString(string xmlString) => throw new NotSupportedException(); + public override void ImportParameters(RSAParameters parameters) => throw new NotSupportedException(); + protected override void Dispose(bool disposing) => throw new NotSupportedException(); + + public override string? KeyExchangeAlgorithm => _impl.KeyExchangeAlgorithm; + + public override string SignatureAlgorithm => _impl.SignatureAlgorithm; + + public override byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) => _impl.Decrypt(data, padding); + + public override byte[] DecryptValue(byte[] rgb) => _impl.DecryptValue(rgb); + + public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) => _impl.Encrypt(data, padding); + + public override byte[] EncryptValue(byte[] rgb) => _impl.EncryptValue(rgb); + + public override RSAParameters ExportParameters(bool includePrivateParameters) => + _impl.ExportParameters(includePrivateParameters); + + public override byte[] ExportRSAPrivateKey() => _impl.ExportRSAPrivateKey(); + + public override byte[] ExportRSAPublicKey() => _impl.ExportRSAPublicKey(); + + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) + { + switch (hashAlgorithm.Name) + { + case nameof(HashAlgorithmName.SHA256): + return SHA256.HashData(data.AsSpan(offset, count)); + } + + throw new NotSupportedException(hashAlgorithm.Name); + } + + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) + { + switch (hashAlgorithm.Name) + { + case nameof(HashAlgorithmName.SHA256): + return SHA256.HashData(data); + } + + throw new NotSupportedException(hashAlgorithm.Name); + } + + protected override bool TryHashData( + ReadOnlySpan data, + Span destination, + HashAlgorithmName hashAlgorithm, + out int bytesWritten) + { + switch (hashAlgorithm.Name) + { + case nameof(HashAlgorithmName.SHA256): + return SHA256.TryHashData(data, destination, out bytesWritten); + } + + throw new NotSupportedException(hashAlgorithm.Name); + } + + public override byte[] SignData( + byte[] data, + int offset, + int count, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _impl.SignData( + data, + offset, + count, + hashAlgorithm, + padding); + + public override byte[] SignData( + Stream data, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _impl.SignData( + data, + hashAlgorithm, + padding); + + public override byte[] SignHash( + byte[] hash, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _impl.SignHash( + hash, + hashAlgorithm, + padding); + + public override string ToXmlString(bool includePrivateParameters) => + _impl.ToXmlString(includePrivateParameters); + + public override bool TryDecrypt( + ReadOnlySpan data, + Span destination, + RSAEncryptionPadding padding, + out int bytesWritten) => + _impl.TryDecrypt( + data, + destination, + padding, + out bytesWritten); + + public override bool TryEncrypt( + ReadOnlySpan data, + Span destination, + RSAEncryptionPadding padding, + out int bytesWritten) => + _impl.TryEncrypt( + data, + destination, + padding, + out bytesWritten); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _impl.TryExportEncryptedPkcs8PrivateKey(passwordBytes, pbeParameters, destination, out bytesWritten); + + public override bool TryExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters, + Span destination, + out int bytesWritten) => + _impl.TryExportEncryptedPkcs8PrivateKey(password, pbeParameters, destination, out bytesWritten); + + public override bool TryExportPkcs8PrivateKey(Span destination, out int bytesWritten) => + _impl.TryExportPkcs8PrivateKey(destination, out bytesWritten); + + public override bool TryExportRSAPrivateKey(Span destination, out int bytesWritten) => + _impl.TryExportRSAPrivateKey(destination, out bytesWritten); + + public override bool TryExportRSAPublicKey(Span destination, out int bytesWritten) => + _impl.TryExportRSAPublicKey(destination, out bytesWritten); + + public override bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => + _impl.TryExportSubjectPublicKeyInfo(destination, out bytesWritten); + + public override bool TrySignData( + ReadOnlySpan data, + Span destination, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding, + out int bytesWritten) => + _impl.TrySignData(data, destination, hashAlgorithm, padding, out bytesWritten); + + public override bool TrySignHash( + ReadOnlySpan hash, + Span destination, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding, + out int bytesWritten) => + _impl.TrySignHash(hash, destination, hashAlgorithm, padding, out bytesWritten); + + public override bool VerifyData( + byte[] data, + int offset, + int count, + byte[] signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _impl.VerifyData(data, offset, count, signature, hashAlgorithm, padding); + + public override bool VerifyData( + ReadOnlySpan data, + ReadOnlySpan signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _impl.VerifyData(data, signature, hashAlgorithm, padding); + + public override bool VerifyHash( + byte[] hash, + byte[] signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _impl.VerifyHash( + hash, + signature, + hashAlgorithm, + padding); + + public override bool VerifyHash( + ReadOnlySpan hash, + ReadOnlySpan signature, + HashAlgorithmName hashAlgorithm, + RSASignaturePadding padding) => + _impl.VerifyHash(hash, signature, hashAlgorithm, padding); + + public override int KeySize + { + get => _impl.KeySize; + set => throw new NotSupportedException(); + } + + public override KeySizes[] LegalKeySizes => _impl.LegalKeySizes; + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + PbeParameters pbeParameters) => + _impl.ExportEncryptedPkcs8PrivateKey( + passwordBytes, + pbeParameters); + + public override byte[] ExportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + PbeParameters pbeParameters) => + _impl.ExportEncryptedPkcs8PrivateKey( + password, + pbeParameters); + + public override byte[] ExportPkcs8PrivateKey() => _impl.ExportPkcs8PrivateKey(); + + public override byte[] ExportSubjectPublicKeyInfo() => _impl.ExportSubjectPublicKeyInfo(); + + public override bool Equals(object? obj) => _impl.Equals(obj); + + public override int GetHashCode() => _impl.GetHashCode(); + + public override string ToString() => _impl.ToString(); + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs index e85100aeb71e28..dd83640e9a1e95 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/CertificateAuthority.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Formats.Asn1; using System.Linq; +using System.Security.Cryptography.Tests; using Xunit; namespace System.Security.Cryptography.X509Certificates.Tests.Common @@ -814,12 +815,13 @@ internal static void BuildPrivatePki( // default to client extensions ??= new X509ExtensionCollection() { s_eeConstraints, s_eeKeyUsage, s_tlsClientEku }; - using (RSA rootKey = RSA.Create(keySize)) - using (RSA eeKey = RSA.Create(keySize)) + using (RSALease rootLease = RSAKeyPool.Rent(keySize)) + using (RSALease imed0Lease = RSAKeyPool.Rent(keySize)) + using (RSALease eeLease = RSAKeyPool.Rent(keySize)) { var rootReq = new CertificateRequest( BuildSubject("A Revocation Test Root", testName, pkiOptions, pkiOptionsInSubject), - rootKey, + rootLease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -853,7 +855,8 @@ internal static void BuildPrivatePki( for (int intermediateIndex = 0; intermediateIndex < intermediateAuthorityCount; intermediateIndex++) { - using RSA intermediateKey = RSA.Create(keySize); + using RSA createdKey = intermediateIndex > 0 ? RSA.Create(keySize) : null; + RSA intermediateKey = createdKey ?? imed0Lease.Key; // Don't dispose this, it's being transferred to the CertificateAuthority X509Certificate2 intermedCert; @@ -885,11 +888,11 @@ internal static void BuildPrivatePki( endEntityCert = issuingAuthority.CreateEndEntity( BuildSubject(subjectName ?? "A Revocation Test Cert", testName, pkiOptions, pkiOptionsInSubject), - eeKey, + eeLease.Key, extensions); X509Certificate2 tmp = endEntityCert; - endEntityCert = endEntityCert.CopyWithPrivateKey(eeKey); + endEntityCert = endEntityCert.CopyWithPrivateKey(eeLease.Key); tmp.Dispose(); } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index 2a66de7311480a..d98633c05716e2 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -74,8 +74,12 @@ Link="Common\System\IO\DelegatingStream.cs" /> + + + + diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index e00fd263ac15e6..aeff03f2c88b4d 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -81,8 +81,12 @@ Link="Common\System\Net\VerboseTestLogging.cs" /> + + + + + + + + + + + ( null, @@ -150,30 +149,27 @@ public static void CtorValidation_ECDSA_X500DN() public static void CtorValidation_RSA_string() { string subjectName = null; - RSA key = null; RSASignaturePadding padding = null; AssertExtensions.Throws( "subjectName", - () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); + () => new CertificateRequest(subjectName, null, default(HashAlgorithmName), padding)); subjectName = ""; AssertExtensions.Throws( "key", - () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); - - key = RSA.Create(TestData.RsaBigExponentParams); + () => new CertificateRequest(subjectName, null, default(HashAlgorithmName), padding)); - using (key) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); + () => new CertificateRequest(subjectName, lease.Key, default(HashAlgorithmName), padding)); AssertExtensions.Throws( "padding", - () => new CertificateRequest(subjectName, key, HashAlgorithmName.SHA256, padding)); + () => new CertificateRequest(subjectName, lease.Key, HashAlgorithmName.SHA256, padding)); } } @@ -181,34 +177,32 @@ public static void CtorValidation_RSA_string() public static void CtorValidation_RSA_X500DN() { X500DistinguishedName subjectName = null; - RSA key = null; + const RSA NullKey = null; RSASignaturePadding padding = null; AssertExtensions.Throws( "subjectName", - () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); + () => new CertificateRequest(subjectName, NullKey, default(HashAlgorithmName), padding)); subjectName = new X500DistinguishedName(""); AssertExtensions.Throws( "key", - () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); + () => new CertificateRequest(subjectName, NullKey, default(HashAlgorithmName), padding)); - key = RSA.Create(TestData.RsaBigExponentParams); - - using (key) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, key, default(HashAlgorithmName), padding)); + () => new CertificateRequest(subjectName, lease.Key, default(HashAlgorithmName), padding)); AssertExtensions.Throws( "hashAlgorithm", - () => new CertificateRequest(subjectName, key, new HashAlgorithmName(""), padding)); + () => new CertificateRequest(subjectName, lease.Key, new HashAlgorithmName(""), padding)); AssertExtensions.Throws( "padding", - () => new CertificateRequest(subjectName, key, HashAlgorithmName.SHA256, padding)); + () => new CertificateRequest(subjectName, lease.Key, HashAlgorithmName.SHA256, padding)); } } diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestChainTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestChainTests.cs index 0c4fd0c8cf9bd1..61f1e7c5b7bcbd 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestChainTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestChainTests.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Linq; -using Test.Cryptography; +using System.Security.Cryptography.Tests; using Xunit; namespace System.Security.Cryptography.X509Certificates.Tests.CertificateCreation @@ -32,18 +32,16 @@ public static void CreateChain_ECC() [Fact] public static void CreateChain_RSA() { - using (RSA rootKey = RSA.Create(3072)) - using (RSA intermed1Key = RSA.Create(2048)) - using (RSA intermed2Key = RSA.Create(2048)) - using (RSA leafKey = RSA.Create(1536)) - using (RSA leafPubKey = RSA.Create(leafKey.ExportParameters(false))) + using (RSALease rootKey = RSAKeyPool.Rent(3072)) + using (RSALease intermed1Key = RSAKeyPool.Rent(2048)) + using (RSALease intermed2Key = RSAKeyPool.Rent(2048)) + using (RSALease leafKey = RSAKeyPool.Rent(1536)) + using (RSA leafPubKey = RSA.Create(leafKey.Key.ExportParameters(false))) { - leafPubKey.ImportParameters(leafKey.ExportParameters(false)); - CreateAndTestChain( - rootKey, - intermed1Key, - intermed2Key, + rootKey.Key, + intermed1Key.Key, + intermed2Key.Key, leafPubKey); } } @@ -52,15 +50,15 @@ public static void CreateChain_RSA() public static void CreateChain_Hybrid() { using (ECDsa rootKey = ECDsa.Create(ECCurve.NamedCurves.nistP521)) - using (RSA intermed1Key = RSA.Create(2048)) - using (RSA intermed2Key = RSA.Create(2048)) + using (RSALease intermed1Key = RSAKeyPool.Rent(2048)) + using (RSALease intermed2Key = RSAKeyPool.Rent(2048)) using (ECDiffieHellman leafKey = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256)) using (ECDiffieHellman leafPubKey = ECDiffieHellman.Create(leafKey.ExportParameters(false))) { CreateAndTestChain( rootKey, - intermed1Key, - intermed2Key, + intermed1Key.Key, + intermed2Key.Key, leafPubKey); } } @@ -464,9 +462,9 @@ private static void CreateAndTestChain( [ConditionalFact(nameof(PlatformSupportsPss))] public static void CreateChain_RSAPSS() { - using (RSA rootKey = RSA.Create()) - using (RSA intermedKey = RSA.Create()) - using (RSA leafKey = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease rootKey = RSAKeyPool.Rent()) + using (RSALease intermedKey = RSAKeyPool.Rent()) + using (RSALease leafKey = RSAKeyPool.RentBigExponentKey()) { X509Certificate2 rootCertWithKey = null; X509Certificate2 intermedCertWithKey = null; @@ -480,7 +478,7 @@ public static void CreateChain_RSAPSS() try { - request = new CertificateRequest("CN=Root", rootKey, HashAlgorithmName.SHA512, padding); + request = new CertificateRequest("CN=Root", rootKey.Key, HashAlgorithmName.SHA512, padding); request.CertificateExtensions.Add( new X509BasicConstraintsExtension(true, false, 0, true)); @@ -488,15 +486,15 @@ public static void CreateChain_RSAPSS() byte[] intermedSerial = { 1, 2, 3, 5, 7, 11, 13 }; - request = new CertificateRequest("CN=Intermediate", intermedKey, HashAlgorithmName.SHA384, padding); + request = new CertificateRequest("CN=Intermediate", intermedKey.Key, HashAlgorithmName.SHA384, padding); request.CertificateExtensions.Add( new X509BasicConstraintsExtension(true, true, 1, true)); X509Certificate2 intermedPublic = request.Create(rootCertWithKey, notBefore, notAfter, intermedSerial); - intermedCertWithKey = intermedPublic.CopyWithPrivateKey(intermedKey); + intermedCertWithKey = intermedPublic.CopyWithPrivateKey(intermedKey.Key); intermedPublic.Dispose(); - request = new CertificateRequest("CN=Leaf", leafKey, HashAlgorithmName.SHA256, padding); + request = new CertificateRequest("CN=Leaf", leafKey.Key, HashAlgorithmName.SHA256, padding); request.CertificateExtensions.Add( new X509BasicConstraintsExtension(false, false, 0, true)); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestLoadTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestLoadTests.cs index 70738ac65c763b..fcfc160dc3b13e 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestLoadTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestLoadTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Net; +using System.Security.Cryptography.Tests; using Test.Cryptography; using Xunit; @@ -329,11 +330,11 @@ public static void VerifySignature_RSA_PKCS1(string hashAlgorithm) { HashAlgorithmName hashAlgorithmName = new HashAlgorithmName(hashAlgorithm); - using (RSA key = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest first = new CertificateRequest( "CN=Test", - key, + lease.Key, hashAlgorithmName, RSASignaturePadding.Pkcs1); @@ -341,7 +342,7 @@ public static void VerifySignature_RSA_PKCS1(string hashAlgorithm) if (hashAlgorithm == "SHA1") { - pkcs10 = first.CreateSigningRequest(new RSASha1Pkcs1SignatureGenerator(key)); + pkcs10 = first.CreateSigningRequest(new RSASha1Pkcs1SignatureGenerator(lease.Key)); } else { @@ -374,11 +375,11 @@ public static void VerifySignature_RSA_PSS(string hashAlgorithm) { HashAlgorithmName hashAlgorithmName = new HashAlgorithmName(hashAlgorithm); - using (RSA key = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest first = new CertificateRequest( "CN=Test", - key, + lease.Key, hashAlgorithmName, RSASignaturePadding.Pss); @@ -386,7 +387,7 @@ public static void VerifySignature_RSA_PSS(string hashAlgorithm) if (hashAlgorithm == "SHA1") { - pkcs10 = first.CreateSigningRequest(new RSASha1PssSignatureGenerator(key)); + pkcs10 = first.CreateSigningRequest(new RSASha1PssSignatureGenerator(lease.Key)); } else { @@ -449,11 +450,11 @@ public static void LoadAndSignRequest_NoRSAPadding() DateTimeOffset notBefore = now.AddMonths(-1); DateTimeOffset notAfter = now.AddMonths(1); - using (RSA rootKey = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease rootKey = RSAKeyPool.RentBigExponentKey()) { CertificateRequest rootReq = new CertificateRequest( "CN=Root", - rootKey, + rootKey.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -475,7 +476,7 @@ public static void LoadAndSignRequest_NoRSAPadding() Assert.Contains(nameof(X509SignatureGenerator), ex.Message); X509SignatureGenerator gen = - X509SignatureGenerator.CreateForRSA(rootKey, RSASignaturePadding.Pkcs1); + X509SignatureGenerator.CreateForRSA(rootKey.Key, RSASignaturePadding.Pkcs1); X509Certificate2 issued = req.Create( rootCert.SubjectName, @@ -500,11 +501,11 @@ public static void LoadAndSignRequest_WithRSAPadding() DateTimeOffset notBefore = now.AddMonths(-1); DateTimeOffset notAfter = now.AddMonths(1); - using (RSA rootKey = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease rootKey = RSAKeyPool.RentBigExponentKey()) { CertificateRequest rootReq = new CertificateRequest( "CN=Root", - rootKey, + rootKey.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -534,7 +535,7 @@ public static void LoadAndSignRequest_WithRSAPadding() // Using a generator overrides the decision X509SignatureGenerator gen = - X509SignatureGenerator.CreateForRSA(rootKey, RSASignaturePadding.Pss); + X509SignatureGenerator.CreateForRSA(rootKey.Key, RSASignaturePadding.Pss); issued = req.Create( rootCert.SubjectName, diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs index 9eb846a2ccb90b..e331ed51f60fbc 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CertificateRequestUsageTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; +using System.Security.Cryptography.Tests; using Test.Cryptography; using Xunit; @@ -23,13 +24,11 @@ public static void ReproduceBigExponentCsr() string csrPem; string autoCsrPem; - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - rsa.ImportParameters(TestData.RsaBigExponentParams); - CertificateRequest request = new CertificateRequest( "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US", - rsa, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -38,7 +37,7 @@ public static void ReproduceBigExponentCsr() autoCsr = request.CreateSigningRequest(); autoCsrPem = request.CreateSigningRequestPem(); - X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); csr = request.CreateSigningRequest(generator); csrPem = request.CreateSigningRequestPem(generator); } @@ -72,16 +71,14 @@ public static void ReproduceBigExponentCert() X509Certificate2 cert; - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - rsa.ImportParameters(TestData.RsaBigExponentParams); - - var request = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + var request = new CertificateRequest(subject, lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add(skidExtension); request.CertificateExtensions.Add(akidExtension); request.CertificateExtensions.Add(basicConstraints); - var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + var signatureGenerator = X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); cert = request.Create(subject, signatureGenerator, notBefore, notAfter, serialNumber); } @@ -131,10 +128,10 @@ public static void ReproduceBigExponentCert() [InlineData(true)] public static void SimpleSelfSign_RSA(bool exportPfx) { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { SimpleSelfSign( - new CertificateRequest("CN=localhost", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), + new CertificateRequest("CN=localhost", lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), "1.2.840.113549.1.1.1", exportPfx); } @@ -200,13 +197,13 @@ public static void SelfSign_RSA_UseCertKeys() RSA priv2; - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { - pubParams = rsa.ExportParameters(false); + pubParams = lease.Key.ExportParameters(false); CertificateRequest request = new CertificateRequest( "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US", - rsa, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -216,15 +213,13 @@ public static void SelfSign_RSA_UseCertKeys() using (cert) using (priv2 = cert.GetRSAPrivateKey()) - using (RSA pub = RSA.Create()) + using (RSA pub = RSA.Create(pubParams)) { Assert.True(cert.HasPrivateKey, "cert.HasPrivateKey"); Assert.NotNull(priv2); byte[] sig = priv2.SignData(pubParams.Modulus, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1); - pub.ImportParameters(pubParams); - Assert.True( pub.VerifyData(pubParams.Modulus, sig, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1), "Cert signature validates with public key"); @@ -393,11 +388,11 @@ public static void AlwaysVersion3() [Fact] public static void UniqueExtensions() { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest request = new CertificateRequest( "CN=Double Extension Test", - rsa, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -418,9 +413,9 @@ public static void CheckTimeNested() { HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA256; - using (RSA rsa = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - CertificateRequest request = new CertificateRequest("CN=Issuer", rsa, hashAlgorithm, RSASignaturePadding.Pkcs1); + var request = new CertificateRequest("CN=Issuer", lease.Key, hashAlgorithm, RSASignaturePadding.Pkcs1); request.CertificateExtensions.Add( new X509BasicConstraintsExtension(true, false, 0, true)); @@ -437,7 +432,7 @@ public static void CheckTimeNested() using (X509Certificate2 issuer = request.CreateSelfSigned(notBefore, notAfter)) { - request = new CertificateRequest("CN=Leaf", rsa, hashAlgorithm, RSASignaturePadding.Pkcs1); + request = new CertificateRequest("CN=Leaf", lease.Key, hashAlgorithm, RSASignaturePadding.Pkcs1); byte[] serial = { 3, 1, 4, 1, 5, 9 }; // Boundary case, exact match: Issue+Dispose @@ -714,7 +709,7 @@ public static void ECDSA_Signing_UnknownPublicKeyAlgorithm() [Fact] public static void ECDSA_Signing_RSA() { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) using (ECDsa ecdsa = ECDsa.Create()) { var request = new CertificateRequest( @@ -730,18 +725,19 @@ public static void ECDSA_Signing_RSA() using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) { X509SignatureGenerator generator = - X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); request = new CertificateRequest( new X500DistinguishedName("CN=Leaf"), - rsa, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 }; - AssertExtensions.Throws("issuerCertificate", () => request.Create(cert, now, now.AddHours(3), serialNumber)); - + AssertExtensions.Throws( + "issuerCertificate", + () => request.Create(cert, now, now.AddHours(3), serialNumber)); // Passes with the generator using (request.Create(cert.SubjectName, generator, now, now.AddHours(3), serialNumber)) @@ -754,7 +750,7 @@ public static void ECDSA_Signing_RSA() [Fact] public static void ECDSA_Signing_RSAPublicKey() { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) using (ECDsa ecdsa = ECDsa.Create()) { var request = new CertificateRequest( @@ -770,7 +766,7 @@ public static void ECDSA_Signing_RSAPublicKey() using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) { X509SignatureGenerator rsaGenerator = - X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); request = new CertificateRequest( new X500DistinguishedName("CN=Leaf"), @@ -779,7 +775,9 @@ public static void ECDSA_Signing_RSAPublicKey() byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 }; - AssertExtensions.Throws("issuerCertificate", () => request.Create(cert, now, now.AddHours(3), serialNumber)); + AssertExtensions.Throws( + "issuerCertificate", + () => request.Create(cert, now, now.AddHours(3), serialNumber)); X509SignatureGenerator ecdsaGenerator = X509SignatureGenerator.CreateForECDsa(ecdsa); @@ -795,12 +793,12 @@ public static void ECDSA_Signing_RSAPublicKey() [Fact] public static void RSA_Signing_ECDSA() { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) using (ECDsa ecdsa = ECDsa.Create()) { var request = new CertificateRequest( new X500DistinguishedName("CN=Test"), - rsa, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -818,10 +816,12 @@ public static void RSA_Signing_ECDSA() byte[] serialNumber = { 1, 1, 2, 3, 5, 8, 13 }; - AssertExtensions.Throws("issuerCertificate", () => request.Create(cert, now, now.AddHours(3), serialNumber)); + AssertExtensions.Throws( + "issuerCertificate", + () => request.Create(cert, now, now.AddHours(3), serialNumber)); X509SignatureGenerator generator = - X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); // Passes with the generator using (request.Create(cert.SubjectName, generator, now, now.AddHours(3), serialNumber)) @@ -834,11 +834,11 @@ public static void RSA_Signing_ECDSA() [Fact] public static void RSACertificateNoPaddingMode() { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { var request = new CertificateRequest( new X500DistinguishedName("CN=Test"), - rsa, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -860,7 +860,7 @@ public static void RSACertificateNoPaddingMode() () => request.Create(cert, now, now.AddHours(3), serialNumber)); X509SignatureGenerator generator = - X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); // Passes with the generator using (request.Create(cert.SubjectName, generator, now, now.AddHours(3), serialNumber)) @@ -986,7 +986,7 @@ public static void CreateSigningRequestWithAttributes(bool reversed) string builtPem; - using (RSA key = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { X500DistinguishedNameBuilder nameBuilder = new(); nameBuilder.AddOrganizationName("Internet Widgits Pty Ltd"); @@ -995,7 +995,7 @@ public static void CreateSigningRequestWithAttributes(bool reversed) CertificateRequest req = new CertificateRequest( nameBuilder.Build(), - key, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -1056,11 +1056,11 @@ public static void CreateSigningRequestWithDuplicateAttributes(bool reversed) string output; - using (RSA key = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { CertificateRequest req = new CertificateRequest( "CN=localhost, OU=.NET Framework (CoreFX), O=Microsoft Corporation, L=Redmond, S=Washington, C=US", - key, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CrlBuilderTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CrlBuilderTests.cs index 563502efbda656..4e41ef132aa4df 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CrlBuilderTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/CrlBuilderTests.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; +using System.Security.Cryptography.Tests; using Test.Cryptography; using Xunit; @@ -273,9 +274,10 @@ public static void BuildWithGeneratorNullAkid() DateTimeOffset now = DateTimeOffset.UtcNow; X500DistinguishedName dn = new X500DistinguishedName("CN=Name"); - using (RSA rsa = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - X509SignatureGenerator gen = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator gen = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); Assert.Throws( "authorityKeyIdentifier", @@ -286,11 +288,11 @@ public static void BuildWithGeneratorNullAkid() [Fact] public static void BuildWithRSACertificateAndNoPadding() { - using (RSA key = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { CertificateRequest req = new CertificateRequest( "CN=RSA Test", - key, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -1332,7 +1334,7 @@ public static void LoadAndResignPublicCrl() +w== -----END X509 CRL-----"; - using (RSA rsa = RSA.Create(4096)) + using (RSALease lease = RSAKeyPool.Rent(4096)) { X500DistinguishedName parentDn = new X500DistinguishedName("CN=Parent"); X500DistinguishedName dn = new X500DistinguishedName( @@ -1340,7 +1342,7 @@ public static void LoadAndResignPublicCrl() CertificateRequest req = new CertificateRequest( dn, - rsa, + lease.Key, HashAlgorithmName.SHA384, RSASignaturePadding.Pkcs1); @@ -1354,12 +1356,12 @@ public static void LoadAndResignPublicCrl() X509Certificate2 pubCert = req.Create( parentDn, - X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1), + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1), thisUpdate.AddMinutes(-1), nextUpdate.AddDays(3), new byte[] { 0x01, 0x02, 0x03, 0x05 }); - using (X509Certificate2 cert = pubCert.CopyWithPrivateKey(rsa)) + using (X509Certificate2 cert = pubCert.CopyWithPrivateKey(lease.Key)) { pubCert.Dispose(); @@ -1467,11 +1469,11 @@ private static void BuildRsaCertificateAndRun( bool addSubjectKeyIdentifier = true, [CallerMemberName] string callerName = null) { - using (RSA key = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { CertificateRequest req = new CertificateRequest( $"CN=\"{callerName}\"", - key, + lease.Key, HashAlgorithmName.SHA384, RSASignaturePadding.Pkcs1); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.cs index 0ded7c8c85950c..b431f66bfd3e7f 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Security.Cryptography.Tests; using Test.Cryptography; using Xunit; @@ -20,11 +21,10 @@ public static void RsaPkcsSignatureGeneratorCtor_Exceptions() [Fact] public static void PublicKeyEncoding() { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - rsa.ImportParameters(TestData.RsaBigExponentParams); - - X509SignatureGenerator signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); PublicKey publicKey = signatureGenerator.PublicKey; // Irrespective of what the current key thinks, the PublicKey value we encode for RSA will always write @@ -62,12 +62,10 @@ public static void PublicKeyEncoding() [InlineData("SHA512")] public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - RSAParameters parameters = TestData.RsaBigExponentParams; - rsa.ImportParameters(parameters); - - var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); @@ -85,12 +83,10 @@ public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) [InlineData("Potato")] public static void SignatureAlgorithm_NotSupported(string hashAlgorithmName) { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - RSAParameters parameters = TestData.RsaBigExponentParams; - rsa.ImportParameters(parameters); - - var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); @@ -131,13 +127,11 @@ public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) string expectedHex = $"30{(expectedOid.Length / 2 + 2):X2}{expectedOid}0500"; - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - RSAParameters parameters = TestData.RsaBigExponentParams; - rsa.ImportParameters(parameters); - HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); - X509SignatureGenerator signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pkcs1); byte[] sigAlg = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); Assert.Equal(expectedHex, sigAlg.ByteArrayToHex()); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs index ef89a1da872d41..b17d56469a9f4f 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Security.Cryptography.Tests; using Test.Cryptography; using Xunit; @@ -20,11 +21,10 @@ public static void RsaPssSignatureGeneratorCtor_Exceptions() [Fact] public static void PublicKeyEncoding() { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - rsa.ImportParameters(TestData.RsaBigExponentParams); - - X509SignatureGenerator signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pss); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pss); PublicKey publicKey = signatureGenerator.PublicKey; // Irrespective of what the current key thinks, the PublicKey value we encode for RSA will always write @@ -62,12 +62,10 @@ public static void PublicKeyEncoding() [InlineData("SHA512")] public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - RSAParameters parameters = TestData.RsaBigExponentParams; - rsa.ImportParameters(parameters); - - var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pss); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pss); HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); @@ -85,12 +83,10 @@ public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) [InlineData("Potato")] public static void SignatureAlgorithm_NotSupported(string hashAlgorithmName) { - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - RSAParameters parameters = TestData.RsaBigExponentParams; - rsa.ImportParameters(parameters); - - var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pss); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pss); HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); @@ -161,13 +157,11 @@ public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) // INTEGER (saltLength == size of hash) "0201" + saltLenByte.ToString("X2"); - using (RSA rsa = RSA.Create()) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { - RSAParameters parameters = TestData.RsaBigExponentParams; - rsa.ImportParameters(parameters); - HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); - var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pss); + X509SignatureGenerator signatureGenerator = + X509SignatureGenerator.CreateForRSA(lease.Key, RSASignaturePadding.Pss); byte[] sigAlg = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); Assert.Equal(expectedHex, sigAlg.ByteArrayToHex()); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/DynamicChainTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/DynamicChainTests.cs index 207cac9ee971e4..4ebcc7dcbf47be 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/DynamicChainTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/DynamicChainTests.cs @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; +using System.Security.Cryptography.Tests; using Test.Cryptography; using Xunit; @@ -326,11 +326,11 @@ public static void BasicConstraints_ViolatesCaFalse() [Fact] public static void TestLeafCertificateWithUnknownCriticalExtension() { - using (RSA key = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest certReq = new CertificateRequest( new X500DistinguishedName("CN=Cert"), - key, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -373,11 +373,11 @@ public static void TestLeafCertificateWithUnknownCriticalExtension() [SkipOnPlatform(TestPlatforms.Android, "Android does not support AIA fetching")] public static void TestInvalidAia() { - using (RSA key = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest rootReq = new CertificateRequest( "CN=Root", - key, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -385,7 +385,7 @@ public static void TestInvalidAia() CertificateRequest certReq = new CertificateRequest( "CN=test", - key, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -422,11 +422,11 @@ public static void VerifyNumericStringSubject() X500DistinguishedName dn = new X500DistinguishedName( "30283117301506052901020203120C313233203635342037383930310D300B0603550403130454657374".HexToByteArray()); - using (RSA key = RSA.Create()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest req = new CertificateRequest( dn, - key, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/HostnameMatchTests.Unix.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/HostnameMatchTests.Unix.cs index fc0a0f66ba0627..dfe01f04e68b81 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/HostnameMatchTests.Unix.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/HostnameMatchTests.Unix.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Security.Cryptography.Tests; using System.Text; using Test.Cryptography; using Xunit; @@ -81,11 +82,11 @@ private static void RunTest( bool flattenCase, bool expectedResult) { - using (RSA rsa = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { CertificateRequest request = new CertificateRequest( $"CN={FixCase(subjectCN, flattenCase)}, O=.NET Framework (CoreFX)", - rsa, + lease.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/PfxFormatTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/PfxFormatTests.cs index c73af1ac3173a7..616253cbab65ea 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/PfxFormatTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/PfxFormatTests.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Security.Cryptography.Pkcs; +using System.Security.Cryptography.Tests; using Test.Cryptography; using Xunit; @@ -248,11 +249,11 @@ public void OneCert_MismatchedKey() // Build the PFX in the normal Windows style, except the private key doesn't match. using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags)) using (RSA realKey = cert.GetRSAPrivateKey()) - using (RSA key = RSA.Create(realKey.KeySize)) + using (RSALease unrelated= RSAKeyPool.Rent(realKey.KeySize)) { Pkcs12Builder builder = new Pkcs12Builder(); Pkcs12SafeContents keyContents = new Pkcs12SafeContents(); - Pkcs12SafeBag keyBag = keyContents.AddShroudedKey(key, pw, s_windowsPbe); + Pkcs12SafeBag keyBag = keyContents.AddShroudedKey(unrelated.Key, pw, s_windowsPbe); Pkcs12SafeContents certContents = new Pkcs12SafeContents(); Pkcs12SafeBag certBag = certContents.AddCertificate(cert); @@ -297,7 +298,7 @@ public void OneCert_TwoKeys_FirstWins(bool correctKeyFirst) // Build the PFX in the normal Windows style, except the private key doesn't match. using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags)) using (RSA key = cert.GetRSAPrivateKey()) - using (RSA unrelated = RSA.Create(key.KeySize)) + using (RSALease unrelated = RSAKeyPool.Rent(key.KeySize)) { Pkcs12Builder builder = new Pkcs12Builder(); Pkcs12SafeContents keyContents = new Pkcs12SafeContents(); @@ -309,11 +310,11 @@ public void OneCert_TwoKeys_FirstWins(bool correctKeyFirst) if (correctKeyFirst) { keyBag = keyContents.AddShroudedKey(key, pw, s_windowsPbe); - keyBag2 = keyContents.AddShroudedKey(unrelated, pw, s_windowsPbe); + keyBag2 = keyContents.AddShroudedKey(unrelated.Key, pw, s_windowsPbe); } else { - keyBag = keyContents.AddShroudedKey(unrelated, pw, s_windowsPbe); + keyBag = keyContents.AddShroudedKey(unrelated.Key, pw, s_windowsPbe); keyBag2 = keyContents.AddShroudedKey(key, pw, s_windowsPbe); } @@ -539,7 +540,7 @@ public void OneCert_TwentyKeys_NoMatches() string pw = nameof(OneCert_NoKey_WithLocalKeyId); using (var cert = new X509Certificate2(TestData.MsCertificate)) - using (RSA rsa = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { Pkcs12Builder builder = new Pkcs12Builder(); Pkcs12SafeContents certContents = new Pkcs12SafeContents(); @@ -548,7 +549,7 @@ public void OneCert_TwentyKeys_NoMatches() Pkcs12CertBag certBag = certContents.AddCertificate(cert); certBag.Attributes.Add(s_keyIdOne); - byte[] keyExport = rsa.ExportEncryptedPkcs8PrivateKey(pw, s_windowsPbe); + byte[] keyExport = lease.Key.ExportEncryptedPkcs8PrivateKey(pw, s_windowsPbe); for (int i = 0; i < 20; i++) { @@ -580,7 +581,7 @@ public void TwoCerts_TwentyKeys_NoMatches(bool msCertFirst) using (var certWithKey = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword)) using (var cert = new X509Certificate2(certWithKey.RawData)) using (var cert2 = new X509Certificate2(TestData.MsCertificate)) - using (RSA rsa = RSA.Create(TestData.RsaBigExponentParams)) + using (RSALease lease = RSAKeyPool.RentBigExponentKey()) { Pkcs12Builder builder = new Pkcs12Builder(); Pkcs12SafeContents certContents = new Pkcs12SafeContents(); @@ -602,7 +603,7 @@ public void TwoCerts_TwentyKeys_NoMatches(bool msCertFirst) certBag.Attributes.Add(s_keyIdOne); } - byte[] keyExport = rsa.ExportEncryptedPkcs8PrivateKey(pw, s_windowsPbe); + byte[] keyExport = lease.Key.ExportEncryptedPkcs8PrivateKey(pw, s_windowsPbe); for (int i = 0; i < 20; i++) { diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/RevocationTests/DynamicRevocationTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/RevocationTests/DynamicRevocationTests.cs index 56440ded4ed6c7..8300b3d53b9a2a 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/RevocationTests/DynamicRevocationTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/RevocationTests/DynamicRevocationTests.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; +using System.Security.Cryptography.Tests; using System.Security.Cryptography.X509Certificates.Tests.Common; using Test.Cryptography; using Xunit; @@ -377,8 +377,8 @@ public static void RevokeEndEntity_IssuerUnrelatedOcsp(PkiOptions pkiOptions) { DateTimeOffset now = DateTimeOffset.UtcNow; - using (RSA tmpRoot = RSA.Create()) - using (RSA rsa = RSA.Create()) + using (RSALease tmpRoot = RSAKeyPool.Rent()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest rootReq = new CertificateRequest( BuildSubject( @@ -386,7 +386,7 @@ public static void RevokeEndEntity_IssuerUnrelatedOcsp(PkiOptions pkiOptions) nameof(RevokeEndEntity_IssuerUnrelatedOcsp), pkiOptions, true), - tmpRoot, + tmpRoot.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -411,11 +411,11 @@ public static void RevokeEndEntity_IssuerUnrelatedOcsp(PkiOptions pkiOptions) nameof(RevokeEndEntity_IssuerUnrelatedOcsp), pkiOptions, true), - rsa); + lease.Key); using (designatedSigner) { - intermediate.DesignateOcspResponder(designatedSigner.CopyWithPrivateKey(rsa)); + intermediate.DesignateOcspResponder(designatedSigner.CopyWithPrivateKey(lease.Key)); } } } @@ -462,8 +462,8 @@ public static void RevokeEndEntity_RootUnrelatedOcsp(PkiOptions pkiOptions) { DateTimeOffset now = DateTimeOffset.UtcNow; - using (RSA tmpRoot = RSA.Create()) - using (RSA rsa = RSA.Create()) + using (RSALease tmpRoot = RSAKeyPool.Rent()) + using (RSALease lease = RSAKeyPool.Rent()) { CertificateRequest rootReq = new CertificateRequest( BuildSubject( @@ -471,7 +471,7 @@ public static void RevokeEndEntity_RootUnrelatedOcsp(PkiOptions pkiOptions) nameof(RevokeEndEntity_IssuerUnrelatedOcsp), pkiOptions, true), - tmpRoot, + tmpRoot.Key, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); @@ -496,11 +496,11 @@ public static void RevokeEndEntity_RootUnrelatedOcsp(PkiOptions pkiOptions) nameof(RevokeEndEntity_IssuerUnrelatedOcsp), pkiOptions, true), - rsa); + lease.Key); using (designatedSigner) { - root.DesignateOcspResponder(designatedSigner.CopyWithPrivateKey(rsa)); + root.DesignateOcspResponder(designatedSigner.CopyWithPrivateKey(lease.Key)); } } } @@ -1505,28 +1505,36 @@ private static void SimpleTest( using (X509Certificate2 rootCert = root.CloneIssuerCert()) using (X509Certificate2 intermediateCert = intermediate.CloneIssuerCert()) { + RSALease? rootOcspLease = null; + RSALease? issuerOcspLease = null; + if (pkiOptions.HasFlag(PkiOptions.RootAuthorityHasDesignatedOcspResponder)) { - using (RSA tmpKey = RSA.Create()) + rootOcspLease = RSAKeyPool.Rent(); + using (X509Certificate2 tmp = root.CreateOcspSigner( BuildSubject("A Root Designated OCSP Responder", callerName, pkiOptions, true), - tmpKey)) + rootOcspLease.Value.Key)) { - root.DesignateOcspResponder(tmp.CopyWithPrivateKey(tmpKey)); + root.DesignateOcspResponder(tmp.CopyWithPrivateKey(rootOcspLease.Value.Key)); } } if (pkiOptions.HasFlag(PkiOptions.IssuerAuthorityHasDesignatedOcspResponder)) { - using (RSA tmpKey = RSA.Create()) + issuerOcspLease = RSAKeyPool.Rent(); + using (X509Certificate2 tmp = intermediate.CreateOcspSigner( BuildSubject("An Intermediate Designated OCSP Responder", callerName, pkiOptions, true), - tmpKey)) + issuerOcspLease.Value.Key)) { - intermediate.DesignateOcspResponder(tmp.CopyWithPrivateKey(tmpKey)); + intermediate.DesignateOcspResponder(tmp.CopyWithPrivateKey(issuerOcspLease.Value.Key)); } } + issuerOcspLease?.Dispose(); + rootOcspLease?.Dispose(); + RetryHelper.Execute(() => { using (ChainHolder holder = new ChainHolder()) { diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestDataGenerator.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestDataGenerator.cs index 0e729c7661b088..60281ac19a460c 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestDataGenerator.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestDataGenerator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Security.Cryptography.Tests; namespace System.Security.Cryptography.X509Certificates.Tests { @@ -17,15 +18,15 @@ internal static void MakeTestChain3( IEnumerable rootExtensions = null, [CallerMemberName] string testName = null) { - using (RSA rootKey = RSA.Create()) - using (RSA intermediateKey = RSA.Create()) - using (RSA endEntityKey = RSA.Create()) + using (RSALease rootKey = RSAKeyPool.Rent()) + using (RSALease intermediateKey = RSAKeyPool.Rent()) + using (RSALease endEntityKey = RSAKeyPool.Rent()) { ReadOnlySpan keys = new[] { - rootKey, - intermediateKey, - endEntityKey, + rootKey.Key, + intermediateKey.Key, + endEntityKey.Key, }; Span certs = new X509Certificate2[keys.Length]; @@ -54,16 +55,16 @@ internal static void MakeTestChain4( IEnumerable rootExtensions = null, [CallerMemberName] string testName = null) { - using (RSA rootKey = RSA.Create()) - using (RSA intermediateKey = RSA.Create()) - using (RSA endEntityKey = RSA.Create()) + using (RSALease rootKey = RSAKeyPool.Rent()) + using (RSALease intermediateKey = RSAKeyPool.Rent()) + using (RSALease endEntityKey = RSAKeyPool.Rent()) { ReadOnlySpan keys = new[] { - rootKey, - intermediateKey, - intermediateKey, - endEntityKey, + rootKey.Key, + intermediateKey.Key, + intermediateKey.Key, + endEntityKey.Key, }; Span certs = new X509Certificate2[keys.Length]; @@ -126,7 +127,6 @@ internal static void MakeTestChain( TimeSpan notAfterInterval = TimeSpan.FromDays(90); DateTimeOffset eeStart = DateTimeOffset.UtcNow.AddDays(-7); DateTimeOffset eeEnd = eeStart.AddDays(45); - byte[] serialBuf = new byte[16]; int rootIndex = keys.Length - 1;