Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Release/2.0] Fix | Fix Enclave Session Cache Issue with Azure Database #628

Merged
merged 12 commits into from
Jul 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ the enclave attestation protocol as well as the logic for creating and caching e
<param name="clientDiffieHellmanKey">A Diffie-Hellman algorithm object that encapsulates a client-side key pair.</param>
<param name="attestationUrl">The endpoint of an attestation service for attesting the enclave.</param>
<param name="servername">The name of the SQL Server instance containing the enclave.</param>
<param name="database">The database that SqlClient contacts to request an enclave session.</param>
<param name="customData">The set of extra data needed for attestating the enclave.</param>
<param name="customDataLength">The length of the extra data needed for attestating the enclave.</param>
<param name="sqlEnclaveSession">The requested enclave session or <see langword="null" /> if the provider doesn't implement session caching.</param>
Expand All @@ -39,6 +40,7 @@ the enclave attestation protocol as well as the logic for creating and caching e
<GetEnclaveSession>
<param name="serverName">The name of the SQL Server instance containing the enclave.</param>
<param name="attestationUrl">The endpoint of an attestation service, SqlClient contacts to attest the enclave.</param>
<param name="database">The database that SqlClient contacts to request an enclave session.</param>
<param name="generateCustomData"><see langword="true" /> to indicate that a set of extra data needs to be generated for attestation; otherwise, <see langword="false" />.</param>
<param name="sqlEnclaveSession">When this method returns, the requested enclave session or <see langword="null" /> if the provider doesn't implement session caching. This parameter is treated as uninitialized.</param>
<param name="counter">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.</param>
Expand All @@ -51,6 +53,7 @@ the enclave attestation protocol as well as the logic for creating and caching e
<InvalidateEnclaveSession>
<param name="serverName">The name of the SQL Server instance containing the enclave.</param>
<param name="enclaveAttestationUrl">The endpoint of an attestation service, SqlClient contacts to attest the enclave.</param>
<param name="database">The database that SqlClient contacts to request an enclave session.</param>
<param name="enclaveSession">The session to be invalidated.</param>
<summary>When overridden in a derived class, looks up and evicts an enclave session from the enclave session cache, if the provider implements session caching.</summary>
<remarks>To be added.</remarks>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ internal class AzureAttestationEnclaveProvider : EnclaveProviderBase
#region Internal methods
// When overridden in a derived class, looks up an existing enclave session information in the enclave session cache.
// If the enclave provider doesn't implement enclave session caching, this method is expected to return null in the sqlEnclaveSession parameter.
internal override void GetEnclaveSession(string servername, string attestationUrl, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength)
internal override void GetEnclaveSession(string servername, string attestationUrl, string database, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength)
{
GetEnclaveSessionHelper(servername, attestationUrl, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);
GetEnclaveSessionHelper(servername, attestationUrl, database, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);
}

// Gets the information that SqlClient subsequently uses to initiate the process of attesting the enclave and to establish a secure session with the enclave.
Expand All @@ -81,14 +81,14 @@ internal override SqlEnclaveAttestationParameters GetAttestationParameters(strin
}

