protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus) { HandshakeMessage handshakeMessage = new HandshakeMessage(22); certificateStatus.Encode((Stream)(object)handshakeMessage); handshakeMessage.WriteToRecordStream(this); }
protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus) { HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_status); certificateStatus.Encode(message); message.WriteToRecordStream(this); }
public virtual OcspResponse GetOcspResponse() { if (!CertificateStatus.IsCorrectType(1, this.mResponse)) { throw new InvalidOperationException("'response' is not an OcspResponse"); } return((OcspResponse)this.mResponse); }
public CertificateStatus(byte statusType, object response) { if (!CertificateStatus.IsCorrectType(statusType, response)) { throw new ArgumentException("not an instance of the correct type", "response"); } this.mStatusType = statusType; this.mResponse = response; }
protected override void CleanupHandshake() { base.CleanupHandshake(); mSelectedSessionID = null; mKeyExchange = null; mAuthentication = null; mCertificateStatus = null; mCertificateRequest = null; }
protected override void CleanupHandshake() { base.CleanupHandshake(); this.mSelectedSessionID = null; this.mKeyExchange = null; this.mAuthentication = null; this.mCertificateStatus = null; this.mCertificateRequest = null; }
protected virtual void ProcessCertificateStatus(DtlsClientProtocol.ClientHandshakeState state, byte[] body) { if (!state.allowCertificateStatus) { throw new TlsFatalAlert(10); } MemoryStream memoryStream = new MemoryStream(body, false); state.certificateStatus = CertificateStatus.Parse(memoryStream); TlsProtocol.AssertEmpty(memoryStream); }
protected virtual void ProcessCertificateStatus(ClientHandshakeState state, byte[] body) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if (!state.allowCertificateStatus) { throw new TlsFatalAlert(10); } MemoryStream val = new MemoryStream(body, false); state.certificateStatus = CertificateStatus.Parse((Stream)(object)val); TlsProtocol.AssertEmpty(val); }
protected virtual void ProcessCertificateStatus(ClientHandshakeState state, byte[] body) { if (!state.allowCertificateStatus) { /* * RFC 3546 3.6. If a server returns a "CertificateStatus" message, then the * server MUST have included an extension of type "status_request" with empty * "extension_data" in the extended server hello.. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } MemoryStream buf = new MemoryStream(body, false); state.certificateStatus = CertificateStatus.Parse(buf); TlsProtocol.AssertEmpty(buf); // TODO[RFC 3546] Figure out how to provide this to the client/authentication. }
protected virtual byte[] GenerateCertificateStatus(ServerHandshakeState state, CertificateStatus certificateStatus) { MemoryStream buf = new MemoryStream(); certificateStatus.Encode(buf); return buf.ToArray(); }
internal virtual DtlsTransport ServerHandshake(DtlsServerProtocol.ServerHandshakeState state, DtlsRecordLayer recordLayer) { SecurityParameters securityParameters = state.serverContext.SecurityParameters; DtlsReliableHandshake dtlsReliableHandshake = new DtlsReliableHandshake(state.serverContext, recordLayer); DtlsReliableHandshake.Message message = dtlsReliableHandshake.ReceiveMessage(); ProtocolVersion discoveredPeerVersion = recordLayer.DiscoveredPeerVersion; state.serverContext.SetClientVersion(discoveredPeerVersion); if (message.Type != 1) { throw new TlsFatalAlert(10); } this.ProcessClientHello(state, message.Body); byte[] body = this.GenerateServerHello(state); DtlsProtocol.ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength); dtlsReliableHandshake.SendMessage(2, body); dtlsReliableHandshake.NotifyHelloComplete(); IList serverSupplementalData = state.server.GetServerSupplementalData(); if (serverSupplementalData != null) { byte[] body2 = DtlsProtocol.GenerateSupplementalData(serverSupplementalData); dtlsReliableHandshake.SendMessage(23, body2); } state.keyExchange = state.server.GetKeyExchange(); state.keyExchange.Init(state.serverContext); state.serverCredentials = state.server.GetCredentials(); Certificate certificate = null; if (state.serverCredentials == null) { state.keyExchange.SkipServerCredentials(); } else { state.keyExchange.ProcessServerCredentials(state.serverCredentials); certificate = state.serverCredentials.Certificate; byte[] body3 = DtlsProtocol.GenerateCertificate(certificate); dtlsReliableHandshake.SendMessage(11, body3); } if (certificate == null || certificate.IsEmpty) { state.allowCertificateStatus = false; } if (state.allowCertificateStatus) { CertificateStatus certificateStatus = state.server.GetCertificateStatus(); if (certificateStatus != null) { byte[] body4 = this.GenerateCertificateStatus(state, certificateStatus); dtlsReliableHandshake.SendMessage(22, body4); } } byte[] array = state.keyExchange.GenerateServerKeyExchange(); if (array != null) { dtlsReliableHandshake.SendMessage(12, array); } if (state.serverCredentials != null) { state.certificateRequest = state.server.GetCertificateRequest(); if (state.certificateRequest != null) { state.keyExchange.ValidateCertificateRequest(state.certificateRequest); byte[] body5 = this.GenerateCertificateRequest(state, state.certificateRequest); dtlsReliableHandshake.SendMessage(13, body5); TlsUtilities.TrackHashAlgorithms(dtlsReliableHandshake.HandshakeHash, state.certificateRequest.SupportedSignatureAlgorithms); } } dtlsReliableHandshake.SendMessage(14, TlsUtilities.EmptyBytes); dtlsReliableHandshake.HandshakeHash.SealHashAlgorithms(); message = dtlsReliableHandshake.ReceiveMessage(); if (message.Type == 23) { this.ProcessClientSupplementalData(state, message.Body); message = dtlsReliableHandshake.ReceiveMessage(); } else { state.server.ProcessClientSupplementalData(null); } if (state.certificateRequest == null) { state.keyExchange.SkipClientCredentials(); } else if (message.Type == 11) { this.ProcessClientCertificate(state, message.Body); message = dtlsReliableHandshake.ReceiveMessage(); } else { if (TlsUtilities.IsTlsV12(state.serverContext)) { throw new TlsFatalAlert(10); } this.NotifyClientCertificate(state, Certificate.EmptyChain); } if (message.Type == 16) { this.ProcessClientKeyExchange(state, message.Body); TlsHandshakeHash tlsHandshakeHash = dtlsReliableHandshake.PrepareToFinish(); securityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(state.serverContext, tlsHandshakeHash, null); TlsProtocol.EstablishMasterSecret(state.serverContext, state.keyExchange); recordLayer.InitPendingEpoch(state.server.GetCipher()); if (this.ExpectCertificateVerifyMessage(state)) { byte[] body6 = dtlsReliableHandshake.ReceiveMessageBody(15); this.ProcessCertificateVerify(state, body6, tlsHandshakeHash); } byte[] expected_verify_data = TlsUtilities.CalculateVerifyData(state.serverContext, "client finished", TlsProtocol.GetCurrentPrfHash(state.serverContext, dtlsReliableHandshake.HandshakeHash, null)); this.ProcessFinished(dtlsReliableHandshake.ReceiveMessageBody(20), expected_verify_data); if (state.expectSessionTicket) { NewSessionTicket newSessionTicket = state.server.GetNewSessionTicket(); byte[] body7 = this.GenerateNewSessionTicket(state, newSessionTicket); dtlsReliableHandshake.SendMessage(4, body7); } byte[] body8 = TlsUtilities.CalculateVerifyData(state.serverContext, "server finished", TlsProtocol.GetCurrentPrfHash(state.serverContext, dtlsReliableHandshake.HandshakeHash, null)); dtlsReliableHandshake.SendMessage(20, body8); dtlsReliableHandshake.Finish(); state.server.NotifyHandshakeComplete(); return(new DtlsTransport(recordLayer)); } throw new TlsFatalAlert(10); }
protected virtual byte[] GenerateCertificateStatus(ServerHandshakeState state, CertificateStatus certificateStatus) { MemoryStream buf = new MemoryStream(); certificateStatus.Encode(buf); return(buf.ToArray()); }
internal virtual DtlsTransport ServerHandshake(ServerHandshakeState state, DtlsRecordLayer recordLayer) { SecurityParameters securityParameters = state.serverContext.SecurityParameters; DtlsReliableHandshake handshake = new DtlsReliableHandshake(state.serverContext, recordLayer); DtlsReliableHandshake.Message clientMessage = handshake.ReceiveMessage(); // NOTE: DTLSRecordLayer requires any DTLS version, we don't otherwise constrain this //ProtocolVersion recordLayerVersion = recordLayer.ReadVersion; if (clientMessage.Type == HandshakeType.client_hello) { ProcessClientHello(state, clientMessage.Body); } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } { byte[] serverHelloBody = GenerateServerHello(state); ApplyMaxFragmentLengthExtension(recordLayer, securityParameters.maxFragmentLength); ProtocolVersion recordLayerVersion = state.serverContext.ServerVersion; recordLayer.ReadVersion = recordLayerVersion; recordLayer.SetWriteVersion(recordLayerVersion); handshake.SendMessage(HandshakeType.server_hello, serverHelloBody); } handshake.NotifyHelloComplete(); IList serverSupplementalData = state.server.GetServerSupplementalData(); if (serverSupplementalData != null) { byte[] supplementalDataBody = GenerateSupplementalData(serverSupplementalData); handshake.SendMessage(HandshakeType.supplemental_data, supplementalDataBody); } state.keyExchange = state.server.GetKeyExchange(); state.keyExchange.Init(state.serverContext); state.serverCredentials = state.server.GetCredentials(); Certificate serverCertificate = null; if (state.serverCredentials == null) { state.keyExchange.SkipServerCredentials(); } else { state.keyExchange.ProcessServerCredentials(state.serverCredentials); serverCertificate = state.serverCredentials.Certificate; byte[] certificateBody = GenerateCertificate(serverCertificate); handshake.SendMessage(HandshakeType.certificate, certificateBody); } // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus if (serverCertificate == null || serverCertificate.IsEmpty) { state.allowCertificateStatus = false; } if (state.allowCertificateStatus) { CertificateStatus certificateStatus = state.server.GetCertificateStatus(); if (certificateStatus != null) { byte[] certificateStatusBody = GenerateCertificateStatus(state, certificateStatus); handshake.SendMessage(HandshakeType.certificate_status, certificateStatusBody); } } byte[] serverKeyExchange = state.keyExchange.GenerateServerKeyExchange(); if (serverKeyExchange != null) { handshake.SendMessage(HandshakeType.server_key_exchange, serverKeyExchange); } if (state.serverCredentials != null) { state.certificateRequest = state.server.GetCertificateRequest(); if (state.certificateRequest != null) { if (TlsUtilities.IsTlsV12(state.serverContext) != (state.certificateRequest.SupportedSignatureAlgorithms != null)) { throw new TlsFatalAlert(AlertDescription.internal_error); } state.keyExchange.ValidateCertificateRequest(state.certificateRequest); byte[] certificateRequestBody = GenerateCertificateRequest(state, state.certificateRequest); handshake.SendMessage(HandshakeType.certificate_request, certificateRequestBody); TlsUtilities.TrackHashAlgorithms(handshake.HandshakeHash, state.certificateRequest.SupportedSignatureAlgorithms); } } handshake.SendMessage(HandshakeType.server_hello_done, TlsUtilities.EmptyBytes); handshake.HandshakeHash.SealHashAlgorithms(); clientMessage = handshake.ReceiveMessage(); if (clientMessage.Type == HandshakeType.supplemental_data) { ProcessClientSupplementalData(state, clientMessage.Body); clientMessage = handshake.ReceiveMessage(); } else { state.server.ProcessClientSupplementalData(null); } if (state.certificateRequest == null) { state.keyExchange.SkipClientCredentials(); } else { if (clientMessage.Type == HandshakeType.certificate) { ProcessClientCertificate(state, clientMessage.Body); clientMessage = handshake.ReceiveMessage(); } else { if (TlsUtilities.IsTlsV12(state.serverContext)) { /* * RFC 5246 If no suitable certificate is available, the client MUST send a * certificate message containing no certificates. * * NOTE: In previous RFCs, this was SHOULD instead of MUST. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } NotifyClientCertificate(state, Certificate.EmptyChain); } } if (clientMessage.Type == HandshakeType.client_key_exchange) { ProcessClientKeyExchange(state, clientMessage.Body); } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } TlsHandshakeHash prepareFinishHash = handshake.PrepareToFinish(); securityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(state.serverContext, prepareFinishHash, null); TlsProtocol.EstablishMasterSecret(state.serverContext, state.keyExchange); recordLayer.InitPendingEpoch(state.server.GetCipher()); /* * RFC 5246 7.4.8 This message is only sent following a client certificate that has signing * capability (i.e., all certificates except those containing fixed Diffie-Hellman * parameters). */ if (ExpectCertificateVerifyMessage(state)) { byte[] certificateVerifyBody = handshake.ReceiveMessageBody(HandshakeType.certificate_verify); ProcessCertificateVerify(state, certificateVerifyBody, prepareFinishHash); } // NOTE: Calculated exclusive of the actual Finished message from the client byte[] expectedClientVerifyData = TlsUtilities.CalculateVerifyData(state.serverContext, ExporterLabel.client_finished, TlsProtocol.GetCurrentPrfHash(state.serverContext, handshake.HandshakeHash, null)); ProcessFinished(handshake.ReceiveMessageBody(HandshakeType.finished), expectedClientVerifyData); if (state.expectSessionTicket) { NewSessionTicket newSessionTicket = state.server.GetNewSessionTicket(); byte[] newSessionTicketBody = GenerateNewSessionTicket(state, newSessionTicket); handshake.SendMessage(HandshakeType.session_ticket, newSessionTicketBody); } // NOTE: Calculated exclusive of the Finished message itself byte[] serverVerifyData = TlsUtilities.CalculateVerifyData(state.serverContext, ExporterLabel.server_finished, TlsProtocol.GetCurrentPrfHash(state.serverContext, handshake.HandshakeHash, null)); handshake.SendMessage(HandshakeType.finished, serverVerifyData); handshake.Finish(); state.server.NotifyHandshakeComplete(); return(new DtlsTransport(recordLayer)); }
protected override void HandleHandshakeMessage(byte type, byte[] data) { MemoryStream buf = new MemoryStream(data); switch (type) { case HandshakeType.client_hello: { switch (this.mConnectionState) { case CS_START: { ReceiveClientHelloMessage(buf); this.mConnectionState = CS_CLIENT_HELLO; SendServerHelloMessage(); this.mConnectionState = CS_SERVER_HELLO; mRecordStream.NotifyHelloComplete(); IList serverSupplementalData = mTlsServer.GetServerSupplementalData(); if (serverSupplementalData != null) { SendSupplementalDataMessage(serverSupplementalData); } this.mConnectionState = CS_SERVER_SUPPLEMENTAL_DATA; this.mKeyExchange = mTlsServer.GetKeyExchange(); this.mKeyExchange.Init(Context); this.mServerCredentials = mTlsServer.GetCredentials(); Certificate serverCertificate = null; if (this.mServerCredentials == null) { this.mKeyExchange.SkipServerCredentials(); } else { this.mKeyExchange.ProcessServerCredentials(this.mServerCredentials); serverCertificate = this.mServerCredentials.Certificate; SendCertificateMessage(serverCertificate); } this.mConnectionState = CS_SERVER_CERTIFICATE; // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus if (serverCertificate == null || serverCertificate.IsEmpty) { this.mAllowCertificateStatus = false; } if (this.mAllowCertificateStatus) { CertificateStatus certificateStatus = mTlsServer.GetCertificateStatus(); if (certificateStatus != null) { SendCertificateStatusMessage(certificateStatus); } } this.mConnectionState = CS_CERTIFICATE_STATUS; byte[] serverKeyExchange = this.mKeyExchange.GenerateServerKeyExchange(); if (serverKeyExchange != null) { SendServerKeyExchangeMessage(serverKeyExchange); } this.mConnectionState = CS_SERVER_KEY_EXCHANGE; if (this.mServerCredentials != null) { this.mCertificateRequest = mTlsServer.GetCertificateRequest(); if (this.mCertificateRequest != null) { this.mKeyExchange.ValidateCertificateRequest(mCertificateRequest); SendCertificateRequestMessage(mCertificateRequest); TlsUtilities.TrackHashAlgorithms(this.mRecordStream.HandshakeHash, this.mCertificateRequest.SupportedSignatureAlgorithms); } } this.mConnectionState = CS_CERTIFICATE_REQUEST; SendServerHelloDoneMessage(); this.mConnectionState = CS_SERVER_HELLO_DONE; this.mRecordStream.HandshakeHash.SealHashAlgorithms(); break; } case CS_END: { RefuseRenegotiation(); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.supplemental_data: { switch (this.mConnectionState) { case CS_SERVER_HELLO_DONE: { mTlsServer.ProcessClientSupplementalData(ReadSupplementalDataMessage(buf)); this.mConnectionState = CS_CLIENT_SUPPLEMENTAL_DATA; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.certificate: { switch (this.mConnectionState) { case CS_SERVER_HELLO_DONE: case CS_CLIENT_SUPPLEMENTAL_DATA: { if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA) { mTlsServer.ProcessClientSupplementalData(null); } if (this.mCertificateRequest == null) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } ReceiveCertificateMessage(buf); this.mConnectionState = CS_CLIENT_CERTIFICATE; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.client_key_exchange: { switch (this.mConnectionState) { case CS_SERVER_HELLO_DONE: case CS_CLIENT_SUPPLEMENTAL_DATA: case CS_CLIENT_CERTIFICATE: { if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA) { mTlsServer.ProcessClientSupplementalData(null); } if (mConnectionState < CS_CLIENT_CERTIFICATE) { if (this.mCertificateRequest == null) { this.mKeyExchange.SkipClientCredentials(); } else { if (TlsUtilities.IsTlsV12(Context)) { /* * RFC 5246 If no suitable certificate is available, the client MUST Send a * certificate message containing no certificates. * * NOTE: In previous RFCs, this was SHOULD instead of MUST. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } else if (TlsUtilities.IsSsl(Context)) { if (this.mPeerCertificate == null) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } } else { NotifyClientCertificate(Certificate.EmptyChain); } } } ReceiveClientKeyExchangeMessage(buf); this.mConnectionState = CS_CLIENT_KEY_EXCHANGE; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.certificate_verify: { switch (this.mConnectionState) { case CS_CLIENT_KEY_EXCHANGE: { /* * RFC 5246 7.4.8 This message is only sent following a client certificate that has * signing capability (i.e., all certificates except those containing fixed * Diffie-Hellman parameters). */ if (!ExpectCertificateVerifyMessage()) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } ReceiveCertificateVerifyMessage(buf); this.mConnectionState = CS_CERTIFICATE_VERIFY; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.finished: { switch (this.mConnectionState) { case CS_CLIENT_KEY_EXCHANGE: case CS_CERTIFICATE_VERIFY: { if (mConnectionState < CS_CERTIFICATE_VERIFY && ExpectCertificateVerifyMessage()) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } ProcessFinishedMessage(buf); this.mConnectionState = CS_CLIENT_FINISHED; if (this.mExpectSessionTicket) { SendNewSessionTicketMessage(mTlsServer.GetNewSessionTicket()); SendChangeCipherSpecMessage(); } this.mConnectionState = CS_SERVER_SESSION_TICKET; SendFinishedMessage(); this.mConnectionState = CS_SERVER_FINISHED; this.mConnectionState = CS_END; CompleteHandshake(); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.hello_request: case HandshakeType.hello_verify_request: case HandshakeType.server_hello: case HandshakeType.server_key_exchange: case HandshakeType.certificate_request: case HandshakeType.server_hello_done: case HandshakeType.session_ticket: default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } }
protected override void HandleHandshakeMessage(byte type, byte[] data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown MemoryStream val = new MemoryStream(data, false); if (mResumedSession) { if (type != 20 || mConnectionState != 2) { throw new TlsFatalAlert(10); } ProcessFinishedMessage(val); mConnectionState = 15; SendFinishedMessage(); mConnectionState = 13; mConnectionState = 16; CompleteHandshake(); return; } switch (type) { case 11: switch (mConnectionState) { case 2: case 3: if (mConnectionState == 2) { HandleSupplementalData(null); } mPeerCertificate = Certificate.Parse((Stream)(object)val); TlsProtocol.AssertEmpty(val); if (mPeerCertificate == null || mPeerCertificate.IsEmpty) { mAllowCertificateStatus = false; } mKeyExchange.ProcessServerCertificate(mPeerCertificate); mAuthentication = mTlsClient.GetAuthentication(); mAuthentication.NotifyServerCertificate(mPeerCertificate); mConnectionState = 4; break; default: throw new TlsFatalAlert(10); } break; case 22: { short num = mConnectionState; if (num == 4) { if (!mAllowCertificateStatus) { throw new TlsFatalAlert(10); } mCertificateStatus = CertificateStatus.Parse((Stream)(object)val); TlsProtocol.AssertEmpty(val); mConnectionState = 5; break; } throw new TlsFatalAlert(10); } case 20: switch (mConnectionState) { case 13: case 14: if (mConnectionState == 13 && mExpectSessionTicket) { throw new TlsFatalAlert(10); } ProcessFinishedMessage(val); mConnectionState = 15; mConnectionState = 16; CompleteHandshake(); break; default: throw new TlsFatalAlert(10); } break; case 2: { short num = mConnectionState; if (num == 1) { ReceiveServerHelloMessage(val); mConnectionState = 2; mRecordStream.NotifyHelloComplete(); ApplyMaxFragmentLengthExtension(); if (mResumedSession) { mSecurityParameters.masterSecret = Arrays.Clone(mSessionParameters.MasterSecret); mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher()); SendChangeCipherSpecMessage(); break; } InvalidateSession(); if (mSelectedSessionID.Length > 0) { mTlsSession = new TlsSessionImpl(mSelectedSessionID, null); } break; } throw new TlsFatalAlert(10); } case 23: { short num = mConnectionState; if (num == 2) { HandleSupplementalData(TlsProtocol.ReadSupplementalDataMessage(val)); break; } throw new TlsFatalAlert(10); } case 14: switch (mConnectionState) { case 2: case 3: case 4: case 5: case 6: case 7: { if (mConnectionState < 3) { HandleSupplementalData(null); } if (mConnectionState < 4) { mKeyExchange.SkipServerCredentials(); mAuthentication = null; } if (mConnectionState < 6) { mKeyExchange.SkipServerKeyExchange(); } TlsProtocol.AssertEmpty(val); mConnectionState = 8; mRecordStream.HandshakeHash.SealHashAlgorithms(); global::System.Collections.IList clientSupplementalData = mTlsClient.GetClientSupplementalData(); if (clientSupplementalData != null) { SendSupplementalDataMessage(clientSupplementalData); } mConnectionState = 9; TlsCredentials tlsCredentials = null; if (mCertificateRequest == null) { mKeyExchange.SkipClientCredentials(); } else { tlsCredentials = mAuthentication.GetClientCredentials(mCertificateRequest); if (tlsCredentials == null) { mKeyExchange.SkipClientCredentials(); SendCertificateMessage(Certificate.EmptyChain); } else { mKeyExchange.ProcessClientCredentials(tlsCredentials); SendCertificateMessage(tlsCredentials.Certificate); } } mConnectionState = 10; SendClientKeyExchangeMessage(); mConnectionState = 11; TlsHandshakeHash tlsHandshakeHash = mRecordStream.PrepareToFinish(); mSecurityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(Context, tlsHandshakeHash, null); TlsProtocol.EstablishMasterSecret(Context, mKeyExchange); mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher()); if (tlsCredentials != null && tlsCredentials is TlsSignerCredentials) { TlsSignerCredentials tlsSignerCredentials = (TlsSignerCredentials)tlsCredentials; SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm(Context, tlsSignerCredentials); byte[] hash = ((signatureAndHashAlgorithm != null) ? tlsHandshakeHash.GetFinalHash(signatureAndHashAlgorithm.Hash) : mSecurityParameters.SessionHash); byte[] signature = tlsSignerCredentials.GenerateCertificateSignature(hash); DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature); SendCertificateVerifyMessage(certificateVerify); mConnectionState = 12; } SendChangeCipherSpecMessage(); SendFinishedMessage(); mConnectionState = 13; break; } default: throw new TlsFatalAlert(40); } break; case 12: switch (mConnectionState) { case 2: case 3: case 4: case 5: if (mConnectionState < 3) { HandleSupplementalData(null); } if (mConnectionState < 4) { mKeyExchange.SkipServerCredentials(); mAuthentication = null; } mKeyExchange.ProcessServerKeyExchange((Stream)(object)val); TlsProtocol.AssertEmpty(val); mConnectionState = 6; break; default: throw new TlsFatalAlert(10); } break; case 13: switch (mConnectionState) { case 4: case 5: case 6: if (mConnectionState != 6) { mKeyExchange.SkipServerKeyExchange(); } if (mAuthentication == null) { throw new TlsFatalAlert(40); } mCertificateRequest = CertificateRequest.Parse(Context, (Stream)(object)val); TlsProtocol.AssertEmpty(val); mKeyExchange.ValidateCertificateRequest(mCertificateRequest); TlsUtilities.TrackHashAlgorithms(mRecordStream.HandshakeHash, mCertificateRequest.SupportedSignatureAlgorithms); mConnectionState = 7; break; default: throw new TlsFatalAlert(10); } break; case 4: { short num = mConnectionState; if (num == 13) { if (!mExpectSessionTicket) { throw new TlsFatalAlert(10); } InvalidateSession(); ReceiveNewSessionTicketMessage(val); mConnectionState = 14; break; } throw new TlsFatalAlert(10); } case 0: TlsProtocol.AssertEmpty(val); if (mConnectionState == 16) { RefuseRenegotiation(); } break; default: throw new TlsFatalAlert(10); } }
protected override void HandleHandshakeMessage(byte type, byte[] data) { MemoryStream memoryStream = new MemoryStream(data); switch (type) { case 1: { short mConnectionState = this.mConnectionState; if (mConnectionState == 0) { this.ReceiveClientHelloMessage(memoryStream); this.mConnectionState = 1; this.SendServerHelloMessage(); this.mConnectionState = 2; this.mRecordStream.NotifyHelloComplete(); IList serverSupplementalData = this.mTlsServer.GetServerSupplementalData(); if (serverSupplementalData != null) { this.SendSupplementalDataMessage(serverSupplementalData); } this.mConnectionState = 3; this.mKeyExchange = this.mTlsServer.GetKeyExchange(); this.mKeyExchange.Init(this.Context); this.mServerCredentials = this.mTlsServer.GetCredentials(); Certificate certificate = null; if (this.mServerCredentials == null) { this.mKeyExchange.SkipServerCredentials(); } else { this.mKeyExchange.ProcessServerCredentials(this.mServerCredentials); certificate = this.mServerCredentials.Certificate; this.SendCertificateMessage(certificate); } this.mConnectionState = 4; if (certificate == null || certificate.IsEmpty) { this.mAllowCertificateStatus = false; } if (this.mAllowCertificateStatus) { CertificateStatus certificateStatus = this.mTlsServer.GetCertificateStatus(); if (certificateStatus != null) { this.SendCertificateStatusMessage(certificateStatus); } } this.mConnectionState = 5; byte[] array = this.mKeyExchange.GenerateServerKeyExchange(); if (array != null) { this.SendServerKeyExchangeMessage(array); } this.mConnectionState = 6; if (this.mServerCredentials != null) { this.mCertificateRequest = this.mTlsServer.GetCertificateRequest(); if (this.mCertificateRequest != null) { this.mKeyExchange.ValidateCertificateRequest(this.mCertificateRequest); this.SendCertificateRequestMessage(this.mCertificateRequest); TlsUtilities.TrackHashAlgorithms(this.mRecordStream.HandshakeHash, this.mCertificateRequest.SupportedSignatureAlgorithms); } } this.mConnectionState = 7; this.SendServerHelloDoneMessage(); this.mConnectionState = 8; this.mRecordStream.HandshakeHash.SealHashAlgorithms(); return; } if (mConnectionState != 16) { throw new TlsFatalAlert(10); } this.RefuseRenegotiation(); return; } case 11: switch (this.mConnectionState) { case 8: case 9: if (this.mConnectionState < 9) { this.mTlsServer.ProcessClientSupplementalData(null); } if (this.mCertificateRequest == null) { throw new TlsFatalAlert(10); } this.ReceiveCertificateMessage(memoryStream); this.mConnectionState = 10; return; default: throw new TlsFatalAlert(10); } break; case 15: { short mConnectionState2 = this.mConnectionState; if (mConnectionState2 != 11) { throw new TlsFatalAlert(10); } if (!this.ExpectCertificateVerifyMessage()) { throw new TlsFatalAlert(10); } this.ReceiveCertificateVerifyMessage(memoryStream); this.mConnectionState = 12; return; } case 16: switch (this.mConnectionState) { case 8: case 9: case 10: if (this.mConnectionState < 9) { this.mTlsServer.ProcessClientSupplementalData(null); } if (this.mConnectionState < 10) { if (this.mCertificateRequest == null) { this.mKeyExchange.SkipClientCredentials(); } else { if (TlsUtilities.IsTlsV12(this.Context)) { throw new TlsFatalAlert(10); } if (TlsUtilities.IsSsl(this.Context)) { if (this.mPeerCertificate == null) { throw new TlsFatalAlert(10); } } else { this.NotifyClientCertificate(Certificate.EmptyChain); } } } this.ReceiveClientKeyExchangeMessage(memoryStream); this.mConnectionState = 11; return; default: throw new TlsFatalAlert(10); } break; case 20: switch (this.mConnectionState) { case 11: case 12: if (this.mConnectionState < 12 && this.ExpectCertificateVerifyMessage()) { throw new TlsFatalAlert(10); } this.ProcessFinishedMessage(memoryStream); this.mConnectionState = 13; if (this.mExpectSessionTicket) { this.SendNewSessionTicketMessage(this.mTlsServer.GetNewSessionTicket()); this.SendChangeCipherSpecMessage(); } this.mConnectionState = 14; this.SendFinishedMessage(); this.mConnectionState = 15; this.mConnectionState = 16; return; default: throw new TlsFatalAlert(10); } break; case 23: { short mConnectionState3 = this.mConnectionState; if (mConnectionState3 == 8) { this.mTlsServer.ProcessClientSupplementalData(TlsProtocol.ReadSupplementalDataMessage(memoryStream)); this.mConnectionState = 9; return; } throw new TlsFatalAlert(10); } } throw new TlsFatalAlert(10); }
protected override void HandleHandshakeMessage(byte type, byte[] data) { MemoryStream buf = new MemoryStream(data, false); if (this.mResumedSession) { if (type != HandshakeType.finished || this.mConnectionState != CS_SERVER_HELLO) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } ProcessFinishedMessage(buf); this.mConnectionState = CS_SERVER_FINISHED; SendFinishedMessage(); this.mConnectionState = CS_CLIENT_FINISHED; this.mConnectionState = CS_END; return; } switch (type) { case HandshakeType.certificate: { switch (this.mConnectionState) { case CS_SERVER_HELLO: case CS_SERVER_SUPPLEMENTAL_DATA: { if (this.mConnectionState == CS_SERVER_HELLO) { HandleSupplementalData(null); } // Parse the Certificate message and Send to cipher suite this.mPeerCertificate = Certificate.Parse(buf); AssertEmpty(buf); // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus if (this.mPeerCertificate == null || this.mPeerCertificate.IsEmpty) { this.mAllowCertificateStatus = false; } this.mKeyExchange.ProcessServerCertificate(this.mPeerCertificate); this.mAuthentication = mTlsClient.GetAuthentication(); this.mAuthentication.NotifyServerCertificate(this.mPeerCertificate); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_SERVER_CERTIFICATE; break; } case HandshakeType.certificate_status: { switch (this.mConnectionState) { case CS_SERVER_CERTIFICATE: { if (!this.mAllowCertificateStatus) { /* * RFC 3546 3.6. If a server returns a "CertificateStatus" message, then the * server MUST have included an extension of type "status_request" with empty * "extension_data" in the extended server hello.. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mCertificateStatus = CertificateStatus.Parse(buf); AssertEmpty(buf); // TODO[RFC 3546] Figure out how to provide this to the client/authentication. this.mConnectionState = CS_CERTIFICATE_STATUS; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.finished: { switch (this.mConnectionState) { case CS_CLIENT_FINISHED: case CS_SERVER_SESSION_TICKET: { if (this.mConnectionState == CS_CLIENT_FINISHED && this.mExpectSessionTicket) { /* * RFC 5077 3.3. This message MUST be sent if the server included a * SessionTicket extension in the ServerHello. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } ProcessFinishedMessage(buf); this.mConnectionState = CS_SERVER_FINISHED; this.mConnectionState = CS_END; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.server_hello: { switch (this.mConnectionState) { case CS_CLIENT_HELLO: { ReceiveServerHelloMessage(buf); this.mConnectionState = CS_SERVER_HELLO; this.mRecordStream.NotifyHelloComplete(); ApplyMaxFragmentLengthExtension(); if (this.mResumedSession) { this.mSecurityParameters.masterSecret = Arrays.Clone(this.mSessionParameters.MasterSecret); this.mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher()); SendChangeCipherSpecMessage(); } else { InvalidateSession(); if (this.mSelectedSessionID.Length > 0) { this.mTlsSession = new TlsSessionImpl(this.mSelectedSessionID, null); } } break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.supplemental_data: { switch (this.mConnectionState) { case CS_SERVER_HELLO: { HandleSupplementalData(ReadSupplementalDataMessage(buf)); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.server_hello_done: { switch (this.mConnectionState) { case CS_SERVER_HELLO: case CS_SERVER_SUPPLEMENTAL_DATA: case CS_SERVER_CERTIFICATE: case CS_CERTIFICATE_STATUS: case CS_SERVER_KEY_EXCHANGE: case CS_CERTIFICATE_REQUEST: { if (mConnectionState < CS_SERVER_SUPPLEMENTAL_DATA) { HandleSupplementalData(null); } if (mConnectionState < CS_SERVER_CERTIFICATE) { // There was no server certificate message; check it's OK this.mKeyExchange.SkipServerCredentials(); this.mAuthentication = null; } if (mConnectionState < CS_SERVER_KEY_EXCHANGE) { // There was no server key exchange message; check it's OK this.mKeyExchange.SkipServerKeyExchange(); } AssertEmpty(buf); this.mConnectionState = CS_SERVER_HELLO_DONE; this.mRecordStream.HandshakeHash.SealHashAlgorithms(); IList clientSupplementalData = mTlsClient.GetClientSupplementalData(); if (clientSupplementalData != null) { SendSupplementalDataMessage(clientSupplementalData); } this.mConnectionState = CS_CLIENT_SUPPLEMENTAL_DATA; TlsCredentials clientCreds = null; if (mCertificateRequest == null) { this.mKeyExchange.SkipClientCredentials(); } else { clientCreds = this.mAuthentication.GetClientCredentials(this.Context, mCertificateRequest); if (clientCreds == null) { this.mKeyExchange.SkipClientCredentials(); /* * RFC 5246 If no suitable certificate is available, the client MUST Send a * certificate message containing no certificates. * * NOTE: In previous RFCs, this was SHOULD instead of MUST. */ SendCertificateMessage(Certificate.EmptyChain); } else { this.mKeyExchange.ProcessClientCredentials(clientCreds); SendCertificateMessage(clientCreds.Certificate); } } this.mConnectionState = CS_CLIENT_CERTIFICATE; /* * Send the client key exchange message, depending on the key exchange we are using * in our CipherSuite. */ SendClientKeyExchangeMessage(); this.mConnectionState = CS_CLIENT_KEY_EXCHANGE; TlsHandshakeHash prepareFinishHash = mRecordStream.PrepareToFinish(); this.mSecurityParameters.sessionHash = GetCurrentPrfHash(Context, prepareFinishHash, null); EstablishMasterSecret(Context, mKeyExchange); mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher()); if (clientCreds != null && clientCreds is TlsSignerCredentials) { TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientCreds; /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( Context, signerCredentials); byte[] hash; if (signatureAndHashAlgorithm == null) { hash = mSecurityParameters.SessionHash; } else { hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); } byte[] signature = signerCredentials.GenerateCertificateSignature(hash); DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature); SendCertificateVerifyMessage(certificateVerify); this.mConnectionState = CS_CERTIFICATE_VERIFY; } SendChangeCipherSpecMessage(); SendFinishedMessage(); break; } default: throw new TlsFatalAlert(AlertDescription.handshake_failure); } this.mConnectionState = CS_CLIENT_FINISHED; break; } case HandshakeType.server_key_exchange: { switch (this.mConnectionState) { case CS_SERVER_HELLO: case CS_SERVER_SUPPLEMENTAL_DATA: case CS_SERVER_CERTIFICATE: case CS_CERTIFICATE_STATUS: { if (mConnectionState < CS_SERVER_SUPPLEMENTAL_DATA) { HandleSupplementalData(null); } if (mConnectionState < CS_SERVER_CERTIFICATE) { // There was no server certificate message; check it's OK this.mKeyExchange.SkipServerCredentials(); this.mAuthentication = null; } this.mKeyExchange.ProcessServerKeyExchange(buf); AssertEmpty(buf); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_SERVER_KEY_EXCHANGE; break; } case HandshakeType.certificate_request: { switch (this.mConnectionState) { case CS_SERVER_CERTIFICATE: case CS_CERTIFICATE_STATUS: case CS_SERVER_KEY_EXCHANGE: { if (this.mConnectionState != CS_SERVER_KEY_EXCHANGE) { // There was no server key exchange message; check it's OK this.mKeyExchange.SkipServerKeyExchange(); } if (this.mAuthentication == null) { /* * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server * to request client identification. */ throw new TlsFatalAlert(AlertDescription.handshake_failure); } this.mCertificateRequest = CertificateRequest.Parse(Context, buf); AssertEmpty(buf); this.mKeyExchange.ValidateCertificateRequest(this.mCertificateRequest); /* * TODO Give the client a chance to immediately select the CertificateVerify hash * algorithm here to avoid tracking the other hash algorithms unnecessarily? */ TlsUtilities.TrackHashAlgorithms(this.mRecordStream.HandshakeHash, this.mCertificateRequest.SupportedSignatureAlgorithms); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_CERTIFICATE_REQUEST; break; } case HandshakeType.session_ticket: { switch (this.mConnectionState) { case CS_CLIENT_FINISHED: { if (!this.mExpectSessionTicket) { /* * RFC 5077 3.3. This message MUST NOT be sent if the server did not include a * SessionTicket extension in the ServerHello. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } /* * RFC 5077 3.4. If the client receives a session ticket from the server, then it * discards any Session ID that was sent in the ServerHello. */ InvalidateSession(); ReceiveNewSessionTicketMessage(buf); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_SERVER_SESSION_TICKET; break; } case HandshakeType.hello_request: { AssertEmpty(buf); /* * RFC 2246 7.4.1.1 Hello request This message will be ignored by the client if the * client is currently negotiating a session. This message may be ignored by the client * if it does not wish to renegotiate a session, or the client may, if it wishes, * respond with a no_renegotiation alert. */ if (this.mConnectionState == CS_END) { RefuseRenegotiation(); } break; } case HandshakeType.client_hello: case HandshakeType.client_key_exchange: case HandshakeType.certificate_verify: case HandshakeType.hello_verify_request: default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } }
protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus) { TlsProtocol.HandshakeMessage handshakeMessage = new TlsProtocol.HandshakeMessage(22); certificateStatus.Encode(handshakeMessage); handshakeMessage.WriteToRecordStream(this); }
protected override void HandleHandshakeMessage(byte type, byte[] data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown MemoryStream val = new MemoryStream(data); switch (type) { case 1: switch (mConnectionState) { case 0: { ReceiveClientHelloMessage(val); mConnectionState = 1; SendServerHelloMessage(); mConnectionState = 2; mRecordStream.NotifyHelloComplete(); global::System.Collections.IList serverSupplementalData = mTlsServer.GetServerSupplementalData(); if (serverSupplementalData != null) { SendSupplementalDataMessage(serverSupplementalData); } mConnectionState = 3; mKeyExchange = mTlsServer.GetKeyExchange(); mKeyExchange.Init(Context); mServerCredentials = mTlsServer.GetCredentials(); Certificate certificate = null; if (mServerCredentials == null) { mKeyExchange.SkipServerCredentials(); } else { mKeyExchange.ProcessServerCredentials(mServerCredentials); certificate = mServerCredentials.Certificate; SendCertificateMessage(certificate); } mConnectionState = 4; if (certificate == null || certificate.IsEmpty) { mAllowCertificateStatus = false; } if (mAllowCertificateStatus) { CertificateStatus certificateStatus = mTlsServer.GetCertificateStatus(); if (certificateStatus != null) { SendCertificateStatusMessage(certificateStatus); } } mConnectionState = 5; byte[] array = mKeyExchange.GenerateServerKeyExchange(); if (array != null) { SendServerKeyExchangeMessage(array); } mConnectionState = 6; if (mServerCredentials != null) { mCertificateRequest = mTlsServer.GetCertificateRequest(); if (mCertificateRequest != null) { if (TlsUtilities.IsTlsV12(Context) != (mCertificateRequest.SupportedSignatureAlgorithms != null)) { throw new TlsFatalAlert(80); } mKeyExchange.ValidateCertificateRequest(mCertificateRequest); SendCertificateRequestMessage(mCertificateRequest); TlsUtilities.TrackHashAlgorithms(mRecordStream.HandshakeHash, mCertificateRequest.SupportedSignatureAlgorithms); } } mConnectionState = 7; SendServerHelloDoneMessage(); mConnectionState = 8; mRecordStream.HandshakeHash.SealHashAlgorithms(); break; } case 16: RefuseRenegotiation(); break; default: throw new TlsFatalAlert(10); } break; case 23: { short num = mConnectionState; if (num == 8) { mTlsServer.ProcessClientSupplementalData(TlsProtocol.ReadSupplementalDataMessage(val)); mConnectionState = 9; break; } throw new TlsFatalAlert(10); } case 11: switch (mConnectionState) { case 8: case 9: if (mConnectionState < 9) { mTlsServer.ProcessClientSupplementalData(null); } if (mCertificateRequest == null) { throw new TlsFatalAlert(10); } ReceiveCertificateMessage(val); mConnectionState = 10; break; default: throw new TlsFatalAlert(10); } break; case 16: switch (mConnectionState) { case 8: case 9: case 10: if (mConnectionState < 9) { mTlsServer.ProcessClientSupplementalData(null); } if (mConnectionState < 10) { if (mCertificateRequest == null) { mKeyExchange.SkipClientCredentials(); } else { if (TlsUtilities.IsTlsV12(Context)) { throw new TlsFatalAlert(10); } if (TlsUtilities.IsSsl(Context)) { if (mPeerCertificate == null) { throw new TlsFatalAlert(10); } } else { NotifyClientCertificate(Certificate.EmptyChain); } } } ReceiveClientKeyExchangeMessage(val); mConnectionState = 11; break; default: throw new TlsFatalAlert(10); } break; case 15: { short num = mConnectionState; if (num == 11) { if (!ExpectCertificateVerifyMessage()) { throw new TlsFatalAlert(10); } ReceiveCertificateVerifyMessage(val); mConnectionState = 12; break; } throw new TlsFatalAlert(10); } case 20: switch (mConnectionState) { case 11: case 12: if (mConnectionState < 12 && ExpectCertificateVerifyMessage()) { throw new TlsFatalAlert(10); } ProcessFinishedMessage(val); mConnectionState = 13; if (mExpectSessionTicket) { SendNewSessionTicketMessage(mTlsServer.GetNewSessionTicket()); SendChangeCipherSpecMessage(); } mConnectionState = 14; SendFinishedMessage(); mConnectionState = 15; mConnectionState = 16; CompleteHandshake(); break; default: throw new TlsFatalAlert(10); } break; default: throw new TlsFatalAlert(10); } }
protected virtual byte[] GenerateCertificateStatus(DtlsServerProtocol.ServerHandshakeState state, CertificateStatus certificateStatus) { MemoryStream memoryStream = new MemoryStream(); certificateStatus.Encode(memoryStream); return(memoryStream.ToArray()); }
protected virtual byte[] GenerateCertificateStatus(ServerHandshakeState state, CertificateStatus certificateStatus) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown MemoryStream val = new MemoryStream(); certificateStatus.Encode((Stream)(object)val); return(val.ToArray()); }
protected override void HandleHandshakeMessage(byte type, byte[] data) { MemoryStream buf = new MemoryStream(data, false); if (this.mResumedSession) { if (type != HandshakeType.finished || this.mConnectionState != CS_SERVER_HELLO) throw new TlsFatalAlert(AlertDescription.unexpected_message); ProcessFinishedMessage(buf); this.mConnectionState = CS_SERVER_FINISHED; SendFinishedMessage(); this.mConnectionState = CS_CLIENT_FINISHED; this.mConnectionState = CS_END; return; } switch (type) { case HandshakeType.certificate: { switch (this.mConnectionState) { case CS_SERVER_HELLO: case CS_SERVER_SUPPLEMENTAL_DATA: { if (this.mConnectionState == CS_SERVER_HELLO) { HandleSupplementalData(null); } // Parse the Certificate message and Send to cipher suite this.mPeerCertificate = Certificate.Parse(buf); AssertEmpty(buf); // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus if (this.mPeerCertificate == null || this.mPeerCertificate.IsEmpty) { this.mAllowCertificateStatus = false; } this.mKeyExchange.ProcessServerCertificate(this.mPeerCertificate); this.mAuthentication = mTlsClient.GetAuthentication(); this.mAuthentication.NotifyServerCertificate(this.mPeerCertificate); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_SERVER_CERTIFICATE; break; } case HandshakeType.certificate_status: { switch (this.mConnectionState) { case CS_SERVER_CERTIFICATE: { if (!this.mAllowCertificateStatus) { /* * RFC 3546 3.6. If a server returns a "CertificateStatus" message, then the * server MUST have included an extension of type "status_request" with empty * "extension_data" in the extended server hello.. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mCertificateStatus = CertificateStatus.Parse(buf); AssertEmpty(buf); // TODO[RFC 3546] Figure out how to provide this to the client/authentication. this.mConnectionState = CS_CERTIFICATE_STATUS; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.finished: { switch (this.mConnectionState) { case CS_CLIENT_FINISHED: case CS_SERVER_SESSION_TICKET: { if (this.mConnectionState == CS_CLIENT_FINISHED && this.mExpectSessionTicket) { /* * RFC 5077 3.3. This message MUST be sent if the server included a * SessionTicket extension in the ServerHello. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } ProcessFinishedMessage(buf); this.mConnectionState = CS_SERVER_FINISHED; this.mConnectionState = CS_END; break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.server_hello: { switch (this.mConnectionState) { case CS_CLIENT_HELLO: { ReceiveServerHelloMessage(buf); this.mConnectionState = CS_SERVER_HELLO; this.mRecordStream.NotifyHelloComplete(); ApplyMaxFragmentLengthExtension(); if (this.mResumedSession) { this.mSecurityParameters.masterSecret = Arrays.Clone(this.mSessionParameters.MasterSecret); this.mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher()); SendChangeCipherSpecMessage(); } else { InvalidateSession(); if (this.mSelectedSessionID.Length > 0) { this.mTlsSession = new TlsSessionImpl(this.mSelectedSessionID, null); } } break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.supplemental_data: { switch (this.mConnectionState) { case CS_SERVER_HELLO: { HandleSupplementalData(ReadSupplementalDataMessage(buf)); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } break; } case HandshakeType.server_hello_done: { switch (this.mConnectionState) { case CS_SERVER_HELLO: case CS_SERVER_SUPPLEMENTAL_DATA: case CS_SERVER_CERTIFICATE: case CS_CERTIFICATE_STATUS: case CS_SERVER_KEY_EXCHANGE: case CS_CERTIFICATE_REQUEST: { if (mConnectionState < CS_SERVER_SUPPLEMENTAL_DATA) { HandleSupplementalData(null); } if (mConnectionState < CS_SERVER_CERTIFICATE) { // There was no server certificate message; check it's OK this.mKeyExchange.SkipServerCredentials(); this.mAuthentication = null; } if (mConnectionState < CS_SERVER_KEY_EXCHANGE) { // There was no server key exchange message; check it's OK this.mKeyExchange.SkipServerKeyExchange(); } AssertEmpty(buf); this.mConnectionState = CS_SERVER_HELLO_DONE; this.mRecordStream.HandshakeHash.SealHashAlgorithms(); IList clientSupplementalData = mTlsClient.GetClientSupplementalData(); if (clientSupplementalData != null) { SendSupplementalDataMessage(clientSupplementalData); } this.mConnectionState = CS_CLIENT_SUPPLEMENTAL_DATA; TlsCredentials clientCreds = null; if (mCertificateRequest == null) { this.mKeyExchange.SkipClientCredentials(); } else { clientCreds = this.mAuthentication.GetClientCredentials(this.Context, mCertificateRequest); if (clientCreds == null) { this.mKeyExchange.SkipClientCredentials(); /* * RFC 5246 If no suitable certificate is available, the client MUST Send a * certificate message containing no certificates. * * NOTE: In previous RFCs, this was SHOULD instead of MUST. */ SendCertificateMessage(Certificate.EmptyChain); } else { this.mKeyExchange.ProcessClientCredentials(clientCreds); SendCertificateMessage(clientCreds.Certificate); } } this.mConnectionState = CS_CLIENT_CERTIFICATE; /* * Send the client key exchange message, depending on the key exchange we are using * in our CipherSuite. */ SendClientKeyExchangeMessage(); this.mConnectionState = CS_CLIENT_KEY_EXCHANGE; TlsHandshakeHash prepareFinishHash = mRecordStream.PrepareToFinish(); this.mSecurityParameters.sessionHash = GetCurrentPrfHash(Context, prepareFinishHash, null); EstablishMasterSecret(Context, mKeyExchange); mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher()); if (clientCreds != null && clientCreds is TlsSignerCredentials) { TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientCreds; /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm( Context, signerCredentials); byte[] hash; if (signatureAndHashAlgorithm == null) { hash = mSecurityParameters.SessionHash; } else { hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); } byte[] signature = signerCredentials.GenerateCertificateSignature(hash); DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature); SendCertificateVerifyMessage(certificateVerify); this.mConnectionState = CS_CERTIFICATE_VERIFY; } SendChangeCipherSpecMessage(); SendFinishedMessage(); break; } default: throw new TlsFatalAlert(AlertDescription.handshake_failure); } this.mConnectionState = CS_CLIENT_FINISHED; break; } case HandshakeType.server_key_exchange: { switch (this.mConnectionState) { case CS_SERVER_HELLO: case CS_SERVER_SUPPLEMENTAL_DATA: case CS_SERVER_CERTIFICATE: case CS_CERTIFICATE_STATUS: { if (mConnectionState < CS_SERVER_SUPPLEMENTAL_DATA) { HandleSupplementalData(null); } if (mConnectionState < CS_SERVER_CERTIFICATE) { // There was no server certificate message; check it's OK this.mKeyExchange.SkipServerCredentials(); this.mAuthentication = null; } this.mKeyExchange.ProcessServerKeyExchange(buf); AssertEmpty(buf); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_SERVER_KEY_EXCHANGE; break; } case HandshakeType.certificate_request: { switch (this.mConnectionState) { case CS_SERVER_CERTIFICATE: case CS_CERTIFICATE_STATUS: case CS_SERVER_KEY_EXCHANGE: { if (this.mConnectionState != CS_SERVER_KEY_EXCHANGE) { // There was no server key exchange message; check it's OK this.mKeyExchange.SkipServerKeyExchange(); } if (this.mAuthentication == null) { /* * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server * to request client identification. */ throw new TlsFatalAlert(AlertDescription.handshake_failure); } this.mCertificateRequest = CertificateRequest.Parse(Context, buf); AssertEmpty(buf); this.mKeyExchange.ValidateCertificateRequest(this.mCertificateRequest); /* * TODO Give the client a chance to immediately select the CertificateVerify hash * algorithm here to avoid tracking the other hash algorithms unnecessarily? */ TlsUtilities.TrackHashAlgorithms(this.mRecordStream.HandshakeHash, this.mCertificateRequest.SupportedSignatureAlgorithms); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_CERTIFICATE_REQUEST; break; } case HandshakeType.session_ticket: { switch (this.mConnectionState) { case CS_CLIENT_FINISHED: { if (!this.mExpectSessionTicket) { /* * RFC 5077 3.3. This message MUST NOT be sent if the server did not include a * SessionTicket extension in the ServerHello. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } /* * RFC 5077 3.4. If the client receives a session ticket from the server, then it * discards any Session ID that was sent in the ServerHello. */ InvalidateSession(); ReceiveNewSessionTicketMessage(buf); break; } default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } this.mConnectionState = CS_SERVER_SESSION_TICKET; break; } case HandshakeType.hello_request: { AssertEmpty(buf); /* * RFC 2246 7.4.1.1 Hello request This message will be ignored by the client if the * client is currently negotiating a session. This message may be ignored by the client * if it does not wish to renegotiate a session, or the client may, if it wishes, * respond with a no_renegotiation alert. */ if (this.mConnectionState == CS_END) { RefuseRenegotiation(); } break; } case HandshakeType.client_hello: case HandshakeType.client_key_exchange: case HandshakeType.certificate_verify: case HandshakeType.hello_verify_request: default: throw new TlsFatalAlert(AlertDescription.unexpected_message); } }
protected override void HandleHandshakeMessage(byte type, byte[] data) { MemoryStream buf = new MemoryStream(data, false); if (base.mResumedSession) { if ((type != 20) || (base.mConnectionState != 2)) { throw new TlsFatalAlert(10); } this.ProcessFinishedMessage(buf); base.mConnectionState = 15; this.SendFinishedMessage(); base.mConnectionState = 13; base.mConnectionState = 0x10; this.CompleteHandshake(); } else { switch (type) { case 0: TlsProtocol.AssertEmpty(buf); if (base.mConnectionState == 0x10) { this.RefuseRenegotiation(); } return; case 2: if (base.mConnectionState != 1) { throw new TlsFatalAlert(10); } this.ReceiveServerHelloMessage(buf); base.mConnectionState = 2; base.mRecordStream.NotifyHelloComplete(); this.ApplyMaxFragmentLengthExtension(); if (base.mResumedSession) { base.mSecurityParameters.masterSecret = Arrays.Clone(base.mSessionParameters.MasterSecret); base.mRecordStream.SetPendingConnectionState(this.Peer.GetCompression(), this.Peer.GetCipher()); this.SendChangeCipherSpecMessage(); } else { this.InvalidateSession(); if (this.mSelectedSessionID.Length > 0) { base.mTlsSession = new TlsSessionImpl(this.mSelectedSessionID, null); } } return; case 4: if (base.mConnectionState != 13) { throw new TlsFatalAlert(10); } if (!base.mExpectSessionTicket) { throw new TlsFatalAlert(10); } this.InvalidateSession(); this.ReceiveNewSessionTicketMessage(buf); base.mConnectionState = 14; return; case 11: switch (base.mConnectionState) { case 2: case 3: if (base.mConnectionState == 2) { this.HandleSupplementalData(null); } base.mPeerCertificate = Certificate.Parse(buf); TlsProtocol.AssertEmpty(buf); if ((base.mPeerCertificate == null) || base.mPeerCertificate.IsEmpty) { base.mAllowCertificateStatus = false; } this.mKeyExchange.ProcessServerCertificate(base.mPeerCertificate); this.mAuthentication = this.mTlsClient.GetAuthentication(); this.mAuthentication.NotifyServerCertificate(base.mPeerCertificate); base.mConnectionState = 4; return; } throw new TlsFatalAlert(10); case 12: switch (base.mConnectionState) { case 2: case 3: case 4: case 5: if (base.mConnectionState < 3) { this.HandleSupplementalData(null); } if (base.mConnectionState < 4) { this.mKeyExchange.SkipServerCredentials(); this.mAuthentication = null; } this.mKeyExchange.ProcessServerKeyExchange(buf); TlsProtocol.AssertEmpty(buf); base.mConnectionState = 6; return; } throw new TlsFatalAlert(10); case 13: switch (base.mConnectionState) { case 4: case 5: case 6: if (base.mConnectionState != 6) { this.mKeyExchange.SkipServerKeyExchange(); } if (this.mAuthentication == null) { throw new TlsFatalAlert(40); } this.mCertificateRequest = CertificateRequest.Parse(this.Context, buf); TlsProtocol.AssertEmpty(buf); this.mKeyExchange.ValidateCertificateRequest(this.mCertificateRequest); TlsUtilities.TrackHashAlgorithms(base.mRecordStream.HandshakeHash, this.mCertificateRequest.SupportedSignatureAlgorithms); base.mConnectionState = 7; return; } throw new TlsFatalAlert(10); case 14: switch (base.mConnectionState) { case 2: case 3: case 4: case 5: case 6: case 7: { if (base.mConnectionState < 3) { this.HandleSupplementalData(null); } if (base.mConnectionState < 4) { this.mKeyExchange.SkipServerCredentials(); this.mAuthentication = null; } if (base.mConnectionState < 6) { this.mKeyExchange.SkipServerKeyExchange(); } TlsProtocol.AssertEmpty(buf); base.mConnectionState = 8; base.mRecordStream.HandshakeHash.SealHashAlgorithms(); IList clientSupplementalData = this.mTlsClient.GetClientSupplementalData(); if (clientSupplementalData != null) { this.SendSupplementalDataMessage(clientSupplementalData); } base.mConnectionState = 9; TlsCredentials clientCredentials = null; if (this.mCertificateRequest == null) { this.mKeyExchange.SkipClientCredentials(); } else { clientCredentials = this.mAuthentication.GetClientCredentials(this.Context, this.mCertificateRequest); if (clientCredentials == null) { this.mKeyExchange.SkipClientCredentials(); this.SendCertificateMessage(Certificate.EmptyChain); } else { this.mKeyExchange.ProcessClientCredentials(clientCredentials); this.SendCertificateMessage(clientCredentials.Certificate); } } base.mConnectionState = 10; this.SendClientKeyExchangeMessage(); base.mConnectionState = 11; TlsHandshakeHash handshakeHash = base.mRecordStream.PrepareToFinish(); base.mSecurityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(this.Context, handshakeHash, null); TlsProtocol.EstablishMasterSecret(this.Context, this.mKeyExchange); base.mRecordStream.SetPendingConnectionState(this.Peer.GetCompression(), this.Peer.GetCipher()); if ((clientCredentials != null) && (clientCredentials is TlsSignerCredentials)) { byte[] sessionHash; TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientCredentials; SignatureAndHashAlgorithm signatureAndHashAlgorithm = TlsUtilities.GetSignatureAndHashAlgorithm(this.Context, signerCredentials); if (signatureAndHashAlgorithm == null) { sessionHash = base.mSecurityParameters.SessionHash; } else { sessionHash = handshakeHash.GetFinalHash(signatureAndHashAlgorithm.Hash); } byte[] signature = signerCredentials.GenerateCertificateSignature(sessionHash); DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature); this.SendCertificateVerifyMessage(certificateVerify); base.mConnectionState = 12; } this.SendChangeCipherSpecMessage(); this.SendFinishedMessage(); base.mConnectionState = 13; return; } } throw new TlsFatalAlert(40); case 20: switch (base.mConnectionState) { case 13: case 14: if ((base.mConnectionState == 13) && base.mExpectSessionTicket) { throw new TlsFatalAlert(10); } this.ProcessFinishedMessage(buf); base.mConnectionState = 15; base.mConnectionState = 0x10; this.CompleteHandshake(); return; } throw new TlsFatalAlert(10); case 0x16: if (base.mConnectionState != 4) { throw new TlsFatalAlert(10); } if (!base.mAllowCertificateStatus) { throw new TlsFatalAlert(10); } this.mCertificateStatus = CertificateStatus.Parse(buf); TlsProtocol.AssertEmpty(buf); base.mConnectionState = 5; return; case 0x17: if (base.mConnectionState != 2) { throw new TlsFatalAlert(10); } this.HandleSupplementalData(TlsProtocol.ReadSupplementalDataMessage(buf)); return; } throw new TlsFatalAlert(10); } }