Skip to content

Commit d2ca8e5

Browse files
committed
Removed hardcoded references to CertificateUtilityWin
These were mostly related to generating CSP keys.
1 parent 41f5002 commit d2ca8e5

File tree

11 files changed

+236
-498
lines changed

11 files changed

+236
-498
lines changed

src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/CspProviderExt.cs

Lines changed: 28 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
using System;
66
using System.Linq;
77
using System.Security.Cryptography.X509Certificates;
8-
using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup;
98
using Xunit;
10-
using System.Collections.Generic;
11-
using static Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.CertificateUtilityWin;
9+
using System.Security.Cryptography;
10+
using Microsoft.Data.SqlClient.TestUtilities.Fixtures;
1211
#if !NETFRAMEWORK
1312
using System.Runtime.Versioning;
1413
#endif
@@ -25,184 +24,48 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
2524
[PlatformSpecific(TestPlatforms.Windows)]
2625
public class CspProviderExt
2726
{
28-
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))]
29-
[ClassData(typeof(AEConnectionStringProvider))]
30-
public void TestKeysFromCertificatesCreatedWithMultipleCryptoProviders(string connectionString)
31-
{
32-
const string providersRegistryKeyPath = @"SOFTWARE\Microsoft\Cryptography\Defaults\Provider";
33-
Microsoft.Win32.RegistryKey defaultCryptoProvidersRegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(providersRegistryKeyPath);
34-
35-
foreach (string subKeyName in defaultCryptoProvidersRegistryKey.GetSubKeyNames())
36-
{
37-
// NOTE: RSACryptoServiceProvider.SignData() fails for other providers when testing locally
38-
if (!subKeyName.Contains(@"RSA and AES"))
39-
{
40-
Console.WriteLine(@"INFO: Skipping Certificate creation for {0}.", subKeyName);
41-
continue;
42-
}
43-
string providerName;
44-
string providerType;
45-
string certificateName;
46-
using (Microsoft.Win32.RegistryKey providerKey = defaultCryptoProvidersRegistryKey.OpenSubKey(subKeyName))
47-
{
48-
// Get Provider Name and its type
49-
providerName = providerKey.Name.Substring(providerKey.Name.LastIndexOf(@"\", StringComparison.Ordinal) + 1);
50-
providerType = providerKey.GetValue(@"Type").ToString();
51-
52-
// Create a certificate from that provider
53-
certificateName = string.Format(@"AETest - {0}", providerName);
54-
}
55-
56-
var extensions = new List<Tuple<string, string, string>>();
57-
CertificateOption certOption = new()
58-
{
59-
Subject = certificateName,
60-
KeyExportPolicy = "Exportable",
61-
CertificateStoreLocation = $"{StoreLocation.CurrentUser}\\My",
62-
Provider = providerName,
63-
Type = providerType,
64-
};
65-
CreateCertificate(certOption);
66-
SQLSetupStrategyCspExt sqlSetupStrategyCsp = null;
67-
try
68-
{
69-
if (false == CertificateUtilityWin.CertificateExists(certificateName, StoreLocation.CurrentUser))
70-
{
71-
Console.WriteLine(@"INFO: Certificate creation for provider {0} failed so skipping it.", providerName);
72-
continue;
73-
}
74-
75-
X509Certificate2 cert = CertificateUtilityWin.GetCertificate(certificateName, StoreLocation.CurrentUser);
76-
string cspPath = CertificateUtilityWin.GetCspPathFromCertificate(cert);
77-
78-
if (string.IsNullOrEmpty(cspPath))
79-
{
80-
Console.WriteLine(@"INFO: Certificate provider {0} is not a csp provider so skipping it.", providerName);
81-
continue;
82-
}
83-
84-
Console.WriteLine("CSP path is {0}", cspPath);
85-
86-
sqlSetupStrategyCsp = new SQLSetupStrategyCspExt(cspPath);
87-
string tableName = sqlSetupStrategyCsp.CspProviderTable.Name;
88-
89-
using SqlConnection sqlConn = new(connectionString);
90-
sqlConn.Open();
91-
92-
Table.DeleteData(tableName, sqlConn);
93-
94-
// insert 1 row data
95-
Customer customer = new Customer(45, "Microsoft", "Corporation");
96-
97-
DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer);
98-
99-
// Test INPUT parameter on an encrypted parameter
100-
using SqlCommand sqlCommand = new(@$"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName",
101-
sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled);
102-
SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft");
103-
customerFirstParam.Direction = System.Data.ParameterDirection.Input;
104-
105-
using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
106-
ValidateResultSet(sqlDataReader);
107-
Console.WriteLine(@"INFO: Successfully validated using a certificate using provider:{0}", providerName);
108-
}
109-
finally
110-
{
111-
CertificateUtilityWin.RemoveCertificate(certificateName, StoreLocation.CurrentUser);
112-
// clean up database resources
113-
sqlSetupStrategyCsp?.Dispose();
114-
}
115-
116-
}
117-
}
118-
11927
// [Fact(Skip="Run this in non-parallel mode")] or [ConditionalFact()]
12028
[Fact(Skip = "Failing in TCE")]
12129
public void TestRoundTripWithCSPAndCertStoreProvider()
12230
{
123-
const string providerName = "Microsoft Enhanced RSA and AES Cryptographic Provider";
124-
string providerType = "24";
125-
126-
string certificateName = string.Format(@"AETest - {0}", providerName);
127-
CertificateOption options = new()
128-
{
129-
Subject = certificateName,
130-
CertificateStoreLocation = StoreLocation.CurrentUser.ToString(),
131-
Provider = providerName,
132-
Type = providerType
133-
};
134-
CertificateUtilityWin.CreateCertificate(options);
135-
try
136-
{
137-
X509Certificate2 cert = CertificateUtilityWin.GetCertificate(certificateName, StoreLocation.CurrentUser);
138-
string cspPath = CertificateUtilityWin.GetCspPathFromCertificate(cert);
139-
string certificatePath = String.Concat(@"CurrentUser/my/", cert.Thumbprint);
31+
using CspCertificateFixture cspCertificateFixture = new CspCertificateFixture();
14032

141-
SqlColumnEncryptionCertificateStoreProvider certProvider = new SqlColumnEncryptionCertificateStoreProvider();
142-
SqlColumnEncryptionCspProvider cspProvider = new SqlColumnEncryptionCspProvider();
143-
byte[] columnEncryptionKey = DatabaseHelper.GenerateRandomBytes(32);
33+
X509Certificate2 cert = cspCertificateFixture.CspCertificate;
34+
string cspPath = cspCertificateFixture.CspKeyPath;
35+
string certificatePath = cspCertificateFixture.CspCertificatePath;
14436

145-
byte[] encryptedColumnEncryptionKeyUsingCert = certProvider.EncryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", columnEncryptionKey);
146-
byte[] columnEncryptionKeyReturnedCert2CSP = cspProvider.DecryptColumnEncryptionKey(cspPath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert);
147-
Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2CSP));
37+
SqlColumnEncryptionCertificateStoreProvider certProvider = new SqlColumnEncryptionCertificateStoreProvider();
38+
SqlColumnEncryptionCspProvider cspProvider = new SqlColumnEncryptionCspProvider();
39+
byte[] columnEncryptionKey = DatabaseHelper.GenerateRandomBytes(32);
14840

149-
byte[] encryptedColumnEncryptionKeyUsingCSP = cspProvider.EncryptColumnEncryptionKey(cspPath, @"RSA_OAEP", columnEncryptionKey);
150-
byte[] columnEncryptionKeyReturnedCSP2Cert = certProvider.DecryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCSP);
151-
Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCSP2Cert));
41+
byte[] encryptedColumnEncryptionKeyUsingCert = certProvider.EncryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", columnEncryptionKey);
42+
byte[] columnEncryptionKeyReturnedCert2CSP = cspProvider.DecryptColumnEncryptionKey(cspPath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCert);
43+
Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCert2CSP));
15244