// 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, ECDiffieHellmanCng clientDHKey, string attestationUrl, string servername, string database, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter)
{
sqlEnclaveSession = null;
counter = 0;
try
{
ThreadRetryCache.Remove(Thread.CurrentThread.ManagedThreadId.ToString());
sqlEnclaveSession = GetEnclaveSessionFromCache(servername, attestationUrl, out counter);
sqlEnclaveSession = GetEnclaveSessionFromCache(servername, attestationUrl, database, out counter);
if (sqlEnclaveSession == null)
{
if (!string.IsNullOrEmpty(attestationUrl) && customData != null && customDataLength > 0)
Expand All @@ -107,7 +107,7 @@ internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHell
byte[] sharedSecret = GetSharedSecret(attestInfo.Identity, nonce, attestInfo.EnclaveType, attestInfo.EnclaveDHInfo, clientDHKey);

// add session to cache
sqlEnclaveSession = AddEnclaveSessionToCache(attestationUrl, servername, sharedSecret, attestInfo.SessionId, out counter);
sqlEnclaveSession = AddEnclaveSessionToCache(attestationUrl, servername, database, sharedSecret, attestInfo.SessionId, out counter);
}
else
{
Expand All @@ -126,9 +126,9 @@ internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHell
}

// When overridden in a derived class, looks up and evicts an enclave session from the enclave session cache, if the provider implements session caching.
internal override void InvalidateEnclaveSession(string serverName, string enclaveAttestationUrl, SqlEnclaveSession enclaveSessionToInvalidate)
internal override void InvalidateEnclaveSession(string serverName, string enclaveAttestationUrl, string database, SqlEnclaveSession enclaveSessionToInvalidate)
{
InvalidateEnclaveSessionHelper(serverName, enclaveAttestationUrl, enclaveSessionToInvalidate);
InvalidateEnclaveSessionHelper(serverName, enclaveAttestationUrl, database, enclaveSessionToInvalidate);
}
#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete
/// <param name="enclaveType">enclave type</param>
/// <param name="serverName">servername</param>
/// <param name="attestationUrl">attestation url for attestation service endpoint</param>
/// <param name="database">The database that SqlClient contacts to request an enclave session.</param>
/// <param name="attestationInfo">attestation info from SQL Server</param>
/// <param name="attestationParameters">attestation parameters</param>
/// <param name="customData">A set of extra data needed for attestating the enclave.</param>
/// <param name="customDataLength">The length of the extra data needed for attestating the enclave.</param>
internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string attestationUrl,
internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string attestationUrl, string database,
byte[] attestationInfo, SqlEnclaveAttestationParameters attestationParameters, byte[] customData, int customDataLength)
{

Expand All @@ -79,15 +80,14 @@ internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationP
SqlEnclaveSession sqlEnclaveSession = null;
byte[] dummyCustomData = null;
int dummyCustomDataLength;

sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(serverName, attestationUrl, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength);
sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(serverName, attestationUrl, database, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength);

if (sqlEnclaveSession != null)
{
return;
}

sqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(attestationInfo, attestationParameters.ClientDiffieHellmanKey, attestationUrl, serverName, customData, customDataLength, out sqlEnclaveSession, out counter);
sqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(attestationInfo, attestationParameters.ClientDiffieHellmanKey, attestationUrl, serverName, database, customData, customDataLength, out sqlEnclaveSession, out counter);

if (sqlEnclaveSession == null)
{
Expand All @@ -105,8 +105,9 @@ internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationP
/// <param name="enclaveType">enclave type</param>
/// <param name="serverName">server name</param>
/// <param name="enclaveAttestationUrl">url for attestation endpoint</param>
/// <param name="database">The database that SqlClient contacts to request an enclave session.</param>
/// <returns></returns>
internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol attestationProtocol, Dictionary<int, SqlTceCipherInfoEntry> keysToBeSentToEnclave, string queryText, string enclaveType, string serverName, string enclaveAttestationUrl)
internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol attestationProtocol, Dictionary<int, SqlTceCipherInfoEntry> keysToBeSentToEnclave, string queryText, string enclaveType, string serverName, string enclaveAttestationUrl, string database)
{

SqlEnclaveSession sqlEnclaveSession = null;
Expand All @@ -116,7 +117,7 @@ internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol

try
{
GetEnclaveSession(attestationProtocol, enclaveType, serverName, enclaveAttestationUrl, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength, throwIfNull: true);
GetEnclaveSession(attestationProtocol, enclaveType, serverName, enclaveAttestationUrl, database, false, out sqlEnclaveSession, out counter, out dummyCustomData, out dummyCustomDataLength, throwIfNull: true);
}
catch (Exception e)
{
Expand All @@ -133,10 +134,10 @@ internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol
return new EnclavePackage(byteArrayToBeSentToEnclave, sqlEnclaveSession);
}

internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string EnclaveAttestationUrl, SqlEnclaveSession enclaveSession)
internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string EnclaveAttestationUrl, string database, SqlEnclaveSession enclaveSession)
{
SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
sqlColumnEncryptionEnclaveProvider.InvalidateEnclaveSession(serverName, EnclaveAttestationUrl, enclaveSession);
sqlColumnEncryptionEnclaveProvider.InvalidateEnclaveSession(serverName, EnclaveAttestationUrl, database, enclaveSession);
}


