// When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. public override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellmanCng clientDHKey, string attestationUrl, string servername, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) { sqlEnclaveSession = null; counter = 0; try { ThreadRetryCache.Remove(Thread.CurrentThread.ManagedThreadId.ToString()); sqlEnclaveSession = GetEnclaveSessionFromCache(servername, attestationUrl, out counter); if (sqlEnclaveSession == null) { if (!string.IsNullOrEmpty(attestationUrl) && customData != null && customDataLength > 0) { byte[] nonce = customData; IdentityModelEventSource.ShowPII = true; // Deserialize the payload AzureAttestationInfo attestInfo = new AzureAttestationInfo(attestationInfo); // Validate the attestation info VerifyAzureAttestationInfo(attestationUrl, attestInfo.EnclaveType, attestInfo.AttestationToken.AttestationToken, attestInfo.Identity, nonce); // Set up shared secret and validate signature byte[] sharedSecret = GetSharedSecret(attestInfo.Identity, nonce, attestInfo.EnclaveType, attestInfo.EnclaveDHInfo, clientDHKey); // add session to cache sqlEnclaveSession = AddEnclaveSessionToCache(attestationUrl, servername, sharedSecret, attestInfo.SessionId, out counter); } else { throw new AlwaysEncryptedAttestationException(Strings.FailToCreateEnclaveSession); } } } finally { // As per current design, we want to minimize the number of create session calls. To acheive this we block all the GetEnclaveSession calls until the first call to // GetEnclaveSession -> GetAttestationParameters -> CreateEnclaveSession completes or the event timeout happen. // Case 1: When the first request successfully creates the session, then all outstanding GetEnclaveSession will use the current session. // Case 2: When the first request unable to create the encalve session (may be due to some error or the first request doesn't require enclave computation) then in those case we set the event timeout to 0. UpdateEnclaveSessionLockStatus(sqlEnclaveSession); } }
// When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellman clientDHKey, EnclaveSessionParameters enclaveSessionParameters, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) { sqlEnclaveSession = null; counter = 0; try { ThreadRetryCache.Remove(Thread.CurrentThread.ManagedThreadId.ToString()); sqlEnclaveSession = GetEnclaveSessionFromCache(enclaveSessionParameters, out counter); if (sqlEnclaveSession == null) { if (!string.IsNullOrEmpty(enclaveSessionParameters.AttestationUrl)) { // Deserialize the payload AttestationInfo info = new AttestationInfo(attestationInfo); // Verify enclave policy matches expected policy VerifyEnclavePolicy(info.EnclaveReportPackage); // Perform Attestation per VSM protocol VerifyAttestationInfo(enclaveSessionParameters.AttestationUrl, info.HealthReport, info.EnclaveReportPackage); // Set up shared secret and validate signature byte[] sharedSecret = GetSharedSecret(info.Identity, info.EnclaveDHInfo, clientDHKey); // add session to cache sqlEnclaveSession = AddEnclaveSessionToCache(enclaveSessionParameters, sharedSecret, info.SessionId, out counter); } else { throw new AlwaysEncryptedAttestationException(Strings.FailToCreateEnclaveSession); } } } finally { UpdateEnclaveSessionLockStatus(sqlEnclaveSession); } }
// When overridden in a derived class, performs enclave attestation, generates a symmetric key for the session, creates a an enclave session and stores the session information in the cache. internal override void CreateEnclaveSession(byte[] attestationInfo, ECDiffieHellman clientDHKey, EnclaveSessionParameters enclaveSessionParameters, byte[] customData, int customDataLength, out SqlEnclaveSession sqlEnclaveSession, out long counter) { ////for simulator: enclave does not send public key, and sends an empty attestation info //// The only non-trivial content it sends is the session setup info (DH pubkey of enclave) sqlEnclaveSession = null; counter = 0; try { ThreadRetryCache.Remove(Thread.CurrentThread.ManagedThreadId.ToString()); sqlEnclaveSession = GetEnclaveSessionFromCache(enclaveSessionParameters, out counter); if (sqlEnclaveSession == null) { if (!string.IsNullOrEmpty(enclaveSessionParameters.AttestationUrl)) { ////Read AttestationInfo int attestationInfoOffset = 0; uint sizeOfTrustedModuleAttestationInfoBuffer = BitConverter.ToUInt32(attestationInfo, attestationInfoOffset); attestationInfoOffset += sizeof(UInt32); int sizeOfTrustedModuleAttestationInfoBufferInt = checked ((int)sizeOfTrustedModuleAttestationInfoBuffer); Debug.Assert(sizeOfTrustedModuleAttestationInfoBuffer == 0); ////read secure session info uint sizeOfSecureSessionInfoResponse = BitConverter.ToUInt32(attestationInfo, attestationInfoOffset); attestationInfoOffset += sizeof(UInt32); byte[] enclaveSessionHandle = new byte[EnclaveSessionHandleSize]; Buffer.BlockCopy(attestationInfo, attestationInfoOffset, enclaveSessionHandle, 0, EnclaveSessionHandleSize); attestationInfoOffset += EnclaveSessionHandleSize; uint sizeOfTrustedModuleDHPublicKeyBuffer = BitConverter.ToUInt32(attestationInfo, attestationInfoOffset); attestationInfoOffset += sizeof(UInt32); uint sizeOfTrustedModuleDHPublicKeySignatureBuffer = BitConverter.ToUInt32(attestationInfo, attestationInfoOffset); attestationInfoOffset += sizeof(UInt32); int sizeOfTrustedModuleDHPublicKeyBufferInt = checked ((int)sizeOfTrustedModuleDHPublicKeyBuffer); byte[] trustedModuleDHPublicKey = new byte[sizeOfTrustedModuleDHPublicKeyBuffer]; Buffer.BlockCopy(attestationInfo, attestationInfoOffset, trustedModuleDHPublicKey, 0, sizeOfTrustedModuleDHPublicKeyBufferInt); attestationInfoOffset += sizeOfTrustedModuleDHPublicKeyBufferInt; byte[] trustedModuleDHPublicKeySignature = new byte[sizeOfTrustedModuleDHPublicKeySignatureBuffer]; Buffer.BlockCopy(attestationInfo, attestationInfoOffset, trustedModuleDHPublicKeySignature, 0, checked ((int)sizeOfTrustedModuleDHPublicKeySignatureBuffer)); byte[] sharedSecret; using ECDiffieHellman ecdh = KeyConverter.CreateECDiffieHellmanFromPublicKeyBlob(trustedModuleDHPublicKey); sharedSecret = KeyConverter.DeriveKey(clientDHKey, ecdh.PublicKey); long sessionId = BitConverter.ToInt64(enclaveSessionHandle, 0); sqlEnclaveSession = AddEnclaveSessionToCache(enclaveSessionParameters, sharedSecret, sessionId, out counter); } else { throw new AlwaysEncryptedAttestationException(Strings.FailToCreateEnclaveSession); } } } finally { UpdateEnclaveSessionLockStatus(sqlEnclaveSession); } }