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

AE with enclaves - multi-platform and .NET Standard 2.1 support #676

Merged
merged 48 commits into from
Aug 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
13857f2
Merge pull request #2 from dotnet/master
May 29, 2020
b807d0b
Merge remote-tracking branch 'upstream/master'
johnnypham Jun 4, 2020
26b0f35
Set up CI with Azure Pipelines
Jun 8, 2020
3da84f8
Delete azure-pipelines.yml
Jun 8, 2020
9b49213
Merge remote-tracking branch 'upstream/master'
johnnypham Jun 14, 2020
d02b69c
Set up CI with Azure Pipelines
Jun 8, 2020
896caa1
Delete azure-pipelines.yml
Jun 8, 2020
0c04741
Merge branch 'master' of https://github.com/johnnypham/SqlClient
johnnypham Jun 18, 2020
035ef3d
Merge remote-tracking branch 'upstream/master'
johnnypham Jun 21, 2020
d1dc8bb
Merge remote-tracking branch 'upstream/master'
johnnypham Jul 3, 2020
acbb0a5
Merge remote-tracking branch 'upstream/master'
johnnypham Jul 10, 2020
0d8b82f
aev2
johnnypham Jul 21, 2020
a98f2a0
azure attestation, vbs
johnnypham Jul 22, 2020
0d5c11e
Update EnclaveProviderBase.NetCoreApp.cs
johnnypham Jul 24, 2020
6eeaf13
Update EnclaveProviderBase.NetCoreApp.cs
johnnypham Jul 24, 2020
7bec0ea
replace tobytearray
johnnypham Jul 24, 2020
1831ef0
move new methods to utils
johnnypham Jul 24, 2020
b79a97e
minor changes
johnnypham Jul 27, 2020
0c898c3
ae apishould tests for linux
johnnypham Jul 29, 2020
361505a
test akv fixture
johnnypham Jul 29, 2020
c9785ea
Update SQLSetupStrategy.cs
johnnypham Jul 29, 2020
50c5b12
bulkcopyae akv test
johnnypham Jul 29, 2020
d1da600
apishould cross platform
johnnypham Jul 30, 2020
2a93a2e
test fixture changes
johnnypham Jul 30, 2020
743d6ce
Update BulkCopyAE.cs
johnnypham Jul 30, 2020
81654cc
Update BulkCopyAE.cs
johnnypham Jul 30, 2020
9ab0eac
test platform specific fixtures
johnnypham Jul 31, 2020
170ddc9
test platform specific fixtures
johnnypham Jul 31, 2020
ba1b31a
update ae tests for linux
johnnypham Jul 31, 2020
1cad3ff
minor changes
johnnypham Jul 31, 2020
daa2b13
netstandard
johnnypham Aug 4, 2020
c12121f
netstandard changes
johnnypham Aug 5, 2020
f264806
change targetframework property to targetframeworks
johnnypham Aug 5, 2020
0448362
Update SqlColumnEncryptionCertificateStoreProvider.Windows.cs
johnnypham Aug 7, 2020
9ba0fc9
Address feedback
johnnypham Aug 7, 2020
bcc7e6c
Merge branch 'aev2' of https://github.com/johnnypham/SqlClient into aev2
johnnypham Aug 7, 2020
4780d48
Merge remote-tracking branch 'upstream/master' into aev2
johnnypham Aug 7, 2020
104e0d6
fix culture exceptions in functional tests for ubuntu 18.04
johnnypham Aug 11, 2020
5575f1c
revert test changes
johnnypham Aug 11, 2020
7a1e9fb
test against .net standard 2.1
johnnypham Aug 13, 2020
5285c26
add dispose to new fixture class
johnnypham Aug 14, 2020
ec12750
Update AlwaysEncryptedEnclaveProviderUtils.cs
johnnypham Aug 18, 2020
dca6da8
Update AlwaysEncryptedEnclaveProviderUtils.cs
johnnypham Aug 18, 2020
e575519
Update AlwaysEncryptedEnclaveProviderUtils.cs
johnnypham Aug 19, 2020
50e2ee3
Merge remote-tracking branch 'upstream/master' into aev2
johnnypham Aug 20, 2020
58235f7
casing
johnnypham Aug 20, 2020
5d0fde8
Address comments
johnnypham Aug 21, 2020
a552100
Address comments
johnnypham Aug 21, 2020
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
Prev Previous commit
Next Next commit
move new methods to utils
  • Loading branch information