153-
}
154-
finally
155-
{
156-
CertificateUtilityWin.RemoveCertificate(certificateName, StoreLocation.CurrentUser);
157-
}
45+
byte[] encryptedColumnEncryptionKeyUsingCSP = cspProvider.EncryptColumnEncryptionKey(cspPath, @"RSA_OAEP", columnEncryptionKey);
46+
byte[] columnEncryptionKeyReturnedCSP2Cert = certProvider.DecryptColumnEncryptionKey(certificatePath, @"RSA_OAEP", encryptedColumnEncryptionKeyUsingCSP);
47+
Assert.True(columnEncryptionKey.SequenceEqual(columnEncryptionKeyReturnedCSP2Cert));
15848
}
15949

16050
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))]
161-
[ClassData(typeof(AEConnectionStringProvider))]
162-
public void TestEncryptDecryptWithCSP(string connectionString)
51+
[ClassData(typeof(AEConnectionStringProviderWithCspParameters))]
52+
public void TestEncryptDecryptWithCSP(string connectionString, CspParameters cspParameters)
16353
{
164-
string providerName = @"Microsoft Enhanced RSA and AES Cryptographic Provider";
16554
string keyIdentifier = DataTestUtility.GetUniqueNameForSqlServer("CSP");
55+
CspParameters namedCspParameters = new CspParameters(cspParameters.ProviderType, cspParameters.ProviderName, keyIdentifier);
56+
using SQLSetupStrategyCspProvider sqlSetupStrategyCsp = new SQLSetupStrategyCspProvider(namedCspParameters);
16657

167-
try
168-
{
169-
CertificateUtilityWin.RSAPersistKeyInCsp(providerName, keyIdentifier);
170-
string cspPath = String.Concat(providerName, @"/", keyIdentifier);
171-
172-
SQLSetupStrategyCspExt sqlSetupStrategyCsp = new SQLSetupStrategyCspExt(cspPath);
173-
string tableName = sqlSetupStrategyCsp.CspProviderTable.Name;
174-
175-
try
176-
{
177-
using SqlConnection sqlConn = new(connectionString);
178-
sqlConn.Open();
179-
180-
Table.DeleteData(tableName, sqlConn);
181-
182-
// insert 1 row data
183-
Customer customer = new Customer(45, "Microsoft", "Corporation");
184-
185-
DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer);
58+
using SqlConnection sqlConn = new(connectionString);
59+
sqlConn.Open();
18660

187-
// Test INPUT parameter on an encrypted parameter
188-
using SqlCommand sqlCommand = new(@$"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @firstName",
189-
sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled);
190-
SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft");
191-
customerFirstParam.Direction = System.Data.ParameterDirection.Input;
61+
// Test INPUT parameter on an encrypted parameter
62+
using SqlCommand sqlCommand = new(@$"SELECT CustomerId, FirstName, LastName FROM [{sqlSetupStrategyCsp.ApiTestTable.Name}] WHERE FirstName = @firstName",
63+
sqlConn, null, SqlCommandColumnEncryptionSetting.Enabled);
64+
SqlParameter customerFirstParam = sqlCommand.Parameters.AddWithValue(@"firstName", @"Microsoft");
65+
customerFirstParam.Direction = System.Data.ParameterDirection.Input;
19266

193-
using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
194-
ValidateResultSet(sqlDataReader);
195-
}
196-
finally
197-
{
198-
// clean up database resources
199-
sqlSetupStrategyCsp.Dispose();
200-
}
201-
}
202-
finally
203-
{
204-
CertificateUtilityWin.RSADeleteKeyInCsp(providerName, keyIdentifier);
205-
}
67+
using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
68+
ValidateResultSet(sqlDataReader);
20669
}
20770

