From 26b0f3506083eef26b9e87925c93c7e3e3f32375 Mon Sep 17 00:00:00 2001 From: Johnny Pham Date: Mon, 8 Jun 2020 12:28:28 -0700 Subject: [PATCH 01/38] Set up CI with Azure Pipelines [skip ci] --- azure-pipelines.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000..2020209994 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,3 @@ +- task: CmdLine@2 + inputs: + script: 'SET' \ No newline at end of file From 3da84f8b0139f549561022e107741e5bf5b7c7a5 Mon Sep 17 00:00:00 2001 From: Johnny Pham Date: Mon, 8 Jun 2020 14:03:26 -0700 Subject: [PATCH 02/38] Delete azure-pipelines.yml --- azure-pipelines.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 2020209994..0000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,3 +0,0 @@ -- task: CmdLine@2 - inputs: - script: 'SET' \ No newline at end of file From d02b69c55c2ccb45c5bc65af7121b781d30c93b9 Mon Sep 17 00:00:00 2001 From: Johnny Pham Date: Mon, 8 Jun 2020 12:28:28 -0700 Subject: [PATCH 03/38] Set up CI with Azure Pipelines [skip ci] --- azure-pipelines.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000..2020209994 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,3 @@ +- task: CmdLine@2 + inputs: + script: 'SET' \ No newline at end of file From 896caa151d55c67ff7f18b7ce32d4cc2eec425ca Mon Sep 17 00:00:00 2001 From: Johnny Pham Date: Mon, 8 Jun 2020 14:03:26 -0700 Subject: [PATCH 04/38] Delete azure-pipelines.yml --- azure-pipelines.yml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 2020209994..0000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,3 +0,0 @@ -- task: CmdLine@2 - inputs: - script: 'SET' \ No newline at end of file From 0d8b82f3a3379e9beb58fcb734a7669bcec869de Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Tue, 21 Jul 2020 09:59:00 -0700 Subject: [PATCH 05/38] aev2 --- .../SqlClient/EnclaveDelegate.NetCoreApp.cs | 2 +- ...ryptionCertificateStoreProvider.Windows.cs | 2 +- ...umnEncryptionEnclaveProvider.NetCoreApp.cs | 2 +- ...EnclaveAttestationParameters.NetCoreApp.cs | 4 +- ...ecureModeEnclaveProviderBase.NetCoreApp.cs | 77 ++++++++++++++++--- 5 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs index 4ab9421bd9..aac08f449e 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs @@ -44,7 +44,7 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete } // clientDHPublicKey - byte[] clientDHPublicKey = sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.Key.Export(CngKeyBlobFormat.EccPublicBlob); + byte[] clientDHPublicKey = sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey.ToByteArray(); // clientDHPublicKey length clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength"); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs index e05025d2f8..95096e0865 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs @@ -482,7 +482,7 @@ private byte[] RSAEncrypt(byte[] plainText, X509Certificate2 certificate) } /// - /// Encrypt the text using specified certificate. + /// Decrypt the text using specified certificate. /// /// Text to decrypt. /// Certificate object. diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs index ccf4fe889c..378ce7f537 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs @@ -20,7 +20,7 @@ internal abstract partial class SqlColumnEncryptionEnclaveProvider /// The length of the extra data needed for attestating the enclave. /// The requested enclave session or null if the provider does not implement session caching. /// A counter that the enclave provider is expected to increment each time SqlClient retrieves the session from the cache. The purpose of this field is to prevent replay attacks. - internal abstract void CreateEnclaveSession(byte[] enclaveAttestationInfo, ECDiffieHellmanCng clientDiffieHellmanKey, string attestationUrl, string servername, byte[] customData, int customDataLength, + internal abstract void CreateEnclaveSession(byte[] enclaveAttestationInfo, ECDiffieHellman clientDiffieHellmanKey, string attestationUrl, string servername, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter); } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnclaveAttestationParameters.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnclaveAttestationParameters.NetCoreApp.cs index 1f59daf511..739187a7e9 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnclaveAttestationParameters.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnclaveAttestationParameters.NetCoreApp.cs @@ -14,10 +14,10 @@ internal partial class SqlEnclaveAttestationParameters private static readonly string _className = "EnclaveAttestationParameters"; /// - internal ECDiffieHellmanCng ClientDiffieHellmanKey { get; } + internal ECDiffieHellman ClientDiffieHellmanKey { get; } /// - internal SqlEnclaveAttestationParameters(int protocol, byte[] input, ECDiffieHellmanCng clientDiffieHellmanKey) + internal SqlEnclaveAttestationParameters(int protocol, byte[] input, ECDiffieHellman clientDiffieHellmanKey) { _input = input ?? throw SQL.NullArgumentInConstructorInternal(_inputName, _className); Protocol = protocol; diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs index 207c5ef11a..1861c894cf 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using System.Runtime.Caching; +using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Threading; @@ -94,14 +95,14 @@ internal override void GetEnclaveSession(string servername, string attestationUr // Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. internal override SqlEnclaveAttestationParameters GetAttestationParameters(string attestationUrl, byte[] customData, int customDataLength) { - ECDiffieHellmanCng clientDHKey = new ECDiffieHellmanCng(DiffieHellmanKeySize); - clientDHKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash; - clientDHKey.HashAlgorithm = CngAlgorithm.Sha256; + ECDiffieHellman clientDHKey = ECDiffieHellman.Create(); + clientDHKey.KeySize = DiffieHellmanKeySize; + return new SqlEnclaveAttestationParameters(VsmHGSProtocolId, new byte[] { }, clientDHKey); } // When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. - internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellmanCng clientDHKey, string attestationUrl, string servername, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) + internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellman clientDHKey, string attestationUrl, string servername, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) { sqlEnclaveSession = null; counter = 0; @@ -349,18 +350,74 @@ private void VerifyEnclavePolicyProperty(string property, uint actual, uint expe } // Derives the shared secret between the client and enclave. - private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellmanCng clientDHKey) + private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellman clientDHKey) { // Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key. - CngKey cngkey = CngKey.Import(enclavePublicKey.PublicKey, CngKeyBlobFormat.GenericPublicBlob); - RSACng rsacng = new RSACng(cngkey); - if (!rsacng.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) + RSAParameters rsaParams = RSAKeyBlobToParams(enclavePublicKey.PublicKey); + RSA rsa = RSA.Create(rsaParams); + + if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { throw new ArgumentException(SR.GetSharedSecretFailed); } - CngKey key = CngKey.Import(enclaveDHInfo.PublicKey, CngKeyBlobFormat.GenericPublicBlob); - return clientDHKey.DeriveKeyMaterial(key); + ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey); + ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); + + return clientDHKey.DeriveKeyMaterial(enclaveDHKey.PublicKey); + } + + // Extracts the public key's modulus and exponent from the key blob + + // this works on windows because the win32 api uses the bcrypt structures + // will it work on linux? + // according to odbc docs, the modulus is always 512 bytes for a VBS-HGS enclave response + // so it should work for any vbs-hgs enclave provider... + private RSAParameters RSAKeyBlobToParams(byte[] keyBlob) + { + // The RSA public key blob is structured as follows: + // BCRYPT_RSAKEY_BLOB header + // byte[cbPublicExp] publicExponent - Exponent + // byte[cbModulus] modulus - Modulus + + // The exponent is the final 3 bytes in the header + // The modulus is the final 512 bytes in the key blob + const int modulusSize = 512; + const int exponentSize = 3; + int BcryptRsaKeyBlobHeaderSize = keyBlob.Length - modulusSize; + int exponentOffset = BcryptRsaKeyBlobHeaderSize - exponentSize; + int modulusOffset = exponentOffset + exponentSize; + + return new RSAParameters() + { + Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(), + Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray() + }; + } + + // Extracts the public key's X and Y coordinate + private ECParameters ECCKeyBlobToParams(byte[] keyBlob) + { + // The ECC public key blob is structured as follows: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] X - X coordinate + // byte[cbKey] Y - Y coordinate + + // The size of each key is found after the first 4 byes (magic number) + const int keySizeOffset = 4; + int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset); + int keyOffset = keySizeOffset + sizeof(int); + + return new ECParameters + { + // should we read the magic bytes and set it based on that? + //Curve = ECCurve.NamedCurves.nistP384, + Q = new ECPoint + { + X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(), + Y = keyBlob.Skip(keyOffset + keySize).Take(keySize).ToArray() + }, + }; } #endregion From a98f2a04ffaef90bf7609e3f057e4db6646f89b1 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Tue, 21 Jul 2020 23:56:51 -0700 Subject: [PATCH 06/38] azure attestation, vbs --- ...estationBasedEnclaveProvider.NetCoreApp.cs | 20 ++--- .../EnclaveProviderBase.NetCoreApp.cs | 48 +++++++++++ ...ecureModeEnclaveProviderBase.NetCoreApp.cs | 81 +++---------------- 3 files changed, 70 insertions(+), 79 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs index 4a461b0532..86cf2a869c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs @@ -73,15 +73,14 @@ internal override void GetEnclaveSession(string servername, string attestationUr // Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. internal override SqlEnclaveAttestationParameters GetAttestationParameters(string attestationUrl, byte[] customData, int customDataLength) { - ECDiffieHellmanCng clientDHKey = new ECDiffieHellmanCng(DiffieHellmanKeySize); - clientDHKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash; - clientDHKey.HashAlgorithm = CngAlgorithm.Sha256; + ECDiffieHellman clientDHKey = ECDiffieHellman.Create(); + clientDHKey.KeySize = DiffieHellmanKeySize; byte[] attestationParam = PrepareAttestationParameters(attestationUrl, customData, customDataLength); return new SqlEnclaveAttestationParameters(AzureBasedAttestationProtocolId, attestationParam, clientDHKey); } // When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. - internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellmanCng clientDHKey, string attestationUrl, string servername, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) + internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellman clientDHKey, string attestationUrl, string servername, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) { sqlEnclaveSession = null; counter = 0; @@ -514,7 +513,7 @@ private void ValidateClaim(Dictionary claims, string claimName, } // Derives the shared secret between the client and enclave. - private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, EnclaveType enclaveType, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellmanCng clientDHKey) + private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, EnclaveType enclaveType, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellman clientDHKey) { byte[] enclaveRsaPublicKey = enclavePublicKey.PublicKey; @@ -529,17 +528,18 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, } // Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key. - CngKey cngkey = CngKey.Import(enclaveRsaPublicKey, CngKeyBlobFormat.GenericPublicBlob); - using (RSACng rsacng = new RSACng(cngkey)) + RSAParameters rsaParams = RSAKeyBlobToParams(enclaveRsaPublicKey); + using (RSA rsa = RSA.Create(rsaParams)) { - if (!rsacng.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) + if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { throw new ArgumentException(SR.GetSharedSecretFailed); } } - CngKey key = CngKey.Import(enclaveDHInfo.PublicKey, CngKeyBlobFormat.GenericPublicBlob); - return clientDHKey.DeriveKeyMaterial(key); + ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey); + ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); + return clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256); } #endregion } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs index 213b6b162b..c31198b423 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Linq; using System.Runtime.Caching; using System.Security.Cryptography; using System.Threading; @@ -210,6 +211,53 @@ protected SqlEnclaveSession AddEnclaveSessionToCache(string attestationUrl, stri { return SessionCache.CreateSession(attestationUrl, servername, sharedSecret, sessionId, out counter); } + + // Extracts the public key's modulus and exponent from the key blob + protected RSAParameters RSAKeyBlobToParams(byte[] keyBlob) + { + // The RSA public key blob is structured as follows: + // BCRYPT_RSAKEY_BLOB header + // byte[cbPublicExp] publicExponent - Exponent + // byte[cbModulus] modulus - Modulus + + // The exponent is the final 3 bytes in the header + // The modulus is the final 512 bytes in the key blob + const int modulusSize = 512; + const int exponentSize = 3; + int BcryptRsaKeyBlobHeaderSize = keyBlob.Length - modulusSize; + int exponentOffset = BcryptRsaKeyBlobHeaderSize - exponentSize; + int modulusOffset = exponentOffset + exponentSize; + + return new RSAParameters() + { + Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(), + Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray() + }; + } + + // Extracts the public key's X and Y coordinate from the key blob + protected ECParameters ECCKeyBlobToParams(byte[] keyBlob) + { + // The ECC public key blob is structured as follows: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] X - X coordinate + // byte[cbKey] Y - Y coordinate + + // The size of each key is found after the first 4 byes (magic number) + const int keySizeOffset = 4; + int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset); + int keyOffset = keySizeOffset + sizeof(int); + + return new ECParameters + { + Curve = ECCurve.NamedCurves.nistP384, + Q = new ECPoint + { + X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(), + Y = keyBlob.Skip(keyOffset + keySize).Take(keySize).ToArray() + }, + }; + } } #endregion } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs index 1861c894cf..62a99c8537 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using System.Runtime.Caching; -using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Threading; @@ -296,15 +295,13 @@ private void VerifyEnclaveReportSignature(EnclaveReportPackage enclaveReportPack } // IDK_S is contained in healthReport cert public key - RSA rsacsp = healthReportCert.GetRSAPublicKey(); - RSAParameters rsaparams = rsacsp.ExportParameters(includePrivateParameters: false); - RSACng rsacng = new RSACng(); - rsacng.ImportParameters(rsaparams); - - if (!rsacng.VerifyData(enclaveReportPackage.ReportAsBytes, enclaveReportPackage.SignatureBlob, HashAlgorithmName.SHA256, RSASignaturePadding.Pss)) + using (RSA rsa = healthReportCert.GetRSAPublicKey()) { - throw new ArgumentException(SR.VerifyEnclaveReportFailed); - + RSAParameters rsaparams = rsa.ExportParameters(includePrivateParameters: false); + if (!rsa.VerifyData(enclaveReportPackage.ReportAsBytes, enclaveReportPackage.SignatureBlob, HashAlgorithmName.SHA256, RSASignaturePadding.Pss)) + { + throw new ArgumentException(SR.VerifyEnclaveReportFailed); + } } } @@ -354,72 +351,18 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieH { // Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key. RSAParameters rsaParams = RSAKeyBlobToParams(enclavePublicKey.PublicKey); - RSA rsa = RSA.Create(rsaParams); - - if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) + using (RSA rsa = RSA.Create(rsaParams)) { - throw new ArgumentException(SR.GetSharedSecretFailed); + if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) + { + throw new ArgumentException(SR.GetSharedSecretFailed); + } } ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey); ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); - - return clientDHKey.DeriveKeyMaterial(enclaveDHKey.PublicKey); + return clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256); } - - // Extracts the public key's modulus and exponent from the key blob - - // this works on windows because the win32 api uses the bcrypt structures - // will it work on linux? - // according to odbc docs, the modulus is always 512 bytes for a VBS-HGS enclave response - // so it should work for any vbs-hgs enclave provider... - private RSAParameters RSAKeyBlobToParams(byte[] keyBlob) - { - // The RSA public key blob is structured as follows: - // BCRYPT_RSAKEY_BLOB header - // byte[cbPublicExp] publicExponent - Exponent - // byte[cbModulus] modulus - Modulus - - // The exponent is the final 3 bytes in the header - // The modulus is the final 512 bytes in the key blob - const int modulusSize = 512; - const int exponentSize = 3; - int BcryptRsaKeyBlobHeaderSize = keyBlob.Length - modulusSize; - int exponentOffset = BcryptRsaKeyBlobHeaderSize - exponentSize; - int modulusOffset = exponentOffset + exponentSize; - - return new RSAParameters() - { - Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(), - Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray() - }; - } - - // Extracts the public key's X and Y coordinate - private ECParameters ECCKeyBlobToParams(byte[] keyBlob) - { - // The ECC public key blob is structured as follows: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] X - X coordinate - // byte[cbKey] Y - Y coordinate - - // The size of each key is found after the first 4 byes (magic number) - const int keySizeOffset = 4; - int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset); - int keyOffset = keySizeOffset + sizeof(int); - - return new ECParameters - { - // should we read the magic bytes and set it based on that? - //Curve = ECCurve.NamedCurves.nistP384, - Q = new ECPoint - { - X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(), - Y = keyBlob.Skip(keyOffset + keySize).Take(keySize).ToArray() - }, - }; - } - #endregion } } From 0d5c11ef6dba052ef666b7aaaad3bffc3b36051b Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 23 Jul 2020 21:24:16 -0700 Subject: [PATCH 07/38] Update EnclaveProviderBase.NetCoreApp.cs --- .../EnclaveProviderBase.NetCoreApp.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs index c31198b423..cf494cef12 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs @@ -258,6 +258,36 @@ protected ECParameters ECCKeyBlobToParams(byte[] keyBlob) }, }; } + + // ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix so we have to + // serialize it in the BCRYPT_ECCKEY_BLOB format + public static byte[] PublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey) + { + // Size of a BCRYPT_ECCKEY_BLOB = 104 bytes + // header 8 bytes, key 96 bytes (48 bytes each coordinate) + const int headerSize = 8; + const int KeySize = 48; + const int keyBlobSize = 104; + byte[] keyBlob = new byte[keyBlobSize]; + + // magic number + keyBlob[0] = 0x45; + keyBlob[1] = 0x43; + keyBlob[2] = 0x4b; + keyBlob[3] = 0x33; + // key size + keyBlob[4] = KeySize; + keyBlob[5] = 0x00; + keyBlob[6] = 0x00; + keyBlob[7] = 0x00; + + ECParameters ecParams = publicKey.ExportParameters(); + // copy x coordinate + Array.Copy(ecParams.Q.X, 0, keyBlob, headerSize, KeySize); + // copy y coordinate + Array.Copy(ecParams.Q.Y, 0, keyBlob, headerSize + KeySize, KeySize); + return keyBlob; + } } #endregion } From 6eeaf13f7dc4f592081e03da4fbda5fe3e1d3e8f Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 23 Jul 2020 21:31:29 -0700 Subject: [PATCH 08/38] Update EnclaveProviderBase.NetCoreApp.cs --- .../Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs index cf494cef12..1c4be9c748 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs @@ -215,6 +215,7 @@ protected SqlEnclaveSession AddEnclaveSessionToCache(string attestationUrl, stri // Extracts the public key's modulus and exponent from the key blob protected RSAParameters RSAKeyBlobToParams(byte[] keyBlob) { + Console.WriteLine("RSAKeyBlobToParams"); // The RSA public key blob is structured as follows: // BCRYPT_RSAKEY_BLOB header // byte[cbPublicExp] publicExponent - Exponent @@ -238,6 +239,7 @@ protected RSAParameters RSAKeyBlobToParams(byte[] keyBlob) // Extracts the public key's X and Y coordinate from the key blob protected ECParameters ECCKeyBlobToParams(byte[] keyBlob) { + Console.WriteLine("ECCKeyBlobToParams"); // The ECC public key blob is structured as follows: // BCRYPT_ECCKEY_BLOB header // byte[cbKey] X - X coordinate @@ -263,6 +265,7 @@ protected ECParameters ECCKeyBlobToParams(byte[] keyBlob) // serialize it in the BCRYPT_ECCKEY_BLOB format public static byte[] PublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey) { + Console.WriteLine("PublicKeyToECCKeyBlob"); // Size of a BCRYPT_ECCKEY_BLOB = 104 bytes // header 8 bytes, key 96 bytes (48 bytes each coordinate) const int headerSize = 8; From 7bec0eae8474d3a1a594a5a75ff7d5fab39643e6 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 23 Jul 2020 21:32:35 -0700 Subject: [PATCH 09/38] replace tobytearray --- .../Data/SqlClient/EnclaveDelegate.NetCoreApp.cs | 12 ++++++++---- ...irtualSecureModeEnclaveProviderBase.NetCoreApp.cs | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs index aac08f449e..c0e671b4d5 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs @@ -4,7 +4,10 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; namespace Microsoft.Data.SqlClient { @@ -44,7 +47,7 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete } // clientDHPublicKey - byte[] clientDHPublicKey = sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey.ToByteArray(); + byte[] clientDHPublicKey = EnclaveProviderBase.PublicKeyToECCKeyBlob(sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey); // clientDHPublicKey length clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength"); @@ -54,7 +57,8 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete throw SQL.NullArgumentInternal("clientDHPublicKeyLengthBytes", ClassName, GetSerializedAttestationParametersName); } - return CombineByteArrays(new[] { attestationProtocolBytes, attestationProtocolInputLengthBytes, attestationProtocolInputBytes, clientDHPublicKeyLengthBytes, clientDHPublicKey }); + return CombineByteArrays(new[] { attestationProtocolBytes, attestationProtocolInputLengthBytes, + attestationProtocolInputBytes, clientDHPublicKeyLengthBytes, clientDHPublicKey }); } /// @@ -89,7 +93,7 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete sqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(attestationInfo, attestationParameters.ClientDiffieHellmanKey, attestationUrl, serverName, customData, customDataLength, out sqlEnclaveSession, out counter); - if (sqlEnclaveSession == null) + if (sqlEnclaveSession == null) { throw SQL.NullEnclaveSessionReturnedFromProvider(enclaveType, attestationUrl); } @@ -139,7 +143,7 @@ internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestat sqlColumnEncryptionEnclaveProvider.InvalidateEnclaveSession(serverName, EnclaveAttestationUrl, enclaveSession); } - + internal SqlEnclaveAttestationParameters GetAttestationParameters(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string attestationUrl, byte[] customData, int customDataLength) { SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs index 62a99c8537..9e3eeac0d5 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs @@ -361,6 +361,7 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieH ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey); ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); + return clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256); } #endregion From 1831ef0eb9d44bf54d1f3464a8d2d555a8d9663f Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Fri, 24 Jul 2020 00:23:39 -0700 Subject: [PATCH 10/38] move new methods to utils --- ...ncryptedEnclaveProviderUtils.NetCoreApp.cs | 88 +++++++++++++++++++ ...estationBasedEnclaveProvider.NetCoreApp.cs | 4 +- .../SqlClient/EnclaveDelegate.NetCoreApp.cs | 2 +- .../EnclaveProviderBase.NetCoreApp.cs | 81 ----------------- ...ecureModeEnclaveProviderBase.NetCoreApp.cs | 5 +- 5 files changed, 93 insertions(+), 87 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs index 066d33be25..9e26957dbf 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs @@ -4,6 +4,7 @@ using System; using System.Linq; +using System.Security.Cryptography; namespace Microsoft.Data.SqlClient { @@ -52,4 +53,91 @@ internal enum EnclaveType Sgx = 2 } + + // Methods for converting keys between different formats + internal class KeyConverter + { + // Extracts the public key's modulus and exponent from an RSA public key blob + // and returns an RSAParameters object + internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob) + { + // The RSA public key blob is structured as follows: + // BCRYPT_RSAKEY_BLOB header + // byte[cbPublicExp] publicExponent + // byte[cbModulus] modulus + + // The exponent is the final 3 bytes in the header + // The modulus is the final 512 bytes in the key blob + const int modulusSize = 512; + const int exponentSize = 3; + int headerSize = keyBlob.Length - modulusSize; + int exponentOffset = headerSize - exponentSize; + int modulusOffset = exponentOffset + exponentSize; + + return new RSAParameters() + { + Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(), + Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray() + }; + } + + // Extracts the public key's X and Y coordinates from an ECC public key blob + // and returns an ECParameters object + internal static ECParameters ECCPublicKeyBlobToParams(byte[] keyBlob) + { + // The ECC public key blob is structured as follows: + // BCRYPT_ECCKEY_BLOB header + // byte[cbKey] X + // byte[cbKey] Y + + // The size of each coordinate is found after the first 4 byes (magic number) + const int keySizeOffset = 4; + int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset); + int keyOffset = keySizeOffset + sizeof(int); + + return new ECParameters + { + Curve = ECCurve.NamedCurves.nistP384, + Q = new ECPoint + { + X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(), + Y = keyBlob.Skip(keyOffset + keySize).Take(keySize).ToArray() + }, + }; + } + + // Serializes an ECDiffieHellmanPublicKey to an ECC public key blob + // "ECDiffieHellmanPublicKey.ToByteArray() doesn't have a (standards-)defined export + // format. The version used by ECDiffieHellmanPublicKeyCng is Windows-specific" + // from https://github.com/dotnet/runtime/issues/27276 + // => ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix + internal static byte[] ECDHPublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey) + { + // Size of an ECC key blob = 104 bytes + // BCRYPT_ECCKEY_BLOB header = 8 bytes + // key = 96 bytes (48 bytes each coordinate) + const int keyBlobSize = 104; + const int headerSize = 8; + const int KeySize = 48; + byte[] keyBlob = new byte[keyBlobSize]; + + // magic number (BCRYPT_ECDH_PUBLIC_P384_MAGIC) + keyBlob[0] = 0x45; + keyBlob[1] = 0x43; + keyBlob[2] = 0x4b; + keyBlob[3] = 0x33; + // key size + keyBlob[4] = KeySize; + keyBlob[5] = 0x00; + keyBlob[6] = 0x00; + keyBlob[7] = 0x00; + + ECParameters ecParams = publicKey.ExportParameters(); + // copy x coordinate + Array.Copy(ecParams.Q.X, 0, keyBlob, headerSize, KeySize); + // copy y coordinate + Array.Copy(ecParams.Q.Y, 0, keyBlob, headerSize + KeySize, KeySize); + return keyBlob; + } + } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs index 86cf2a869c..4a4c952a20 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs @@ -528,7 +528,7 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, } // Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key. - RSAParameters rsaParams = RSAKeyBlobToParams(enclaveRsaPublicKey); + RSAParameters rsaParams = KeyConverter.RSAPublicKeyBlobToParams(enclaveRsaPublicKey); using (RSA rsa = RSA.Create(rsaParams)) { if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) @@ -537,7 +537,7 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, } } - ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey); + ECParameters ecParams = KeyConverter.ECCPublicKeyBlobToParams(enclaveDHInfo.PublicKey); ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); return clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256); } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs index c0e671b4d5..c37b43c318 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs @@ -47,7 +47,7 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete } // clientDHPublicKey - byte[] clientDHPublicKey = EnclaveProviderBase.PublicKeyToECCKeyBlob(sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey); + byte[] clientDHPublicKey = KeyConverter.ECDHPublicKeyToECCKeyBlob(sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey); // clientDHPublicKey length clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength"); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs index 1c4be9c748..213b6b162b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Linq; using System.Runtime.Caching; using System.Security.Cryptography; using System.Threading; @@ -211,86 +210,6 @@ protected SqlEnclaveSession AddEnclaveSessionToCache(string attestationUrl, stri { return SessionCache.CreateSession(attestationUrl, servername, sharedSecret, sessionId, out counter); } - - // Extracts the public key's modulus and exponent from the key blob - protected RSAParameters RSAKeyBlobToParams(byte[] keyBlob) - { - Console.WriteLine("RSAKeyBlobToParams"); - // The RSA public key blob is structured as follows: - // BCRYPT_RSAKEY_BLOB header - // byte[cbPublicExp] publicExponent - Exponent - // byte[cbModulus] modulus - Modulus - - // The exponent is the final 3 bytes in the header - // The modulus is the final 512 bytes in the key blob - const int modulusSize = 512; - const int exponentSize = 3; - int BcryptRsaKeyBlobHeaderSize = keyBlob.Length - modulusSize; - int exponentOffset = BcryptRsaKeyBlobHeaderSize - exponentSize; - int modulusOffset = exponentOffset + exponentSize; - - return new RSAParameters() - { - Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(), - Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray() - }; - } - - // Extracts the public key's X and Y coordinate from the key blob - protected ECParameters ECCKeyBlobToParams(byte[] keyBlob) - { - Console.WriteLine("ECCKeyBlobToParams"); - // The ECC public key blob is structured as follows: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] X - X coordinate - // byte[cbKey] Y - Y coordinate - - // The size of each key is found after the first 4 byes (magic number) - const int keySizeOffset = 4; - int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset); - int keyOffset = keySizeOffset + sizeof(int); - - return new ECParameters - { - Curve = ECCurve.NamedCurves.nistP384, - Q = new ECPoint - { - X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(), - Y = keyBlob.Skip(keyOffset + keySize).Take(keySize).ToArray() - }, - }; - } - - // ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix so we have to - // serialize it in the BCRYPT_ECCKEY_BLOB format - public static byte[] PublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey) - { - Console.WriteLine("PublicKeyToECCKeyBlob"); - // Size of a BCRYPT_ECCKEY_BLOB = 104 bytes - // header 8 bytes, key 96 bytes (48 bytes each coordinate) - const int headerSize = 8; - const int KeySize = 48; - const int keyBlobSize = 104; - byte[] keyBlob = new byte[keyBlobSize]; - - // magic number - keyBlob[0] = 0x45; - keyBlob[1] = 0x43; - keyBlob[2] = 0x4b; - keyBlob[3] = 0x33; - // key size - keyBlob[4] = KeySize; - keyBlob[5] = 0x00; - keyBlob[6] = 0x00; - keyBlob[7] = 0x00; - - ECParameters ecParams = publicKey.ExportParameters(); - // copy x coordinate - Array.Copy(ecParams.Q.X, 0, keyBlob, headerSize, KeySize); - // copy y coordinate - Array.Copy(ecParams.Q.Y, 0, keyBlob, headerSize + KeySize, KeySize); - return keyBlob; - } } #endregion } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs index 9e3eeac0d5..183ba058dc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs @@ -350,7 +350,7 @@ private void VerifyEnclavePolicyProperty(string property, uint actual, uint expe private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellman clientDHKey) { // Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key. - RSAParameters rsaParams = RSAKeyBlobToParams(enclavePublicKey.PublicKey); + RSAParameters rsaParams = KeyConverter.RSAPublicKeyBlobToParams(enclavePublicKey.PublicKey); using (RSA rsa = RSA.Create(rsaParams)) { if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) @@ -359,9 +359,8 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieH } } - ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey); + ECParameters ecParams = KeyConverter.ECCPublicKeyBlobToParams(enclaveDHInfo.PublicKey); ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); - return clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256); } #endregion From b79a97e637128d6b77ba8b3172c358b6515d68e8 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Mon, 27 Jul 2020 12:01:37 -0700 Subject: [PATCH 11/38] minor changes --- .../AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs | 3 +-- .../VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs index 9e26957dbf..59261f57c0 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs @@ -133,9 +133,8 @@ internal static byte[] ECDHPublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey public keyBlob[7] = 0x00; ECParameters ecParams = publicKey.ExportParameters(); - // copy x coordinate + // copy x and y coordinates to key blob Array.Copy(ecParams.Q.X, 0, keyBlob, headerSize, KeySize); - // copy y coordinate Array.Copy(ecParams.Q.Y, 0, keyBlob, headerSize + KeySize, KeySize); return keyBlob; } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs index 183ba058dc..4b0dbcbb72 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs @@ -297,7 +297,6 @@ private void VerifyEnclaveReportSignature(EnclaveReportPackage enclaveReportPack // IDK_S is contained in healthReport cert public key using (RSA rsa = healthReportCert.GetRSAPublicKey()) { - RSAParameters rsaparams = rsa.ExportParameters(includePrivateParameters: false); if (!rsa.VerifyData(enclaveReportPackage.ReportAsBytes, enclaveReportPackage.SignatureBlob, HashAlgorithmName.SHA256, RSASignaturePadding.Pss)) { throw new ArgumentException(SR.VerifyEnclaveReportFailed); From 0c898c37c99b3776dbe8d50928e529602b1a41fe Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Wed, 29 Jul 2020 11:33:58 -0700 Subject: [PATCH 12/38] ae apishould tests for linux --- .../tests/ManualTests/AlwaysEncrypted/ApiShould.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index bb74323fe0..098e29c2c3 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -20,7 +20,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted /// Always Encrypted public API Manual tests. /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - [PlatformSpecific(TestPlatforms.Windows)] + // [PlatformSpecific(TestPlatforms.Windows)] public class ApiShould : IClassFixture, IDisposable { private SQLSetupStrategyCertStoreProvider fixture; From 361505ad572520f8455e88bc5fd26759304a2d81 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Wed, 29 Jul 2020 12:37:11 -0700 Subject: [PATCH 13/38] test akv fixture --- .../tests/ManualTests/AlwaysEncrypted/ApiShould.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index 098e29c2c3..db82fe9586 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -20,14 +20,14 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted /// Always Encrypted public API Manual tests. /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - // [PlatformSpecific(TestPlatforms.Windows)] - public class ApiShould : IClassFixture, IDisposable + //[PlatformSpecific(TestPlatforms.Windows)] + public class ApiShould : IClassFixture, IDisposable { - private SQLSetupStrategyCertStoreProvider fixture; + private SQLSetupStrategyAzureKeyVault fixture; private readonly string tableName; - public ApiShould(SQLSetupStrategyCertStoreProvider fixture) + public ApiShould(SQLSetupStrategyAzureKeyVault fixture) { this.fixture = fixture; tableName = fixture.ApiTestTable.Name; From c9785ea184f491ca8af54f6b7c977df90785cc6f Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Wed, 29 Jul 2020 16:01:51 -0700 Subject: [PATCH 14/38] Update SQLSetupStrategy.cs --- .../AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index dc165a2747..09459eb4b5 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -12,7 +12,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { public class SQLSetupStrategy : IDisposable { - internal const string ColumnEncryptionAlgorithmName = @"AEAD_AES_256_CBC_HMAC_SHA256"; + internal const string ColumnEncryptionAlgorithmName = @"AEAD_AES_256_CBC_HMAC_SHA_256"; protected internal readonly X509Certificate2 certificate; public string keyPath { get; internal set; } From 50c5b1240ee53d287befc508f172d7b1ab62bec9 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Wed, 29 Jul 2020 16:11:14 -0700 Subject: [PATCH 15/38] bulkcopyae akv test --- .../tests/ManualTests/AlwaysEncrypted/ApiShould.cs | 8 ++++---- .../tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs | 8 ++++---- .../AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index db82fe9586..bb74323fe0 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -20,14 +20,14 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted /// Always Encrypted public API Manual tests. /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - //[PlatformSpecific(TestPlatforms.Windows)] - public class ApiShould : IClassFixture, IDisposable + [PlatformSpecific(TestPlatforms.Windows)] + public class ApiShould : IClassFixture, IDisposable { - private SQLSetupStrategyAzureKeyVault fixture; + private SQLSetupStrategyCertStoreProvider fixture; private readonly string tableName; - public ApiShould(SQLSetupStrategyAzureKeyVault fixture) + public ApiShould(SQLSetupStrategyCertStoreProvider fixture) { this.fixture = fixture; tableName = fixture.ApiTestTable.Name; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs index dccd65736a..9fa0d21a8b 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs @@ -13,14 +13,14 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted /// Always Encrypted public API Manual tests. /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - [PlatformSpecific(TestPlatforms.Windows)] - public class BulkCopyAE : IClassFixture, IDisposable + //[PlatformSpecific(TestPlatforms.Windows)] + public class BulkCopyAE : IClassFixture, IDisposable { - private SQLSetupStrategyCertStoreProvider fixture; + private SQLSetupStrategyAzureKeyVault fixture; private readonly string tableName; - public BulkCopyAE(SQLSetupStrategyCertStoreProvider fixture) + public BulkCopyAE(SQLSetupStrategyAzureKeyVault fixture) { this.fixture = fixture; tableName = fixture.BulkCopyAETestTable.Name; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index 09459eb4b5..dc165a2747 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -12,7 +12,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { public class SQLSetupStrategy : IDisposable { - internal const string ColumnEncryptionAlgorithmName = @"AEAD_AES_256_CBC_HMAC_SHA_256"; + internal const string ColumnEncryptionAlgorithmName = @"AEAD_AES_256_CBC_HMAC_SHA256"; protected internal readonly X509Certificate2 certificate; public string keyPath { get; internal set; } From d1da600950d30a1a672776d24a75d22d2b0e3f82 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 14:31:47 -0700 Subject: [PATCH 16/38] apishould cross platform --- .../ManualTests/AlwaysEncrypted/ApiShould.cs | 17 ++++++++++++----- .../SQLSetupStrategyAzureKeyVault.cs | 2 +- .../TestFixtures/Setup/AkvColumnMasterKey.cs | 7 ++++++- .../TestFixtures/Setup/ColumnMasterKey.cs | 10 +++------- .../TestFixtures/Setup/CspColumnMasterKey.cs | 4 ++-- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index bb74323fe0..959376e2ad 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; @@ -20,16 +21,22 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted /// Always Encrypted public API Manual tests. /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - [PlatformSpecific(TestPlatforms.Windows)] - public class ApiShould : IClassFixture, IDisposable + public class ApiShould : IDisposable { - private SQLSetupStrategyCertStoreProvider fixture; + private SQLSetupStrategy fixture; private readonly string tableName; - public ApiShould(SQLSetupStrategyCertStoreProvider fixture) + public ApiShould() { - this.fixture = fixture; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + fixture = new SQLSetupStrategyCertStoreProvider(); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + fixture = new SQLSetupStrategyAzureKeyVault(); + } tableName = fixture.ApiTestTable.Name; } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyAzureKeyVault.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyAzureKeyVault.cs index 288e6f069a..b144673e82 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyAzureKeyVault.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategyAzureKeyVault.cs @@ -36,7 +36,7 @@ public SQLSetupStrategyAzureKeyVault() : base() internal override void SetupDatabase() { - ColumnMasterKey akvColumnMasterKey = new AkvColumnMasterKey(GenerateUniqueName("AKVCMK"), akvUrl: DataTestUtility.AKVUrl); + ColumnMasterKey akvColumnMasterKey = new AkvColumnMasterKey(GenerateUniqueName("AKVCMK"), akvUrl: DataTestUtility.AKVUrl, AkvStoreProvider, DataTestUtility.EnclaveEnabled); databaseObjects.Add(akvColumnMasterKey); List akvColumnEncryptionKeys = CreateColumnEncryptionKeys(akvColumnMasterKey, 2, AkvStoreProvider); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs index 5f3f51f72e..f92b93c908 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs @@ -2,16 +2,21 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; + namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup { public class AkvColumnMasterKey : ColumnMasterKey { public override string KeyPath { get; } - public AkvColumnMasterKey(string name, string akvUrl) : base(name) + public AkvColumnMasterKey(string name, string akvUrl, SqlColumnEncryptionKeyStoreProvider akvStoreProvider, bool allEnclaveComputations) : base(name) { KeyStoreProviderName = @"AZURE_KEY_VAULT"; KeyPath = akvUrl; + + byte[] cmkSign = akvStoreProvider.SignColumnMasterKeyMetadata(KeyPath, allEnclaveComputations); + CmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); } } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs index 5eb02ffcd9..792acc05b7 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs @@ -3,9 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Data; -using System.Data.SqlTypes; -using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup { @@ -17,21 +14,20 @@ protected ColumnMasterKey(string name) : base(name) } protected string KeyStoreProviderName { get; set; } - protected string cmkSignStr { get; set; } + protected string CmkSignStr { get; set; } public abstract string KeyPath { get; } public override void Create(SqlConnection sqlConnection) { string sql; - var connStrings = sqlConnection.ConnectionString; - if (DataTestUtility.EnclaveEnabled && !String.IsNullOrEmpty(cmkSignStr)) + if (DataTestUtility.EnclaveEnabled && !string.IsNullOrEmpty(CmkSignStr)) { sql = $@"CREATE COLUMN MASTER KEY [{Name}] WITH ( KEY_STORE_PROVIDER_NAME = N'{KeyStoreProviderName}', KEY_PATH = N'{KeyPath}', - ENCLAVE_COMPUTATIONS (SIGNATURE = {cmkSignStr}) + ENCLAVE_COMPUTATIONS (SIGNATURE = {CmkSignStr}) );"; } else diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs index 22b31ab888..7e909ab023 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs @@ -21,7 +21,7 @@ public CspColumnMasterKey(string name, string certificateThumbprint, SqlColumnEn KeyPath = string.Concat(CertificateStoreLocation.ToString(), "/", CertificateStoreName.ToString(), "/", Thumbprint); byte[] cmkSign = certStoreProvider.SignColumnMasterKeyMetadata(KeyPath, allEnclaveComputations); - cmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); + CmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); } public CspColumnMasterKey(string name, string providerName, string cspKeyPath, SqlColumnEncryptionKeyStoreProvider certStoreProvider, bool allEnclaveComputations) : base(name) @@ -29,7 +29,7 @@ public CspColumnMasterKey(string name, string providerName, string cspKeyPath, S KeyStoreProviderName = providerName; KeyPath = cspKeyPath; byte[] cmkSign = certStoreProvider.SignColumnMasterKeyMetadata(KeyPath, allEnclaveComputations); - cmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); + CmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); } } From 2a93a2eeb56e4899339153386dab559108fc3618 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 14:57:06 -0700 Subject: [PATCH 17/38] test fixture changes --- .../ManualTests/AlwaysEncrypted/ApiShould.cs | 1 - .../ManualTests/AlwaysEncrypted/BulkCopyAE.cs | 20 ++++++++++++------- .../AlwaysEncrypted/ExceptionTestAKVStore.cs | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index 959376e2ad..a3a6d7d5d6 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -19,7 +19,6 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { /// /// Always Encrypted public API Manual tests. - /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// public class ApiShould : IDisposable { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs index 9fa0d21a8b..f97deb99f8 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs @@ -4,6 +4,7 @@ using System; using System.Data; +using System.Runtime.InteropServices; using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; using Xunit; @@ -11,19 +12,24 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { /// /// Always Encrypted public API Manual tests. - /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - //[PlatformSpecific(TestPlatforms.Windows)] - public class BulkCopyAE : IClassFixture, IDisposable + public class BulkCopyAE : IDisposable { - private SQLSetupStrategyAzureKeyVault fixture; + private SQLSetupStrategy fixture; private readonly string tableName; - public BulkCopyAE(SQLSetupStrategyAzureKeyVault fixture) + public BulkCopyAE(SQLSetupStrategy fixture) { - this.fixture = fixture; - tableName = fixture.BulkCopyAETestTable.Name; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + fixture = new SQLSetupStrategyCertStoreProvider(); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + fixture = new SQLSetupStrategyAzureKeyVault(); + } + tableName = fixture.ApiTestTable.Name; } [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs index 50eccd0b9e..a9503d69de 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs @@ -163,7 +163,7 @@ public void InvalidCertificatePath() Assert.Matches(errorMessage, ex2.Message); } - // [InlineData(true)] -> Enable with AE v2 + [InlineData(true)] [InlineData(false)] [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))] public void AkvStoreProviderVerifyFunctionWithInvalidSignature(bool fEnclaveEnabled) From 743d6ce3f36f07ec52278a4b9c336713ba4eb725 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 15:01:15 -0700 Subject: [PATCH 18/38] Update BulkCopyAE.cs --- .../tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs index f97deb99f8..ff9aa5002e 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs @@ -19,7 +19,7 @@ public class BulkCopyAE : IDisposable private readonly string tableName; - public BulkCopyAE(SQLSetupStrategy fixture) + public BulkCopyAE() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { From 81654ccd221c7a03b841c7afa3cea795c6b6628f Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 16:11:21 -0700 Subject: [PATCH 19/38] Update BulkCopyAE.cs --- .../tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs index ff9aa5002e..d51a21f358 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs @@ -29,7 +29,7 @@ public BulkCopyAE() { fixture = new SQLSetupStrategyAzureKeyVault(); } - tableName = fixture.ApiTestTable.Name; + tableName = fixture.BulkCopyAETestTable.Name; } [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] From 9ab0eace2d2a92c1c7742f3279b5d738ff3d789e Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 17:08:00 -0700 Subject: [PATCH 20/38] test platform specific fixtures --- .../ManualTests/AlwaysEncrypted/ApiShould.cs | 18 +++++++--------- .../ManualTests/AlwaysEncrypted/BulkCopyAE.cs | 21 +++++++------------ .../TestFixtures/SQLSetupStrategy.cs | 12 +++++++++++ 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index a3a6d7d5d6..59b644b63a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -8,7 +8,6 @@ using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; @@ -19,23 +18,18 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { /// /// Always Encrypted public API Manual tests. + /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - public class ApiShould : IDisposable + //[PlatformSpecific(TestPlatforms.Windows)] + public class ApiShould : IClassFixture, IDisposable { private SQLSetupStrategy fixture; private readonly string tableName; - public ApiShould() + public ApiShould(PlatformSpecificTestContext testContext) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - fixture = new SQLSetupStrategyCertStoreProvider(); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - fixture = new SQLSetupStrategyAzureKeyVault(); - } + fixture = testContext.Fixture; tableName = fixture.ApiTestTable.Name; } @@ -765,12 +759,14 @@ public void TestExecuteReaderWithCommandBehavior(string connection, CommandBehav // select the set of rows that were inserted just now. using (SqlCommand sqlCommand = new SqlCommand( + // remove customerid from the where clause and the test passes cmdText: $"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @FirstName AND CustomerId = @CustomerId", connection: sqlConnection, transaction: null, columnEncryptionSetting: SqlCommandColumnEncryptionSetting.Enabled)) { sqlCommand.Parameters.AddWithValue(@"FirstName", values[1]); + // comment this out to make test pass sqlCommand.Parameters.AddWithValue(@"CustomerId", values[0]); IAsyncResult asyncResult = sqlCommand.BeginExecuteReader(commandBehavior); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs index d51a21f358..cf8bf0a340 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs @@ -4,7 +4,6 @@ using System; using System.Data; -using System.Runtime.InteropServices; using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; using Xunit; @@ -12,23 +11,18 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { /// /// Always Encrypted public API Manual tests. + /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - public class BulkCopyAE : IDisposable + [PlatformSpecific(TestPlatforms.Windows)] + public class BulkCopyAE : IClassFixture, IDisposable { - private SQLSetupStrategy fixture; + private SQLSetupStrategyCertStoreProvider fixture; private readonly string tableName; - public BulkCopyAE() + public BulkCopyAE(SQLSetupStrategyCertStoreProvider fixture) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - fixture = new SQLSetupStrategyCertStoreProvider(); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - fixture = new SQLSetupStrategyAzureKeyVault(); - } + this.fixture = fixture; tableName = fixture.BulkCopyAETestTable.Name; } @@ -40,7 +34,7 @@ public void TestBulkCopyString(string connectionString) dataTable.Columns.Add("c1", typeof(string)); var dataRow = dataTable.NewRow(); - String result = "stringValue"; + string result = "stringValue"; dataRow["c1"] = result; dataTable.Rows.Add(dataRow); dataTable.AcceptChanges(); @@ -64,6 +58,7 @@ public void TestBulkCopyString(string connectionString) bulkCopy.WriteToServer(dataTable); string queryString = "SELECT * FROM [" + tableName + "];"; + SqlCommand command = new SqlCommand(queryString, connection); SqlDataReader reader = command.ExecuteReader(); reader.Read(); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index dc165a2747..3c7f105c1c 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup; using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.TestFixtures.Setup; @@ -253,4 +254,15 @@ public void Dispose() } } } + + public class PlatformSpecificTestContext + { + private SQLSetupStrategy certStoreFixture = new SQLSetupStrategyCertStoreProvider(); + private SQLSetupStrategy akvFixture = new SQLSetupStrategyAzureKeyVault(); + + public SQLSetupStrategy Fixture + { + get => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? certStoreFixture : akvFixture; + } + } } From 170ddc9ca1ac5964231e9eaeab60009d2f2c39df Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 17:18:40 -0700 Subject: [PATCH 21/38] test platform specific fixtures --- .../ManualTests/AlwaysEncrypted/ApiShould.cs | 4 ++-- .../TestFixtures/SQLSetupStrategy.cs | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index 59b644b63a..ae33983f47 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -27,9 +27,9 @@ public class ApiShould : IClassFixture, IDisposable private readonly string tableName; - public ApiShould(PlatformSpecificTestContext testContext) + public ApiShould(PlatformSpecificTestContext context) { - fixture = testContext.Fixture; + fixture = context.Fixture; tableName = fixture.ApiTestTable.Name; } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index 3c7f105c1c..87263880cd 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -257,12 +257,24 @@ public void Dispose() public class PlatformSpecificTestContext { - private SQLSetupStrategy certStoreFixture = new SQLSetupStrategyCertStoreProvider(); - private SQLSetupStrategy akvFixture = new SQLSetupStrategyAzureKeyVault(); + private SQLSetupStrategy certStoreFixture; + private SQLSetupStrategy akvFixture; + + public PlatformSpecificTestContext() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + certStoreFixture = new SQLSetupStrategyCertStoreProvider(); + } + else + { + akvFixture = new SQLSetupStrategyAzureKeyVault(); + } + } public SQLSetupStrategy Fixture { - get => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? certStoreFixture : akvFixture; + get => certStoreFixture ?? akvFixture; } } } From ba1b31aca185f480f247e2b5774bf8c953da39ad Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 22:25:50 -0700 Subject: [PATCH 22/38] update ae tests for linux --- .../ManualTests/AlwaysEncrypted/ApiShould.cs | 2 -- .../ManualTests/AlwaysEncrypted/BulkCopyAE.cs | 10 ++++----- .../AlwaysEncrypted/BulkCopyAEErrorMessage.cs | 22 +++++++++---------- .../AlwaysEncrypted/End2EndSmokeTests.cs | 9 ++++---- .../AlwaysEncrypted/SqlBulkCopyTruncation.cs | 11 +++++----- .../AlwaysEncrypted/SqlNullValues.cs | 13 +++++------ .../TestFixtures/SQLSetupStrategy.cs | 13 +++++------ 7 files changed, 35 insertions(+), 45 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index ae33983f47..387a0e9752 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -18,9 +18,7 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { /// /// Always Encrypted public API Manual tests. - /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - //[PlatformSpecific(TestPlatforms.Windows)] public class ApiShould : IClassFixture, IDisposable { private SQLSetupStrategy fixture; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs index cf8bf0a340..46a5181335 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs @@ -11,18 +11,16 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { /// /// Always Encrypted public API Manual tests. - /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - [PlatformSpecific(TestPlatforms.Windows)] - public class BulkCopyAE : IClassFixture, IDisposable + public class BulkCopyAE : IClassFixture, IDisposable { - private SQLSetupStrategyCertStoreProvider fixture; + private SQLSetupStrategy fixture; private readonly string tableName; - public BulkCopyAE(SQLSetupStrategyCertStoreProvider fixture) + public BulkCopyAE(PlatformSpecificTestContext context) { - this.fixture = fixture; + fixture = context.Fixture; tableName = fixture.BulkCopyAETestTable.Name; } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAEErrorMessage.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAEErrorMessage.cs index 111c64fd43..cf2da1c4b6 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAEErrorMessage.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAEErrorMessage.cs @@ -10,20 +10,18 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { /// /// Always Encrypted public API Manual tests. - /// TODO: These tests are marked as Windows only for now but should be run for all platforms once the Master Key is accessible to this app from Azure Key Vault. /// - [PlatformSpecific(TestPlatforms.Windows)] - public class BulkCopyAEErrorMessage : IClassFixture + public class BulkCopyAEErrorMessage : IClassFixture { - private SQLSetupStrategyCertStoreProvider _fixture; - + private SQLSetupStrategy _fixture; + private readonly string _tableName; private readonly string _columnName; - public BulkCopyAEErrorMessage(SQLSetupStrategyCertStoreProvider fixture) + public BulkCopyAEErrorMessage(PlatformSpecificTestContext context) { - _fixture = fixture; - _tableName = fixture.BulkCopyAEErrorMessageTestTable.Name; + _fixture = context.Fixture; + _tableName = _fixture.BulkCopyAEErrorMessageTestTable.Name; _columnName = "c1"; } @@ -35,8 +33,8 @@ public void TextToIntErrorMessageTest(string connectionString) DataTable dataTable = CreateDataTable(value); Assert.True(StringToIntTest(connectionString, _tableName, dataTable, value, dataTable.Rows.Count), "Did not get any exceptions for DataTable when converting data from 'string' to 'int' datatype!"); - Assert.True(StringToIntTest(connectionString, _tableName, dataTable.Select(), value, dataTable.Rows.Count),"Did not get any exceptions for DataRow[] when converting data from 'string' to 'int' datatype!"); - Assert.True(StringToIntTest(connectionString, _tableName, dataTable.CreateDataReader(), value, -1),"Did not get any exceptions for DataReader when converting data from 'string' to 'int' datatype!"); + Assert.True(StringToIntTest(connectionString, _tableName, dataTable.Select(), value, dataTable.Rows.Count), "Did not get any exceptions for DataRow[] when converting data from 'string' to 'int' datatype!"); + Assert.True(StringToIntTest(connectionString, _tableName, dataTable.CreateDataReader(), value, -1), "Did not get any exceptions for DataReader when converting data from 'string' to 'int' datatype!"); } private DataTable CreateDataTable(string value) @@ -44,7 +42,7 @@ private DataTable CreateDataTable(string value) var dataTable = new DataTable(); dataTable.Columns.Add(_columnName, typeof(string)); - var dataRow = dataTable.NewRow(); + var dataRow = dataTable.NewRow(); dataRow[_columnName] = value; dataTable.Rows.Add(dataRow); dataTable.AcceptChanges(); @@ -90,7 +88,7 @@ private bool StringToIntTest(string connectionString, string targetTable, object catch (Exception ex) { string pattern; - object[] args = + object[] args = new object[] { string.Empty, value.GetType().Name, targetType, 0, _columnName, rowNo }; if (rowNo == -1) { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs index a8cbde4f1b..88fc0f6f66 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/End2EndSmokeTests.cs @@ -11,16 +11,15 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { - [PlatformSpecific(TestPlatforms.Windows)] - public class End2EndSmokeTests : IClassFixture, IDisposable + public class End2EndSmokeTests : IClassFixture, IDisposable { - private SQLSetupStrategyCertStoreProvider fixture; + private SQLSetupStrategy fixture; private readonly string tableName; - public End2EndSmokeTests(SQLSetupStrategyCertStoreProvider fixture) + public End2EndSmokeTests(PlatformSpecificTestContext context) { - this.fixture = fixture; + fixture = context.Fixture; tableName = fixture.End2EndSmokeTable.Name; } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs index cd2c2dadc9..32dd86cd94 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlBulkCopyTruncation.cs @@ -11,17 +11,16 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { - [PlatformSpecific(TestPlatforms.Windows)] - public class SqlBulkCopyTruncation : IClassFixture + public class SqlBulkCopyTruncation : IClassFixture { - private SQLSetupStrategyCertStoreProvider _fixture; + private SQLSetupStrategy _fixture; private readonly Dictionary tableNames = new Dictionary(); - public SqlBulkCopyTruncation(SQLSetupStrategyCertStoreProvider fixture) + public SqlBulkCopyTruncation(PlatformSpecificTestContext context) { - _fixture = fixture; - tableNames = fixture.sqlBulkTruncationTableNames; + _fixture = context.Fixture; + tableNames = _fixture.sqlBulkTruncationTableNames; } [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringSetupForAE))] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlNullValues.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlNullValues.cs index 91d29836d0..caa174b3ce 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlNullValues.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/SqlNullValues.cs @@ -11,17 +11,16 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted { - [PlatformSpecific(TestPlatforms.Windows)] - public class SqlNullValuesTests : IClassFixture, IDisposable + public class SqlNullValuesTests : IClassFixture, IDisposable { - private SQLSetupStrategyCertStoreProvider fixture; + private SQLSetupStrategy fixture; private readonly string tableName; private string UdfName = DatabaseHelper.GenerateUniqueName("SqlNullValuesRetVal"); private string UdfNameNotNull = DatabaseHelper.GenerateUniqueName("SqlNullValuesRetValNotNull"); - public SqlNullValuesTests(SQLSetupStrategyCertStoreProvider fixture) + public SqlNullValuesTests(PlatformSpecificTestContext context) { - this.fixture = fixture; + fixture = context.Fixture; tableName = fixture.SqlNullValuesTable.Name; // Disable the cache to avoid false failures. SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false; @@ -33,7 +32,7 @@ public SqlNullValuesTests(SQLSetupStrategyCertStoreProvider fixture) { sqlConnection.Open(); - using (SqlCommand cmd = new SqlCommand(String.Format("INSERT INTO [{0}] (c1) VALUES (@c1)", tableName), sqlConnection, null, SqlCommandColumnEncryptionSetting.Enabled)) + using (SqlCommand cmd = new SqlCommand(string.Format("INSERT INTO [{0}] (c1) VALUES (@c1)", tableName), sqlConnection, null, SqlCommandColumnEncryptionSetting.Enabled)) { SqlParameter param = cmd.Parameters.Add("@c1", SqlDbType.Int); param.Value = DBNull.Value; @@ -79,7 +78,7 @@ public void NullValueTests(string connString, ConnStringColumnEncryptionSetting SqlParameter param; // Create a command similarly - using (SqlCommand cmd = new SqlCommand(String.Format("SELECT c1 FROM [{0}] ORDER BY c2 ASC", tableName), + using (SqlCommand cmd = new SqlCommand(string.Format("SELECT c1 FROM [{0}] ORDER BY c2 ASC", tableName), sqlConn, null, commandSetting)) { using (SqlDataReader reader = cmd.ExecuteReader()) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index 87263880cd..6769bbad37 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -255,10 +255,14 @@ public void Dispose() } } + + // Use this class as the fixture for AE tests to ensure only one platform-specific fixture + // is created for each test class public class PlatformSpecificTestContext { - private SQLSetupStrategy certStoreFixture; - private SQLSetupStrategy akvFixture; + private SQLSetupStrategy certStoreFixture = null; + private SQLSetupStrategy akvFixture = null; + public SQLSetupStrategy Fixture => certStoreFixture ?? akvFixture; public PlatformSpecificTestContext() { @@ -271,10 +275,5 @@ public PlatformSpecificTestContext() akvFixture = new SQLSetupStrategyAzureKeyVault(); } } - - public SQLSetupStrategy Fixture - { - get => certStoreFixture ?? akvFixture; - } } } From 1cad3ff174e1a4e5014003a365eb9298fae21d06 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 30 Jul 2020 23:19:21 -0700 Subject: [PATCH 23/38] minor changes --- .../Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs | 4 ---- .../SqlColumnEncryptionCertificateStoreProvider.Windows.cs | 1 + .../tests/ManualTests/AlwaysEncrypted/ApiShould.cs | 2 -- .../tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs | 1 - .../AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs | 1 - .../AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs | 3 --- 6 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs index c37b43c318..6d040f8a84 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs @@ -4,10 +4,6 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using System.Text; namespace Microsoft.Data.SqlClient { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs index 95096e0865..f524e6ffcc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs @@ -486,6 +486,7 @@ private byte[] RSAEncrypt(byte[] plainText, X509Certificate2 certificate) /// /// Text to decrypt. /// Certificate object. + /// Returns a decrypted blob or throws an exception if there are any errors. private byte[] RSADecrypt(byte[] cipherText, X509Certificate2 certificate) { Debug.Assert((cipherText != null) && (cipherText.Length != 0)); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs index 387a0e9752..5096d15af4 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ApiShould.cs @@ -757,14 +757,12 @@ public void TestExecuteReaderWithCommandBehavior(string connection, CommandBehav // select the set of rows that were inserted just now. using (SqlCommand sqlCommand = new SqlCommand( - // remove customerid from the where clause and the test passes cmdText: $"SELECT CustomerId, FirstName, LastName FROM [{tableName}] WHERE FirstName = @FirstName AND CustomerId = @CustomerId", connection: sqlConnection, transaction: null, columnEncryptionSetting: SqlCommandColumnEncryptionSetting.Enabled)) { sqlCommand.Parameters.AddWithValue(@"FirstName", values[1]); - // comment this out to make test pass sqlCommand.Parameters.AddWithValue(@"CustomerId", values[0]); IAsyncResult asyncResult = sqlCommand.BeginExecuteReader(commandBehavior); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs index 46a5181335..dd2b2b2561 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/BulkCopyAE.cs @@ -56,7 +56,6 @@ public void TestBulkCopyString(string connectionString) bulkCopy.WriteToServer(dataTable); string queryString = "SELECT * FROM [" + tableName + "];"; - SqlCommand command = new SqlCommand(queryString, connection); SqlDataReader reader = command.ExecuteReader(); reader.Read(); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index 6769bbad37..e8f8be85bd 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -255,7 +255,6 @@ public void Dispose() } } - // Use this class as the fixture for AE tests to ensure only one platform-specific fixture // is created for each test class public class PlatformSpecificTestContext diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs index 792acc05b7..4e4cf8acf8 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/ColumnMasterKey.cs @@ -2,13 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup { public abstract class ColumnMasterKey : DbObject { - protected ColumnMasterKey(string name) : base(name) { } From daa2b13e5218783e2d61087ed3b53d34669e726c Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Tue, 4 Aug 2020 15:29:16 -0700 Subject: [PATCH 24/38] netstandard --- .../src/Microsoft.Data.SqlClient.csproj | 32 ++-- ...=> AlwaysEncryptedAttestationException.cs} | 0 ...ncryptedEnclaveProviderUtils.NetCoreApp.cs | 142 ---------------- .../AlwaysEncryptedEnclaveProviderUtils.cs | 152 ++++++++++++++++++ ...> AzureAttestationBasedEnclaveProvider.cs} | 0 ...e.NetCoreApp.cs => EnclaveProviderBase.cs} | 0 ...e.NetCoreApp.cs => EnclaveSessionCache.cs} | 0 ...cs => VirtualSecureModeEnclaveProvider.cs} | 0 ...> VirtualSecureModeEnclaveProviderBase.cs} | 0 9 files changed, 170 insertions(+), 156 deletions(-) rename src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/{AlwaysEncryptedAttestationException.NetCoreApp.cs => AlwaysEncryptedAttestationException.cs} (100%) delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs create mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs rename src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/{AzureAttestationBasedEnclaveProvider.NetCoreApp.cs => AzureAttestationBasedEnclaveProvider.cs} (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/{EnclaveProviderBase.NetCoreApp.cs => EnclaveProviderBase.cs} (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/{EnclaveSessionCache.NetCoreApp.cs => EnclaveSessionCache.cs} (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/{VirtualSecureModeEnclaveProvider.NetCoreApp.cs => VirtualSecureModeEnclaveProvider.cs} (100%) rename src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/{VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs => VirtualSecureModeEnclaveProviderBase.cs} (100%) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 29a0f61505..986776adb2 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -1,7 +1,7 @@  Microsoft.Data.SqlClient - netcoreapp2.1;netcoreapp3.1;netstandard2.0 + netstandard2.0;netstandard2.1 SR.PlatformNotSupported_DataSqlClient $(OS) true @@ -223,11 +223,25 @@ - - - + + + + + + + + + + + + + + + + + @@ -235,18 +249,8 @@ - - - - - - - - - - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedAttestationException.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedAttestationException.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedAttestationException.NetCoreApp.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedAttestationException.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs deleted file mode 100644 index 59261f57c0..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Linq; -using System.Security.Cryptography; - -namespace Microsoft.Data.SqlClient -{ - internal class EnclavePublicKey - { - public byte[] PublicKey { get; set; } - - public EnclavePublicKey(byte[] payload) - { - PublicKey = payload; - } - } - - internal class EnclaveDiffieHellmanInfo - { - public int Size { get; private set; } - - public byte[] PublicKey { get; private set; } - - public byte[] PublicKeySignature { get; private set; } - - public EnclaveDiffieHellmanInfo(byte[] payload) - { - Size = payload.Length; - - int offset = 0; - int publicKeySize = BitConverter.ToInt32(payload, offset); - offset += sizeof(int); - - int publicKeySignatureSize = BitConverter.ToInt32(payload, offset); - offset += sizeof(int); - - PublicKey = payload.Skip(offset).Take(publicKeySize).ToArray(); - offset += publicKeySize; - - PublicKeySignature = payload.Skip(offset).Take(publicKeySignatureSize).ToArray(); - offset += publicKeySignatureSize; - } - } - - internal enum EnclaveType - { - None = 0, - - Vbs = 1, - - Sgx = 2 - } - - // Methods for converting keys between different formats - internal class KeyConverter - { - // Extracts the public key's modulus and exponent from an RSA public key blob - // and returns an RSAParameters object - internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob) - { - // The RSA public key blob is structured as follows: - // BCRYPT_RSAKEY_BLOB header - // byte[cbPublicExp] publicExponent - // byte[cbModulus] modulus - - // The exponent is the final 3 bytes in the header - // The modulus is the final 512 bytes in the key blob - const int modulusSize = 512; - const int exponentSize = 3; - int headerSize = keyBlob.Length - modulusSize; - int exponentOffset = headerSize - exponentSize; - int modulusOffset = exponentOffset + exponentSize; - - return new RSAParameters() - { - Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(), - Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray() - }; - } - - // Extracts the public key's X and Y coordinates from an ECC public key blob - // and returns an ECParameters object - internal static ECParameters ECCPublicKeyBlobToParams(byte[] keyBlob) - { - // The ECC public key blob is structured as follows: - // BCRYPT_ECCKEY_BLOB header - // byte[cbKey] X - // byte[cbKey] Y - - // The size of each coordinate is found after the first 4 byes (magic number) - const int keySizeOffset = 4; - int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset); - int keyOffset = keySizeOffset + sizeof(int); - - return new ECParameters - { - Curve = ECCurve.NamedCurves.nistP384, - Q = new ECPoint - { - X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(), - Y = keyBlob.Skip(keyOffset + keySize).Take(keySize).ToArray() - }, - }; - } - - // Serializes an ECDiffieHellmanPublicKey to an ECC public key blob - // "ECDiffieHellmanPublicKey.ToByteArray() doesn't have a (standards-)defined export - // format. The version used by ECDiffieHellmanPublicKeyCng is Windows-specific" - // from https://github.com/dotnet/runtime/issues/27276 - // => ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix - internal static byte[] ECDHPublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey) - { - // Size of an ECC key blob = 104 bytes - // BCRYPT_ECCKEY_BLOB header = 8 bytes - // key = 96 bytes (48 bytes each coordinate) - const int keyBlobSize = 104; - const int headerSize = 8; - const int KeySize = 48; - byte[] keyBlob = new byte[keyBlobSize]; - - // magic number (BCRYPT_ECDH_PUBLIC_P384_MAGIC) - keyBlob[0] = 0x45; - keyBlob[1] = 0x43; - keyBlob[2] = 0x4b; - keyBlob[3] = 0x33; - // key size - keyBlob[4] = KeySize; - keyBlob[5] = 0x00; - keyBlob[6] = 0x00; - keyBlob[7] = 0x00; - - ECParameters ecParams = publicKey.ExportParameters(); - // copy x and y coordinates to key blob - Array.Copy(ecParams.Q.X, 0, keyBlob, headerSize, KeySize); - Array.Copy(ecParams.Q.Y, 0, keyBlob, headerSize + KeySize, KeySize); - return keyBlob; - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs new file mode 100644 index 0000000000..92357fa760 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs @@ -0,0 +1,152 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Linq; +using System.Security.Cryptography; + +namespace Microsoft.Data.SqlClient +{ + internal class EnclavePublicKey + { + public byte[] PublicKey { get; set; } + + public EnclavePublicKey(byte[] payload) + { + PublicKey = payload; + } + } + + internal class EnclaveDiffieHellmanInfo + { + public int Size { get; private set; } + + public byte[] PublicKey { get; private set; } + + public byte[] PublicKeySignature { get; private set; } + + public EnclaveDiffieHellmanInfo(byte[] payload) + { + Size = payload.Length; + + int offset = 0; + int publicKeySize = BitConverter.ToInt32(payload, offset); + offset += sizeof(int); + + int publicKeySignatureSize = BitConverter.ToInt32(payload, offset); + offset += sizeof(int); + + PublicKey = payload.Skip(offset).Take(publicKeySize).ToArray(); + offset += publicKeySize; + + PublicKeySignature = payload.Skip(offset).Take(publicKeySignatureSize).ToArray(); + offset += publicKeySignatureSize; + } + } + + internal enum EnclaveType + { + None = 0, + + Vbs = 1, + + Sgx = 2 + } + + // Contains methods to convert cryptography keys between different formats. + internal sealed class KeyConverter + { + // The RSA public key blob is structured as follows: + // BCRYPT_RSAKEY_BLOB header + // byte[ExponentSize] publicExponent + // byte[ModulusSize] modulus + private readonly struct RSAPublicKeyBlob + { + // Size of an RSA public key blob + internal static readonly int Size = 539; + // Size of the BCRYPT_RSAKEY_BLOB header + internal static readonly int HeaderSize = 27; + // Size of the exponent (final 3 bytes of the header) + internal static readonly int ExponentSize = 3; + // Size of the modulus (remaining bytes after the header) + internal static readonly int ModulusSize = Size - HeaderSize; + internal static readonly int ExponentOffset = HeaderSize - ExponentSize; + internal static readonly int ModulusOffset = HeaderSize; + } + + // The ECC public key blob is structured as follows: + // BCRYPT_ECCKEY_BLOB header + // byte[KeySize] X + // byte[KeySize] Y + private readonly struct ECCPublicKeyBlob + { + // Size of an ECC public key blob + internal static readonly int Size = 104; + // Size of the BCRYPT_ECCKEY_BLOB header + internal static readonly int HeaderSize = 8; + // Size of each coordinate + internal static readonly int KeySize = (Size - HeaderSize) / 2; + } + + // Magic numbers identifying blob types + private readonly struct KeyBlobMagicNumber + { + internal static readonly byte[] ECDHPublicP384 = new byte[] { 0x45, 0x43, 0x4b, 0x33 }; + } + + // Extracts the public key's modulus and exponent from an RSA public key blob + // and returns an RSAParameters object + internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob) + { + Debug.Assert(keyBlob.Length == RSAPublicKeyBlob.Size, + $"RSA public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {RSAPublicKeyBlob.Size}"); + return new RSAParameters() + { + Exponent = keyBlob.Skip(RSAPublicKeyBlob.ExponentOffset).Take(RSAPublicKeyBlob.ExponentSize).ToArray(), + Modulus = keyBlob.Skip(RSAPublicKeyBlob.ModulusOffset).Take(RSAPublicKeyBlob.ModulusSize).ToArray() + }; + } + + // Extracts the public key's X and Y coordinates from an ECC public key blob + // and returns an ECParameters object + internal static ECParameters ECCPublicKeyBlobToParams(byte[] keyBlob) + { + Debug.Assert(keyBlob.Length == ECCPublicKeyBlob.Size, + $"ECC public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {ECCPublicKeyBlob.Size}"); + return new ECParameters + { + Curve = ECCurve.NamedCurves.nistP384, + Q = new ECPoint + { + X = keyBlob.Skip(ECCPublicKeyBlob.HeaderSize).Take(ECCPublicKeyBlob.KeySize).ToArray(), + Y = keyBlob.Skip(ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize).Take(ECCPublicKeyBlob.KeySize).ToArray() + }, + }; + } + + // Serializes an ECDiffieHellmanPublicKey to an ECC public key blob + // "ECDiffieHellmanPublicKey.ToByteArray() doesn't have a (standards-)defined export + // format. The version used by ECDiffieHellmanPublicKeyCng is Windows-specific" + // from https://github.com/dotnet/runtime/issues/27276 + // => ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix + internal static byte[] ECDHPublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey) + { + byte[] keyBlob = new byte[ECCPublicKeyBlob.Size]; + + // Set magic number + Array.Copy(KeyBlobMagicNumber.ECDHPublicP384, 0, keyBlob, 0, 4); + // Set key size + keyBlob[4] = (byte)ECCPublicKeyBlob.KeySize; + + ECPoint ecPoint = publicKey.ExportParameters().Q; + Debug.Assert(ecPoint.X.Length == ECCPublicKeyBlob.KeySize && ecPoint.Y.Length == ECCPublicKeyBlob.KeySize, + $"ECDH public key was not the expected length. Actual (X): {ecPoint.X.Length}. Actual (Y): {ecPoint.Y.Length} Expected: {ECCPublicKeyBlob.Size}"); + // Copy x and y coordinates to key blob + Array.Copy(ecPoint.X, 0, keyBlob, ECCPublicKeyBlob.HeaderSize, ECCPublicKeyBlob.KeySize); + Array.Copy(ecPoint.Y, 0, keyBlob, ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize, ECCPublicKeyBlob.KeySize); + return keyBlob; + } + } +} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.NetCoreApp.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.NetCoreApp.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveProviderBase.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveSessionCache.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveSessionCache.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveSessionCache.NetCoreApp.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveSessionCache.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.NetCoreApp.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs From c12121f13c3e8fe84dc62968fdc0505b0b7887cd Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Wed, 5 Aug 2020 09:30:53 -0700 Subject: [PATCH 25/38] netstandard changes --- .../ref/Microsoft.Data.SqlClient.csproj | 2 +- .../src/Microsoft.Data.SqlClient.csproj | 8 ++--- .../Microsoft.Data.SqlClient.NSLibrary.csproj | 2 +- tools/specs/Microsoft.Data.SqlClient.nuspec | 29 +++++++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj index b1934599e6..383f69f6af 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj @@ -1,7 +1,7 @@  false - netcoreapp2.1;netcoreapp3.1;netstandard2.0 + netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1 $(ObjFolder)$(Configuration)\$(AssemblyName)\ref\ $(BinFolder)$(Configuration)\$(AssemblyName)\ref\ $(OutputPath)\$(TargetFramework)\Microsoft.Data.SqlClient.xml diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 986776adb2..18c697c483 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -1,7 +1,7 @@  Microsoft.Data.SqlClient - netstandard2.0;netstandard2.1 + netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1 SR.PlatformNotSupported_DataSqlClient $(OS) true @@ -229,6 +229,8 @@ + + @@ -255,10 +257,6 @@ - - - - diff --git a/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj b/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj index 5c1d2ce4c5..27762051a8 100644 --- a/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj +++ b/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0;netstandard2.1 AnyCPU;x86;x64 $(ObjFolder)$(Configuration).$(Platform)\$(AssemblyName) $(BinFolder)$(Configuration).$(Platform)\$(AssemblyName) diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 3e09d83333..362ffdd7c8 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -67,6 +67,17 @@ When using NuGet 3.x this package requires at least version 3.4. + + + + + + + + + + + @@ -93,6 +104,11 @@ When using NuGet 3.x this package requires at least version 3.4. + + + + + @@ -117,6 +133,10 @@ When using NuGet 3.x this package requires at least version 3.4. + + + + @@ -148,6 +168,10 @@ When using NuGet 3.x this package requires at least version 3.4. + + + + @@ -169,5 +193,10 @@ When using NuGet 3.x this package requires at least version 3.4. + + + + + From f2648066a1b273dc02203ace6871cb78dfdfa16b Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Wed, 5 Aug 2020 16:45:56 -0700 Subject: [PATCH 26/38] change targetframework property to targetframeworks --- src/Microsoft.Data.SqlClient/tests/Directory.Build.props | 8 ++++---- .../NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/Directory.Build.props b/src/Microsoft.Data.SqlClient/tests/Directory.Build.props index 5d26340cf8..2df7ae0080 100644 --- a/src/Microsoft.Data.SqlClient/tests/Directory.Build.props +++ b/src/Microsoft.Data.SqlClient/tests/Directory.Build.props @@ -15,20 +15,20 @@ - $(TargetNetCoreVersion) + $(TargetNetCoreVersion) - $(TargetNetCoreVersion) - $(TargetNetFxVersion) + $(TargetNetCoreVersion) + $(TargetNetFxVersion) - $(Configuration.Split('-')[0]) + $(Configuration.Split('-')[0]) diff --git a/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj b/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj index 27762051a8..7991706e56 100644 --- a/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj +++ b/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj @@ -1,7 +1,7 @@ - netstandard2.0;netstandard2.1 + netstandard2.0;netstandard2.1 AnyCPU;x86;x64 $(ObjFolder)$(Configuration).$(Platform)\$(AssemblyName) $(BinFolder)$(Configuration).$(Platform)\$(AssemblyName) From 04483621be9cf5365b06c629828783e1be81ba5b Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Fri, 7 Aug 2020 11:42:17 -0700 Subject: [PATCH 27/38] Update SqlColumnEncryptionCertificateStoreProvider.Windows.cs --- .../SqlColumnEncryptionCertificateStoreProvider.Windows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs index f524e6ffcc..c6f2786583 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.Windows.cs @@ -482,7 +482,7 @@ private byte[] RSAEncrypt(byte[] plainText, X509Certificate2 certificate) } /// - /// Decrypt the text using specified certificate. + /// Decrypt the data using specified certificate. /// /// Text to decrypt. /// Certificate object. From 9ba0fc918254131be032e51b7d39387b3b8e259c Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Fri, 7 Aug 2020 11:58:09 -0700 Subject: [PATCH 28/38] Address feedback --- .../Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs | 1 + .../Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs index 4a4c952a20..ff722545f5 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs @@ -73,6 +73,7 @@ internal override void GetEnclaveSession(string servername, string attestationUr // Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. internal override SqlEnclaveAttestationParameters GetAttestationParameters(string attestationUrl, byte[] customData, int customDataLength) { + // The key derivation function and hash algorithm name are specified when key derivation is performed ECDiffieHellman clientDHKey = ECDiffieHellman.Create(); clientDHKey.KeySize = DiffieHellmanKeySize; byte[] attestationParam = PrepareAttestationParameters(attestationUrl, customData, customDataLength); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs index 4b0dbcbb72..f5149ab6d9 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs @@ -94,6 +94,7 @@ internal override void GetEnclaveSession(string servername, string attestationUr // Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. internal override SqlEnclaveAttestationParameters GetAttestationParameters(string attestationUrl, byte[] customData, int customDataLength) { + // The key derivation function and hash algorithm name are specified when key derivation is performed ECDiffieHellman clientDHKey = ECDiffieHellman.Create(); clientDHKey.KeySize = DiffieHellmanKeySize; From 104e0d6a37be643523668e126476fb85cfaf89d8 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Tue, 11 Aug 2020 11:11:01 -0700 Subject: [PATCH 29/38] fix culture exceptions in functional tests for ubuntu 18.04 --- .../tests/FunctionalTests/SqlDataRecordTest.cs | 5 +++++ .../tests/FunctionalTests/SqlParameterTest.cs | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs index 56f95b9962..f8aa970e0c 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs @@ -18,6 +18,11 @@ public class SqlDataRecordTest [Fact] public void SqlRecordFillTest() { + // Explicitly set the culture because the default culture for some environments + // (eg Ubuntu 18.04) throws an exception when comparing SqlStrings + // TODO: investigate culture support for Ubuntu 18.04 + System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US"); + SqlMetaData[] metaData = new SqlMetaData[] { new SqlMetaData("col1", SqlDbType.Bit), diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs index 203fcc5a65..8107030ad2 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs @@ -1479,7 +1479,10 @@ public void SqlTypes_SqlSingle() public void SqlTypes_SqlString() { SqlParameter parameter; - SqlString value = new SqlString("XA"); + // Explicitly set the culture because the default culture for some environments + // (eg Ubuntu 18.04) throws an exception when comparing SqlStrings + // TODO: investigate culture support for Ubuntu 18.04 + SqlString value = new SqlString("XA", new System.Globalization.CultureInfo("en-US").LCID); parameter = new SqlParameter(); parameter.SqlValue = value; From 5575f1c44d1f6cf05aa6990b1fa632e120e981aa Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Tue, 11 Aug 2020 16:58:33 -0700 Subject: [PATCH 30/38] revert test changes --- .../tests/FunctionalTests/SqlDataRecordTest.cs | 5 ----- .../tests/FunctionalTests/SqlParameterTest.cs | 5 +---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs index f8aa970e0c..56f95b9962 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs @@ -18,11 +18,6 @@ public class SqlDataRecordTest [Fact] public void SqlRecordFillTest() { - // Explicitly set the culture because the default culture for some environments - // (eg Ubuntu 18.04) throws an exception when comparing SqlStrings - // TODO: investigate culture support for Ubuntu 18.04 - System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US"); - SqlMetaData[] metaData = new SqlMetaData[] { new SqlMetaData("col1", SqlDbType.Bit), diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs index 8107030ad2..203fcc5a65 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs @@ -1479,10 +1479,7 @@ public void SqlTypes_SqlSingle() public void SqlTypes_SqlString() { SqlParameter parameter; - // Explicitly set the culture because the default culture for some environments - // (eg Ubuntu 18.04) throws an exception when comparing SqlStrings - // TODO: investigate culture support for Ubuntu 18.04 - SqlString value = new SqlString("XA", new System.Globalization.CultureInfo("en-US").LCID); + SqlString value = new SqlString("XA"); parameter = new SqlParameter(); parameter.SqlValue = value; From 7a1e9fb20ec5bfc3b721b1375039ad7d9f750e12 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 13 Aug 2020 15:46:50 -0700 Subject: [PATCH 31/38] test against .net standard 2.1 --- build.proj | 8 +-- ...waysEncrypted.AzureKeyVaultProvider.csproj | 2 +- .../add-ons/Directory.Build.props | 1 + .../ref/Microsoft.Data.SqlClient.csproj | 1 + .../src/Microsoft.Data.SqlClient.csproj | 1 + .../tests/Directory.Build.props | 1 + .../Microsoft.Data.SqlClient.Tests.csproj | 12 ++-- ....Data.SqlClient.ManualTesting.Tests.csproj | 58 +++++++++---------- .../Microsoft.Data.SqlClient.NSLibrary.csproj | 1 + 9 files changed, 45 insertions(+), 40 deletions(-) diff --git a/build.proj b/build.proj index edebcec39e..32f1734db9 100644 --- a/build.proj +++ b/build.proj @@ -25,7 +25,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -116,14 +116,14 @@ - + - + diff --git a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj index 9a32df9809..77b6e7e1be 100644 --- a/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj +++ b/src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj @@ -6,7 +6,7 @@ {9073ABEF-92E0-4702-BB23-2C99CEF9BDD7} netcoreapp netfx - Debug;Release;net46-Release;net46-Debug;netcoreapp2.1-Debug;netcoreapp2.1-Release; + Debug;Release;net46-Release;net46-Debug;netcoreapp2.1-Debug;netcoreapp2.1-Release;netcoreapp3.1-Debug;netcoreapp3.1-Release AnyCPU;x86;x64 $(ObjFolder)$(Configuration).$(Platform)\$(AddOnName) $(BinFolder)$(Configuration).$(Platform)\$(AddOnName) diff --git a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props index 4fc891665f..e2303ef132 100644 --- a/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props +++ b/src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props @@ -19,6 +19,7 @@ netcoreapp2.1 + netcoreapp3.1 net46 diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj index 199bfaaf87..0902edd7c1 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.csproj @@ -2,6 +2,7 @@ false netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1 + netstandard2.1 $(ObjFolder)$(Configuration)\$(AssemblyName)\ref\ $(BinFolder)$(Configuration)\$(AssemblyName)\ref\ $(OutputPath)\$(TargetFramework)\Microsoft.Data.SqlClient.xml diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 690befa487..8074efc2e8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -2,6 +2,7 @@ Microsoft.Data.SqlClient netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1 + netstandard2.1 Strings.PlatformNotSupported_DataSqlClient $(OS) true diff --git a/src/Microsoft.Data.SqlClient/tests/Directory.Build.props b/src/Microsoft.Data.SqlClient/tests/Directory.Build.props index 2df7ae0080..3225e9461a 100644 --- a/src/Microsoft.Data.SqlClient/tests/Directory.Build.props +++ b/src/Microsoft.Data.SqlClient/tests/Directory.Build.props @@ -7,6 +7,7 @@ net46 + netcoreapp3.1 netcoreapp2.1 Project diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index ed7e701212..5c4204cc29 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -10,20 +10,20 @@ $(BinFolder)$(Configuration).$(Platform).$(AssemblyName) - - - + + + + + - - @@ -48,7 +48,6 @@ - @@ -60,6 +59,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index 34bd1e6ead..ca9859b551 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -17,46 +17,46 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + Common\System\Collections\DictionaryExtensions.cs @@ -277,7 +277,7 @@ - + diff --git a/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj b/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj index 7991706e56..d526f2497c 100644 --- a/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj +++ b/src/Microsoft.Data.SqlClient/tests/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj @@ -2,6 +2,7 @@ netstandard2.0;netstandard2.1 + netstandard2.1 AnyCPU;x86;x64 $(ObjFolder)$(Configuration).$(Platform)\$(AssemblyName) $(BinFolder)$(Configuration).$(Platform)\$(AssemblyName) From 5285c262328f8aa2ce26fa003449f6090ee2d343 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Fri, 14 Aug 2020 11:35:39 -0700 Subject: [PATCH 32/38] add dispose to new fixture class --- .../AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs index e8f8be85bd..7183655c41 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/SQLSetupStrategy.cs @@ -257,7 +257,7 @@ public void Dispose() // Use this class as the fixture for AE tests to ensure only one platform-specific fixture // is created for each test class - public class PlatformSpecificTestContext + public class PlatformSpecificTestContext : IDisposable { private SQLSetupStrategy certStoreFixture = null; private SQLSetupStrategy akvFixture = null; @@ -274,5 +274,10 @@ public PlatformSpecificTestContext() akvFixture = new SQLSetupStrategyAzureKeyVault(); } } + + public void Dispose() + { + Fixture.Dispose(); + } } } From ec1275045198fbe900d3d2084aea3892962730ee Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Tue, 18 Aug 2020 12:46:06 -0700 Subject: [PATCH 33/38] Update AlwaysEncryptedEnclaveProviderUtils.cs --- .../AlwaysEncryptedEnclaveProviderUtils.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs index 92357fa760..12367987fe 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs @@ -62,7 +62,7 @@ internal sealed class KeyConverter // BCRYPT_RSAKEY_BLOB header // byte[ExponentSize] publicExponent // byte[ModulusSize] modulus - private readonly struct RSAPublicKeyBlob + private sealed class RSAPublicKeyBlob { // Size of an RSA public key blob internal static readonly int Size = 539; @@ -76,11 +76,24 @@ internal sealed class KeyConverter internal static readonly int ModulusOffset = HeaderSize; } + // Extracts the public key's modulus and exponent from an RSA public key blob + // and returns an RSAParameters object + internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob) + { + Debug.Assert(keyBlob.Length == RSAPublicKeyBlob.Size, + $"RSA public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {RSAPublicKeyBlob.Size}"); + return new RSAParameters() + { + Exponent = keyBlob.Skip(RSAPublicKeyBlob.ExponentOffset).Take(RSAPublicKeyBlob.ExponentSize).ToArray(), + Modulus = keyBlob.Skip(RSAPublicKeyBlob.ModulusOffset).Take(RSAPublicKeyBlob.ModulusSize).ToArray() + }; + } + // The ECC public key blob is structured as follows: // BCRYPT_ECCKEY_BLOB header // byte[KeySize] X // byte[KeySize] Y - private readonly struct ECCPublicKeyBlob + private sealed class ECCPublicKeyBlob { // Size of an ECC public key blob internal static readonly int Size = 104; @@ -91,24 +104,11 @@ internal sealed class KeyConverter } // Magic numbers identifying blob types - private readonly struct KeyBlobMagicNumber + private sealed class KeyBlobMagicNumber { internal static readonly byte[] ECDHPublicP384 = new byte[] { 0x45, 0x43, 0x4b, 0x33 }; } - // Extracts the public key's modulus and exponent from an RSA public key blob - // and returns an RSAParameters object - internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob) - { - Debug.Assert(keyBlob.Length == RSAPublicKeyBlob.Size, - $"RSA public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {RSAPublicKeyBlob.Size}"); - return new RSAParameters() - { - Exponent = keyBlob.Skip(RSAPublicKeyBlob.ExponentOffset).Take(RSAPublicKeyBlob.ExponentSize).ToArray(), - Modulus = keyBlob.Skip(RSAPublicKeyBlob.ModulusOffset).Take(RSAPublicKeyBlob.ModulusSize).ToArray() - }; - } - // Extracts the public key's X and Y coordinates from an ECC public key blob // and returns an ECParameters object internal static ECParameters ECCPublicKeyBlobToParams(byte[] keyBlob) From dca6da844de6353cbf6caabb2ba00540d9ba24ed Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Tue, 18 Aug 2020 15:44:13 -0700 Subject: [PATCH 34/38] Update AlwaysEncryptedEnclaveProviderUtils.cs --- .../Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs index 12367987fe..812f1b4d99 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs @@ -62,7 +62,7 @@ internal sealed class KeyConverter // BCRYPT_RSAKEY_BLOB header // byte[ExponentSize] publicExponent // byte[ModulusSize] modulus - private sealed class RSAPublicKeyBlob + private readonly struct RSAPublicKeyBlob { // Size of an RSA public key blob internal static readonly int Size = 539; @@ -93,7 +93,7 @@ internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob) // BCRYPT_ECCKEY_BLOB header // byte[KeySize] X // byte[KeySize] Y - private sealed class ECCPublicKeyBlob + private readonly struct ECCPublicKeyBlob { // Size of an ECC public key blob internal static readonly int Size = 104; @@ -104,7 +104,7 @@ private sealed class ECCPublicKeyBlob } // Magic numbers identifying blob types - private sealed class KeyBlobMagicNumber + private readonly struct KeyBlobMagicNumber { internal static readonly byte[] ECDHPublicP384 = new byte[] { 0x45, 0x43, 0x4b, 0x33 }; } From e57551918675c933c28944a053d0c5b2ffd05afd Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Wed, 19 Aug 2020 09:23:48 -0700 Subject: [PATCH 35/38] Update AlwaysEncryptedEnclaveProviderUtils.cs --- .../Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs index 812f1b4d99..23abf6b247 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs @@ -104,6 +104,7 @@ internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob) } // Magic numbers identifying blob types + // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/cba27df5-4880-4f95-a879-783f8657e53b private readonly struct KeyBlobMagicNumber { internal static readonly byte[] ECDHPublicP384 = new byte[] { 0x45, 0x43, 0x4b, 0x33 }; From 58235f799c3e8b9feafc05ae4fcecc2b3473ac38 Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Thu, 20 Aug 2020 16:11:38 -0700 Subject: [PATCH 36/38] casing --- .../AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs | 2 +- .../AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs index a9469d79b6..353f7ac97a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/AkvColumnMasterKey.cs @@ -17,7 +17,7 @@ public AkvColumnMasterKey(string name, string akvUrl, SqlColumnEncryptionKeyStor // For keys which allow enclave computation byte[] cmkSign = akvProvider.SignColumnMasterKeyMetadata(akvUrl, allowEnclaveComputations); - cmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); + CmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); } } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs index 9e26b1105e..8a27b2b860 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/TestFixtures/Setup/CspColumnMasterKey.cs @@ -21,7 +21,7 @@ public CspColumnMasterKey(string name, string certificateThumbprint, SqlColumnEn KeyPath = string.Concat(CertificateStoreLocation.ToString(), "/", CertificateStoreName.ToString(), "/", Thumbprint); byte[] cmkSign = certStoreProvider.SignColumnMasterKeyMetadata(KeyPath, allowEnclaveComputations); - cmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); + CmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); } public CspColumnMasterKey(string name, string providerName, string cspKeyPath, SqlColumnEncryptionKeyStoreProvider certStoreProvider, bool allowEnclaveComputations) : base(name) @@ -29,7 +29,7 @@ public CspColumnMasterKey(string name, string providerName, string cspKeyPath, S KeyStoreProviderName = providerName; KeyPath = cspKeyPath; byte[] cmkSign = certStoreProvider.SignColumnMasterKeyMetadata(KeyPath, allowEnclaveComputations); - cmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); + CmkSignStr = string.Concat("0x", BitConverter.ToString(cmkSign).Replace("-", string.Empty)); } } From 5d0fde82ad860573e319f8479cfdf6cb3cab227b Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Fri, 21 Aug 2020 00:21:11 -0700 Subject: [PATCH 37/38] Address comments --- .../SimulatorEnclaveProvider.NetCoreApp.cs | 13 +++++++------ .../VirtualSecureModeEnclaveProviderBase.cs | 2 +- .../Microsoft.Data.SqlClient.Tests.csproj | 2 +- .../AlwaysEncrypted/EnclaveAzureDatabaseTests.cs | 1 - 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SimulatorEnclaveProvider.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SimulatorEnclaveProvider.NetCoreApp.cs index 064742be3c..bed6ada9e3 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SimulatorEnclaveProvider.NetCoreApp.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SimulatorEnclaveProvider.NetCoreApp.cs @@ -30,15 +30,15 @@ internal override void GetEnclaveSession(EnclaveSessionParameters enclaveSession // Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave. internal override SqlEnclaveAttestationParameters GetAttestationParameters(string attestationUrl, byte[] customData, int customDataLength) { - ECDiffieHellmanCng clientDHKey = new ECDiffieHellmanCng(384); - clientDHKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash; - clientDHKey.HashAlgorithm = CngAlgorithm.Sha256; + // The key derivation function and hash algorithm name are specified when key derivation is performed + ECDiffieHellman clientDHKey = ECDiffieHellman.Create(); + clientDHKey.KeySize = 384; return new SqlEnclaveAttestationParameters(2, new byte[] { }, clientDHKey); } // When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. - internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellmanCng clientDHKey, EnclaveSessionParameters enclaveSessionParameters, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) + internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellman clientDHKey, EnclaveSessionParameters enclaveSessionParameters, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) { ////for simulator: enclave does not send public key, and sends an empty attestation info //// The only non-trivial content it sends is the session setup info (DH pubkey of enclave) @@ -84,8 +84,9 @@ internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHell Buffer.BlockCopy(attestationInfo, attestationInfoOffset, trustedModuleDHPublicKeySignature, 0, checked((int)sizeOfTrustedModuleDHPublicKeySignatureBuffer)); - CngKey k = CngKey.Import(trustedModuleDHPublicKey, CngKeyBlobFormat.EccPublicBlob); - byte[] sharedSecret = clientDHKey.DeriveKeyMaterial(k); + ECParameters ecParams = KeyConverter.ECCPublicKeyBlobToParams(trustedModuleDHPublicKey); + ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); + byte[] sharedSecret = clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256); long sessionId = BitConverter.ToInt64(enclaveSessionHandle, 0); sqlEnclaveSession = AddEnclaveSessionToCache(enclaveSessionParameters, sharedSecret, sessionId, out counter); } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs index dbee8d3267..663b4a4e19 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProviderBase.cs @@ -356,7 +356,7 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieH { if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { - throw new ArgumentException(Strings.GetSharedSecretFailed); + throw new ArgumentException(Strings.GetSharedSecretFailed); } } diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index 5c4204cc29..5d046a2b92 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -15,6 +15,7 @@ + @@ -59,7 +60,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs index d90529976d..289ad6bc63 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/EnclaveAzureDatabaseTests.cs @@ -68,7 +68,6 @@ public EnclaveAzureDatabaseTests() } } - [PlatformSpecific(TestPlatforms.Windows)] [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsEnclaveAzureDatabaseSetup))] public void ConnectToAzureDatabaseWithEnclave() { From a552100c2cca7c6a805ac77b311df938a49e3a2c Mon Sep 17 00:00:00 2001 From: Johnny Pham <23270162+johnnypham@users.noreply.github.com> Date: Fri, 21 Aug 2020 11:40:17 -0700 Subject: [PATCH 38/38] Address comments --- .../tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj | 2 +- .../tests/FunctionalTests/SqlConnectionStringBuilderTest.cs | 2 ++ .../Microsoft.Data.SqlClient.ManualTesting.Tests.csproj | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj index 5d046a2b92..cbaa4a9520 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj @@ -15,7 +15,6 @@ - @@ -49,6 +48,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs index f0b08da092..e1eae7b608 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs @@ -52,8 +52,10 @@ public class SqlConnectionStringBuilderTest [InlineData("PersistSecurityInfo = true")] [InlineData("Pooling = no")] [InlineData("Pooling = false")] +#if netcoreapp // PoolBlockingPeriod is not supported in .NET Standard [InlineData("PoolBlockingPeriod = Auto")] [InlineData("PoolBlockingperiod = NeverBlock")] +#endif [InlineData("Replication = true")] [InlineData("Transaction Binding = Explicit Unbind")] [InlineData("Trust Server Certificate = true")] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index 991fe543a3..810775db77 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -20,7 +20,6 @@ - @@ -34,6 +33,7 @@ +