Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
08f86b6
Merge test behavior overrides
benrr101 Sep 4, 2025
9063c0b
Create encryption partial - the reader partial is getting too big.
benrr101 Sep 4, 2025
85bda18
Merge GetParameterEncryptionDataReader from netcore, update netfx to …
benrr101 Sep 4, 2025
45e568b
Merge GetParameterEncryptionDataReaderAsync from netcore, update netf…
benrr101 Sep 4, 2025
cc242fb
Factor out the second result set read for ReadDescribeEncryptionParam…
benrr101 Sep 5, 2025
d1fbee0
Factor out ReadDescribeEncryptionParameterResults1 from ReadDescribeE…
benrr101 Sep 5, 2025
04ea706
Factor out ReadDescribeEncryptionParameterResults3 from ReadDescribeE…
benrr101 Sep 5, 2025
70ba99f
Repeat factoring out in netcore
benrr101 Sep 5, 2025
db8bd2a
Executive decision: removing debug-only row count - it's to make sure…
benrr101 Sep 5, 2025
2f870c2
Merge ReadDescribeEncryptionParameterResults
benrr101 Sep 5, 2025
31662a0
Merge ShouldCacheEncryptinMetadata, keysToBeSentToEnclave and require…
benrr101 Sep 8, 2025
ee8ce4c
Merge enclavePackage, enclaveAttestationParameters, customData, custo…
benrr101 Sep 8, 2025
ee295ee
Merge ShouldUseEnclaveBasedWorkflow, _customColumnEncryptionKeyStoreP…
benrr101 Sep 8, 2025
cfd3353
Merge _sqlRPCParameterEncryptionRegArray, _currentlyExecutingDescribe…
benrr101 Sep 8, 2025
cd5ce3f
Merge InvalidateEnclaveession, GetEnclaveSessionParameters
benrr101 Sep 8, 2025
f4046b5
Merge ValidateCustomProviders
benrr101 Sep 8, 2025
e0656c3
Merge ResetEncryptionState()
benrr101 Sep 8, 2025
cb34479
Merge PrepareTransparentEncryptionFinallyBlock
benrr101 Sep 8, 2025
6b82413
Merge _rowsAffectedBySpDescribeParameterEncryption and RowsAffectedBy…
benrr101 Sep 9, 2025
588a724
Merge SetColumnEncryptionSetting and _wasBatchModeColumnEncryptionSet…
benrr101 Sep 9, 2025
016756b
Merge GetColumnEncryptionCustomKeyProvidersNames and TryGetColumnEncr…
benrr101 Sep 9, 2025
5bc19f9
Merge TryFetchInputParameterEncryptionInfo
benrr101 Sep 9, 2025
06e0bf1
Merge PrepareDescribeParameterEncryptionRequest
benrr101 Sep 10, 2025
db8b2e7
Merge ClearDescribeParameterEncryptionRequests
benrr101 Sep 11, 2025
0b683cc
Merge _rpcForEncryption, BuildStoredProcedureStatementForColumnEncryp…
benrr101 Sep 11, 2025
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 @@ -582,6 +582,9 @@
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.cs">
<Link>Microsoft\Data\SqlClient\SqlCommand.cs</Link>
</Compile>
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.Encryption.cs">
<Link>Microsoft\Data\SqlClient\SqlCommand.Encryption.cs</Link>
</Compile>
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.NonQuery.cs">
<Link>Microsoft\Data\SqlClient\SqlCommand.NonQuery.cs</Link>
</Compile>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,9 @@
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.cs">
<Link>Microsoft\Data\SqlClient\SqlCommand.cs</Link>
</Compile>
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.Encryption.cs">
<Link>Microsoft\Data\SqlClient\SqlCommand.Encryption.cs</Link>
</Compile>
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCommand.NonQuery.cs">
<Link>Microsoft\Data\SqlClient\SqlCommand.NonQuery.cs</Link>
</Compile>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Microsoft.Data.SqlClient
/// <summary>
/// A delegate for communicating with secure enclave
/// </summary>
// @TODO: This isn't a delegate... it's a utility class
internal sealed partial class EnclaveDelegate
{
private static readonly SqlAeadAes256CbcHmac256Factory s_sqlAeadAes256CbcHmac256Factory = new SqlAeadAes256CbcHmac256Factory();
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
Expand Down Expand Up @@ -43,7 +44,45 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
#endregion

#region Fields

#region Test-Only Behavior Overrides
#if DEBUG
/// <summary>
/// Force the client to sleep during sp_describe_parameter_encryption in the function TryFetchInputParameterEncryptionInfo.
/// </summary>
private static bool _sleepDuringTryFetchInputParameterEncryptionInfo = false;

/// <summary>
/// Force the client to sleep during sp_describe_parameter_encryption in the function RunExecuteReaderTds.
/// </summary>
private static bool _sleepDuringRunExecuteReaderTdsForSpDescribeParameterEncryption = false;

/// <summary>
/// Force the client to sleep during sp_describe_parameter_encryption after ReadDescribeEncryptionParameterResults.
/// </summary>
private static bool _sleepAfterReadDescribeEncryptionParameterResults = false;

/// <summary>
/// Internal flag for testing purposes that forces all queries to internally end async calls.
/// </summary>
private static bool _forceInternalEndQuery = false;

/// <summary>
/// Internal flag for testing purposes that forces one RetryableEnclaveQueryExecutionException during GenerateEnclavePackage
/// </summary>
private static bool _forceRetryableEnclaveQueryExecutionExceptionDuringGenerateEnclavePackage = false;
#endif
#endregion

// @TODO: Make property - non-private fields are bad
// @TODO: Rename to match naming convention _enclavePackage
internal EnclavePackage enclavePackage = null;

// @TODO: Make property - non-private fields are bad (this should be read-only externally)
internal ConcurrentDictionary<int, SqlTceCipherInfoEntry> keysToBeSentToEnclave;

// @TODO: Make property - non-private fields are bad (this can be read-only externally)
internal bool requiresEnclaveComputations = false;

// @TODO: Make property - non-private fields are bad
internal SqlDependency _sqlDep;

Expand All @@ -66,7 +105,7 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
/// false. This may also be used to set other behavior which overrides connection level
/// setting.
/// </summary>
// @TODO: Make auto-property
// @TODO: Make auto-property, also make nullable.
private SqlCommandColumnEncryptionSetting _columnEncryptionSetting =
SqlCommandColumnEncryptionSetting.UseConnectionSetting;

Expand All @@ -85,6 +124,25 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
/// </summary>
private CommandType _commandType;

/// <summary>
/// This variable is used to keep track of which RPC batch's results are being read when reading the results of
/// describe parameter encryption RPC requests in BatchRPCMode.
/// </summary>
// @TODO: Rename to match naming conventions
private int _currentlyExecutingDescribeParameterEncryptionRPC;

/// <summary>
/// Per-command custom providers. It can be provided by the user and can be set more than
/// once.
/// </summary>
private IReadOnlyDictionary<string, SqlColumnEncryptionKeyStoreProvider> _customColumnEncryptionKeyStoreProviders;

// @TODO: Rename to indicate that this is for enclave stuff, I think...
private byte[] customData = null;

// @TODO: Rename to indicate that this is for enclave stuff. Or just get rid of it and use the length of customData if possible.
private int customDataLength = 0;

/// <summary>
/// By default, the cmd object is visible on the design surface (i.e. VS7 Server Tray) to
/// limit the number of components that clutter the design surface, when the DataAdapter
Expand All @@ -93,20 +151,23 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
/// </summary>
// @TODO: Make auto-property
private bool _designTimeInvisible;

/// <summary>
/// Current state of preparation of the command.
/// By default, assume the user is not sharing a connection so the command has not been prepared.
/// </summary>
private EXECTYPE _execType = EXECTYPE.UNPREPARED;

/// <summary>
/// True if the user changes the command text or number of parameters after the command has
/// already prepared.
/// </summary>
// @TODO: Consider renaming "_IsUserDirty"
private bool _dirty = false;


/// <summary>
/// Current state of preparation of the command.
/// By default, assume the user is not sharing a connection so the command has not been prepared.
/// </summary>
private EXECTYPE _execType = EXECTYPE.UNPREPARED;

// @TODO: Rename to match naming conventions _enclaveAttestationParameters
private SqlEnclaveAttestationParameters enclaveAttestationParameters = null;

/// <summary>
/// On 8.0 and above the Prepared state cannot be left. Once a command is prepared it will
/// always be prepared. A change in parameters, command text, etc (IsDirty) automatically
Expand Down Expand Up @@ -174,6 +235,22 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
// @TODO: Use int? and replace -1 usage with null
private int _rowsAffected = -1;

/// <summary>
/// number of rows affected by sp_describe_parameter_encryption.
/// </summary>
// @TODO: Use int? and replace -1 usage with null
// @TODO: This is only used for debug asserts?
// @TODO: Rename to drop Sp
private int _rowsAffectedBySpDescribeParameterEncryption = -1;

/// <summary>
/// RPC for tracking execution of sp_describe_parameter_encryption.
/// </summary>
private _SqlRPC _rpcForEncryption = null;

// @TODO: Rename to match naming convention
private _SqlRPC[] _sqlRPCParameterEncryptionReqArray;

/// <summary>
/// TDS session the current instance is using.
/// </summary>
Expand All @@ -195,7 +272,14 @@ public sealed partial class SqlCommand : DbCommand, ICloneable
/// DbDataAdapter.
/// </summary>
private UpdateRowSource _updatedRowSource = UpdateRowSource.Both;


/// <summary>
/// Indicates if the column encryption setting was set at-least once in the batch rpc mode,
/// when using AddBatchCommand.
/// </summary>
// @TODO: can be replaced by using nullable for _columnEncryptionSetting.
private bool _wasBatchModeColumnEncryptionSettingSetOnce;

#endregion

#region Constructors
Expand Down Expand Up @@ -615,9 +699,15 @@ public override UpdateRowSource UpdatedRowSource
#endregion

#region Internal/Protected/Private Properties


internal bool HasColumnEncryptionKeyStoreProvidersRegistered
{
get => _customColumnEncryptionKeyStoreProviders?.Count > 0;
}

internal bool InPrepare => _inPrepare;

// @TODO: Rename RowsAffectedInternal or
internal int InternalRecordsAffected
{
get => _rowsAffected;
Expand All @@ -634,9 +724,36 @@ internal int InternalRecordsAffected
}
}

