77using System . Reflection ;
88using System . Security . Cryptography . X509Certificates ;
99using System . Text ;
10+ using Microsoft . Data . SqlClient . TestUtilities . Fixtures ;
1011using Xunit ;
1112using static Microsoft . Data . SqlClient . Tests . AlwaysEncryptedTests . Utility ;
1213
1314namespace Microsoft . Data . SqlClient . Tests . AlwaysEncryptedTests
1415{
15- public class ExceptionsAlgorithmErrors : IClassFixture < CertFixture >
16+ public class ExceptionsAlgorithmErrors : IClassFixture < ColumnEncryptionCertificateFixture >
1617 {
1718 // Reflection
1819 public static Assembly systemData = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
1920 public static Type sqlClientSymmetricKey = systemData . GetType ( "Microsoft.Data.SqlClient.SqlClientSymmetricKey" ) ;
2021 public static ConstructorInfo sqlColumnEncryptionKeyConstructor = sqlClientSymmetricKey . GetConstructor ( BindingFlags . NonPublic | BindingFlags . Instance , null , new Type [ ] { typeof ( byte [ ] ) } , null ) ;
2122
23+ private readonly ColumnEncryptionCertificateFixture _fixture ;
24+ private readonly byte [ ] _cek ;
25+ private readonly byte [ ] _encryptedCek ;
26+ private readonly string _certificatePath ;
27+
28+ public ExceptionsAlgorithmErrors ( ColumnEncryptionCertificateFixture fixture )
29+ {
30+ // Disable the cache to avoid false failures.
31+ SqlConnection . ColumnEncryptionQueryMetadataCacheEnabled = false ;
32+
33+ SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider ( ) ;
34+ X509Certificate2 currUserCertificate = fixture . GetCertificate ( StoreLocation . CurrentUser ) ;
35+
36+ _cek = GenerateRandomBytes ( 32 ) ;
37+ _fixture = fixture ;
38+ _certificatePath = string . Format ( "CurrentUser/My/{0}" , currUserCertificate . Thumbprint ) ;
39+ _encryptedCek = provider . EncryptColumnEncryptionKey ( _certificatePath , "RSA_OAEP" , _cek ) ;
40+ }
41+
2242 [ Fact ]
2343 [ PlatformSpecific ( TestPlatforms . Windows ) ]
2444 public void TestNullCEK ( )
@@ -52,9 +72,9 @@ public void TestInvalidEncryptionType()
5272 {
5373 const byte invalidEncryptionType = 3 ;
5474 Object cipherMD = GetSqlCipherMetadata ( 0 , 2 , null , invalidEncryptionType , 0x01 ) ;
55- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
75+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
5676 byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
57- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
77+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
5878
5979 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_InvalidEncryptionType ,
6080 "AEAD_AES_256_CBC_HMAC_SHA256" , invalidEncryptionType , "'Deterministic', 'Randomized'" ) ;
@@ -74,7 +94,7 @@ public void TestInvalidCipherText()
7494 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_InvalidCipherTextSize ,
7595 invalidCiphertextLength , 65 ) ;
7696 byte [ ] cipherText = GenerateRandomBytes ( invalidCiphertextLength ) ; // minimum length is 65
77- TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ) ;
97+ TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , _cek , CColumnEncryptionType . Deterministic ) ) ;
7898 Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
7999 }
80100
@@ -85,10 +105,10 @@ public void TestInvalidAlgorithmVersion()
85105 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_InvalidAlgorithmVersion ,
86106 40 , "01" ) ;
87107 byte [ ] plainText = Encoding . Unicode . GetBytes ( "Hello World" ) ;
88- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
108+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
89109 // Put a version number of 0x10
90110 cipherText [ 0 ] = 0x40 ;
91- TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ) ;
111+ TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , _cek , CColumnEncryptionType . Deterministic ) ) ;
92112 Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
93113 }
94114
@@ -98,13 +118,13 @@ public void TestInvalidAuthenticationTag()
98118 {
99119 string expectedMessage = SystemDataResourceManager . Instance . TCE_InvalidAuthenticationTag ;
100120 byte [ ] plainText = Encoding . Unicode . GetBytes ( "Hello World" ) ;
101- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
121+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
102122 // Zero out 4 bytes of authentication tag
103123 for ( int i = 0 ; i < 4 ; i ++ )
104124 {
105125 cipherText [ i + 1 ] = 0x00 ;
106126 }
107- TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ) ;
127+ TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptDataUsingAED ( cipherText , _cek , CColumnEncryptionType . Deterministic ) ) ;
108128 Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
109129 }
110130
@@ -115,9 +135,9 @@ public void TestNullColumnEncryptionAlgorithm()
115135 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_NullColumnEncryptionAlgorithm ,
116136 "'AEAD_AES_256_CBC_HMAC_SHA256'" ) ;
117137 Object cipherMD = GetSqlCipherMetadata ( 0 , 0 , null , 1 , 0x01 ) ;
118- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
138+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
119139 byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
120- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
140+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
121141
122142 TargetInvocationException e = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
123143 Assert . Contains ( expectedMessage , e . InnerException . Message ) ;
@@ -133,9 +153,9 @@ public void TestUnknownEncryptionAlgorithmId()
133153 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_UnknownColumnEncryptionAlgorithmId ,
134154 unknownEncryptionAlgoId , "'1', '2'" ) ;
135155 Object cipherMD = GetSqlCipherMetadata ( 0 , unknownEncryptionAlgoId , null , 1 , 0x01 ) ;
136- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
156+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
137157 byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
138- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
158+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
139159
140160 Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( plainText , cipherMD ) ) ;
141161 Assert . Matches ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -157,9 +177,9 @@ public void TestUnknownCustomKeyStoreProvider()
157177 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_UnrecognizedKeyStoreProviderName ,
158178 invalidProviderName , "'MSSQL_CERTIFICATE_STORE', 'MSSQL_CNG_STORE', 'MSSQL_CSP_PROVIDER'" , "" ) ;
159179 Object cipherMD = GetSqlCipherMetadata ( 0 , 1 , null , 1 , 0x03 ) ;
160- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , invalidProviderName , "RSA_OAEP" ) ;
180+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , invalidProviderName , "RSA_OAEP" ) ;
161181 byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
162- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
182+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
163183
164184 Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( plainText , cipherMD ) ) ;
165185 Assert . Contains ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -179,9 +199,9 @@ public void TestTceUnknownEncryptionAlgorithm()
179199 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_UnknownColumnEncryptionAlgorithm ,
180200 unknownEncryptionAlgorithm , "'AEAD_AES_256_CBC_HMAC_SHA256'" ) ;
181201 Object cipherMD = GetSqlCipherMetadata ( 0 , 0 , "Dummy" , 1 , 0x01 ) ;
182- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
202+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
183203 byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
184- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
204+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
185205
186206 Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
187207 Assert . Contains ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -194,15 +214,15 @@ public void TestTceUnknownEncryptionAlgorithm()
194214 [ PlatformSpecific ( TestPlatforms . Windows ) ]
195215 public void TestExceptionsFromCertStore ( )
196216 {
197- byte [ ] corruptedCek = GenerateInvalidEncryptedCek ( CertFixture . cek , ECEKCorruption . SIGNATURE ) ;
217+ byte [ ] corruptedCek = GenerateInvalidEncryptedCek ( _cek , ECEKCorruption . SIGNATURE ) ;
198218
199219 string expectedMessage = string . Format ( SystemDataResourceManager . Instance . TCE_KeyDecryptionFailedCertStore ,
200220 "MSSQL_CERTIFICATE_STORE" , BitConverter . ToString ( corruptedCek , corruptedCek . Length - 10 , 10 ) ) ;
201221
202222 Object cipherMD = GetSqlCipherMetadata ( 0 , 1 , null , 1 , 0x01 ) ;
203- AddEncryptionKeyToCipherMD ( cipherMD , corruptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
223+ AddEncryptionKeyToCipherMD ( cipherMD , corruptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "MSSQL_CERTIFICATE_STORE" , "RSA_OAEP" ) ;
204224 byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
205- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
225+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
206226
207227 Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
208228 Assert . Matches ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -224,9 +244,9 @@ public void TestExceptionsFromCustomKeyStore()
224244 SqlConnection . RegisterColumnEncryptionKeyStoreProviders ( customProviders ) ;
225245
226246 object cipherMD = GetSqlCipherMetadata ( 0 , 1 , null , 1 , 0x01 ) ;
227- AddEncryptionKeyToCipherMD ( cipherMD , CertFixture . encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , CertFixture . certificatePath , "DummyProvider" , "DummyAlgo" ) ;
247+ AddEncryptionKeyToCipherMD ( cipherMD , _encryptedCek , 0 , 0 , 0 , new byte [ ] { 0x01 , 0x02 , 0x03 } , _certificatePath , "DummyProvider" , "DummyAlgo" ) ;
228248 byte [ ] plainText = Encoding . Unicode . GetBytes ( "HelloWorld" ) ;
229- byte [ ] cipherText = EncryptDataUsingAED ( plainText , CertFixture . cek , CColumnEncryptionType . Deterministic ) ;
249+ byte [ ] cipherText = EncryptDataUsingAED ( plainText , _cek , CColumnEncryptionType . Deterministic ) ;
230250
231251 Exception decryptEx = Assert . Throws < TargetInvocationException > ( ( ) => DecryptWithKey ( cipherText , cipherMD ) ) ;
232252 Assert . Contains ( expectedMessage , decryptEx . InnerException . Message ) ;
@@ -238,35 +258,4 @@ public void TestExceptionsFromCustomKeyStore()
238258 }
239259 }
240260 }
241-
242- public class CertFixture : IDisposable
243- {
244- private readonly SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider ( ) ;
245-
246- public static X509Certificate2 certificate ;
247- public static string thumbprint ;
248- public static string certificatePath ;
249- public static byte [ ] cek ;
250- public static byte [ ] encryptedCek ;
251-
252- public CertFixture ( )
253- {
254- if ( certificate == null )
255- {
256- certificate = Utility . CreateCertificate ( ) ;
257- }
258- thumbprint = certificate . Thumbprint ;
259- certificatePath = string . Format ( "CurrentUser/My/{0}" , thumbprint ) ;
260- cek = GenerateRandomBytes ( 32 ) ;
261- encryptedCek = provider . EncryptColumnEncryptionKey ( certificatePath , "RSA_OAEP" , cek ) ;
262-
263- // Disable the cache to avoid false failures.
264- SqlConnection . ColumnEncryptionQueryMetadataCacheEnabled = false ;
265- }
266-
267- public void Dispose ( )
268- {
269- // Do NOT remove certificate for concurrent consistency. Certificates are used for other test cases as well.
270- }
271- }
272261}
0 commit comments