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 ee827d65ac..12ce6b4f01 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -319,6 +319,12 @@
Microsoft\Data\SqlClient\AlwaysEncryptedAttestationException.cs
+
+ Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs
+
+
+ Microsoft\Data\SqlClient\AlwaysEncryptedKeyConverter.cs
+
Microsoft\Data\SqlClient\EnclaveProviderBase.cs
@@ -327,11 +333,12 @@
-
+
-
+
+ Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.cs
+
-
@@ -419,6 +426,12 @@
+
+ Microsoft\Data\SqlClient\EnclaveDelegate.cs
+
+
+ Microsoft\Data\SqlClient\EnclavePackage.cs
+
@@ -451,6 +464,9 @@
+
+ Microsoft\Data\SqlClient\SqlEnclaveSession.cs
+
@@ -506,12 +522,15 @@
-
-
-
+
+ Microsoft\Data\SqlClient\Reliability\SqlConfigurableRetryLogicManager.cs
+
+
+ Microsoft\Data\SqlClient\SqlUtil.cs
+
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 a4bff1a65d..0ffa1ad5ce 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
@@ -215,7 +215,7 @@ public AzureAttestationInfo(byte[] attestationInfo)
}
catch (Exception exception)
{
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.FailToParseAttestationInfo, exception.Message));
+ throw new AlwaysEncryptedAttestationException(string.Format(Strings.FailToParseAttestationInfo, exception.Message));
}
}
}
@@ -313,7 +313,7 @@ private void VerifyAzureAttestationInfo(string attestationUrl, EnclaveType encla
if (!isSignatureValid)
{
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.AttestationTokenSignatureValidationFailed, exceptionMessage));
+ throw new AlwaysEncryptedAttestationException(string.Format(Strings.AttestationTokenSignatureValidationFailed, exceptionMessage));
}
// Validate claims in the token
@@ -349,7 +349,7 @@ private OpenIdConnectConfiguration GetOpenIdConfigForSigningKeys(string url, boo
}
catch (Exception exception)
{
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.GetAttestationTokenSigningKeysFailed, GetInnerMostExceptionMessage(exception)), exception);
+ throw new AlwaysEncryptedAttestationException(string.Format(Strings.GetAttestationTokenSigningKeysFailed, GetInnerMostExceptionMessage(exception)), exception);
}
OpenIdConnectConfigurationCache.Add(url, openIdConnectConfig, DateTime.UtcNow.AddDays(1));
@@ -381,7 +381,7 @@ private static ICollection GenerateListOfIssuers(string tokenIssuerUrl)
if (isDefaultPort)
{
- issuerUrls.Add(String.Concat(issuerUrl, ":", port.ToString()));
+ issuerUrls.Add(string.Concat(issuerUrl, ":", port.ToString()));
}
return issuerUrls;
@@ -428,7 +428,7 @@ private bool VerifyTokenSignature(string attestationToken, string tokenIssuerUrl
}
catch (Exception exception)
{
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.InvalidAttestationToken, GetInnerMostExceptionMessage(exception)));
+ throw new AlwaysEncryptedAttestationException(string.Format(Strings.InvalidAttestationToken, GetInnerMostExceptionMessage(exception)));
}
return isSignatureValid;
@@ -456,7 +456,7 @@ private byte[] ComputeSHA256(byte[] data)
private void ValidateAttestationClaims(EnclaveType enclaveType, string attestationToken, EnclavePublicKey enclavePublicKey, byte[] nonce)
{
// Read the json token
- JsonWebToken token = null;
+ JsonWebToken token;
try
{
JsonWebTokenHandler tokenHandler = new JsonWebTokenHandler();
@@ -464,7 +464,7 @@ private void ValidateAttestationClaims(EnclaveType enclaveType, string attestati
}
catch (ArgumentException argumentException)
{
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.FailToParseAttestationToken, argumentException.Message));
+ throw new AlwaysEncryptedAttestationException(string.Format(Strings.FailToParseAttestationToken, argumentException.Message));
}
// Get all the claims from the token
@@ -492,7 +492,7 @@ private void ValidateClaim(Dictionary claims, string claimName,
bool hasClaim = claims.TryGetValue(claimName, out claimData);
if (!hasClaim)
{
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.MissingClaimInAttestationToken, claimName));
+ throw new AlwaysEncryptedAttestationException(string.Format(Strings.MissingClaimInAttestationToken, claimName));
}
// Get the Base64Url of the actual data and compare it with claim
@@ -506,14 +506,13 @@ private void ValidateClaim(Dictionary claims, string claimName,
throw new AlwaysEncryptedAttestationException(Strings.InvalidArgumentToBase64UrlDecoder);
}
- bool hasValidClaim = String.Equals(encodedActualData, claimData, StringComparison.Ordinal);
+ bool hasValidClaim = string.Equals(encodedActualData, claimData, StringComparison.Ordinal);
if (!hasValidClaim)
{
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.InvalidClaimInAttestationToken, claimName, claimData));
+ throw new AlwaysEncryptedAttestationException(string.Format(Strings.InvalidClaimInAttestationToken, claimName, claimData));
}
}
- // Derives the shared secret between the client and enclave.
private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, EnclaveType enclaveType, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellman clientDHKey)
{
byte[] enclaveRsaPublicKey = enclavePublicKey.PublicKey;
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.CrossPlatformCrypto.cs
similarity index 74%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetCoreApp.cs
rename to src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.CrossPlatformCrypto.cs
index e1cff2d0e0..1f0d8ebc07 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.CrossPlatformCrypto.cs
@@ -7,55 +7,9 @@
namespace Microsoft.Data.SqlClient
{
- ///
- /// A delegate for communicating with secure enclave
- ///
- internal partial class EnclaveDelegate
+ internal sealed partial class EnclaveDelegate
{
- private static readonly string GetSerializedAttestationParametersName = "GetSerializedAttestationParameters";
-
- private static Dictionary EnclaveProviders = new Dictionary();
-
- internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParameters sqlEnclaveAttestationParameters, string enclaveType)
- {
- byte[] attestationProtocolBytes = null;
- byte[] attestationProtocolInputLengthBytes = null;
- byte[] clientDHPublicKeyLengthBytes = null;
- int attestationProtocolInt = sqlEnclaveAttestationParameters.Protocol;
-
- // attestation protocol
- attestationProtocolBytes = GetUintBytes(enclaveType, attestationProtocolInt, "attestationProtocol");
-
- if (attestationProtocolBytes == null)
- {
- throw SQL.NullArgumentInternal("attestationProtocolBytes", ClassName, GetSerializedAttestationParametersName);
- }
-
- // attestationProtocolInput
- byte[] attestationProtocolInputBytes = sqlEnclaveAttestationParameters.GetInput();
-
- // attestationProtocolInput length
- attestationProtocolInputLengthBytes = GetUintBytes(enclaveType, attestationProtocolInputBytes.Length, "attestationProtocolInputLength");
-
- if (attestationProtocolInputLengthBytes == null)
- {
- throw SQL.NullArgumentInternal("attestationProtocolInputLengthBytes", ClassName, GetSerializedAttestationParametersName);
- }
-
- // clientDHPublicKey
- byte[] clientDHPublicKey = KeyConverter.ECDHPublicKeyToECCKeyBlob(sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey);
-
- // clientDHPublicKey length
- clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength");
-
- if (clientDHPublicKeyLengthBytes == null)
- {
- throw SQL.NullArgumentInternal("clientDHPublicKeyLengthBytes", ClassName, GetSerializedAttestationParametersName);
- }
-
- return CombineByteArrays(new[] { attestationProtocolBytes, attestationProtocolInputLengthBytes,
- attestationProtocolInputBytes, clientDHPublicKeyLengthBytes, clientDHPublicKey });
- }
+ private static readonly Dictionary s_enclaveProviders = new Dictionary();
///
/// Create a new enclave session
@@ -70,23 +24,33 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete
internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters,
byte[] attestationInfo, SqlEnclaveAttestationParameters attestationParameters, byte[] customData, int customDataLength)
{
-
lock (_lock)
{
SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
- long counter;
- SqlEnclaveSession sqlEnclaveSession = null;
- byte[] dummyCustomData = null;
- int dummyCustomDataLength;
- sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(enclaveSessionParameters, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength);
+ sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(
+ enclaveSessionParameters,
+ generateCustomData: false,
+ sqlEnclaveSession: out SqlEnclaveSession sqlEnclaveSession,
+ counter: out _,
+ customData: out _,
+ customDataLength: out _
+ );
if (sqlEnclaveSession != null)
{
return;
}
- sqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(attestationInfo, attestationParameters.ClientDiffieHellmanKey, enclaveSessionParameters, customData, customDataLength, out sqlEnclaveSession, out counter);
+ sqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(
+ attestationInfo,
+ attestationParameters.ClientDiffieHellmanKey,
+ enclaveSessionParameters,
+ customData,
+ customDataLength,
+ out sqlEnclaveSession,
+ counter: out _
+ );
if (sqlEnclaveSession == null)
{
@@ -95,6 +59,68 @@ internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationP
}
}
+ internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
+ {
+ GetEnclaveSession(attestationProtocol, enclaveType, enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out _, out customData, out customDataLength, throwIfNull: false);
+ }
+
+ private void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength, bool throwIfNull)
+ {
+ SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
+ sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);
+
+ if (throwIfNull && sqlEnclaveSession == null)
+ {
+ throw SQL.NullEnclaveSessionDuringQueryExecution(enclaveType, enclaveSessionParameters.AttestationUrl);
+ }
+ }
+
+ internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, SqlEnclaveSession enclaveSession)
+ {
+ SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
+ sqlColumnEncryptionEnclaveProvider.InvalidateEnclaveSession(enclaveSessionParameters, enclaveSession);
+ }
+
+
+ private SqlColumnEncryptionEnclaveProvider GetEnclaveProvider(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType)
+ {
+ if (!s_enclaveProviders.TryGetValue(attestationProtocol, out SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider))
+ {
+ switch (attestationProtocol)
+ {
+ case SqlConnectionAttestationProtocol.AAS:
+ AzureAttestationEnclaveProvider azureAttestationEnclaveProvider = new AzureAttestationEnclaveProvider();
+ s_enclaveProviders[attestationProtocol] = azureAttestationEnclaveProvider;
+ sqlColumnEncryptionEnclaveProvider = s_enclaveProviders[attestationProtocol];
+ break;
+
+ case SqlConnectionAttestationProtocol.HGS:
+ HostGuardianServiceEnclaveProvider hostGuardianServiceEnclaveProvider = new HostGuardianServiceEnclaveProvider();
+ s_enclaveProviders[attestationProtocol] = hostGuardianServiceEnclaveProvider;
+ sqlColumnEncryptionEnclaveProvider = s_enclaveProviders[attestationProtocol];
+ break;
+
+#if ENCLAVE_SIMULATOR
+ case SqlConnectionAttestationProtocol.SIM:
+ SimulatorEnclaveProvider simulatorEnclaveProvider = new SimulatorEnclaveProvider();
+ s_enclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)simulatorEnclaveProvider;
+ sqlColumnEncryptionEnclaveProvider = s_enclaveProviders[attestationProtocol];
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+
+ if (sqlColumnEncryptionEnclaveProvider == null)
+ {
+ throw SQL.EnclaveProviderNotFound(enclaveType, ConvertAttestationProtocolToString(attestationProtocol));
+ }
+
+ return sqlColumnEncryptionEnclaveProvider;
+ }
+
///
/// Generate the byte package that needs to be sent to the enclave
///
@@ -106,15 +132,22 @@ internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationP
///
internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol attestationProtocol, Dictionary keysToBeSentToEnclave, string queryText, string enclaveType, EnclaveSessionParameters enclaveSessionParameters)
{
-
- SqlEnclaveSession sqlEnclaveSession = null;
+ SqlEnclaveSession sqlEnclaveSession;
long counter;
- byte[] dummyCustomData = null;
- int dummyCustomDataLength;
try
{
- GetEnclaveSession(attestationProtocol, enclaveType, enclaveSessionParameters, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength, throwIfNull: true);
+ GetEnclaveSession(
+ attestationProtocol,
+ enclaveType,
+ enclaveSessionParameters,
+ generateCustomData: false,
+ sqlEnclaveSession: out sqlEnclaveSession,
+ counter: out counter,
+ customData: out _,
+ customDataLength: out _,
+ throwIfNull: true
+ );
}
catch (Exception e)
{
@@ -127,16 +160,10 @@ internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol
byte[] sessionKey = sqlEnclaveSession.GetSessionKey();
byte[] encryptedBytePackage = EncryptBytePackage(keyBytePackage, sessionKey, enclaveSessionParameters.ServerName);
byte[] enclaveSessionHandle = BitConverter.GetBytes(sqlEnclaveSession.SessionId);
- byte[] byteArrayToBeSentToEnclave = CombineByteArrays(new[] { enclaveSessionHandle, encryptedBytePackage });
+ byte[] byteArrayToBeSentToEnclave = CombineByteArrays(enclaveSessionHandle, encryptedBytePackage);
return new EnclavePackage(byteArrayToBeSentToEnclave, sqlEnclaveSession);
}
- internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, SqlEnclaveSession enclaveSession)
- {
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
- sqlColumnEncryptionEnclaveProvider.InvalidateEnclaveSession(enclaveSessionParameters, enclaveSession);
- }
-
internal SqlEnclaveAttestationParameters GetAttestationParameters(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string attestationUrl, byte[] customData, int customDataLength)
{
@@ -144,45 +171,39 @@ internal SqlEnclaveAttestationParameters GetAttestationParameters(SqlConnectionA
return sqlColumnEncryptionEnclaveProvider.GetAttestationParameters(attestationUrl, customData, customDataLength);
}
- private SqlColumnEncryptionEnclaveProvider GetEnclaveProvider(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType)
+ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParameters sqlEnclaveAttestationParameters, string enclaveType)
{
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = null;
+ byte[] attestationProtocolBytes = null;
+ byte[] attestationProtocolInputLengthBytes = null;
+ byte[] clientDHPublicKeyLengthBytes = null;
+ int attestationProtocolInt = sqlEnclaveAttestationParameters.Protocol;
+
+ attestationProtocolBytes = GetUintBytes(enclaveType, attestationProtocolInt, "attestationProtocol");
- if (!EnclaveProviders.TryGetValue(attestationProtocol, out sqlColumnEncryptionEnclaveProvider))
+ if (attestationProtocolBytes == null)
{
- switch (attestationProtocol)
- {
- case SqlConnectionAttestationProtocol.AAS:
- AzureAttestationEnclaveProvider azureAttestationEnclaveProvider = new AzureAttestationEnclaveProvider();
- EnclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)azureAttestationEnclaveProvider;
- sqlColumnEncryptionEnclaveProvider = EnclaveProviders[attestationProtocol];
- break;
+ throw SQL.NullArgumentInternal(nameof(attestationProtocolBytes), nameof(EnclaveDelegate), nameof(GetSerializedAttestationParameters));
+ }
- case SqlConnectionAttestationProtocol.HGS:
- HostGuardianServiceEnclaveProvider hostGuardianServiceEnclaveProvider = new HostGuardianServiceEnclaveProvider();
- EnclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)hostGuardianServiceEnclaveProvider;
- sqlColumnEncryptionEnclaveProvider = EnclaveProviders[attestationProtocol];
- break;
+ byte[] attestationProtocolInputBytes = sqlEnclaveAttestationParameters.GetInput();
-#if ENCLAVE_SIMULATOR
- case SqlConnectionAttestationProtocol.SIM:
- SimulatorEnclaveProvider simulatorEnclaveProvider = new SimulatorEnclaveProvider();
- EnclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)simulatorEnclaveProvider;
- sqlColumnEncryptionEnclaveProvider = EnclaveProviders[attestationProtocol];
- break;
-#endif
+ attestationProtocolInputLengthBytes = GetUintBytes(enclaveType, attestationProtocolInputBytes.Length, "attestationProtocolInputLength");
- default:
- break;
- }
+ if (attestationProtocolInputLengthBytes == null)
+ {
+ throw SQL.NullArgumentInternal(nameof(attestationProtocolInputLengthBytes), nameof(EnclaveDelegate), nameof(GetSerializedAttestationParameters));
}
- if (sqlColumnEncryptionEnclaveProvider == null)
+ byte[] clientDHPublicKey = KeyConverter.ECDHPublicKeyToECCKeyBlob(sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey);
+
+ clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength");
+
+ if (clientDHPublicKeyLengthBytes == null)
{
- throw SQL.EnclaveProviderNotFound(enclaveType, ConvertAttestationProtocolToString(attestationProtocol));
+ throw SQL.NullArgumentInternal(nameof(clientDHPublicKeyLengthBytes), nameof(EnclaveDelegate), nameof(GetSerializedAttestationParameters));
}
- return sqlColumnEncryptionEnclaveProvider;
+ return CombineByteArrays(attestationProtocolBytes, attestationProtocolInputLengthBytes, attestationProtocolInputBytes, clientDHPublicKeyLengthBytes, clientDHPublicKey);
}
private string ConvertAttestationProtocolToString(SqlConnectionAttestationProtocol attestationProtocol)
@@ -204,22 +225,5 @@ private string ConvertAttestationProtocolToString(SqlConnectionAttestationProtoc
return "NotSpecified";
}
}
-
- internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
- {
- long counter;
- GetEnclaveSession(attestationProtocol, enclaveType, enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength, throwIfNull: false);
- }
-
- private void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength, bool throwIfNull)
- {
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
- sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);
-
- if (throwIfNull && sqlEnclaveSession == null)
- {
- throw SQL.NullEnclaveSessionDuringQueryExecution(enclaveType, enclaveSessionParameters.AttestationUrl);
- }
- }
}
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetStandard.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetStandard.cs
index 3005105a14..f33dac5f78 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetStandard.cs
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.NetStandard.cs
@@ -7,10 +7,7 @@
namespace Microsoft.Data.SqlClient
{
- ///
- /// A delegate for communicating with secure enclave
- ///
- internal partial class EnclaveDelegate
+ internal sealed partial class EnclaveDelegate
{
internal byte[] GetSerializedAttestationParameters(
SqlEnclaveAttestationParameters sqlEnclaveAttestationParameters, string enclaveType)
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 020103207e..58e0037059 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -136,15 +136,24 @@
Microsoft\Data\SqlClient\ActiveDirectoryAuthenticationTimeoutRetryHelper.cs
-
- Microsoft\Data\SqlClient\AzureManagedIdentityAuthenticationProvider.cs
-
Microsoft\Data\SqlClient\ApplicationIntent.cs
Microsoft\Data\SqlClient\ActiveDirectoryAuthenticationProvider.cs
+
+ Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs
+
+
+ Microsoft\Data\SqlClient\AzureManagedIdentityAuthenticationProvider.cs
+
+
+ Microsoft\Data\SqlClient\EnclaveDelegate.cs
+
+
+ Microsoft\Data\SqlClient\EnclavePackage.cs
+
Microsoft\Data\SqlClient\Server\ExtendedClrTypeCode.cs
@@ -295,6 +304,9 @@
Microsoft\Data\SqlClient\SqlSymmetricKeyCache.cs
+
+ Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.cs
+
Microsoft\Data\SqlTypes\SqlTypeWorkarounds.cs
@@ -375,10 +387,9 @@
-
-
+
@@ -386,7 +397,6 @@
-
@@ -426,7 +436,9 @@
-
+
+ Microsoft\Data\SqlClient\SqlEnclaveSession.cs
+
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs
index a79c4900b8..84a92c7ccc 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AzureAttestationBasedEnclaveProvider.cs
@@ -133,6 +133,7 @@ internal override void InvalidateEnclaveSession(EnclaveSessionParameters enclave
#endregion
#region Internal Class
+
// A model class representing the deserialization of the byte payload the client
// receives from SQL Server while setting up a session.
// Protocol format:
@@ -280,6 +281,7 @@ internal byte[] PrepareAttestationParameters(string attestationUrl, byte[] attes
}
}
+ // Performs Attestation per the protocol used by Azure Attestation Service
private void VerifyAzureAttestationInfo(string attestationUrl, EnclaveType enclaveType, string attestationToken, EnclavePublicKey enclavePublicKey, byte[] nonce)
{
bool shouldForceUpdateSigningKeys = false;
@@ -318,6 +320,7 @@ private void VerifyAzureAttestationInfo(string attestationUrl, EnclaveType encla
ValidateAttestationClaims(enclaveType, attestationToken, enclavePublicKey, nonce);
}
+ // Returns the innermost exception value
private static string GetInnerMostExceptionMessage(Exception exception)
{
Exception exLocal = exception;
@@ -329,6 +332,8 @@ private static string GetInnerMostExceptionMessage(Exception exception)
return exLocal.Message;
}
+ // For the given attestation url it downloads the token signing keys from the well-known openid configuration end point.
+ // It also caches that information for 1 day to avoid DDOS attacks.
private OpenIdConnectConfiguration GetOpenIdConfigForSigningKeys(string url, bool forceUpdate)
{
OpenIdConnectConfiguration openIdConnectConfig = OpenIdConnectConfigurationCache[url] as OpenIdConnectConfiguration;
@@ -353,12 +358,16 @@ private OpenIdConnectConfiguration GetOpenIdConfigForSigningKeys(string url, boo
return openIdConnectConfig;
}
+ // Return the attestation instance url for given attestation url
+ // such as for https://sql.azure.attest.com/attest/SgxEnclave?api-version=2017-11-01
+ // It will return https://sql.azure.attest.com
private string GetAttestationInstanceUrl(string attestationUrl)
{
Uri attestationUri = new Uri(attestationUrl);
return attestationUri.GetLeftPart(UriPartial.Authority);
}
+ // Generate the list of valid issuer Url's (in case if tokenIssuerUrl is using default port)
private static ICollection GenerateListOfIssuers(string tokenIssuerUrl)
{
List issuerUrls = new List();
@@ -378,6 +387,7 @@ private static ICollection GenerateListOfIssuers(string tokenIssuerUrl)
return issuerUrls;
}
+ // Verifies the attestation token is signed by correct signing keys.
private bool VerifyTokenSignature(string attestationToken, string tokenIssuerUrl, ICollection issuerSigningKeys, out bool isKeySigningExpired, out string exceptionMessage)
{
exceptionMessage = string.Empty;
@@ -424,6 +434,7 @@ private bool VerifyTokenSignature(string attestationToken, string tokenIssuerUrl
return isSignatureValid;
}
+ // Computes the SHA256 hash of the byte array
private byte[] ComputeSHA256(byte[] data)
{
byte[] result = null;
@@ -441,6 +452,7 @@ private byte[] ComputeSHA256(byte[] data)
return result;
}
+ // Validate the claims in the attestation token
private void ValidateAttestationClaims(EnclaveType enclaveType, string attestationToken, EnclavePublicKey enclavePublicKey, byte[] nonce)
{
// Read the json token
@@ -472,6 +484,7 @@ private void ValidateAttestationClaims(EnclaveType enclaveType, string attestati
}
}
+ // Validate the claim value against the actual data
private void ValidateClaim(Dictionary claims, string claimName, byte[] actualData)
{
// Get required claim data
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/EnclaveDelegate.CngCryto.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/EnclaveDelegate.CngCryto.cs
new file mode 100644
index 0000000000..fb93672b20
--- /dev/null
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/EnclaveDelegate.CngCryto.cs
@@ -0,0 +1,230 @@
+// 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.Collections.Generic;
+using System.Security.Cryptography;
+
+namespace Microsoft.Data.SqlClient
+{
+ internal sealed partial class EnclaveDelegate
+ {
+ private static readonly Dictionary s_enclaveProviders = new Dictionary();
+
+ ///
+ /// Create a new enclave session
+ ///
+ /// attestation protocol
+ /// enclave type
+ /// The set of parameters required for enclave session.
+ /// attestation info from SQL Server
+ /// attestation parameters
+ /// A set of extra data needed for attestating the enclave.
+ /// The length of the extra data needed for attestating the enclave.
+ internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters,
+ byte[] attestationInfo, SqlEnclaveAttestationParameters attestationParameters, byte[] customData, int customDataLength)
+ {
+ lock (_lock)
+ {
+ SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
+
+ sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(
+ enclaveSessionParameters,
+ generateCustomData: false,
+ sqlEnclaveSession: out SqlEnclaveSession sqlEnclaveSession,
+ counter: out _,
+ customData: out _,
+ customDataLength: out _
+ );
+
+ if (sqlEnclaveSession != null)
+ {
+ return;
+ }
+
+ sqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(
+ attestationInfo,
+ attestationParameters.ClientDiffieHellmanKey,
+ enclaveSessionParameters,
+ customData,
+ customDataLength,
+ out sqlEnclaveSession,
+ counter: out _
+ );
+
+ if (sqlEnclaveSession == null)
+ {
+ throw SQL.NullEnclaveSessionReturnedFromProvider(enclaveType, enclaveSessionParameters.AttestationUrl);
+ }
+ }
+ }
+
+ internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
+ {
+ GetEnclaveSession(attestationProtocol, enclaveType, enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out _, out customData, out customDataLength, throwIfNull: false);
+ }
+
+ private void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength, bool throwIfNull)
+ {
+ SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
+ sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);
+
+ if (throwIfNull && sqlEnclaveSession == null)
+ {
+ throw SQL.NullEnclaveSessionDuringQueryExecution(enclaveType, enclaveSessionParameters.AttestationUrl);
+ }
+ }
+
+ internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, SqlEnclaveSession enclaveSession)
+ {
+ SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
+ sqlColumnEncryptionEnclaveProvider.InvalidateEnclaveSession(enclaveSessionParameters, enclaveSession);
+ }
+
+
+ private SqlColumnEncryptionEnclaveProvider GetEnclaveProvider(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType)
+ {
+ if (!s_enclaveProviders.TryGetValue(attestationProtocol, out SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider))
+ {
+ switch (attestationProtocol)
+ {
+ case SqlConnectionAttestationProtocol.AAS:
+ AzureAttestationEnclaveProvider azureAttestationEnclaveProvider = new AzureAttestationEnclaveProvider();
+ s_enclaveProviders[attestationProtocol] = azureAttestationEnclaveProvider;
+ sqlColumnEncryptionEnclaveProvider = s_enclaveProviders[attestationProtocol];
+ break;
+
+ case SqlConnectionAttestationProtocol.HGS:
+ HostGuardianServiceEnclaveProvider hostGuardianServiceEnclaveProvider = new HostGuardianServiceEnclaveProvider();
+ s_enclaveProviders[attestationProtocol] = hostGuardianServiceEnclaveProvider;
+ sqlColumnEncryptionEnclaveProvider = s_enclaveProviders[attestationProtocol];
+ break;
+
+#if ENCLAVE_SIMULATOR
+ case SqlConnectionAttestationProtocol.SIM:
+ SimulatorEnclaveProvider simulatorEnclaveProvider = new SimulatorEnclaveProvider();
+ s_enclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)simulatorEnclaveProvider;
+ sqlColumnEncryptionEnclaveProvider = s_enclaveProviders[attestationProtocol];
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+
+ if (sqlColumnEncryptionEnclaveProvider == null)
+ {
+ throw SQL.EnclaveProviderNotFound(enclaveType, ConvertAttestationProtocolToString(attestationProtocol));
+ }
+
+ return sqlColumnEncryptionEnclaveProvider;
+ }
+
+ ///
+ /// Generate the byte package that needs to be sent to the enclave
+ ///
+ /// attestation protocol
+ /// Keys to be sent to enclave
+ ///
+ /// enclave type
+ /// The set of parameters required for enclave session.
+ ///
+ internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol attestationProtocol, Dictionary keysToBeSentToEnclave, string queryText, string enclaveType, EnclaveSessionParameters enclaveSessionParameters)
+ {
+ SqlEnclaveSession sqlEnclaveSession;
+ long counter;
+
+ try
+ {
+ GetEnclaveSession(
+ attestationProtocol,
+ enclaveType,
+ enclaveSessionParameters,
+ generateCustomData: false,
+ sqlEnclaveSession: out sqlEnclaveSession,
+ counter: out counter,
+ customData: out _,
+ customDataLength: out _,
+ throwIfNull: true
+ );
+ }
+ catch (Exception e)
+ {
+ throw new RetryableEnclaveQueryExecutionException(e.Message, e);
+ }
+
+ List decryptedKeysToBeSentToEnclave = GetDecryptedKeysToBeSentToEnclave(keysToBeSentToEnclave, enclaveSessionParameters.ServerName);
+ byte[] queryStringHashBytes = ComputeQueryStringHash(queryText);
+ byte[] keyBytePackage = GenerateBytePackageForKeys(counter, queryStringHashBytes, decryptedKeysToBeSentToEnclave);
+ byte[] sessionKey = sqlEnclaveSession.GetSessionKey();
+ byte[] encryptedBytePackage = EncryptBytePackage(keyBytePackage, sessionKey, enclaveSessionParameters.ServerName);
+ byte[] enclaveSessionHandle = BitConverter.GetBytes(sqlEnclaveSession.SessionId);
+ byte[] byteArrayToBeSentToEnclave = CombineByteArrays(enclaveSessionHandle, encryptedBytePackage);
+ return new EnclavePackage(byteArrayToBeSentToEnclave, sqlEnclaveSession);
+ }
+
+
+ internal SqlEnclaveAttestationParameters GetAttestationParameters(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string attestationUrl, byte[] customData, int customDataLength)
+ {
+ SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
+ return sqlColumnEncryptionEnclaveProvider.GetAttestationParameters(attestationUrl, customData, customDataLength);
+ }
+
+ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParameters sqlEnclaveAttestationParameters, string enclaveType)
+ {
+ byte[] attestationProtocolBytes = null;
+ byte[] attestationProtocolInputLengthBytes = null;
+ byte[] clientDHPublicKeyLengthBytes = null;
+ int attestationProtocolInt = sqlEnclaveAttestationParameters.Protocol;
+
+ attestationProtocolBytes = GetUintBytes(enclaveType, attestationProtocolInt, "attestationProtocol");
+
+ if (attestationProtocolBytes == null)
+ {
+ throw SQL.NullArgumentInternal(nameof(attestationProtocolBytes), nameof(EnclaveDelegate), nameof(GetSerializedAttestationParameters));
+ }
+
+ byte[] attestationProtocolInputBytes = sqlEnclaveAttestationParameters.GetInput();
+
+ attestationProtocolInputLengthBytes = GetUintBytes(enclaveType, attestationProtocolInputBytes.Length, "attestationProtocolInputLength");
+
+ if (attestationProtocolInputLengthBytes == null)
+ {
+ throw SQL.NullArgumentInternal(nameof(attestationProtocolInputLengthBytes), nameof(EnclaveDelegate), nameof(GetSerializedAttestationParameters));
+ }
+
+ byte[] clientDHPublicKey = sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.Key.Export(CngKeyBlobFormat.EccPublicBlob);
+
+ clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength");
+
+ if (clientDHPublicKeyLengthBytes == null)
+ {
+ throw SQL.NullArgumentInternal(nameof(clientDHPublicKeyLengthBytes), nameof(EnclaveDelegate), nameof(GetSerializedAttestationParameters));
+ }
+
+ return CombineByteArrays(attestationProtocolBytes, attestationProtocolInputLengthBytes, attestationProtocolInputBytes, clientDHPublicKeyLengthBytes, clientDHPublicKey);
+ }
+
+ private string ConvertAttestationProtocolToString(SqlConnectionAttestationProtocol attestationProtocol)
+ {
+ switch (attestationProtocol)
+ {
+ case SqlConnectionAttestationProtocol.AAS:
+ return "AAS";
+
+ case SqlConnectionAttestationProtocol.HGS:
+ return "HGS";
+
+#if ENCLAVE_SIMULATOR
+ case SqlConnectionAttestationProtocol.SIM:
+ return "SIM";
+#endif
+
+ default:
+ return "NotSpecified";
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs
deleted file mode 100644
index 09ba954353..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs
+++ /dev/null
@@ -1,433 +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.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Microsoft.Data.SqlClient
-{
- ///
- /// A delegate for communicating with secure enclave
- ///
- internal class EnclaveDelegate
- {
- private static readonly SqlAeadAes256CbcHmac256Factory SqlAeadAes256CbcHmac256Factory = new SqlAeadAes256CbcHmac256Factory();
- private static readonly string GetAttestationInfoQueryString = String.Format(@"Select GetTrustedModuleIdentityAndAttestationInfo({0}) as attestationInfo", 0);
- private static readonly EnclaveDelegate _EnclaveDelegate = new EnclaveDelegate();
-
- private static readonly string ClassName = "EnclaveDelegate";
- private static readonly string GetDecryptedKeysToBeSentToEnclaveName = "GetDecryptedKeysToBeSentToEnclave";
- private static readonly string GetSerializedAttestationParametersName = "GetSerializedAttestationParameters";
- private static readonly string ComputeQueryStringHashName = "ComputeQueryStringHash";
-
- private static Dictionary EnclaveProviders = new Dictionary();
-
- private readonly Object _lock = new Object();
-
- //singleton instance
- public static EnclaveDelegate Instance { get { return _EnclaveDelegate; } }
-
- private EnclaveDelegate() { }
-
- ///
- /// Generate the byte package that needs to be sent to the enclave
- ///
- /// attestation protocol
- /// Keys to be sent to enclave
- ///
- /// enclave type
- /// The set of parameters required for enclave session.
- ///
- internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol attestationProtocol, Dictionary keysTobeSentToEnclave, string queryText, string enclaveType, EnclaveSessionParameters enclaveSessionParameters)
- {
-
- SqlEnclaveSession sqlEnclaveSession = null;
- long counter;
- byte[] dummyCustomData = null;
- int dummyCustomDataLength;
- try
- {
- GetEnclaveSession(attestationProtocol, enclaveType, enclaveSessionParameters, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength, throwIfNull: true);
- }
- catch (Exception e)
- {
- throw new RetryableEnclaveQueryExecutionException(e.Message, e);
- }
-
- List decryptedKeysToBeSentToEnclave = GetDecryptedKeysToBeSentToEnclave(keysTobeSentToEnclave, enclaveSessionParameters.ServerName);
- byte[] queryStringHashBytes = ComputeQueryStringHash(queryText);
- byte[] keyBytePackage = GenerateBytePackageForKeys(counter, queryStringHashBytes, decryptedKeysToBeSentToEnclave);
- byte[] sessionKey = sqlEnclaveSession.GetSessionKey();
- byte[] encryptedBytePackage = EncryptBytePackage(keyBytePackage, sessionKey, enclaveSessionParameters.ServerName);
- byte[] enclaveSessionHandle = BitConverter.GetBytes(sqlEnclaveSession.SessionId);
- byte[] byteArrayToBeSentToEnclave = CombineByteArrays(new[] { enclaveSessionHandle, encryptedBytePackage });
- return new EnclavePackage(byteArrayToBeSentToEnclave, sqlEnclaveSession);
- }
-
- internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, SqlEnclaveSession enclaveSession)
- {
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
- sqlColumnEncryptionEnclaveProvider.InvalidateEnclaveSession(enclaveSessionParameters, enclaveSession);
- }
-
- internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
- {
- long counter;
- GetEnclaveSession(attestationProtocol, enclaveType, enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength, throwIfNull: false);
- }
-
- private void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength, bool throwIfNull)
- {
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
- sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(enclaveSessionParameters, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);
-
- if (throwIfNull && sqlEnclaveSession == null)
- {
- throw SQL.NullEnclaveSessionDuringQueryExecution(enclaveType, enclaveSessionParameters.AttestationUrl);
- }
- }
-
- internal SqlEnclaveAttestationParameters GetAttestationParameters(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string attestationUrl, byte[] customData, int customDataLength)
- {
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
- return sqlColumnEncryptionEnclaveProvider.GetAttestationParameters(attestationUrl, customData, customDataLength);
- }
-
- internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParameters sqlEnclaveAttestationParameters, string enclaveType)
- {
- byte[] attestationProtocolBytes = null;
- byte[] attestationProtocolInputLengthBytes = null;
- byte[] clientDHPublicKeyLengthBytes = null;
- int attestationProtocolInt = sqlEnclaveAttestationParameters.Protocol;
-
- // attestation protocol
- attestationProtocolBytes = GetUintBytes(enclaveType, attestationProtocolInt, "attestationProtocol");
-
- if (attestationProtocolBytes == null)
- {
- throw SQL.NullArgumentInternal("attestationProtocolBytes", ClassName, GetSerializedAttestationParametersName);
- }
-
- // attestationProtocolInput
- byte[] attestationProtocolInputBytes = sqlEnclaveAttestationParameters.GetInput();
-
- // attestationProtocolInput length
- attestationProtocolInputLengthBytes = GetUintBytes(enclaveType, attestationProtocolInputBytes.Length, "attestationProtocolInputLength");
-
- if (attestationProtocolInputLengthBytes == null)
- {
- throw SQL.NullArgumentInternal("attestationProtocolInputLengthBytes", ClassName, GetSerializedAttestationParametersName);
- }
-
- // clientDHPublicKey
- byte[] clientDHPublicKey = sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.Key.Export(CngKeyBlobFormat.EccPublicBlob);
-
- // clientDHPublicKey length
- clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength");
-
- if (clientDHPublicKeyLengthBytes == null)
- {
- throw SQL.NullArgumentInternal("clientDHPublicKeyLengthBytes", ClassName, GetSerializedAttestationParametersName);
- }
-
- return CombineByteArrays(new[] { attestationProtocolBytes, attestationProtocolInputLengthBytes, attestationProtocolInputBytes, clientDHPublicKeyLengthBytes, clientDHPublicKey });
- }
-
- private byte[] GetUintBytes(string enclaveType, int intValue, string variableName)
- {
- try
- {
- uint attestationProtocol = Convert.ToUInt32(intValue);
- return BitConverter.GetBytes(attestationProtocol);
- }
- catch (Exception e)
- {
- throw SQL.InvalidAttestationParameterUnableToConvertToUnsignedInt(
- variableName, intValue, enclaveType, e);
- }
- }
-
- ///
- /// Create a new enclave session
- ///
- /// attestation protocol
- /// enclave type
- /// The set of parameters required for enclave session.
- /// attestation info from SQL Server
- /// attestation parameters
- /// A set of extra data needed for attestating the enclave.
- /// The length of the extra data needed for attestating the enclave.
- internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, EnclaveSessionParameters enclaveSessionParameters,
- byte[] attestationInfo, SqlEnclaveAttestationParameters attestationParameters, byte[] customData, int customDataLength)
- {
-
- lock (_lock)
- {
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
- long counter;
- SqlEnclaveSession sqlEnclaveSession = null;
- byte[] dummyCustomData = null;
- int dummyCustomDataLength;
- sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(enclaveSessionParameters, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength);
-
- if (sqlEnclaveSession != null)
- {
- return;
- }
-
- sqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(attestationInfo, attestationParameters.ClientDiffieHellmanKey, enclaveSessionParameters, customData, customDataLength, out sqlEnclaveSession, out counter);
-
- if (sqlEnclaveSession == null)
- {
- throw SQL.NullEnclaveSessionReturnedFromProvider(enclaveType, enclaveSessionParameters.AttestationUrl);
- }
- }
- }
-
- private SqlColumnEncryptionEnclaveProvider GetEnclaveProvider(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType)
- {
- SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = null;
-
- if (!EnclaveProviders.TryGetValue(attestationProtocol, out sqlColumnEncryptionEnclaveProvider))
- {
- switch (attestationProtocol)
- {
- case SqlConnectionAttestationProtocol.AAS:
- AzureAttestationEnclaveProvider azureAttestationEnclaveProvider = new AzureAttestationEnclaveProvider();
- EnclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)azureAttestationEnclaveProvider;
- sqlColumnEncryptionEnclaveProvider = EnclaveProviders[attestationProtocol];
- break;
-
- case SqlConnectionAttestationProtocol.HGS:
- HostGuardianServiceEnclaveProvider hostGuardianServiceEnclaveProvider = new HostGuardianServiceEnclaveProvider();
- EnclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)hostGuardianServiceEnclaveProvider;
- sqlColumnEncryptionEnclaveProvider = EnclaveProviders[attestationProtocol];
- break;
-
-#if ENCLAVE_SIMULATOR
- case SqlConnectionAttestationProtocol.SIM:
- SimulatorEnclaveProvider simulatorEnclaveProvider = new SimulatorEnclaveProvider();
- EnclaveProviders[attestationProtocol] = (SqlColumnEncryptionEnclaveProvider)simulatorEnclaveProvider;
- sqlColumnEncryptionEnclaveProvider = EnclaveProviders[attestationProtocol];
- break;
-#endif
-
- default:
- break;
- }
- }
-
- if (sqlColumnEncryptionEnclaveProvider == null)
- {
- throw SQL.EnclaveProviderNotFound(enclaveType, ConvertAttestationProtocolToString(attestationProtocol));
- }
-
- return sqlColumnEncryptionEnclaveProvider;
- }
-
- private string ConvertAttestationProtocolToString(SqlConnectionAttestationProtocol attestationProtocol)
- {
- switch (attestationProtocol)
- {
- case SqlConnectionAttestationProtocol.AAS:
- return "AAS";
-
- case SqlConnectionAttestationProtocol.HGS:
- return "HGS";
-
-#if ENCLAVE_SIMULATOR
- case SqlConnectionAttestationProtocol.SIM:
- return "SIM";
-#endif
-
- default:
- return "NotSpecified";
- }
- }
-
- ///
- /// Decrypt the keys that need to be sent to the enclave
- ///
- /// Keys that need to sent to the enclave
- ///
- ///
- private List GetDecryptedKeysToBeSentToEnclave(Dictionary keysTobeSentToEnclave, string serverName)
- {
- List decryptedKeysToBeSentToEnclave = new List();
-
- foreach (SqlTceCipherInfoEntry cipherInfo in keysTobeSentToEnclave.Values)
- {
- SqlClientSymmetricKey sqlClientSymmetricKey = null;
- SqlEncryptionKeyInfo? encryptionkeyInfoChosen = null;
- SqlSecurityUtility.DecryptSymmetricKey(cipherInfo, serverName, out sqlClientSymmetricKey,
- out encryptionkeyInfoChosen);
-
- if (sqlClientSymmetricKey == null)
- throw SQL.NullArgumentInternal("sqlClientSymmetricKey", ClassName, GetDecryptedKeysToBeSentToEnclaveName);
- if (cipherInfo.ColumnEncryptionKeyValues == null)
- throw SQL.NullArgumentInternal("ColumnEncryptionKeyValues", ClassName, GetDecryptedKeysToBeSentToEnclaveName);
- if (!(cipherInfo.ColumnEncryptionKeyValues.Count > 0))
- throw SQL.ColumnEncryptionKeysNotFound();
-
- //cipherInfo.CekId is always 0, hence used cipherInfo.ColumnEncryptionKeyValues[0].cekId. Even when cek has multiple ColumnEncryptionKeyValues
- //the cekid and the plaintext value will remain the same, what varies is the encrypted cek value, since the cek can be encrypted by
- //multiple CMKs
- decryptedKeysToBeSentToEnclave.Add(new ColumnEncryptionKeyInfo(sqlClientSymmetricKey.RootKey,
- cipherInfo.ColumnEncryptionKeyValues[0].databaseId,
- cipherInfo.ColumnEncryptionKeyValues[0].cekMdVersion, cipherInfo.ColumnEncryptionKeyValues[0].cekId));
- }
- return decryptedKeysToBeSentToEnclave;
- }
-
- ///
- /// Generate a byte package consisting of decrypted keys and some headers expected by the enclave
- ///
- /// counter to avoid replay attacks
- ///
- ///
- ///
- private byte[] GenerateBytePackageForKeys(long enclaveSessionCounter, byte[] queryStringHashBytes, List keys)
- {
-
- //Format GUID | counter | queryStringHash | key[1]id | key[1]Bytes | ...... key[n]id | key[n]bytes
- Guid guid = Guid.NewGuid();
- byte[] guidBytes = guid.ToByteArray();
- byte[] counterBytes = BitConverter.GetBytes(enclaveSessionCounter);
-
- int lengthOfByteArrayToAllocate = guidBytes.Length;
- lengthOfByteArrayToAllocate += counterBytes.Length;
- lengthOfByteArrayToAllocate += queryStringHashBytes.Length;
-
- foreach (ColumnEncryptionKeyInfo key in keys)
- {
- lengthOfByteArrayToAllocate += key.GetLengthForSerialization();
- }
-
- byte[] bytePackage = new byte[lengthOfByteArrayToAllocate];
- int startOffset = 0;
-
- Buffer.BlockCopy(guidBytes, 0, bytePackage, startOffset, guidBytes.Length);
- startOffset += guidBytes.Length;
-
- Buffer.BlockCopy(counterBytes, 0, bytePackage, startOffset, counterBytes.Length);
- startOffset += counterBytes.Length;
-
- Buffer.BlockCopy(queryStringHashBytes, 0, bytePackage, startOffset, queryStringHashBytes.Length);
- startOffset += queryStringHashBytes.Length;
-
- foreach (ColumnEncryptionKeyInfo key in keys)
- {
- startOffset = key.SerializeToBuffer(bytePackage, startOffset);
- }
-
- return bytePackage;
- }
-
- ///
- /// Encrypt the byte package containing keys with the session key
- ///
- /// byte package containing keys
- /// session key used to encrypt the package
- /// server hosting the enclave
- ///
- private byte[] EncryptBytePackage(byte[] bytePackage, byte[] sessionKey, string serverName)
- {
- if (sessionKey == null)
- throw SQL.NullArgumentInternal("sessionKey", ClassName, "EncryptBytePackage");
- if (sessionKey.Length == 0)
- throw SQL.EmptyArgumentInternal("sessionKey", ClassName, "EncryptBytePackage");
- //bytePackage is created internally in this class and is guaranteed to be non null and non empty
-
- try
- {
- SqlClientSymmetricKey symmetricKey = new SqlClientSymmetricKey(sessionKey);
- SqlClientEncryptionAlgorithm sqlClientEncryptionAlgorithm =
- SqlAeadAes256CbcHmac256Factory.Create(symmetricKey, SqlClientEncryptionType.Randomized,
- SqlAeadAes256CbcHmac256Algorithm.AlgorithmName);
- return sqlClientEncryptionAlgorithm.EncryptData(bytePackage);
- }
- catch (Exception e)
- {
- throw SQL.FailedToEncryptRegisterRulesBytePackage(e);
- }
- }
-
- ///
- /// Combine the array of given byte arrays into one
- ///
- /// byte arrays to be combined
- ///
- private byte[] CombineByteArrays(byte[][] byteArraysToCombine)
- {
- byte[] combinedArray = new byte[byteArraysToCombine.Sum(ba => ba.Length)];
- int offset = 0;
- foreach (byte[] byteArray in byteArraysToCombine)
- {
- Buffer.BlockCopy(byteArray, 0, combinedArray, offset, byteArray.Length);
- offset += byteArray.Length;
- }
- return combinedArray;
- }
-
- private byte[] ComputeQueryStringHash(string queryString)
- {
- // Validate the input parameters
- if (string.IsNullOrWhiteSpace(queryString))
- {
- string argumentName = "queryString";
- if (null == queryString)
- {
- throw SQL.NullArgumentInternal(argumentName, ClassName, ComputeQueryStringHashName);
- }
- else
- {
- throw SQL.EmptyArgumentInternal(argumentName, ClassName, ComputeQueryStringHashName);
- }
- }
-
- byte[] queryStringBytes = Encoding.Unicode.GetBytes(queryString);
-
- // Compute hash
- byte[] hash;
- using (SHA256Cng sha256 = new SHA256Cng())
- {
- sha256.TransformFinalBlock(queryStringBytes, 0, queryStringBytes.Length);
- hash = sha256.Hash;
- }
- return hash;
- }
-
- ///
- /// Exception when executing a enclave based Always Encrypted query
- ///
- internal class RetryableEnclaveQueryExecutionException : Exception
- {
- internal RetryableEnclaveQueryExecutionException(string message, Exception innerException) : base(message, innerException) { }
- }
-
- ///
- /// Class encapsulating necessary information about the byte package that needs to be sent to the enclave
- ///
- internal class EnclavePackage
- {
-
- internal SqlEnclaveSession EnclaveSession { get; }
- internal byte[] EnclavePackageBytes { get; }
-
- ///
- /// Constructor
- ///
- /// byte package to be sent to enclave
- /// enclave session to be used
- internal EnclavePackage(byte[] enclavePackageBytes, SqlEnclaveSession enclaveSession)
- {
- EnclavePackageBytes = enclavePackageBytes;
- EnclaveSession = enclaveSession;
- }
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs
index 8d02518557..b7a0cecc27 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs
@@ -121,7 +121,7 @@ private enum EXECTYPE
private Dictionary keysToBeSentToEnclave;
private bool requiresEnclaveComputations = false;
- internal EnclaveDelegate.EnclavePackage enclavePackage = null;
+ internal EnclavePackage enclavePackage = null;
private SqlEnclaveAttestationParameters enclaveAttestationParameters = null;
private byte[] customData = null;
private int customDataLength = 0;
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs
deleted file mode 100644
index a2d0cf56a4..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs
+++ /dev/null
@@ -1,70 +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.
-
-namespace Microsoft.Data.SqlClient
-{
-
- ///
- internal class SqlEnclaveSession
- {
-
- private static readonly string _sessionKeyName = "SessionKey";
- private static readonly string _className = "EnclaveSession";
-
- private readonly byte[] _sessionKey;
-
- ///
- internal long SessionId { get; }
-
- ///
- internal byte[] GetSessionKey()
- {
- return Clone(_sessionKey);
- }
-
- ///
- /// Deep copy the array into a new array
- ///
- ///
- ///
- private byte[] Clone(byte[] arrayToClone)
- {
-
- byte[] returnValue = new byte[arrayToClone.Length];
-
- for (int i = 0; i < arrayToClone.Length; i++)
- {
- returnValue[i] = arrayToClone[i];
- }
-
- return returnValue;
- }
-
- ///
- internal SqlEnclaveSession(byte[] sessionKey, long sessionId/*, long counter*/)
- {
- if (null == sessionKey)
- { throw SQL.NullArgumentInConstructorInternal(_sessionKeyName, _className); }
- if (0 == sessionKey.Length)
- { throw SQL.EmptyArgumentInConstructorInternal(_sessionKeyName, _className); }
-
- _sessionKey = sessionKey;
- SessionId = sessionId;
- }
- }
-
- internal class EnclaveSessionParameters
- {
- internal string ServerName { get; set; } // The name of the SQL Server instance containing the enclave.
- internal string AttestationUrl { get; set; } // The endpoint of an attestation service for attesting the enclave.
- internal string Database { get; set; } // The database that SqlClient contacts to request an enclave session.
-
- internal EnclaveSessionParameters(string serverName, string attestationUrl, string database)
- {
- ServerName = serverName;
- AttestationUrl = attestationUrl;
- Database = database;
- }
- }
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs
deleted file mode 100644
index 212d7a0047..0000000000
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs
+++ /dev/null
@@ -1,500 +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.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Runtime.Serialization.Json;
-using System.Security.Cryptography.X509Certificates;
-using System.Threading;
-
-namespace Microsoft.Data.SqlClient
-{
- // Implementation of an Enclave provider for Windows Virtual Secure Mode enclaves
- internal class HostGuardianServiceEnclaveProvider : VirtualizationBasedSecurityEnclaveProviderBase
- {
- #region Members
-
- // this is endpoint given to us by HGS team from windows
- private const string AttestationUrlSuffix = @"/v2.0/signingCertificates";
-
- public int MaxNumRetries { get; set; }
-
- private int enclaveRetrySleepInSeconds = 3;
-
- public int EnclaveRetrySleepInSeconds
- {
- get
- {
- return enclaveRetrySleepInSeconds;
- }
- set
- {
- if (value < 1)
- {
- throw new ArgumentException(Strings.EnclaveRetrySleepInSecondsValueException);
- }
-
- enclaveRetrySleepInSeconds = value;
- }
- }
-
- #endregion
-
- #region Private helpers
-
- // Return the endpoint for given attestation url
- protected override string GetAttestationUrl(string attestationUrl)
- {
- return attestationUrl.TrimEnd('/') + AttestationUrlSuffix;
- }
-
- // Makes a web request to the provided url and returns the response as a byte[]
- protected override byte[] MakeRequest(string url)
- {
- Exception exception = null;
-
- for (int n = 0; n < MaxNumRetries + 1 /* Initial attempt + numRetries */; n++)
- {
- try
- {
- if (n != 0)
- {
- Thread.Sleep(EnclaveRetrySleepInSeconds * 1000);
- }
-
- WebRequest request = WebRequest.Create(url);
-
- using (WebResponse response = request.GetResponse())
- using (Stream stream = response.GetResponseStream())
- {
- var deserializer = new DataContractJsonSerializer(typeof(byte[]));
- return (byte[])deserializer.ReadObject(stream);
- }
- }
- catch (Exception e)
- {
- exception = e;
- }
- }
-
- throw new AlwaysEncryptedAttestationException(String.Format(Strings.GetAttestationSigningCertificateRequestFailedFormat, url, exception.Message), exception);
- }
-
- #endregion
- }
-
- #region Models
-
- // A model class respresenting the deserialization of the byte payload the client
- // receives from SQL Server while setting up a session.
- internal class AttestationInfo
- {
- public uint TotalSize { get; set; }
-
- // The enclave's RSA Public Key.
- // Needed to establish trust of the enclave.
- // Used to verify the enclave's DiffieHellman info.
- public EnclavePublicKey Identity { get; set; }
-
- // The SQL Server host's health report the server received from the attestation service
- // and forwarded to the client.
- // Needed to establish trust of the enclave report received from SQL Server.
- // Used to verify the enclave report's signature.
- public HealthReport HealthReport { get; set; }
-
- // The enclave report from the SQL Server host's enclave.
- public EnclaveReportPackage EnclaveReportPackage { get; set; }
-
- // The id of the current session.
- // Needed to set up a secure session between the client and enclave.
- public long SessionId { get; set; }
-
- // The DiffieHellman public key and signature of SQL Server host's enclave.
- // Needed to set up a secure session between the client and enclave.
- public EnclaveDiffieHellmanInfo EnclaveDHInfo { get; set; }
-
- public AttestationInfo(byte[] attestationInfo)
- {
- int offset = 0;
-
- TotalSize = BitConverter.ToUInt32(attestationInfo, offset);
- offset += sizeof(uint);
-
- int identitySize = BitConverter.ToInt32(attestationInfo, offset);
- offset += sizeof(uint);
-
- int healthReportSize = BitConverter.ToInt32(attestationInfo, offset);
- offset += sizeof(uint);
-
- int enclaveReportSize = BitConverter.ToInt32(attestationInfo, offset);
- offset += sizeof(uint);
-
- byte[] identityBuffer = attestationInfo.Skip(offset).Take(identitySize).ToArray();
- Identity = new EnclavePublicKey(identityBuffer);
- offset += identitySize;
-
- byte[] healthReportBuffer = attestationInfo.Skip(offset).Take(healthReportSize).ToArray();
- HealthReport = new HealthReport(healthReportBuffer);
- offset += healthReportSize;
-
- byte[] enclaveReportBuffer = attestationInfo.Skip(offset).Take(enclaveReportSize).ToArray();
- EnclaveReportPackage = new EnclaveReportPackage(enclaveReportBuffer);
- offset += EnclaveReportPackage.GetSizeInPayload();
-
- uint secureSessionInfoResponseSize = BitConverter.ToUInt32(attestationInfo, offset);
- offset += sizeof(uint);
-
- SessionId = BitConverter.ToInt64(attestationInfo, offset);
- offset += sizeof(long);
-
- int secureSessionBufferSize = Convert.ToInt32(secureSessionInfoResponseSize) - sizeof(uint);
- byte[] secureSessionBuffer = attestationInfo.Skip(offset).Take(secureSessionBufferSize).ToArray();
- EnclaveDHInfo = new EnclaveDiffieHellmanInfo(secureSessionBuffer);
- offset += Convert.ToInt32(EnclaveDHInfo.Size);
- }
- }
-
- // A model class to hold the SQL Server's host health report in an X509Certificate2
- internal class HealthReport
- {
- private int Size { get; set; }
-
- public X509Certificate2 Certificate { get; set; }
-
- public HealthReport(byte[] payload)
- {
- Size = payload.Length;
- Certificate = new X509Certificate2(payload);
- }
-
- public int GetSizeInPayload()
- {
- return Size;
- }
- }
-
- // A managed model representing the output of EnclaveGetAttestationReport
- // https://msdn.microsoft.com/en-us/library/windows/desktop/mt844233(v=vs.85).aspx
- internal class EnclaveReportPackage
- {
- private int Size { get; set; }
-
- public EnclaveReportPackageHeader PackageHeader { get; set; }
-
- public EnclaveReport Report { get; set; }
-
- public List Modules { get; set; }
-
- public byte[] ReportAsBytes { get; set; }
-
- public byte[] SignatureBlob { get; set; }
-
- public EnclaveReportPackage(byte[] payload)
- {
- Size = payload.Length;
-
- int offset = 0;
- PackageHeader = new EnclaveReportPackageHeader(payload.Skip(offset).ToArray());
- offset += PackageHeader.GetSizeInPayload();
-
- Report = new EnclaveReport(payload.Skip(offset).ToArray());
- offset += Report.GetSizeInPayload();
-
- // Modules are not used for anything currently, ignore parsing for now
- //
- // Modules = new List();
- // int reportSizeRemaining = Convert.ToInt32(Report.ReportSize) - Report.GetSizeInPayload();
- // while (reportSizeRemaining > 0)
- // {
- // var module = new VSMEnclaveReportModule(payload.Skip(offset).ToArray());
- // Modules.Add(module);
- // reportSizeRemaining -= module.GetSizeInPayload();
- // offset += module.GetSizeInPayload();
- // }
-
- // Moving the offset back to the start of the report,
- // we need the report as a byte buffer for signature verification.
- offset = PackageHeader.GetSizeInPayload();
- int dataToHashSize = Convert.ToInt32(PackageHeader.SignedStatementSize);
- ReportAsBytes = payload.Skip(offset).Take(dataToHashSize).ToArray();
- offset += dataToHashSize;
-
- int signatureSize = Convert.ToInt32(PackageHeader.SignatureSize);
- SignatureBlob = payload.Skip(offset).Take(signatureSize).ToArray();
- offset += signatureSize;
- }
-
- public int GetSizeInPayload()
- {
- return Size;
- }
- }
-
- // A managed model of struct VBS_ENCLAVE_REPORT_PKG_HEADER
- // https://msdn.microsoft.com/en-us/library/windows/desktop/mt844257(v=vs.85).aspx
- internal class EnclaveReportPackageHeader
- {
- public uint PackageSize { get; set; }
-
- public uint Version { get; set; }
-
- public uint SignatureScheme { get; set; }
-
- public uint SignedStatementSize { get; set; }
-
- public uint SignatureSize { get; set; }
-
- public uint Reserved { get; set; }
-
- public EnclaveReportPackageHeader(byte[] payload)
- {
- int offset = 0;
- PackageSize = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- Version = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- SignatureScheme = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- SignedStatementSize = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- SignatureSize = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- Reserved = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
- }
-
- public int GetSizeInPayload()
- {
- return 6 * sizeof(uint);
- }
- }
-
- // A managed model of struct VBS_ENCLAVE_REPORT
- // https://msdn.microsoft.com/en-us/library/windows/desktop/mt844255(v=vs.85).aspx
- internal class EnclaveReport
- {
- private int Size { get; set; }
-
- public uint ReportSize { get; set; }
-
- public uint ReportVersion { get; set; }
-
- public byte[] EnclaveData { get; set; }
-
- private const int EnclaveDataLength = 64;
-
- public EnclaveIdentity Identity { get; set; }
-
- public EnclaveReport(byte[] payload)
- {
- Size = payload.Length;
-
- int offset = 0;
-
- ReportSize = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- ReportVersion = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- EnclaveData = payload.Skip(offset).Take(EnclaveDataLength).ToArray();
- offset += EnclaveDataLength;
-
- Identity = new EnclaveIdentity(payload.Skip(offset).ToArray());
- offset += Identity.GetSizeInPayload();
- }
-
- public int GetSizeInPayload()
- {
- return sizeof(uint) * 2 + sizeof(byte) * 64 + Identity.GetSizeInPayload();
- }
- }
-
- // A managed model of struct ENCLAVE_IDENTITY
- // https://msdn.microsoft.com/en-us/library/windows/desktop/mt844239(v=vs.85).aspx
- internal class EnclaveIdentity
- {
- private int Size { get; set; }
-
- private static readonly int ImageEnclaveLongIdLength = 32;
-
- private static readonly int ImageEnclaveShortIdLength = 16;
-
- public byte[] OwnerId = new byte[ImageEnclaveLongIdLength];
-
- public byte[] UniqueId = new byte[ImageEnclaveLongIdLength];
-
- public byte[] AuthorId = new byte[ImageEnclaveLongIdLength];
-
- public byte[] FamilyId = new byte[ImageEnclaveShortIdLength];
-
- public byte[] ImageId = new byte[ImageEnclaveShortIdLength];
-
- public uint EnclaveSvn { get; set; }
-
- public uint SecureKernelSvn { get; set; }
-
- public uint PlatformSvn { get; set; }
-
- public uint Flags { get; set; }
-
- public uint SigningLevel { get; set; }
-
- public uint Reserved { get; set; }
-
- public EnclaveIdentity() { }
-
- public EnclaveIdentity(byte[] payload)
- {
- Size = payload.Length;
-
- int offset = 0;
-
- int ownerIdLength = ImageEnclaveLongIdLength;
- OwnerId = payload.Skip(offset).Take(ownerIdLength).ToArray();
- offset += ownerIdLength;
-
- int uniqueIdLength = ImageEnclaveLongIdLength;
- UniqueId = payload.Skip(offset).Take(uniqueIdLength).ToArray();
- offset += uniqueIdLength;
-
- int authorIdLength = ImageEnclaveLongIdLength;
- AuthorId = payload.Skip(offset).Take(authorIdLength).ToArray();
- offset += authorIdLength;
-
- int familyIdLength = ImageEnclaveShortIdLength;
- FamilyId = payload.Skip(offset).Take(familyIdLength).ToArray();
- offset += familyIdLength;
-
- int imageIdLength = ImageEnclaveShortIdLength;
- ImageId = payload.Skip(offset).Take(imageIdLength).ToArray();
- offset += imageIdLength;
-
- EnclaveSvn = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- SecureKernelSvn = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- PlatformSvn = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- Flags = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- SigningLevel = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- Reserved = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
- }
-
- public int GetSizeInPayload()
- {
- return sizeof(byte) * ImageEnclaveLongIdLength * 3 + sizeof(byte) * ImageEnclaveShortIdLength * 2 + sizeof(uint) * 6;
- }
- }
-
- // A managed model of struct VBS_ENCLAVE_REPORT_VARDATA_HEADER
- // https://msdn.microsoft.com/en-us/library/windows/desktop/mt827065(v=vs.85).aspx
- internal class EnclaveReportModuleHeader
- {
- public uint DataType { get; set; }
-
- public uint ModuleSize { get; set; }
-
- public EnclaveReportModuleHeader(byte[] payload)
- {
- int offset = 0;
- DataType = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- ModuleSize = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
- }
-
- public int GetSizeInPayload()
- {
- return 2 * sizeof(uint);
- }
- }
-
- // A managed model of struct VBS_ENCLAVE_REPORT_MODULE
- // https://msdn.microsoft.com/en-us/library/windows/desktop/mt844256(v=vs.85).aspx
- internal class EnclaveReportModule
- {
- private static readonly int ImageEnclaveLongIdLength = 32;
-
- private static readonly int ImageEnclaveShortIdLength = 16;
-
- public EnclaveReportModuleHeader Header { get; set; }
-
- public byte[] UniqueId = new byte[ImageEnclaveLongIdLength];
-
- public byte[] AuthorId = new byte[ImageEnclaveLongIdLength];
-
- public byte[] FamilyId = new byte[ImageEnclaveShortIdLength];
-
- public byte[] ImageId = new byte[ImageEnclaveShortIdLength];
-
- public uint Svn { get; set; }
-
- public string ModuleName { get; set; }
-
- public EnclaveReportModule(byte[] payload)
- {
- int offset = 0;
- Header = new EnclaveReportModuleHeader(payload);
- offset += Convert.ToInt32(Header.GetSizeInPayload());
-
- int uniqueIdLength = ImageEnclaveLongIdLength;
- UniqueId = payload.Skip(offset).Take(uniqueIdLength).ToArray();
- offset += uniqueIdLength;
-
- int authorIdLength = ImageEnclaveLongIdLength;
- AuthorId = payload.Skip(offset).Take(authorIdLength).ToArray();
- offset += authorIdLength;
-
- int familyIdLength = ImageEnclaveShortIdLength;
- FamilyId = payload.Skip(offset).Take(familyIdLength).ToArray();
- offset += familyIdLength;
-
- int imageIdLength = ImageEnclaveShortIdLength;
- ImageId = payload.Skip(offset).Take(familyIdLength).ToArray();
- offset += imageIdLength;
-
- Svn = BitConverter.ToUInt32(payload, offset);
- offset += sizeof(uint);
-
- int strLen = Convert.ToInt32(Header.ModuleSize) - offset;
- ModuleName = BitConverter.ToString(payload, offset, 1);
- offset += sizeof(char) * 1;
- }
-
- public int GetSizeInPayload()
- {
- return Header.GetSizeInPayload() + Convert.ToInt32(Header.ModuleSize);
- }
- }
-
- // An enum representing the Flags property of ENCLAVE_IDENTITY
- // https://msdn.microsoft.com/en-us/library/windows/desktop/mt844239(v=vs.85).aspx
- internal enum EnclaveIdentityFlags
- {
- ENCLAVE_FLAG_NONE = 0x00000000,
- ENCLAVE_FLAG_FULL_DEBUG_ENABLED = 0x00000001,
- ENCLAVE_FLAG_DYNAMIC_DEBUG_ENABLED = 0x00000002,
- ENCLAVE_FLAG_DYNAMIC_DEBUG_ACTIVE = 0x00000004
- }
-
- #endregion
-}
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs
similarity index 63%
rename from src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs
index 066d33be25..3263031dde 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Linq;
namespace Microsoft.Data.SqlClient
{
@@ -29,27 +28,26 @@ public EnclaveDiffieHellmanInfo(byte[] payload)
{
Size = payload.Length;
- int offset = 0;
- int publicKeySize = BitConverter.ToInt32(payload, offset);
- offset += sizeof(int);
+ int publicKeySize = BitConverter.ToInt32(payload, 0);
+ int publicKeySignatureSize = BitConverter.ToInt32(payload, 4);
- 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;
+ PublicKey = new byte[publicKeySize];
+ PublicKeySignature = new byte[publicKeySignatureSize];
+ Buffer.BlockCopy(payload, 8, PublicKey, 0, publicKeySize);
+ Buffer.BlockCopy(payload, 8 + publicKeySize, PublicKeySignature, 0, publicKeySignatureSize);
}
}
internal enum EnclaveType
{
None = 0,
-
+ ///
+ /// Virtualization Based Security
+ ///
Vbs = 1,
-
+ ///
+ /// Intel SGX based security
+ ///
Sgx = 2
}
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AlwaysEncryptedKeyConverter.cs
similarity index 61%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AlwaysEncryptedKeyConverter.cs
index 23abf6b247..6ccbd67fb6 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/AlwaysEncryptedEnclaveProviderUtils.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/AlwaysEncryptedKeyConverter.cs
@@ -4,57 +4,10 @@
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
{
@@ -65,15 +18,15 @@ internal sealed class KeyConverter
private readonly struct RSAPublicKeyBlob
{
// Size of an RSA public key blob
- internal static readonly int Size = 539;
+ internal const int Size = 539;
// Size of the BCRYPT_RSAKEY_BLOB header
- internal static readonly int HeaderSize = 27;
+ internal const int HeaderSize = 27;
// Size of the exponent (final 3 bytes of the header)
- internal static readonly int ExponentSize = 3;
+ internal const 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;
+ internal const int ModulusSize = Size - HeaderSize;
+ internal const int ExponentOffset = HeaderSize - ExponentSize;
+ internal const int ModulusOffset = HeaderSize;
}
// Extracts the public key's modulus and exponent from an RSA public key blob
@@ -82,10 +35,16 @@ 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}");
+
+ byte[] exponent = new byte[RSAPublicKeyBlob.ExponentSize];
+ byte[] modulus = new byte[RSAPublicKeyBlob.ModulusSize];
+ Buffer.BlockCopy(keyBlob, RSAPublicKeyBlob.ExponentOffset, exponent, 0, RSAPublicKeyBlob.ExponentSize);
+ Buffer.BlockCopy(keyBlob, RSAPublicKeyBlob.ModulusOffset, modulus, 0, RSAPublicKeyBlob.ModulusSize);
+
return new RSAParameters()
{
- Exponent = keyBlob.Skip(RSAPublicKeyBlob.ExponentOffset).Take(RSAPublicKeyBlob.ExponentSize).ToArray(),
- Modulus = keyBlob.Skip(RSAPublicKeyBlob.ModulusOffset).Take(RSAPublicKeyBlob.ModulusSize).ToArray()
+ Exponent = exponent,
+ Modulus = modulus
};
}
@@ -96,11 +55,11 @@ internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob)
private readonly struct ECCPublicKeyBlob
{
// Size of an ECC public key blob
- internal static readonly int Size = 104;
+ internal const int Size = 104;
// Size of the BCRYPT_ECCKEY_BLOB header
- internal static readonly int HeaderSize = 8;
+ internal const int HeaderSize = 8;
// Size of each coordinate
- internal static readonly int KeySize = (Size - HeaderSize) / 2;
+ internal const int KeySize = (Size - HeaderSize) / 2;
}
// Magic numbers identifying blob types
@@ -116,13 +75,19 @@ 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}");
+
+ byte[] x = new byte[ECCPublicKeyBlob.KeySize];
+ byte[] y = new byte[ECCPublicKeyBlob.KeySize];
+ Buffer.BlockCopy(keyBlob, ECCPublicKeyBlob.HeaderSize, x, 0, ECCPublicKeyBlob.KeySize);
+ Buffer.BlockCopy(keyBlob, ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize, y, 0, ECCPublicKeyBlob.KeySize);
+
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()
+ X = x,
+ Y = y
},
};
}
@@ -137,7 +102,7 @@ internal static byte[] ECDHPublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey public
byte[] keyBlob = new byte[ECCPublicKeyBlob.Size];
// Set magic number
- Array.Copy(KeyBlobMagicNumber.ECDHPublicP384, 0, keyBlob, 0, 4);
+ Buffer.BlockCopy(KeyBlobMagicNumber.ECDHPublicP384, 0, keyBlob, 0, 4);
// Set key size
keyBlob[4] = (byte)ECCPublicKeyBlob.KeySize;
@@ -145,8 +110,8 @@ internal static byte[] ECDHPublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey public
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);
+ Buffer.BlockCopy(ecPoint.X, 0, keyBlob, ECCPublicKeyBlob.HeaderSize, ECCPublicKeyBlob.KeySize);
+ Buffer.BlockCopy(ecPoint.Y, 0, keyBlob, ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize, ECCPublicKeyBlob.KeySize);
return keyBlob;
}
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs
similarity index 63%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs
index 27c8bb18a9..ba9b91bffc 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveDelegate.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Security.Cryptography;
using System.Text;
@@ -13,20 +12,19 @@ namespace Microsoft.Data.SqlClient
///
/// A delegate for communicating with secure enclave
///
- internal partial class EnclaveDelegate
+ internal sealed partial class EnclaveDelegate
{
- private static readonly SqlAeadAes256CbcHmac256Factory SqlAeadAes256CbcHmac256Factory = new SqlAeadAes256CbcHmac256Factory();
- private static readonly string GetAttestationInfoQueryString = String.Format(@"Select GetTrustedModuleIdentityAndAttestationInfo({0}) as attestationInfo", 0);
- private static readonly string ClassName = "EnclaveDelegate";
- private static readonly string GetDecryptedKeysToBeSentToEnclaveName = "GetDecryptedKeysToBeSentToEnclave";
- private static readonly string ComputeQueryStringHashName = "ComputeQueryStringHash";
+ private static readonly SqlAeadAes256CbcHmac256Factory s_sqlAeadAes256CbcHmac256Factory = new SqlAeadAes256CbcHmac256Factory();
+ private static readonly EnclaveDelegate s_enclaveDelegate = new EnclaveDelegate();
- private readonly Object _lock = new Object();
+ private readonly object _lock;
- //singleton instance
- internal static EnclaveDelegate Instance { get; } = new EnclaveDelegate();
+ public static EnclaveDelegate Instance => s_enclaveDelegate;
- private EnclaveDelegate() { }
+ private EnclaveDelegate()
+ {
+ _lock = new object();
+ }
private byte[] GetUintBytes(string enclaveType, int intValue, string variableName)
{
@@ -54,24 +52,32 @@ private List GetDecryptedKeysToBeSentToEnclave(Dictiona
foreach (SqlTceCipherInfoEntry cipherInfo in keysTobeSentToEnclave.Values)
{
- SqlClientSymmetricKey sqlClientSymmetricKey = null;
- SqlEncryptionKeyInfo? encryptionkeyInfoChosen = null;
- SqlSecurityUtility.DecryptSymmetricKey(cipherInfo, serverName, out sqlClientSymmetricKey,
- out encryptionkeyInfoChosen);
+ SqlSecurityUtility.DecryptSymmetricKey(cipherInfo, serverName, out SqlClientSymmetricKey sqlClientSymmetricKey, out SqlEncryptionKeyInfo? encryptionkeyInfoChosen);
if (sqlClientSymmetricKey == null)
- throw SQL.NullArgumentInternal("sqlClientSymmetricKey", ClassName, GetDecryptedKeysToBeSentToEnclaveName);
+ {
+ throw SQL.NullArgumentInternal(nameof(sqlClientSymmetricKey), nameof(EnclaveDelegate), nameof(GetDecryptedKeysToBeSentToEnclave));
+ }
if (cipherInfo.ColumnEncryptionKeyValues == null)
- throw SQL.NullArgumentInternal("ColumnEncryptionKeyValues", ClassName, GetDecryptedKeysToBeSentToEnclaveName);
+ {
+ throw SQL.NullArgumentInternal(nameof(cipherInfo.ColumnEncryptionKeyValues), nameof(EnclaveDelegate), nameof(GetDecryptedKeysToBeSentToEnclave));
+ }
if (!(cipherInfo.ColumnEncryptionKeyValues.Count > 0))
+ {
throw SQL.ColumnEncryptionKeysNotFound();
+ }
//cipherInfo.CekId is always 0, hence used cipherInfo.ColumnEncryptionKeyValues[0].cekId. Even when cek has multiple ColumnEncryptionKeyValues
//the cekid and the plaintext value will remain the same, what varies is the encrypted cek value, since the cek can be encrypted by
//multiple CMKs
- decryptedKeysToBeSentToEnclave.Add(new ColumnEncryptionKeyInfo(sqlClientSymmetricKey.RootKey,
- cipherInfo.ColumnEncryptionKeyValues[0].databaseId,
- cipherInfo.ColumnEncryptionKeyValues[0].cekMdVersion, cipherInfo.ColumnEncryptionKeyValues[0].cekId));
+ decryptedKeysToBeSentToEnclave.Add(
+ new ColumnEncryptionKeyInfo(
+ sqlClientSymmetricKey.RootKey,
+ cipherInfo.ColumnEncryptionKeyValues[0].databaseId,
+ cipherInfo.ColumnEncryptionKeyValues[0].cekMdVersion,
+ cipherInfo.ColumnEncryptionKeyValues[0].cekId
+ )
+ );
}
return decryptedKeysToBeSentToEnclave;
}
@@ -130,17 +136,23 @@ private byte[] GenerateBytePackageForKeys(long enclaveSessionCounter, byte[] que
private byte[] EncryptBytePackage(byte[] bytePackage, byte[] sessionKey, string serverName)
{
if (sessionKey == null)
- throw SQL.NullArgumentInternal("sessionKey", ClassName, "EncryptBytePackage");
+ {
+ throw SQL.NullArgumentInternal(nameof(sessionKey), nameof(EnclaveDelegate), nameof(EncryptBytePackage));
+ }
if (sessionKey.Length == 0)
- throw SQL.EmptyArgumentInternal("sessionKey", ClassName, "EncryptBytePackage");
+ {
+ throw SQL.EmptyArgumentInternal(nameof(sessionKey), nameof(EnclaveDelegate), nameof(EncryptBytePackage));
+ }
//bytePackage is created internally in this class and is guaranteed to be non null and non empty
try
{
SqlClientSymmetricKey symmetricKey = new SqlClientSymmetricKey(sessionKey);
- SqlClientEncryptionAlgorithm sqlClientEncryptionAlgorithm =
- SqlAeadAes256CbcHmac256Factory.Create(symmetricKey, SqlClientEncryptionType.Randomized,
- SqlAeadAes256CbcHmac256Algorithm.AlgorithmName);
+ SqlClientEncryptionAlgorithm sqlClientEncryptionAlgorithm = s_sqlAeadAes256CbcHmac256Factory.Create(
+ symmetricKey,
+ SqlClientEncryptionType.Randomized,
+ SqlAeadAes256CbcHmac256Algorithm.AlgorithmName
+ );
return sqlClientEncryptionAlgorithm.EncryptData(bytePackage);
}
catch (Exception e)
@@ -149,20 +161,36 @@ private byte[] EncryptBytePackage(byte[] bytePackage, byte[] sessionKey, string
}
}
- ///
- /// Combine the array of given byte arrays into one
- ///
- /// byte arrays to be combined
- ///
- private byte[] CombineByteArrays(byte[][] byteArraysToCombine)
+ private byte[] CombineByteArrays(byte[] arr1, byte[] arr2)
{
- byte[] combinedArray = new byte[byteArraysToCombine.Sum(ba => ba.Length)];
- int offset = 0;
- foreach (byte[] byteArray in byteArraysToCombine)
- {
- Buffer.BlockCopy(byteArray, 0, combinedArray, offset, byteArray.Length);
- offset += byteArray.Length;
- }
+ // this complication avoids the usless allocation of a byte[][] to hold args
+ // it would be easier with spans so revisit if System.Memory is now a standard include
+ int length = arr1.Length + arr2.Length;
+ byte[] combinedArray = new byte[length];
+
+ Buffer.BlockCopy(arr1, 0, combinedArray, 0, arr1.Length);
+ Buffer.BlockCopy(arr2, 0, combinedArray, arr1.Length, arr2.Length);
+
+ return combinedArray;
+ }
+
+ private byte[] CombineByteArrays(byte[] arr1, byte[] arr2, byte[] arr3, byte[] arr4, byte[] arr5)
+ {
+ // this complication avoids the usless allocation of a byte[][] to hold args
+ // it would be easier with spans so revisit if System.Memory is now a standard include
+ int length = arr1.Length + arr2.Length + arr3.Length + arr4.Length + arr5.Length;
+ byte[] combinedArray = new byte[length];
+
+ Buffer.BlockCopy(arr1, 0, combinedArray, 0, arr1.Length);
+ int copied = arr1.Length;
+ Buffer.BlockCopy(arr2, 0, combinedArray, copied, arr2.Length);
+ copied += arr2.Length;
+ Buffer.BlockCopy(arr3, 0, combinedArray, copied, arr3.Length);
+ copied += arr3.Length;
+ Buffer.BlockCopy(arr4, 0, combinedArray, copied, arr4.Length);
+ copied += arr4.Length;
+ Buffer.BlockCopy(arr5, 0, combinedArray, copied, arr5.Length);
+
return combinedArray;
}
@@ -171,14 +199,13 @@ private byte[] ComputeQueryStringHash(string queryString)
// Validate the input parameters
if (string.IsNullOrWhiteSpace(queryString))
{
- string argumentName = "queryString";
- if (null == queryString)
+ if (queryString == null)
{
- throw SQL.NullArgumentInternal(argumentName, ClassName, ComputeQueryStringHashName);
+ throw SQL.NullArgumentInternal(nameof(queryString), nameof(EnclaveDelegate), nameof(ComputeQueryStringHash));
}
else
{
- throw SQL.EmptyArgumentInternal(argumentName, ClassName, ComputeQueryStringHashName);
+ throw SQL.EmptyArgumentInternal(nameof(queryString), nameof(EnclaveDelegate), nameof(ComputeQueryStringHash));
}
}
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclavePackage.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclavePackage.cs
similarity index 100%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/EnclavePackage.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclavePackage.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs
similarity index 75%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs
index fbafb58efa..b7b87112af 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnclaveSession.cs
@@ -4,7 +4,7 @@
namespace Microsoft.Data.SqlClient
{
- ///
+ ///
internal class SqlEnclaveSession
{
@@ -13,10 +13,10 @@ internal class SqlEnclaveSession
private readonly byte[] _sessionKey;
- ///
+ ///
internal long SessionId { get; }
- ///
+ ///
internal byte[] GetSessionKey()
{
return Clone(_sessionKey);
@@ -40,8 +40,8 @@ private byte[] Clone(byte[] arrayToClone)
return returnValue;
}
- ///
- internal SqlEnclaveSession(byte[] sessionKey, long sessionId/*, long counter*/)
+ ///
+ internal SqlEnclaveSession(byte[] sessionKey, long sessionId)
{
if (null == sessionKey)
{
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs
similarity index 100%
rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/VirtualSecureModeEnclaveProvider.cs