johnnypham committed Jul 24, 2020
commit 1831ef0eb9d44bf54d1f3464a8d2d555a8d9663f
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

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

namespace Microsoft.Data.SqlClient
{
Expand Down Expand Up @@ -52,4 +53,91 @@ internal enum EnclaveType

Sgx = 2
}

// Methods for converting keys between different formats
internal class KeyConverter
{
// 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)
{
// The RSA public key blob is structured as follows:
// BCRYPT_RSAKEY_BLOB header
// byte[cbPublicExp] publicExponent
// byte[cbModulus] modulus

// The exponent is the final 3 bytes in the header
// The modulus is the final 512 bytes in the key blob
const int modulusSize = 512;
const int exponentSize = 3;
int headerSize = keyBlob.Length - modulusSize;
int exponentOffset = headerSize - exponentSize;
int modulusOffset = exponentOffset + exponentSize;

return new RSAParameters()
{
Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(),
Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray()
};
}

// 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)
{
// The ECC public key blob is structured as follows:
// BCRYPT_ECCKEY_BLOB header
// byte[cbKey] X
// byte[cbKey] Y

// The size of each coordinate is found after the first 4 byes (magic number)
const int keySizeOffset = 4;
int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset);
int keyOffset = keySizeOffset + sizeof(int);

return new ECParameters
{
Curve = ECCurve.NamedCurves.nistP384,
Q = new ECPoint
{
X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(),
Y = keyBlob.Skip(keyOffset + keySize).Take(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)
{
// Size of an ECC key blob = 104 bytes
// BCRYPT_ECCKEY_BLOB header = 8 bytes
// key = 96 bytes (48 bytes each coordinate)
const int keyBlobSize = 104;
const int headerSize = 8;
const int KeySize = 48;
byte[] keyBlob = new byte[keyBlobSize];

// magic number (BCRYPT_ECDH_PUBLIC_P384_MAGIC)
keyBlob[0] = 0x45;
keyBlob[1] = 0x43;
keyBlob[2] = 0x4b;
keyBlob[3] = 0x33;
// key size
keyBlob[4] = KeySize;
keyBlob[5] = 0x00;
keyBlob[6] = 0x00;
keyBlob[7] = 0x00;

ECParameters ecParams = publicKey.ExportParameters();
// copy x coordinate
Array.Copy(ecParams.Q.X, 0, keyBlob, headerSize, KeySize);
// copy y coordinate
Array.Copy(ecParams.Q.Y, 0, keyBlob, headerSize + KeySize, KeySize);
return keyBlob;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce,
}

// Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key.
RSAParameters rsaParams = RSAKeyBlobToParams(enclaveRsaPublicKey);
RSAParameters rsaParams = KeyConverter.RSAPublicKeyBlobToParams(enclaveRsaPublicKey);
using (RSA rsa = RSA.Create(rsaParams))
{
if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
Expand All @@ -537,7 +537,7 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce,
}
}

ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey);
ECParameters ecParams = KeyConverter.ECCPublicKeyBlobToParams(enclaveDHInfo.PublicKey);
ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams);
return clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal byte[] GetSerializedAttestationParameters(SqlEnclaveAttestationParamete
}

// clientDHPublicKey
byte[] clientDHPublicKey = EnclaveProviderBase.PublicKeyToECCKeyBlob(sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey);
byte[] clientDHPublicKey = KeyConverter.ECDHPublicKeyToECCKeyBlob(sqlEnclaveAttestationParameters.ClientDiffieHellmanKey.PublicKey);

