Skip to content

Commit

Permalink
Remade attestation NONE to work in all cases (#1942)
Browse files Browse the repository at this point in the history
* Fixed none to work property again.

* Temp code change to see if hotswapping db works.

* Clean up NONE according to Eclipse, and revert the db hotswapping.

* Added an exclusion in EnclavePackageTest::testInvalidProperties, as NONE should be allowed without a protocol.

* Cleanup

* Formatting again.

* More formatting.

* Fix AESetup (was changed for testing).

* Updated azure identity in gradle file (#1941)

* Fixed none to work property again.

* Temp code change to see if hotswapping db works.

* Clean up NONE according to Eclipse, and revert the db hotswapping.

* Added an exclusion in EnclavePackageTest::testInvalidProperties, as NONE should be allowed without a protocol.

* Cleanup

* Formatting again.

* More formatting.

* Fix AESetup (was changed for testing).

* ..

Co-authored-by: Terry <32403408+tkyc@users.noreply.github.com>
  • Loading branch information
Jeffery-Wasty and tkyc authored Nov 1, 2022
1 parent 4ce81bb commit a2bcb60
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 87 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ dependencies {
implementation 'org.osgi:org.osgi.core:6.0.0',
'org.osgi:org.osgi.compendium:5.0.0'
compileOnly 'com.azure:azure-security-keyvault-keys:4.2.8',
'com.azure:azure-identity:1.7.0-beta.2',
'com.azure:azure-identity:1.3.3',
'org.antlr:antlr4-runtime:4.9.2',
'com.google.code.gson:gson:2.8.7',
'org.bouncycastle:bcprov-jdk15on:1.69',
Expand All @@ -152,7 +152,7 @@ dependencies {
'com.google.code.gson:gson:2.8.7',
'org.bouncycastle:bcprov-jdk15on:1.69',
'com.azure:azure-security-keyvault-keys:4.2.8',
'com.azure:azure-identity:1.7.0-beta.2',
'com.azure:azure-identity:1.3.3',
'com.microsoft.azure:adal4j:1.6.7',
'com.h2database:h2:1.4.200'
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@

package com.microsoft.sqlserver.jdbc;

import static java.nio.charset.StandardCharsets.UTF_16LE;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
Expand Down Expand Up @@ -42,11 +39,7 @@ public SQLServerNoneEnclaveProvider() {}
public void getAttestationParameters(String url) throws SQLServerException {
if (null == noneParams) {
attestationUrl = url;
try {
noneParams = new NoneAttestationParameters(attestationUrl);
} catch (IOException e) {
SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false);
}
noneParams = new NoneAttestationParameters();
}
}

Expand Down Expand Up @@ -100,16 +93,6 @@ public EnclaveSession getEnclaveSession() {
return enclaveSession;
}

private void validateAttestationResponse() throws SQLServerException {
if (null != noneResponse) {
try {
noneResponse.validateDHPublicKey();
} catch (GeneralSecurityException e) {
SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false);
}
}
}

private ArrayList<byte[]> describeParameterEncryption(SQLServerConnection connection, SQLServerStatement statement,
String userSql, String preparedTypeDefinitions, Parameter[] params,
ArrayList<String> parameterNames) throws SQLServerException {
Expand All @@ -130,11 +113,9 @@ private ArrayList<byte[]> describeParameterEncryption(SQLServerConnection connec
rs, enclaveRequestedCEKs);
// Process the third result set.
if (connection.isAEv2() && stmt.getMoreResults()) {
try (ResultSet hgsRs = stmt.getResultSet()) {
if (hgsRs.next()) {
noneResponse = new NoneAttestationResponse(hgsRs.getBytes(1));
// This validates and establishes the enclave session if valid
validateAttestationResponse();
try (ResultSet noneRs = stmt.getResultSet()) {
if (noneRs.next()) {
noneResponse = new NoneAttestationResponse(noneRs.getBytes(1));
} else {
SQLServerException.makeFromDriverError(null, this,
SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), "0",
Expand All @@ -147,10 +128,9 @@ private ArrayList<byte[]> describeParameterEncryption(SQLServerConnection connec
} catch (SQLException | IOException e) {
if (e instanceof SQLServerException) {
throw (SQLServerException) e;
} else {
throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null,
0, e);
}
throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null, 0,
e);
}
return enclaveRequestedCEKs;
}
Expand All @@ -165,41 +145,24 @@ private ArrayList<byte[]> describeParameterEncryption(SQLServerConnection connec
class NoneAttestationParameters extends BaseAttestationRequest {

// Type 2 is NONE, sent as Little Endian 0x20000000
private static final byte[] ENCLAVE_TYPE = new byte[] {0x2, 0x0, 0x0, 0x0};
// Nonce length is always 256
private static final byte[] NONCE_LENGTH = new byte[] {0x0, 0x1, 0x0, 0x0};
private final byte[] nonce = new byte[256];

NoneAttestationParameters(String attestationUrl) throws SQLServerException, IOException {
byte[] attestationUrlBytes = (attestationUrl + '\0').getBytes(UTF_16LE);

ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(attestationUrlBytes.length).array());
os.write(attestationUrlBytes);
os.write(NONCE_LENGTH);
new SecureRandom().nextBytes(nonce);
os.write(nonce);
enclaveChallenge = os.toByteArray();
private static byte ENCLAVE_TYPE[] = new byte[] {0x2, 0x0, 0x0, 0x0};

NoneAttestationParameters() throws SQLServerException {
enclaveChallenge = new byte[] {0x0, 0x0, 0x0, 0x0};
initBcryptECDH();
}

@Override
byte[] getBytes() throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write(ENCLAVE_TYPE);
os.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(enclaveChallenge.length).array());
os.write(enclaveChallenge);
os.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ENCLAVE_LENGTH).array());
os.write(ECDH_MAGIC);
os.write(x);
os.write(y);
return os.toByteArray();
}

byte[] getNonce() {
return nonce;
}
}


Expand All @@ -213,42 +176,32 @@ class NoneAttestationResponse extends BaseAttestationResponse {

NoneAttestationResponse(byte[] b) throws SQLServerException {
/*-
* Protocol format:
* 1. Total Size of the attestation blob as UINT
* 2. Size of Enclave RSA public key as UINT
* 3. Size of Attestation token as UINT
* 4. Enclave Type as UINT
* 5. Enclave RSA public key (raw key, of length #2)
* 6. Attestation token (of length #3)
* 7. Size of Session ID was UINT
* 8. Session id value
* 9. Size of enclave ECDH public key
* 10. Enclave ECDH public key (of length #9)
*/
ByteBuffer response = ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN);
this.totalSize = response.getInt();
this.identitySize = response.getInt();
this.attestationTokenSize = response.getInt();
this.enclaveType = response.getInt(); // 1 for VBS, 2 for SGX

enclavePK = new byte[identitySize];
byte[] attestationToken = new byte[attestationTokenSize];

response.get(enclavePK, 0, identitySize);
response.get(attestationToken, 0, attestationTokenSize);

this.sessionInfoSize = response.getInt();
response.get(sessionID, 0, 8);
this.DHPKsize = response.getInt();
this.DHPKSsize = response.getInt();

DHpublicKey = new byte[DHPKsize];
publicKeySig = new byte[DHPKSsize];

response.get(DHpublicKey, 0, DHPKsize);
response.get(publicKeySig, 0, DHPKSsize);
* Parse the attestation response.
*
* Total Size of the response - 4B
* Session Info Size - 4B
* Session ID - 8B
* DH Public Key Size - 4B
* DH Public Key Signature Size - 4B
* DH Public Key - DHPKsize bytes
* DH Public Key Signature - DHPKSsize bytes
*/
ByteBuffer response = (null != b) ? ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN) : null;
if (null != response) {
this.totalSize = response.getInt();
this.sessionInfoSize = response.getInt();
response.get(sessionID, 0, 8);
this.DHPKsize = response.getInt();
this.DHPKSsize = response.getInt();

DHpublicKey = new byte[DHPKsize];
publicKeySig = new byte[DHPKSsize];

response.get(DHpublicKey, 0, DHPKsize);
response.get(publicKeySig, 0, DHPKSsize);
}

if (0 != response.remaining()) {
if (null == response || 0 != response.remaining()) {
SQLServerException.makeFromDriverError(null, this,
SQLServerResource.getResource("R_EnclaveResponseLengthError"), "0", false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ public static void testBasicConnection(String cString, String protocol) throws E
}

/**
* Tests invalid connection property combinations.
* Tests invalid connection property combinations. NONE protocol is allowed without an attestation URL, and so
* an exclusion is defined for NONE.
*
* @throws Exception
*/
Expand All @@ -262,9 +263,11 @@ public static void testInvalidProperties(String serverName, String url, String p
testInvalidProperties(TestUtils.removeProperty(connectionStringEnclave, "enclaveAttestationProtocol"),
"R_enclavePropertiesError");

// enclaveAttestationProtocol without enclaveAttestationUrl
testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringEnclave, "enclaveAttestationUrl", ""),
"R_enclavePropertiesError");
// enclaveAttestationProtocol without enclaveAttestationUrl (given that it is not NONE)
if (!String.valueOf(AttestationProtocol.NONE).equals(protocol)) {
testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringEnclave, "enclaveAttestationUrl", ""),
"R_enclavePropertiesError");
}

// bad enclaveAttestationProtocol
testInvalidProperties(
Expand Down

0 comments on commit a2bcb60

Please sign in to comment.