/// <summary> /// Continue transaction for Message 3/4 sequence /// </summary> /// <param name="request">Client Message 3 response/4 request</param> public static async Task <M4ResponseMessage> Message3(HttpRequestMessage request) { log.Debug("Message3(.) started."); if (request == null) { HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError); options.LogThrownException(e); throw e; } M4ResponseMessage m4Response = null; try { ClientTransaction mClient = GetTransaction(request, Constants.msg3Str); if (mClient == null) { HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError); options.LogThrownException(e); throw e; } // kill client wait thread so we don't time out. mClient.killTimerThread(); // NOTE: There is a potential race-condition where the client is removed from the database during the time that the cilent sends its response // Can choose to check to re-add the client here in that case log.Info("\n ***** State: Starting Message 3/4 sequence for client: " + mClient.ID + "\n"); Msg3 msg3 = new Msg3(); m4Response = await msg3.ProcessMessage3(request, mClient.sigmaSequenceCheck); log.Debug("Message3(.) returning."); } catch (HttpResponseException) { throw; } catch (Exception e) { log.Debug("Error processing Message 3/4. " + e.Message); } // Return challenge to client return(m4Response); }
//Buid an M4 response public void buildM4Response(out M4ResponseMessage m4Resp) { string respond = Constants.Respond; var m4Response = new M4ResponseMessage(respond); var m4Body = new ResponseM4Body(); m4Body.platformInfo = null; //m4Body.pltfrmInfoRsrvd handled by instantiation m4Body.attestationStatus = MsgInitValues.DS_ZERO_BA4; m4Body.cmacStatus = MsgInitValues.DS_ZERO_BA16; m4Body.isvCryptPayloadSize = MsgInitValues.DS_ZERO_BA4; m4Body.isvClearPayloadSize = MsgInitValues.DS_ZERO_BA4; m4Body.CryptIv = null; m4Body.isvPayloadTag = null; m4Body.isvPayload = null; m4Response.respMsg4Body = m4Body; m4Resp = m4Response; return; }
/// <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); }
public async Task <IHttpActionResult> Msg3() { log.Debug("SpSequenceCheck(.) started."); bool error = false; HttpStatusCode errorCode = System.Net.HttpStatusCode.InternalServerError; M4ResponseMessage m4Response = null; try { m4Response = await ClientDatabase.Message3(this.Request); } catch (WebException we) { error = true; log.Debug("Web Exception in Provisioning Request: " + we.Message); HttpWebResponse webResponse = we.Response as HttpWebResponse; errorCode = (HttpStatusCode)webResponse.StatusCode; } catch (HttpResponseException re) { error = true; log.Debug("HttpResponseException in Message 3/4: " + re.Message); errorCode = (HttpStatusCode)re.Response.StatusCode; } catch (Exception e) { error = true; log.Debug("Error occurred processing Message 3 or 4. " + e.Message); errorCode = System.Net.HttpStatusCode.InternalServerError; } // always cleanup database on Message 4 try { ClientDatabase.RemoveTransaction(this.Request, Constants.msg3Str); } catch (HttpResponseException re) { log.Debug("HttpResponseException in Message 3/4 RemoveTransaction: " + re.Message); if (!error) { error = true; errorCode = (HttpStatusCode)re.Response.StatusCode; } } catch (Exception e) { log.Debug("Error occurred processing Message 3 or 4 RemoveTransaction: " + e.Message); if (!error) { error = true; errorCode = System.Net.HttpStatusCode.InternalServerError; } } if (error) { log.DebugFormat("Msg3(.) returning HTTP status code {0}.", errorCode); return(StatusCode(errorCode)); } else { log.Debug("Msg3(.) returning HTTP status success."); return(Json(m4Response)); } }