Expand Down Expand Up @@ -207,16 +208,16 @@ private string ConvertAttestationProtocolToString(SqlConnectionAttestationProtoc
}
}

internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string enclaveAttestationUrl, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string enclaveAttestationUrl, string database, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
{
long counter;
GetEnclaveSession(attestationProtocol, enclaveType, serverName, enclaveAttestationUrl, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength, throwIfNull: false);
GetEnclaveSession(attestationProtocol, enclaveType, serverName, enclaveAttestationUrl, database, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength, throwIfNull: false);
}

private void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string enclaveAttestationUrl, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength, bool throwIfNull)
private void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string enclaveAttestationUrl, string database, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out long counter, out byte[] customData, out int customDataLength, bool throwIfNull)
{
SqlColumnEncryptionEnclaveProvider sqlColumnEncryptionEnclaveProvider = GetEnclaveProvider(attestationProtocol, enclaveType);
sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(serverName, enclaveAttestationUrl, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);
sqlColumnEncryptionEnclaveProvider.GetEnclaveSession(serverName, enclaveAttestationUrl, database, generateCustomData, out sqlEnclaveSession, out counter, out customData, out customDataLength);

if (throwIfNull && sqlEnclaveSession == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,28 @@ internal byte[] GetSerializedAttestationParameters(
/// <param name="enclaveType">enclave type</param>
/// <param name="serverName">servername</param>
/// <param name="attestationUrl">attestation url for attestation service endpoint</param>
/// <param name="database">The database that SqlClient contacts to request an enclave session.</param>
/// <param name="attestationInfo">attestation info from SQL Server</param>
/// <param name="attestationParameters">attestation parameters</param>
/// <param name="customData">A set of extra data needed for attestating the enclave.</param>
/// <param name="customDataLength">The length of the extra data needed for attestating the enclave.</param>
internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string attestationUrl,
internal void CreateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string attestationUrl, string database,
byte[] attestationInfo, SqlEnclaveAttestationParameters attestationParameters, byte[] customData, int customDataLength)
{
throw new PlatformNotSupportedException();
}

internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string enclaveAttestationUrl, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
internal void GetEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string enclaveAttestationUrl, string database, bool generateCustomData, out SqlEnclaveSession sqlEnclaveSession, out byte[] customData, out int customDataLength)
{
throw new PlatformNotSupportedException();
}

internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol attestationProtocol, Dictionary<int, SqlTceCipherInfoEntry> keysTobeSentToEnclave, string queryText, string enclaveType, string serverName, string enclaveAttestationUrl)
internal EnclavePackage GenerateEnclavePackage(SqlConnectionAttestationProtocol attestationProtocol, Dictionary<int, SqlTceCipherInfoEntry> keysTobeSentToEnclave, string queryText, string enclaveType, string serverName, string enclaveAttestationUrl, string database)
{
throw new PlatformNotSupportedException();
}

internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string EnclaveAttestationUrl, SqlEnclaveSession enclaveSession)
internal void InvalidateEnclaveSession(SqlConnectionAttestationProtocol attestationProtocol, string enclaveType, string serverName, string EnclaveAttestationUrl, string database, SqlEnclaveSession enclaveSession)
{
throw new PlatformNotSupportedException();
}
Expand Down
Loading