Skip to content
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 @@ -318,7 +318,12 @@
<Compile Include="Microsoft.Data.SqlClient.TypeForwards.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netstandard' AND '$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft\Data\SqlClient\EnclaveDelegate.NetStandard.cs" />
<Compile Include="..\..\src\Microsoft\Data\SqlClient\EnclaveDelegate.NotSupported.cs">
<Link>Microsoft\Data\SqlClient\EnclaveDelegate.NotSupported.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.NotSupported.cs">
<Link>Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.NotSupported.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netstandard'">
<Compile Include="Microsoft\Data\SqlClient\SqlAuthenticationProviderManager.NetStandard.cs" />
Expand All @@ -335,23 +340,29 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs">
<Link>Microsoft\Data\SqlClient\AlwaysEncryptedEnclaveProviderUtils.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\AlwaysEncryptedKeyConverter.cs">
<Link>Microsoft\Data\SqlClient\AlwaysEncryptedKeyConverter.cs</Link>
</Compile>
<Compile Include="Microsoft\Data\SqlClient\AlwaysEncryptedKeyConverter.CrossPlatform.cs" />
<Compile Include="..\..\src\Microsoft\Data\SqlClient\EnclaveProviderBase.cs">
<Link>Microsoft\Data\SqlClient\EnclaveProviderBase.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\EnclaveSessionCache.cs">
<Link>Microsoft\Data\SqlClient\EnclaveSessionCache.cs</Link>
</Compile>
<Compile Include="Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\EnclaveDelegate.CrossPlatformCrypto.cs" />
<Compile Include="Microsoft\Data\SqlClient\AzureAttestationBasedEnclaveProvider.cs" />
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs">
<Link>Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\EnclaveDelegate.Crypto.cs">
<Link>Microsoft\Data\SqlClient\EnclaveDelegate.Crypto.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\AzureAttestationBasedEnclaveProvider.cs">
<Link>Microsoft\Data\SqlClient\AzureAttestationBasedEnclaveProvider.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.cs">
<Link>Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProvider.cs</Link>
</Compile>
<Compile Include="Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProviderBase.cs" />
<Compile Include="..\..\src\Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProviderBase.cs">
<Link>Microsoft\Data\SqlClient\VirtualSecureModeEnclaveProviderBase.cs</Link>
</Compile>
</ItemGroup>
<!-- netcoreapp 3.1 & netstandard 2.1 and above -->
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetFramework)' != 'netcoreapp2.1' AND '$(TargetFramework)' != 'netstandard2.0'">
Expand Down Expand Up @@ -523,7 +534,6 @@
<Compile Include="Microsoft\Data\SqlClient\AlwaysEncryptedHelperClasses.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlQueryMetadataCache.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.cs" />
</ItemGroup>
<!-- Windows only -->
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,56 @@
using System;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace Microsoft.Data.SqlClient
{
// Contains methods to convert cryptography keys between different formats.
internal sealed class KeyConverter
{
internal sealed partial class KeyConverter
{
// 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 };
}

// 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 const int Size = 104;
// Size of the BCRYPT_ECCKEY_BLOB header
internal const int HeaderSize = 8;
// Size of each coordinate
internal const int KeySize = (Size - HeaderSize) / 2;
}

// 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[] GetECDiffieHellmanPublicKeyBlob(ECDiffieHellman ecDiffieHellman)
{
byte[] keyBlob = new byte[ECCPublicKeyBlob.Size];

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

ECPoint ecPoint = ecDiffieHellman.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
Buffer.BlockCopy(ecPoint.X, 0, keyBlob, ECCPublicKeyBlob.HeaderSize, ECCPublicKeyBlob.KeySize);
Buffer.BlockCopy(ecPoint.Y, 0, keyBlob, ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize, ECCPublicKeyBlob.KeySize);
return keyBlob;
}

// The RSA public key blob is structured as follows:
// BCRYPT_RSAKEY_BLOB header
// byte[ExponentSize] publicExponent
Expand All @@ -29,59 +73,32 @@ private readonly struct RSAPublicKeyBlob
internal const 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)
internal static RSA CreateRSAFromPublicKeyBlob(byte[] keyBlob)
{
Debug.Assert(keyBlob.Length == RSAPublicKeyBlob.Size,
$"RSA public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {RSAPublicKeyBlob.Size}");
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()
var rsaParameters = new RSAParameters()
{
Exponent = exponent,
Modulus = modulus
};
return RSA.Create(rsaParameters);
}

// 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 const int Size = 104;
// Size of the BCRYPT_ECCKEY_BLOB header
internal const int HeaderSize = 8;
// Size of each coordinate
internal const 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)
internal static ECDiffieHellman CreateECDiffieHellmanFromPublicKeyBlob(byte[] keyBlob)
{
Debug.Assert(keyBlob.Length == ECCPublicKeyBlob.Size,
$"ECC public key blob was not the expected length. Actual: {keyBlob.Length}. Expected: {ECCPublicKeyBlob.Size}");
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
var parameters = new ECParameters
{
Curve = ECCurve.NamedCurves.nistP384,
Q = new ECPoint
Expand All @@ -90,29 +107,29 @@ internal static ECParameters ECCPublicKeyBlobToParams(byte[] keyBlob)
Y = y
},
};

return ECDiffieHellman.Create(parameters);
}

// 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)
internal static ECDiffieHellman CreateECDiffieHellman(int keySize)
{
byte[] keyBlob = new byte[ECCPublicKeyBlob.Size];
// platform agnostic creates a key of the correct size but does not
// set the key derivation type or algorithm, these must be set by calling
// DeriveKeyFromHash later in DeriveKey
ECDiffieHellman clientDHKey = ECDiffieHellman.Create();
clientDHKey.KeySize = keySize;
return clientDHKey;
}

// Set magic number
Buffer.BlockCopy(KeyBlobMagicNumber.ECDHPublicP384, 0, keyBlob, 0, 4);
// Set key size
keyBlob[4] = (byte)ECCPublicKeyBlob.KeySize;
internal static byte[] DeriveKey(ECDiffieHellman ecd, ECDiffieHellmanPublicKey publicKey)
{
// see notes in CreateECDDiffieHellman
return ecd.DeriveKeyFromHash(publicKey, HashAlgorithmName.SHA256);
}

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
Buffer.BlockCopy(ecPoint.X, 0, keyBlob, ECCPublicKeyBlob.HeaderSize, ECCPublicKeyBlob.KeySize);
Buffer.BlockCopy(ecPoint.Y, 0, keyBlob, ECCPublicKeyBlob.HeaderSize + ECCPublicKeyBlob.KeySize, ECCPublicKeyBlob.KeySize);
return keyBlob;
internal static RSA GetRSAFromCertificate(X509Certificate2 certificate)
{
return certificate.GetRSAPublicKey();
}
}
}

This file was deleted.

This file was deleted.

Loading