20871
/// <summary>

src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/DatabaseHelper.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,4 +342,39 @@ public IEnumerator<object[]> GetEnumerator()
342342
}
343343
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
344344
}
345+
346+
public class AEConnectionStringProviderWithCspParameters : IEnumerable<object[]>
347+
{
348+
public IEnumerator<object[]> GetEnumerator()
349+
{
350+
const string ProvidersRegistryKeyPath = @"SOFTWARE\Microsoft\Cryptography\Defaults\Provider";
351+
using Microsoft.Win32.RegistryKey defaultCryptoProvidersRegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(ProvidersRegistryKeyPath);
352+
353+
foreach (string subKeyName in defaultCryptoProvidersRegistryKey.GetSubKeyNames())
354+
{
355+
CspParameters providerCspParameters;
356+
357+
// NOTE: RSACryptoServiceProvider.SignData() fails for other providers when testing locally
358+
if (!subKeyName.Contains(@"RSA and AES"))
359+
{
360+
continue;
361+
}
362+
363+
using (Microsoft.Win32.RegistryKey providerKey = defaultCryptoProvidersRegistryKey.OpenSubKey(subKeyName))
364+
{
365+
// Get Provider Name and its type
366+
string providerName = providerKey.Name.Substring(providerKey.Name.LastIndexOf(@"\", StringComparison.Ordinal) + 1);
367+
int providerType = (int)providerKey.GetValue(@"Type");
368+
369+
providerCspParameters = new CspParameters(providerType, providerName);
370+
}
371+
372+
foreach (string connStrAE in DataTestUtility.AEConnStrings)
373+
{
374+
yield return new object[] { connStrAE, providerCspParameters };
375+
}
376+
}
377+
}
378+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
379+
}
345380
}

src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ public class SQLSetupStrategy : ColumnMasterKeyCertificateFixture
5959
public Dictionary<string, string> sqlBulkTruncationTableNames = new Dictionary<string, string>();
6060

6161
public SQLSetupStrategy()
62-
: base()
62+
: base(true)
6363
{
6464
ColumnMasterKeyPath = string.Concat(StoreLocation.CurrentUser.ToString(), "/", StoreName.My.ToString(), "/", ColumnMasterKeyCertificate.Thumbprint);
6565
}
6666

6767
protected SQLSetupStrategy(string customKeyPath)
68-
: base()
68+
: base(false)
6969
{
7070
ColumnMasterKeyPath = customKeyPath;
7171
}
@@ -90,6 +90,14 @@ internal virtual void SetupDatabase()
9090
}
9191

