Skip to content

Commit

Permalink
Feature | AE with enclaves - multi-platform and .NET Standard 2.1 sup…
Browse files Browse the repository at this point in the history
…port (#676)
  • Loading branch information
johnnypham committed Aug 21, 2020
1 parent e10b230 commit 146ecd9
Show file tree
Hide file tree
Showing 36 changed files with 371 additions and 221 deletions.
8 changes: 4 additions & 4 deletions build.proj
Expand Up @@ -25,7 +25,7 @@
<NetCoreDriver Include="**/netcore/**/Microsoft.Data.SqlClient*.csproj" />
<AKVProvider Include="**/add-ons/**/AzureKeyVaultProvider/*.csproj" />

<FunctionalTests Include="**/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj" />
<FunctionalTests Condition="$(ReferenceType.Contains('NetStandard'))" Include="**/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj" />
<FunctionalTests Include="**/tools/TDS/TDS/TDS.csproj" />
<FunctionalTests Include="**/tools/TDS/TDS.EndPoint/TDS.EndPoint.csproj" />
<FunctionalTests Include="**/tools/TDS/TDS.Servers/TDS.Servers.csproj" />
Expand All @@ -34,7 +34,7 @@
<FunctionalTests Include="**/ManualTests/SQL/UdtTest/UDTs/Address/Address.csproj" />
<FunctionalTests Include="**/Microsoft.Data.SqlClient.Tests.csproj" />

<ManualTests Include="**/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj" />
<ManualTests Condition="$(ReferenceType.Contains('NetStandard'))" Include="**/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj" />
<ManualTests Include="**/ManualTests/SQL/UdtTest/UDTs/Address/Address.csproj" />
<ManualTests Include="**/ManualTests/SQL/UdtTest/UDTs/Circle/Circle.csproj" />
<ManualTests Include="**/ManualTests/SQL/UdtTest/UDTs/Shapes/Shapes.csproj" />
Expand Down Expand Up @@ -116,14 +116,14 @@
<MSBuild Projects="@(AKVProvider)" Properties="TestTargetOS=$(TestOS)netfx;Platform=$(Platform);$(TestProjectProperties)" />
</Target>

<Target Name="BuildAKVNetCore" Condition="!$(ReferenceType.Contains('NetStandard'))">
<Target Name="BuildAKVNetCore">
<MSBuild Projects="@(AKVProvider)" Targets="restore" Properties="TestTargetOS=$(TestOS)netcoreapp" />
<!-- Only build platform specific builds for Package reference types -->
<MSBuild Projects="@(AKVProvider)" Properties="TestTargetOS=$(TestOS)netcoreapp;$(ProjectProperties);Platform=AnyCPU;" Condition="!$(ReferenceType.Contains('Package'))"/>
<MSBuild Projects="@(AKVProvider)" Properties="TestTargetOS=$(TestOS)netcoreapp;$(ProjectProperties);Platform=$(Platform);" Condition="$(ReferenceType.Contains('Package'))"/>
</Target>

<Target Name="BuildAKVNetCoreAllOS" Condition="!$(ReferenceType.Contains('NetStandard'))">
<Target Name="BuildAKVNetCoreAllOS">
<MSBuild Projects="@(AKVProvider)" Targets="restore" Properties="TestTargetOS=$(TestOS)netcoreapp" />
<MSBuild Projects="@(AKVProvider)" Properties="TestTargetOS=$(TestOS)netcoreapp;$(ProjectProperties);Platform=AnyCPU;OSGroup=Unix;" RemoveProperties="TargetsWindows;TargetsUnix;" />
<MSBuild Projects="@(AKVProvider)" Properties="TestTargetOS=$(TestOS)netcoreapp;$(ProjectProperties);Platform=AnyCPU;OSGroup=Windows_NT;" RemoveProperties="TargetsWindows;TargetsUnix;" Condition="'$(IsEnabledWindows)' == 'true'" />
Expand Down
Expand Up @@ -6,7 +6,7 @@
<ProjectGuid>{9073ABEF-92E0-4702-BB23-2C99CEF9BDD7}</ProjectGuid>
<TargetGroup Condition="$(TargetFramework.StartsWith('netcoreapp'))">netcoreapp</TargetGroup>
<TargetGroup Condition="$(TargetFramework.StartsWith('net4'))">netfx</TargetGroup>
<Configurations>Debug;Release;net46-Release;net46-Debug;netcoreapp2.1-Debug;netcoreapp2.1-Release;</Configurations>
<Configurations>Debug;Release;net46-Release;net46-Debug;netcoreapp2.1-Debug;netcoreapp2.1-Release;netcoreapp3.1-Debug;netcoreapp3.1-Release</Configurations>
<Platforms>AnyCPU;x86;x64</Platforms>
<IntermediateOutputPath>$(ObjFolder)$(Configuration).$(Platform)\$(AddOnName)</IntermediateOutputPath>
<OutputPath>$(BinFolder)$(Configuration).$(Platform)\$(AddOnName)</OutputPath>
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.Data.SqlClient/add-ons/Directory.Build.props
Expand Up @@ -19,6 +19,7 @@
<When Condition="'$(TestTargetOS)' != ''">
<PropertyGroup>
<TargetFramework Condition="'$(TestTargetOS)' == 'Windowsnetcoreapp' OR '$(TestTargetOS)' == 'Unixnetcoreapp'">netcoreapp2.1</TargetFramework>
<TargetFramework Condition="('$(TestTargetOS)' == 'Windowsnetcoreapp' OR '$(TestTargetOS)' == 'Unixnetcoreapp') AND ($(ReferenceType)=='NetStandard' AND $(TargetNetStandardVersion)=='netstandard2.1')">netcoreapp3.1</TargetFramework>
<TargetFramework Condition="'$(TestTargetOS)' == 'Windowsnetfx'">net46</TargetFramework>
</PropertyGroup>
</When>
Expand Down
@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;netstandard2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks Condition="$(ReferenceType)=='NetStandard' AND $(TargetNetStandardVersion)=='netstandard2.1'">netstandard2.1</TargetFrameworks>
<IntermediateOutputPath>$(ObjFolder)$(Configuration)\$(AssemblyName)\ref\</IntermediateOutputPath>
<OutputPath>$(BinFolder)$(Configuration)\$(AssemblyName)\ref\</OutputPath>
<DocumentationFile>$(OutputPath)\$(TargetFramework)\Microsoft.Data.SqlClient.xml</DocumentationFile>
Expand Down
@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Microsoft.Data.SqlClient</AssemblyName>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;netstandard2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks Condition="$(ReferenceType)=='NetStandard' AND $(TargetNetStandardVersion)=='netstandard2.1'">netstandard2.1</TargetFrameworks>
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(OSGroup)' == 'AnyOS'">Strings.PlatformNotSupported_DataSqlClient</GeneratePlatformNotSupportedAssemblyMessage>
<OSGroup Condition="'$(OSGroup)' == ''">$(OS)</OSGroup>
<TargetsWindows Condition="'$(OSGroup)'=='Windows_NT'">true</TargetsWindows>
Expand Down Expand Up @@ -226,38 +227,40 @@
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard' OR '$(TargetGroup)' == 'netcoreapp' OR '$(IsUAPAssembly)' == 'true'">
<Compile Include="Microsoft.Data.SqlClient.TypeForwards.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netstandard'">
<Compile Include="Microsoft\Data\SqlClient\SqlAuthenticationProviderManager.NetStandard.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDiagnosticListener.NetStandard.cs" />
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netstandard' AND '$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft\Data\SqlClient\EnclaveDelegate.NetStandard.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netstandard'">
<Compile Include="Microsoft\Data\SqlClient\SqlAuthenticationProviderManager.NetStandard.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDiagnosticListener.NetStandard.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDelegatedTransaction.NetStandard.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParser.NetStandard.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetFramework)' != 'netstandard2.0'">
<Compile Include="Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\EnclaveDelegate.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\AzureAttestationBasedEnclaveProvider.cs" />
<Compile Include="Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.cs" />
<Compile Include="Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProviderBase.cs" />
<Compile Include="Microsoft\Data\SqlClient\AlwaysEncryptedAttestationException.cs" />
<Compile Include="Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs" />
<Compile Include="Microsoft\Data\SqlClient\EnclaveProviderBase.cs" />
<Compile Include="Microsoft\Data\SqlClient\EnclaveSessionCache.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="Microsoft\Data\Common\DbConnectionStringCommon.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\ProviderBase\DbConnectionPool.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlAuthenticationProviderManager.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionString.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionStringBuilder.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDiagnosticListener.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\EnclaveDelegate.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDelegatedTransaction.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParser.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\AzureAttestationBasedEnclaveProvider.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProviderBase.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\AlwaysEncryptedAttestationException.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\EnclaveProviderBase.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\EnclaveSessionCache.NetCoreApp.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netcoreapp' AND '$(BuildSimulator)' == 'true'">
<Compile Include="Microsoft\Data\SqlClient\SimulatorEnclaveProvider.NetCoreApp.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netstandard'">
<Compile Include="Microsoft\Data\SqlClient\SqlDelegatedTransaction.NetStandard.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParser.NetStandard.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS'">
<Compile Include="Microsoft\Data\SqlClient\Server\MetadataUtilsSmi.cs" />
<Compile Include="Microsoft\Data\SqlClient\Server\SmiEventSink.cs" />
Expand Down

This file was deleted.

@@ -0,0 +1,153 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;

namespace Microsoft.Data.SqlClient
{
internal class EnclavePublicKey
{
public byte[] PublicKey { get; set; }

public EnclavePublicKey(byte[] payload)
{
PublicKey = payload;
}
}

internal class EnclaveDiffieHellmanInfo
{
public int Size { get; private set; }

public byte[] PublicKey { get; private set; }

public byte[] PublicKeySignature { get; private set; }

public EnclaveDiffieHellmanInfo(byte[] payload)
{
Size = payload.Length;

int offset = 0;
int publicKeySize = BitConverter.ToInt32(payload, offset);
offset += sizeof(int);

int publicKeySignatureSize = BitConverter.ToInt32(payload, offset);
offset += sizeof(int);

PublicKey = payload.Skip(offset).Take(publicKeySize).ToArray();
offset += publicKeySize;

PublicKeySignature = payload.Skip(offset).Take(publicKeySignatureSize).ToArray();
offset += publicKeySignatureSize;
}
}

internal enum EnclaveType
{
None = 0,

Vbs = 1,

Sgx = 2
}

// Contains methods to convert cryptography keys between different formats.
internal sealed class KeyConverter
{
// The RSA public key blob is structured as follows:
// BCRYPT_RSAKEY_BLOB header
// byte[ExponentSize] publicExponent
// byte[ModulusSize] modulus
private readonly struct RSAPublicKeyBlob
{
// Size of an RSA public key blob
internal static readonly int Size = 539;
// Size of the BCRYPT_RSAKEY_BLOB header
internal static readonly int HeaderSize = 27;
// Size of the exponent (final 3 bytes of the header)
internal static readonly int ExponentSize = 3;
// Size of the modulus (remaining bytes after the header)
internal static readonly int ModulusSize = Size - HeaderSize;
internal static readonly int ExponentOffset = HeaderSize - ExponentSize;
internal static readonly int ModulusOffset = HeaderSize;
}

// Extracts the public key's modulus and exponent from an RSA public key blob
// and returns an RSAParameters object
internal static RSAParameters RSAPublicKeyBlobToParams(byte[] keyBlob)
{
Debug.Assert(keyBlob.Length == RSAPublicKeyBlob.Size,
$"RSA public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {RSAPublicKeyBlob.Size}");
return new RSAParameters()
{
Exponent = keyBlob.Skip(RSAPublicKeyBlob.ExponentOffset).Take(RSAPublicKeyBlob.ExponentSize).ToArray(),
Modulus = keyBlob.Skip(RSAPublicKeyBlob.ModulusOffset).Take(RSAPublicKeyBlob.ModulusSize).ToArray()
};
}

// The ECC public key blob is structured as follows:
// BCRYPT_ECCKEY_BLOB header
// byte[KeySize] X
// byte[KeySize] Y
private readonly struct ECCPublicKeyBlob
{
// Size of an ECC public key blob
internal static readonly int Size = 104;
// Size of the BCRYPT_ECCKEY_BLOB header
internal static readonly int HeaderSize = 8;
// Size of each coordinate
internal static readonly int KeySize = (Size - HeaderSize) / 2;
}

// Magic numbers identifying blob types
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/cba27df5-4880-4f95-a879-783f8657e53b
private readonly struct KeyBlobMagicNumber
{
internal static readonly byte[] ECDHPublicP384 = new byte[] { 0x45, 0x43, 0x4b, 0x33 };
}

// Extracts the public key's X and Y coordinates from an ECC public key blob
// and returns an ECParameters object
internal static ECParameters ECCPublicKeyBlobToParams(byte[] keyBlob)
{
Debug.Assert(keyBlob.Length == ECCPublicKeyBlob.Size,
$"ECC public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {ECCPublicKeyBlob.Size}");
return new ECParameters
{
Curve = ECCurve.NamedCurves.nistP384,
Q = new ECPoint
{
X = keyBlob.Skip(ECCPublicKeyBlob.HeaderSize).Take(ECCPublicKeyBlob.KeySize).ToArray(),
Y = keyBlob.Skip(ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize).Take(ECCPublicKeyBlob.KeySize).ToArray()
},
};
}

// Serializes an ECDiffieHellmanPublicKey to an ECC public key blob
// "ECDiffieHellmanPublicKey.ToByteArray() doesn't have a (standards-)defined export
// format. The version used by ECDiffieHellmanPublicKeyCng is Windows-specific"
// from https://github.com/dotnet/runtime/issues/27276
// => ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix
internal static byte[] ECDHPublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey)
{
byte[] keyBlob = new byte[ECCPublicKeyBlob.Size];

// Set magic number
Array.Copy(KeyBlobMagicNumber.ECDHPublicP384, 0, keyBlob, 0, 4);
// Set key size
keyBlob[4] = (byte)ECCPublicKeyBlob.KeySize;

ECPoint ecPoint = publicKey.ExportParameters().Q;
Debug.Assert(ecPoint.X.Length == ECCPublicKeyBlob.KeySize && ecPoint.Y.Length == ECCPublicKeyBlob.KeySize,
$"ECDH public key was not the expected length. Actual (X): {ecPoint.X.Length}. Actual (Y): {ecPoint.Y.Length} Expected: {ECCPublicKeyBlob.Size}");
// Copy x and y coordinates to key blob
Array.Copy(ecPoint.X, 0, keyBlob, ECCPublicKeyBlob.HeaderSize, ECCPublicKeyBlob.KeySize);
Array.Copy(ecPoint.Y, 0, keyBlob, ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize, ECCPublicKeyBlob.KeySize);
return keyBlob;
}
}
}

0 comments on commit 146ecd9

Please sign in to comment.