From 64f5c48e1741a3cbf06d34ac45e7c20817eb1ad3 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Thu, 12 Jan 2023 11:07:59 -0500 Subject: [PATCH 1/4] Add tests for exercising certificate with platform provider keys. --- .../tests/X509Certificates/CertTests.cs | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs index ed0db080a5cf65..3196406f191fc1 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs @@ -571,6 +571,86 @@ public static void SignatureAlgorithmOidReadableForGostCertificate() } } + [ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))] + [OuterLoop("Hardware backed key generation takes several seconds.")] + public static void MicrosoftPlatformCryptoProvider_EcdsaKey() + { + CngKey key = null; + + try + { + CngKeyCreationParameters cngCreationParameters = new CngKeyCreationParameters + { + Provider = CngProvider.MicrosoftPlatformCryptoProvider, + KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, + }; + + key = CngKey.Create( + CngAlgorithm.ECDsaP384, + nameof(MicrosoftPlatformCryptoProvider_EcdsaKey), + cngCreationParameters); + + using (ECDsaCng ecdsa = new ECDsaCng(key)) + { + CertificateRequest req = new CertificateRequest("CN=potato", ecdsa, HashAlgorithmName.SHA256); + + using (X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow)) + using (ECDsa certKey = cert.GetECDsaPrivateKey()) + { + Assert.NotNull(certKey); + byte[] data = new byte[] { 12, 11, 02, 08, 25, 14, 11, 18, 16 }; + byte[] signature = certKey.SignData(data, HashAlgorithmName.SHA256); + bool valid = ecdsa.VerifyData(data, signature, HashAlgorithmName.SHA256); + Assert.True(valid, "valid signature"); + } + } + } + finally + { + key?.Delete(); + } + } + + [ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))] + [OuterLoop("Hardware backed key generation takes several seconds.")] + public static void MicrosoftPlatformCryptoProvider_RsaKey() + { + CngKey key = null; + + try + { + CngKeyCreationParameters cngCreationParameters = new CngKeyCreationParameters + { + Provider = CngProvider.MicrosoftPlatformCryptoProvider, + KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, + }; + + key = CngKey.Create( + CngAlgorithm.Rsa, + nameof(MicrosoftPlatformCryptoProvider_EcdsaKey), + cngCreationParameters); + + using (RSACng rsa = new RSACng(key)) + { + CertificateRequest req = new CertificateRequest("CN=potato", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + + using (X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow)) + using (RSA certKey = cert.GetRSAPrivateKey()) + { + Assert.NotNull(certKey); + byte[] data = new byte[] { 12, 11, 02, 08, 25, 14, 11, 18, 16 }; + byte[] signature = certKey.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + bool valid = rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + Assert.True(valid, "valid signature"); + } + } + } + finally + { + key?.Delete(); + } + } + public static IEnumerable StorageFlags => CollectionImportTests.StorageFlags; } } From fffacc2c2d0894bec2df2f4028499e9191ab1188 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Thu, 12 Jan 2023 11:18:58 -0500 Subject: [PATCH 2/4] Fix test key name --- .../tests/X509Certificates/CertTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs index 3196406f191fc1..091f7f3481355e 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs @@ -627,7 +627,7 @@ public static void MicrosoftPlatformCryptoProvider_RsaKey() key = CngKey.Create( CngAlgorithm.Rsa, - nameof(MicrosoftPlatformCryptoProvider_EcdsaKey), + nameof(MicrosoftPlatformCryptoProvider_RsaKey), cngCreationParameters); using (RSACng rsa = new RSACng(key)) From d965006f0ac27efbf7a83af04391862243873c30 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Thu, 12 Jan 2023 11:20:45 -0500 Subject: [PATCH 3/4] Better test name --- .../tests/X509Certificates/CertTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs index 091f7f3481355e..cdbdc8aee3cb49 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs @@ -573,7 +573,7 @@ public static void SignatureAlgorithmOidReadableForGostCertificate() [ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))] [OuterLoop("Hardware backed key generation takes several seconds.")] - public static void MicrosoftPlatformCryptoProvider_EcdsaKey() + public static void CreateCertificate_MicrosoftPlatformCryptoProvider_EcdsaKey() { CngKey key = null; @@ -587,7 +587,7 @@ public static void MicrosoftPlatformCryptoProvider_EcdsaKey() key = CngKey.Create( CngAlgorithm.ECDsaP384, - nameof(MicrosoftPlatformCryptoProvider_EcdsaKey), + nameof(CreateCertificate_MicrosoftPlatformCryptoProvider_EcdsaKey), cngCreationParameters); using (ECDsaCng ecdsa = new ECDsaCng(key)) @@ -613,7 +613,7 @@ public static void MicrosoftPlatformCryptoProvider_EcdsaKey() [ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))] [OuterLoop("Hardware backed key generation takes several seconds.")] - public static void MicrosoftPlatformCryptoProvider_RsaKey() + public static void CreateCertificate_MicrosoftPlatformCryptoProvider_RsaKey() { CngKey key = null; @@ -627,7 +627,7 @@ public static void MicrosoftPlatformCryptoProvider_RsaKey() key = CngKey.Create( CngAlgorithm.Rsa, - nameof(MicrosoftPlatformCryptoProvider_RsaKey), + nameof(CreateCertificate_MicrosoftPlatformCryptoProvider_RsaKey), cngCreationParameters); using (RSACng rsa = new RSACng(key)) From 354cbd994d35fc9be02cd872c216487b5a016204 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Fri, 13 Jan 2023 17:04:11 -0500 Subject: [PATCH 4/4] Refactor CngKey PCP test key creation --- .../Cryptography/CngPlatformProviderKey.cs | 39 ++++++++++ .../tests/ECDiffieHellmanCngTests.cs | 39 ++-------- .../tests/PropertyTests.cs | 45 +++-------- ...tem.Security.Cryptography.Cng.Tests.csproj | 2 + .../System.Security.Cryptography.Tests.csproj | 2 + .../tests/X509Certificates/CertTests.cs | 78 +++++-------------- 6 files changed, 80 insertions(+), 125 deletions(-) create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/CngPlatformProviderKey.cs diff --git a/src/libraries/Common/tests/System/Security/Cryptography/CngPlatformProviderKey.cs b/src/libraries/Common/tests/System/Security/Cryptography/CngPlatformProviderKey.cs new file mode 100644 index 00000000000000..b33636ae957855 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/CngPlatformProviderKey.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; + +namespace Test.Cryptography +{ + internal sealed class CngPlatformProviderKey : IDisposable + { + public CngPlatformProviderKey( + CngAlgorithm algorithm, + string keySuffix = null, + [CallerMemberName] string testName = null, + params CngProperty[] additionalParameters) + { + CngKeyCreationParameters cngCreationParameters = new CngKeyCreationParameters + { + Provider = CngProvider.MicrosoftPlatformCryptoProvider, + KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, + }; + + foreach (CngProperty parameter in additionalParameters) + { + cngCreationParameters.Parameters.Add(parameter); + } + + Key = CngKey.Create(algorithm, $"{testName}{algorithm.Algorithm}{keySuffix}", cngCreationParameters); + } + + internal CngKey Key { get; } + + public void Dispose() + { + Key.Delete(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngTests.cs b/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngTests.cs index 6d5406ef67a399..638a7d4c95a97a 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngTests.cs +++ b/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngTests.cs @@ -193,39 +193,14 @@ public static void HashAlgorithm_SupportsOtherECDHImplementations() [OuterLoop("Hardware backed key generation takes several seconds.")] public static void PlatformCryptoProvider_DeriveKeyMaterial() { - CngKey key1 = null; - CngKey key2 = null; - - try - { - CngKeyCreationParameters cngCreationParameters = new CngKeyCreationParameters - { - Provider = CngProvider.MicrosoftPlatformCryptoProvider, - KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, - }; - - key1 = CngKey.Create( - CngAlgorithm.ECDiffieHellmanP256, - $"{nameof(PlatformCryptoProvider_DeriveKeyMaterial)}{nameof(key1)}", - cngCreationParameters); - - key2 = CngKey.Create( - CngAlgorithm.ECDiffieHellmanP256, - $"{nameof(PlatformCryptoProvider_DeriveKeyMaterial)}{nameof(key2)}", - cngCreationParameters); - - using (ECDiffieHellmanCng ecdhCng1 = new ECDiffieHellmanCng(key1)) - using (ECDiffieHellmanCng ecdhCng2 = new ECDiffieHellmanCng(key2)) - { - byte[] derivedKey1 = ecdhCng1.DeriveKeyMaterial(key2); - byte[] derivedKey2 = ecdhCng2.DeriveKeyMaterial(key1); - Assert.Equal(derivedKey1, derivedKey2); - } - } - finally + using (CngPlatformProviderKey platformKey1 = new CngPlatformProviderKey(CngAlgorithm.ECDiffieHellmanP256, "key1")) + using (CngPlatformProviderKey platformKey2 = new CngPlatformProviderKey(CngAlgorithm.ECDiffieHellmanP256, "key2")) + using (ECDiffieHellmanCng ecdhCng1 = new ECDiffieHellmanCng(platformKey1.Key)) + using (ECDiffieHellmanCng ecdhCng2 = new ECDiffieHellmanCng(platformKey2.Key)) { - key1?.Delete(); - key2?.Delete(); + byte[] derivedKey1 = ecdhCng1.DeriveKeyMaterial(platformKey2.Key); + byte[] derivedKey2 = ecdhCng2.DeriveKeyMaterial(platformKey1.Key); + Assert.Equal(derivedKey1, derivedKey2); } } } diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/PropertyTests.cs b/src/libraries/System.Security.Cryptography.Cng/tests/PropertyTests.cs index f37f7f8bedfa8b..c6224678c46ade 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/PropertyTests.cs +++ b/src/libraries/System.Security.Cryptography.Cng/tests/PropertyTests.cs @@ -17,24 +17,11 @@ public static class PropertyTests [OuterLoop("Hardware backed key generation takes several seconds.")] public static void CreatePersisted_PlatformEccKeyHasKeySize(string algorithm, int expectedKeySize) { - CngKey key = null; + CngAlgorithm cngAlgorithm = new CngAlgorithm(algorithm); - try + using (CngPlatformProviderKey platformKey = new CngPlatformProviderKey(cngAlgorithm)) { - key = CngKey.Create( - new CngAlgorithm(algorithm), - $"{nameof(CreatePersisted_PlatformEccKeyHasKeySize)}_{algorithm}", - new CngKeyCreationParameters - { - Provider = CngProvider.MicrosoftPlatformCryptoProvider, - KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, - }); - - Assert.Equal(expectedKeySize, key.KeySize); - } - finally - { - key?.Delete(); // Delete does a Dispose for us. + Assert.Equal(expectedKeySize, platformKey.Key.KeySize); } } @@ -44,27 +31,15 @@ public static void CreatePersisted_PlatformEccKeyHasKeySize(string algorithm, in [OuterLoop("Hardware backed key generation takes several seconds.")] public static void CreatePersisted_PlatformRsaKeyHasKeySize(int keySize) { - CngKey key = null; + CngProperty keyLengthProperty = new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None); + CngPlatformProviderKey platformKey = new CngPlatformProviderKey( + CngAlgorithm.Rsa, + keySuffix: keySize.ToString(), + additionalParameters: keyLengthProperty); - try - { - CngKeyCreationParameters cngCreationParameters = new CngKeyCreationParameters - { - Provider = CngProvider.MicrosoftPlatformCryptoProvider, - KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, - }; - cngCreationParameters.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None)); - - key = CngKey.Create( - CngAlgorithm.Rsa, - $"{nameof(CreatePersisted_PlatformRsaKeyHasKeySize)}_{keySize}", - cngCreationParameters); - - Assert.Equal(keySize, key.KeySize); - } - finally + using (platformKey) { - key?.Delete(); // Delete does a Dispose for us. + Assert.Equal(keySize, platformKey.Key.KeySize); } } diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj index 4bfc1719abf9d8..8bd0699feeb6d6 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj @@ -42,6 +42,8 @@ Link="CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDiffieHellmanFactory.cs" /> + + StorageFlags => CollectionImportTests.StorageFlags;