/// <summary>
/// A flag to indicate if we have in-progress describe parameter encryption RPC requests.
/// Reset to false when completed.
/// </summary>
// @TODO: Rename to match naming conventions
internal bool IsDescribeParameterEncryptionRPCCurrentlyInProgress { get; private set; }

// @TODO: Rename to match conventions.
internal int ObjectID { get; } = Interlocked.Increment(ref _objectTypeCount);

/// <summary>
/// Get or add to the number of records affected by SpDescribeParameterEncryption.
/// The below line is used only for debug asserts and not exposed publicly or impacts functionality otherwise.
/// </summary>
internal int RowsAffectedByDescribeParameterEncryption
{
get => _rowsAffectedBySpDescribeParameterEncryption;
set
{
if (_rowsAffectedBySpDescribeParameterEncryption == -1)
{
_rowsAffectedBySpDescribeParameterEncryption = value;
}
else if (value > 0)
{
_rowsAffectedBySpDescribeParameterEncryption += value;
}
}
}

internal SqlStatistics Statistics
{
get
Expand Down Expand Up @@ -763,6 +880,20 @@ private bool IsDirty
private bool IsSimpleTextQuery => CommandType is CommandType.Text &&
(_parameters is null || _parameters.Count == 0);

private bool ShouldCacheEncryptionMetadata
{
// @TODO: Should we check for null on _activeConnection?
get => !requiresEnclaveComputations || _activeConnection.Parser.AreEnclaveRetriesSupported;
}

private bool ShouldUseEnclaveBasedWorkflow
{
// @TODO: I'm pretty sure the or'd condition is used in several places. We could factor that out.
get => (!string.IsNullOrWhiteSpace(_activeConnection.EnclaveAttestationUrl) ||
_activeConnection.AttestationProtocol is SqlConnectionAttestationProtocol.None) &&
IsColumnEncryptionEnabled;
}

#endregion

#region Public/Internal Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,7 @@ internal string GetPrefixedParameterName()
/// </summary>
/// <param name="builder"></param>
/// <param name="rawParameterName"></param>
// @TODO: This is only used in SqlCommand, and literally just adds a '@' at the beginning. This belongs in SqlCommand, without the append logic.
internal static void AppendPrefixedParameterName(StringBuilder builder, string rawParameterName)
{
if (!string.IsNullOrEmpty(rawParameterName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ internal static void DecryptSymmetricKey(SqlCipherMetadata md, SqlConnection con
/// </summary>
internal static void DecryptSymmetricKey(SqlTceCipherInfoEntry sqlTceCipherInfoEntry, out SqlClientSymmetricKey sqlClientSymmetricKey, out SqlEncryptionKeyInfo encryptionkeyInfoChosen, SqlConnection connection, SqlCommand command)
{
Debug.Assert(connection is not null, "Connection should not be null.");
Debug.Assert(sqlTceCipherInfoEntry is not null, "sqlTceCipherInfoEntry should not be null in DecryptSymmetricKey.");
Debug.Assert(sqlTceCipherInfoEntry.ColumnEncryptionKeyValues is not null,
"sqlTceCipherInfoEntry.ColumnEncryptionKeyValues should not be null in DecryptSymmetricKey.");
Expand Down
Loading