예제 #1
0
        /// <summary>
        /// Build Message 2
        /// </summary>
        /// <param name="sigmaSequenceCheck">Service Provider Sequence (State) Check</param>
        /// <param name="m1Received">Message 1</param>
        /// <returns>Message 2 Repsonse to Client</returns>
        public M2ResponseMessage BuildMessage2(SpSequenceCheck sigmaSequenceCheck, M1RequestMessage m1Received,
                                               String gidBaString, byte[] gbXLittleEndian, byte[] gbYLittleEndian, byte[] sigSPXLittleEndian, byte[] sigSPYLittleEndian, byte[] cMACsmk)
        {
            log.Debug("BuildMessage2(.) started.");

            if (sigmaSequenceCheck == null || m1Received == null)
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            // Update Client state
            if (!sigmaSequenceCheck.UpdateState(Constants.SequenceState.Msg2))
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.PreconditionFailed);
                options.LogThrownException(e);
                throw e;
            }

            SetDiffieHellmanExchange(gidBaString, gbXLittleEndian, gbYLittleEndian, sigSPXLittleEndian, sigSPYLittleEndian, cMACsmk);

            // Check that  Diffie Hellman values are initialized
            if (!initialized)
            {
                return(null);
            }

            log.Debug("Building message 2");

            if (SpStartup.iasConnectionMgr.UseIAS)
            {
                // Connect to IAS for Signature Revocation List
                BuildIASMessage2(sigmaSequenceCheck);
            }
            else
            {
                // Simulate IAS
                // For testing the SGX client connection only, override the IAS connection settings by setting "UseIAS" to false.
                // This setting should be temporary, and once the SGX messaging is working, set "UseIAS" to true.
                BuildNonIasMessage2(sigmaSequenceCheck);
            }

            log.Debug("BuildMessage2(.) returning.");
            return(msg2);
        }