9292
// Insert data for TrustedMasterKeyPaths tests.
93+
InsertSampleData(TrustedMasterKeyPathsTestTable.Name);
94+
}
95+
}
96+
97+
protected void InsertSampleData(string tableName)
98+
{
99+
foreach(string value in DataTestUtility.AEConnStringsSetup)
100+
{
93101
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(value)
94102
{
95103
ConnectTimeout = 10000
@@ -98,7 +106,9 @@ internal virtual void SetupDatabase()
98106
using (SqlConnection sqlConn = new SqlConnection(builder.ToString()))
99107
{
100108
sqlConn.Open();
101-
DatabaseHelper.InsertCustomerData(sqlConn, null, TrustedMasterKeyPathsTestTable.Name, customer);
109+
110+
Table.DeleteData(tableName, sqlConn);
111+
DatabaseHelper.InsertCustomerData(sqlConn, null, tableName, customer);
102112
}
103113
}
104114
}
@@ -147,9 +157,12 @@ protected List<Table> CreateTables(IList<ColumnEncryptionKey> columnEncryptionKe
147157
SqlNullValuesTable = new SqlNullValuesTable(GenerateUniqueName("SqlNullValuesTable"), columnEncryptionKeys[0]);
148158
tables.Add(SqlNullValuesTable);
149159

150-
// columnEncryptionKeys[2] is encrypted with DummyCMK. use this encrypted column to test custom key store providers
151-
CustomKeyStoreProviderTestTable = new ApiTestTable(GenerateUniqueName("CustomKeyStoreProviderTestTable"), columnEncryptionKeys[2], columnEncryptionKeys[0], useDeterministicEncryption: true);
152-
tables.Add(CustomKeyStoreProviderTestTable);
160+
if (columnEncryptionKeys.Count > 2)
161+
{
162+
// columnEncryptionKeys[2] is encrypted with DummyCMK. use this encrypted column to test custom key store providers
163+
CustomKeyStoreProviderTestTable = new ApiTestTable(GenerateUniqueName("CustomKeyStoreProviderTestTable"), columnEncryptionKeys[2], columnEncryptionKeys[0], useDeterministicEncryption: true);
164+
tables.Add(CustomKeyStoreProviderTestTable);
165+
}
153166

154167
TabNVarCharMaxSource = new BulkCopyTruncationTables(GenerateUniqueName("TabNVarCharMaxSource"), columnEncryptionKeys[0]);
155168
tables.Add(TabNVarCharMaxSource);

src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyCertStoreProvider.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// See the LICENSE file in the project root for more information.using System;
44

55
using System.Collections.Generic;
6-
using System.Security.Cryptography.X509Certificates;
76
using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup;
87

98
namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
@@ -20,9 +19,6 @@ public SQLSetupStrategyCertStoreProvider() : base()
2019
SetupDatabase();
2120
}
2221

23-
protected SQLSetupStrategyCertStoreProvider(string customKeyPath) : base(customKeyPath)
24-
{ }
25-
2622
internal override void SetupDatabase()
2723
{
2824
CspColumnMasterKey = new CspColumnMasterKey(GenerateUniqueName("CMK"), ColumnMasterKeyCertificate.Thumbprint, CertStoreProvider, DataTestUtility.EnclaveEnabled);

0 commit comments

Comments
 (0)