* Add tests for exercising certificate with platform provider keys.
* Refactor CngKey PCP test key creation
--- /dev/null
+// 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();
+ }
+ }
+}
[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);
}
}
}
[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);
}
}
[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);
}
}
Link="CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDiffieHellmanFactory.cs" />
<Compile Include="$(CommonTestPath)System\Security\Cryptography\ByteUtils.cs"
Link="CommonTest\System\Security\Cryptography\ByteUtils.cs" />
+ <Compile Include="$(CommonTestPath)System\Security\Cryptography\CngPlatformProviderKey.cs"
+ Link="CommonTest\System\Security\Cryptography\CngPlatformProviderKey.cs" />
<Compile Include="$(CommonTestPath)System\Security\Cryptography\CryptoUtils.cs"
Link="CommonTest\System\Security\Cryptography\CryptoUtils.cs" />
<Compile Include="$(CommonTestPath)System\Security\Cryptography\PlatformSupport.cs"
Link="CommonTest\System\Security\Cryptography\509Certificates\RevocationResponder.cs" />
<Compile Include="$(CommonTestPath)System\Security\Cryptography\ByteUtils.cs"
Link="CommonTest\System\Security\Cryptography\ByteUtils.cs" />
+ <Compile Include="$(CommonTestPath)System\Security\Cryptography\CngPlatformProviderKey.cs"
+ Link="CommonTest\System\Security\Cryptography\CngPlatformProviderKey.cs" />
<Compile Include="$(CommonTestPath)System\Security\Cryptography\CryptoUtils.cs"
Link="CommonTest\System\Security\Cryptography\CryptoUtils.cs" />
<Compile Include="$(CommonTestPath)System\Security\Cryptography\PlatformSupport.cs"
}
}
+ [ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))]
+ [OuterLoop("Hardware backed key generation takes several seconds.")]
+ public static void CreateCertificate_MicrosoftPlatformCryptoProvider_EcdsaKey()
+ {
+ using (CngPlatformProviderKey platformKey = new CngPlatformProviderKey(CngAlgorithm.ECDsaP384))
+ using (ECDsaCng ecdsa = new ECDsaCng(platformKey.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");
+ }
+ }
+ }
+
+ [ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))]
+ [OuterLoop("Hardware backed key generation takes several seconds.")]
+ public static void CreateCertificate_MicrosoftPlatformCryptoProvider_RsaKey()
+ {
+ using (CngPlatformProviderKey platformKey = new CngPlatformProviderKey(CngAlgorithm.Rsa))
+ using (RSACng rsa = new RSACng(platformKey.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");
+ }
+ }
+ }
+
public static IEnumerable<object[]> StorageFlags => CollectionImportTests.StorageFlags;
}
}