예제 #2
0
        /// <summary>
        /// Verify that Message 1 is valid
        /// </summary>
        /// <param name="Request">Client Message 1 Response</param>
        /// <param name="sigmaSequenceCheck">Service Provider Sequence (State) Check</param>
        /// <returns>Parsed and validated Message 1</returns>
        private M1RequestMessage VerifyMessage1IsValid(HttpRequestMessage request, SpSequenceCheck sigmaSequenceCheck)
        {
            log.Debug("VerifyMessage1IsValid(.) started.");

            if (request == null || sigmaSequenceCheck == null)
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            // Update Client state
            if (!sigmaSequenceCheck.UpdateState(Constants.SequenceState.Msg1))
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.PreconditionFailed);
                options.LogThrownException(e);
                throw e;
            }

            // Check m1 and if valid, process, create a nonce, get the sigRL and return m2.
            // M1 = msg1 = m1 = s1 = ga||GID
            var    result          = request.Content.ReadAsStringAsync();
            string jsonMsg1Request = result.Result;

            M1RequestMessage m1Received = new M1RequestMessage();

            try
            {
                m1Received = JsonConvert.DeserializeObject <M1RequestMessage>(jsonMsg1Request);
            }
            catch (Exception msg1reqError)
            {
                options.LogCaughtErrorException(msg1reqError);
                log.DebugFormat("******* Message 1 JSON Content Error: {0}", msg1reqError);
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            string m1ReceivedString = m1Received.GetMsgString();

            log.Info("******* Received M1 Request");
            log.DebugFormat("{0}{1}", request.Headers, jsonMsg1Request);
            log.DebugFormat("M1 Base 16 Encoded String: {0}", m1ReceivedString);

            // Check the nonce and the base16 encoded length of the inbound request
            bool nonceCheckSuccess = false;

            try
            {
                log.Debug("Checking nonce");
                nonceCheckSuccess = sigmaSequenceCheck.currentNonce.SequenceEqual(m1Received.reqHeader.nonce);
            }
            catch (Exception e)
            {
                options.LogCaughtErrorException(e);
                log.DebugFormat("****Message 1 Nonce Error: {0}", e);
                HttpResponseException newException = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(newException);
                throw newException;
            }

            if (!nonceCheckSuccess)
            {
                log.Debug("Msg1 Nonce check failed");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Compare the reported length against the actual length (base16 string length/2)
            // Could BigEndian a replay attempt if the nonce field does not match.
            // Could also be other tampering if other fields do not pass checks.
            // Restart the session, and reject the request.
            if (!(BitConverter.ToUInt32(m1Received.reqHeader.msgLength, 0) == (m1ReceivedString.Length / 2)))
            {
                log.Debug("Msg1 Message length check failed");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            if (m1Received.reqM1Body.gaX.SequenceEqual(MsgInitValues.DS_EMPTY_BA32))
            {
                log.Debug("Msg1 GaX check failed");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            if (m1Received.reqM1Body.gaY.SequenceEqual(MsgInitValues.DS_EMPTY_BA32))
            {
                log.Debug("Msg1 GaY check failed");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            if (m1Received.reqM1Body.pltfrmGid.SequenceEqual(MsgInitValues.DS_EMPTY_BA32))
            {
                log.Debug("Msg1 Platform Group ID check failed");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            log.Debug("VerifyMessage1IsValid(.) returning.");
            return(m1Received);
        }
예제 #3
0
        /// <summary>
        /// Process Message 3 and Build Message 4
        /// </summary>
        /// <param name="Request">Message 3 Client Response</param>
        /// <param name="sigmaSequenceCheck">Service Provider Sequence (State) Check</param>
        /// <returns>Message 4 Repsonse to Client</returns>
        public async Task <M4ResponseMessage> ProcessMessage3(HttpRequestMessage Request, SpSequenceCheck sigmaSequenceChk)
        {
            log.Debug("ProcessMessage3(.) started.");

            if (Request == null || sigmaSequenceChk == null)
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.PreconditionFailed);
                options.LogThrownException(e);
                throw e;
            }

            sigmaSequenceCheck = sigmaSequenceChk;

            // Update Client state
            if (!sigmaSequenceCheck.UpdateState(Constants.SequenceState.Msg3))
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.PreconditionFailed);
                options.LogThrownException(e);
                throw e;
            }

            var              result          = Request.Content.ReadAsStringAsync();
            string           jsonMsg3Request = result.Result;
            M3RequestMessage m3Received      = new M3RequestMessage();

            try
            {
                // Attempt to parse request in message 3
                m3Received = JsonConvert.DeserializeObject <M3RequestMessage>(jsonMsg3Request);
            }
            catch (Exception msg3ReqError)
            {
                log.DebugFormat("******* Message 3 JSON Content Error: {0}", msg3ReqError);
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            if (m3Received == null)
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.PreconditionFailed);
                options.LogThrownException(e);
                throw e;
            }

            // Check the nonce and the base16 encoded length of the inbound request
            string m3ReceivedString = m3Received.GetMsgString();

            log.Info("******* Received M3 Request");
            log.DebugFormat("{0}{1}", Request.Headers, jsonMsg3Request);
            log.DebugFormat("M3 Base16 Encoded String: {0}", m3ReceivedString);

            // If failed a check, throw an error
            // Getting to this point means there was a problem with the M3 content (including possible quote check failure).
            // Reset the state machine and return "Forbidden"

            // Check whether to use Nonce or not, and is valid
            bool nonceCheck = sigmaSequenceCheck.currentNonce.SequenceEqual(m3Received.reqHeader.nonce);

            if (!nonceCheck)
            {
                log.Debug("Invalid Message 3 Nonce");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Check the message has the correct length
            bool lengthCheck = CheckMessageLength(m3Received, m3ReceivedString);

            if (!lengthCheck)
            {
                log.Debug("Invalid Message 3 Length");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Check the M3 components & Ga
            byte[] m3Ga = new byte[m3Received.reqM3Body.gaX.Length + m3Received.reqM3Body.gaY.Length];
            System.Buffer.BlockCopy(m3Received.reqM3Body.gaX, 0, m3Ga, 0, m3Received.reqM3Body.gaX.Length);
            System.Buffer.BlockCopy(m3Received.reqM3Body.gaY, 0, m3Ga, m3Received.reqM3Body.gaX.Length, m3Received.reqM3Body.gaY.Length);
            string m3GaStr      = bMessage.BaToBlobStr(m3Ga);
            string currentGaStr = bMessage.BaToBlobStr(sigmaSequenceCheck.currentGa);

            // Check the ga is correct
            bool gaCheck = CheckGa(currentGaStr, m3GaStr);

            if (!gaCheck)
            {
                log.Debug("Invalid Message 3 ga");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Check that the CMAC is correct
            bool cmacCheck = CheckCmac(m3Received, m3GaStr);

            if (!cmacCheck)
            {
                log.Debug("Invalid Message 3 CMAC");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            string m3QuoteStr = bMessage.BaToBlobStr(m3Received.reqM3Body.quote);

            if (String.IsNullOrEmpty(m3QuoteStr))
            {
                log.Debug("Message 3 Quote is NULL");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Get MRSIGNER and ISVPRODID from the Quote to find the correct enclave type from Enclave.json
            string MRSIGNERString = m3QuoteStr.Substring((int)Constants.QuoteInfo.MRSIGNEROffset * 2, Constants.QuoteInfo.MRSIGNERSize * 2);     // MR Enclave String from Quote

            log.InfoFormat("Quote came from enclave with MRSIGNER:   {0}", MRSIGNERString);

            ushort ISVPRODID = (ushort)BitConverter.ToInt16(bMessage.BlobStrToBa(m3QuoteStr.Substring((int)Constants.QuoteInfo.ISVPRODIDOffset * 2, 4)), 0);

            log.DebugFormat("ISVPRODID:\t{0}", ISVPRODID);

            sigmaSequenceCheck.SetEnclaveType(MRSIGNERString, ISVPRODID);

            bool quoteOk = CheckQuoteOk(m3Received, m3QuoteStr, currentGaStr);

            if (!quoteOk)
            {
                log.Debug("Invalid Message 3 Quote");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Check whether using Debug quote or not
            bool debugCheck = CheckDebug(m3QuoteStr);

            if (!debugCheck)
            {
                log.Debug("Invalid Message 3 - Using Debug or Production quote when opposite is expected");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Check Signature Type
            bool sigTypeCheck = CheckSignatureType(m3QuoteStr);

            if (!sigTypeCheck)
            {
                log.Debug("Invalid Message 3 Signature");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Check ISV SVN
            bool isvSVNCheck = CheckISVSVN(m3QuoteStr);

            if (!isvSVNCheck)
            {
                log.Debug("Invalid Message 3 ISV SVN");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Successful
            // At this point, we know that a valid message 3 was received and we can send the quote to IAS.
            // Complete the state transition.
            M4ResponseMessage msg4Respsonse = new M4ResponseMessage();

            try
            {
                sigmaSequenceCheck.m3Received = true;
                Msg4Builder msgProcessor = new Msg4Builder();
                msg4Respsonse = await msgProcessor.BuildMessage4(sigmaSequenceCheck, m3Received);
            }
            catch (HttpRequestException re)
            {
                options.LogCaughtErrorException(re);
                log.Debug("Failed to create Message 4. " + re.Message);
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            log.Debug("ProcessMessage3(.) returning.");
            return(msg4Respsonse);
        }
예제 #4
0
        /// <summary>
        /// Verify that Message 0 is valid
        /// </summary>
        /// <param name="Request">Client Message 0 Response</param>
        /// <param name="sigmaSequenceCheck">Service Provider Sequence (State) Check</param>
        /// <returns>Parsed and validated Message 0</returns>
        private M0RequestMessage VerifyMessage0IsValid(HttpRequestMessage request, SpSequenceCheck sigmaSequenceCheck)
        {
            log.Debug("VerifyMessage0IsValid(.) started.");

            if (request == null || sigmaSequenceCheck == null)
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            // Update Client state
            if (!sigmaSequenceCheck.UpdateState(Constants.SequenceState.Msg0))
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.PreconditionFailed);
                options.LogThrownException(e);
                throw e;
            }

            // Check m0 and if valid, process
            var    result          = request.Content.ReadAsStringAsync();
            string jsonMsg0Request = result.Result;

            M0RequestMessage m0Received = new M0RequestMessage();

            try
            {
                m0Received = JsonConvert.DeserializeObject <M0RequestMessage>(jsonMsg0Request);
            }
            catch (Exception msg0reqError)
            {
                options.LogCaughtErrorException(msg0reqError);
                log.DebugFormat("******* Message 0 JSON Content Error: {0}", msg0reqError);
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            string m0ReceivedString = m0Received.GetMsgString();

            log.Info("******* Received M0 Request");
            log.DebugFormat("{0}{1}", request.Headers, jsonMsg0Request);
            log.DebugFormat("M0 Base 16 Encoded String: {0}", m0ReceivedString);

            // Check the nonce and the base16 encoded length of the inbound request
            bool nonceCheckSuccess = false;

            try
            {
                log.Debug("Checking nonce");
                nonceCheckSuccess = sigmaSequenceCheck.currentNonce.SequenceEqual(m0Received.reqHeader.nonce);
            }
            catch (Exception e)
            {
                options.LogCaughtErrorException(e);
                log.DebugFormat("****Message 0 Nonce Error: {0}", e);
                HttpResponseException newException = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(newException);
                throw newException;
            }

            if (!nonceCheckSuccess)
            {
                log.Debug("Msg0 Nonce check failed");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // Compare the reported length against the actual length (base16 string length/2)
            // Could BigEndian a replay attempt if the nonce field does not match.
            // Could also be other tampering if other fields do not pass checks.
            // Restart the session, and reject the request.
            if (!(BitConverter.ToUInt32(m0Received.reqHeader.msgLength, 0) == (m0ReceivedString.Length / 2)))
            {
                log.Debug("Msg0 Message length check failed");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            if (m0Received.reqM0Body.ExtGID.SequenceEqual(MsgInitValues.DS_EMPTY_BA4))
            {
                log.Debug("Msg0: Extended GID wasn't sent");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Forbidden);
                options.LogThrownException(e);
                throw e;
            }

            // NOTE: Extended GID = 0 indicates that IAS is selected for enclave verification.
            // This Service Provider only supports IAS for enclave verification at this time.
            // Note to ISV: if non-Intel Attestation Service (i.e. Extended GID != 0) is being used, replace this logic
            //      to point to your service.
            if (!m0Received.reqM0Body.ExtGID.SequenceEqual(MsgInitValues.DS_ZERO_BA4))
            {
                log.Debug("Msg0: Invalid Extended GID. This server only processes Extended GID = 0");
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.Unauthorized);
                options.LogThrownException(e);
                throw e;
            }

            log.Debug("VerifyMessage0IsValid(.) returning.");
            return(m0Received);
        }