// clientDHPublicKey length
clientDHPublicKeyLengthBytes = GetUintBytes(enclaveType, clientDHPublicKey.Length, "clientDHPublicKeyLength");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Linq;
using System.Runtime.Caching;
using System.Security.Cryptography;
using System.Threading;
Expand Down Expand Up @@ -211,86 +210,6 @@ protected SqlEnclaveSession AddEnclaveSessionToCache(string attestationUrl, stri
{
return SessionCache.CreateSession(attestationUrl, servername, sharedSecret, sessionId, out counter);
}

// Extracts the public key's modulus and exponent from the key blob
protected RSAParameters RSAKeyBlobToParams(byte[] keyBlob)
{
Console.WriteLine("RSAKeyBlobToParams");
// The RSA public key blob is structured as follows:
// BCRYPT_RSAKEY_BLOB header
// byte[cbPublicExp] publicExponent - Exponent
// byte[cbModulus] modulus - Modulus

// The exponent is the final 3 bytes in the header
// The modulus is the final 512 bytes in the key blob
const int modulusSize = 512;
const int exponentSize = 3;
int BcryptRsaKeyBlobHeaderSize = keyBlob.Length - modulusSize;
int exponentOffset = BcryptRsaKeyBlobHeaderSize - exponentSize;
int modulusOffset = exponentOffset + exponentSize;

return new RSAParameters()
{
Exponent = keyBlob.Skip(exponentOffset).Take(exponentSize).ToArray(),
Modulus = keyBlob.Skip(modulusOffset).Take(modulusSize).ToArray()
};
}

// Extracts the public key's X and Y coordinate from the key blob
protected ECParameters ECCKeyBlobToParams(byte[] keyBlob)
{
Console.WriteLine("ECCKeyBlobToParams");
// The ECC public key blob is structured as follows:
// BCRYPT_ECCKEY_BLOB header
// byte[cbKey] X - X coordinate
// byte[cbKey] Y - Y coordinate

// The size of each key is found after the first 4 byes (magic number)
const int keySizeOffset = 4;
int keySize = BitConverter.ToInt32(keyBlob, keySizeOffset);
int keyOffset = keySizeOffset + sizeof(int);

return new ECParameters
{
Curve = ECCurve.NamedCurves.nistP384,
Q = new ECPoint
{
X = keyBlob.Skip(keyOffset).Take(keySize).ToArray(),
Y = keyBlob.Skip(keyOffset + keySize).Take(keySize).ToArray()
},
};
}

// ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix so we have to
// serialize it in the BCRYPT_ECCKEY_BLOB format
public static byte[] PublicKeyToECCKeyBlob(ECDiffieHellmanPublicKey publicKey)
{
Console.WriteLine("PublicKeyToECCKeyBlob");
// Size of a BCRYPT_ECCKEY_BLOB = 104 bytes
// header 8 bytes, key 96 bytes (48 bytes each coordinate)
const int headerSize = 8;
const int KeySize = 48;
const int keyBlobSize = 104;
byte[] keyBlob = new byte[keyBlobSize];

// magic number
keyBlob[0] = 0x45;
keyBlob[1] = 0x43;
keyBlob[2] = 0x4b;
keyBlob[3] = 0x33;
// key size
keyBlob[4] = KeySize;
keyBlob[5] = 0x00;
keyBlob[6] = 0x00;
keyBlob[7] = 0x00;

ECParameters ecParams = publicKey.ExportParameters();
// copy x coordinate
Array.Copy(ecParams.Q.X, 0, keyBlob, headerSize, KeySize);
// copy y coordinate
Array.Copy(ecParams.Q.Y, 0, keyBlob, headerSize + KeySize, KeySize);
return keyBlob;
}
}
#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ private void VerifyEnclavePolicyProperty(string property, uint actual, uint expe
private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellman clientDHKey)
{
// Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key.
RSAParameters rsaParams = RSAKeyBlobToParams(enclavePublicKey.PublicKey);
RSAParameters rsaParams = KeyConverter.RSAPublicKeyBlobToParams(enclavePublicKey.PublicKey);
using (RSA rsa = RSA.Create(rsaParams))
{
if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
Expand All @@ -359,9 +359,8 @@ private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, EnclaveDiffieH
}
}

ECParameters ecParams = ECCKeyBlobToParams(enclaveDHInfo.PublicKey);
ECParameters ecParams = KeyConverter.ECCPublicKeyBlobToParams(enclaveDHInfo.PublicKey);
ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams);

return clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256);
}
#endregion
Expand Down