protected virtual void HandleSupplementalData(global::System.Collections.IList serverSupplementalData) { mTlsClient.ProcessServerSupplementalData(serverSupplementalData); mConnectionState = 3; mKeyExchange = mTlsClient.GetKeyExchange(); mKeyExchange.Init(Context); }
protected virtual void HandleSupplementalData(IList serverSupplementalData) { this.mTlsClient.ProcessServerSupplementalData(serverSupplementalData); base.mConnectionState = 3; this.mKeyExchange = this.mTlsClient.GetKeyExchange(); this.mKeyExchange.Init(this.Context); }
protected override void CleanupHandshake() { base.CleanupHandshake(); this.mKeyExchange = null; this.mServerCredentials = null; this.mCertificateRequest = null; this.mPrepareFinishHash = null; }
protected virtual void HandleSupplementalData(IList serverSupplementalData) { this.mTlsClient.ProcessServerSupplementalData(serverSupplementalData); this.mConnectionState = CS_SERVER_SUPPLEMENTAL_DATA; this.mKeyExchange = mTlsClient.GetKeyExchange(); this.mKeyExchange.Init(Context); }
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 HandleSupplementalData(IList serverSupplementalData) { if (HTTPManager.Logger.Level <= Loglevels.All) { HTTPManager.Logger.Verbose("TlsClientProtocol", "HandleSupplementalData", this.LoggingContext); } this.mTlsClient.ProcessServerSupplementalData(serverSupplementalData); this.mConnectionState = CS_SERVER_SUPPLEMENTAL_DATA; this.mKeyExchange = mTlsClient.GetKeyExchange(); this.mKeyExchange.Init(Context); }
protected internal static void EstablishMasterSecret(TlsContext context, TlsKeyExchange keyExchange) { byte[] array = keyExchange.GeneratePremasterSecret(); try { context.SecurityParameters.masterSecret = TlsUtilities.CalculateMasterSecret(context, array); } finally { if (array != null) { Arrays.Fill(array, 0); } } }
protected override void CleanupHandshake() { if (HTTPManager.Logger.Level <= Loglevels.All) { HTTPManager.Logger.Verbose("TlsClientProtocol", "CleanupHandshake", this.LoggingContext); } base.CleanupHandshake(); this.mSelectedSessionID = null; this.mKeyExchange = null; this.mAuthentication = null; this.mTlsClient.CertificateStatus = null; this.mCertificateRequest = null; }
protected internal static void EstablishMasterSecret(TlsContext context, TlsKeyExchange keyExchange) { byte[] pre_master_secret = keyExchange.GeneratePremasterSecret(); try { context.SecurityParameters.masterSecret = TlsUtilities.CalculateMasterSecret(context, pre_master_secret); } finally { // TODO Is there a way to ensure the data is really overwritten? /* * RFC 2246 8.1. The pre_master_secret should be deleted from memory once the * master_secret has been computed. */ if (pre_master_secret != null) { Arrays.Fill(pre_master_secret, (byte)0); } } }
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) { 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); } }
private void ProcessHandshakeMessage(HandshakeType type, byte[] buf) { MemoryStream inStr = new MemoryStream(buf, false); /* * Check the type. */ switch (type) { case HandshakeType.certificate: { switch (connection_state) { case CS_SERVER_HELLO_RECEIVED: { // Parse the Certificate message and send to cipher suite Certificate serverCertificate = Certificate.Parse(inStr); AssertEmpty(inStr); this.keyExchange.ProcessServerCertificate(serverCertificate); this.authentication = tlsClient.GetAuthentication(); this.authentication.NotifyServerCertificate(serverCertificate); break; } default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } connection_state = CS_SERVER_CERTIFICATE_RECEIVED; break; } case HandshakeType.finished: switch (connection_state) { case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED: /* * Read the checksum from the finished message, it has always 12 bytes. */ byte[] serverVerifyData = new byte[12]; TlsUtilities.ReadFully(serverVerifyData, inStr); AssertEmpty(inStr); /* * Calculate our own checksum. */ byte[] expectedServerVerifyData = TlsUtilities.PRF( securityParameters.masterSecret, "server finished", rs.GetCurrentHash(), 12); /* * Compare both checksums. */ if (!Arrays.ConstantTimeAreEqual(expectedServerVerifyData, serverVerifyData)) { /* * Wrong checksum in the finished message. */ this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); } connection_state = CS_DONE; /* * We are now ready to receive application data. */ this.appDataReady = true; break; default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } break; case HandshakeType.server_hello: switch (connection_state) { case CS_CLIENT_HELLO_SEND: /* * Read the server hello message */ TlsUtilities.CheckVersion(inStr, this); /* * Read the server random */ securityParameters.serverRandom = new byte[32]; TlsUtilities.ReadFully(securityParameters.serverRandom, inStr); byte[] sessionID = TlsUtilities.ReadOpaque8(inStr); if (sessionID.Length > 32) { this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } this.tlsClient.NotifySessionID(sessionID); /* * Find out which CipherSuite the server has chosen and check that * it was one of the offered ones. */ CipherSuite selectedCipherSuite = (CipherSuite)TlsUtilities.ReadUint16(inStr); if (!ArrayContains(offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } this.tlsClient.NotifySelectedCipherSuite(selectedCipherSuite); /* * Find out which CompressionMethod the server has chosen and check that * it was one of the offered ones. */ CompressionMethod selectedCompressionMethod = (CompressionMethod)TlsUtilities.ReadUint8(inStr); if (!ArrayContains(offeredCompressionMethods, selectedCompressionMethod)) { this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } this.tlsClient.NotifySelectedCompressionMethod(selectedCompressionMethod); /* * RFC3546 2.2 The extended server hello message format MAY be * sent in place of the server hello message when the client has * requested extended functionality via the extended client hello * message specified in Section 2.1. * ... * Note that the extended server hello message is only sent in response * to an extended client hello message. This prevents the possibility * that the extended server hello message could "break" existing TLS 1.0 * clients. */ /* * TODO RFC 3546 2.3 * If [...] the older session is resumed, then the server MUST ignore * extensions appearing in the client hello, and send a server hello * containing no extensions. */ // ExtensionType -> byte[] IDictionary serverExtensions = Platform.CreateHashtable(); if (inStr.Position < inStr.Length) { // Process extensions from extended server hello byte[] extBytes = TlsUtilities.ReadOpaque16(inStr); MemoryStream ext = new MemoryStream(extBytes, false); while (ext.Position < ext.Length) { ExtensionType extType = (ExtensionType)TlsUtilities.ReadUint16(ext); byte[] extValue = TlsUtilities.ReadOpaque16(ext); // Note: RFC 5746 makes a special case for EXT_RenegotiationInfo if (extType != ExtensionType.renegotiation_info && !clientExtensions.Contains(extType)) { /* * RFC 3546 2.3 * Note that for all extension types (including those defined in * future), the extension type MUST NOT appear in the extended server * hello unless the same extension type appeared in the corresponding * client hello. Thus clients MUST abort the handshake if they receive * an extension type in the extended server hello that they did not * request in the associated (extended) client hello. */ this.FailWithError(AlertLevel.fatal, AlertDescription.unsupported_extension); } if (serverExtensions.Contains(extType)) { /* * RFC 3546 2.3 * Also note that when multiple extensions of different types are * present in the extended client hello or the extended server hello, * the extensions may appear in any order. There MUST NOT be more than * one extension of the same type. */ this.FailWithError(AlertLevel.fatal, AlertDescription.illegal_parameter); } serverExtensions.Add(extType, extValue); } } AssertEmpty(inStr); /* * RFC 5746 3.4. When a ServerHello is received, the client MUST check if it * includes the "renegotiation_info" extension: */ { bool secure_negotiation = serverExtensions.Contains(ExtensionType.renegotiation_info); /* * If the extension is present, set the secure_renegotiation flag * to TRUE. The client MUST then verify that the length of the * "renegotiated_connection" field is zero, and if it is not, MUST * abort the handshake (by sending a fatal handshake_failure * alert). */ if (secure_negotiation) { byte[] renegExtValue = (byte[])serverExtensions[ExtensionType.renegotiation_info]; if (!Arrays.ConstantTimeAreEqual(renegExtValue, CreateRenegotiationInfo(emptybuf))) { this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); } } tlsClient.NotifySecureRenegotiation(secure_negotiation); } if (clientExtensions != null) { tlsClient.ProcessServerExtensions(serverExtensions); } this.keyExchange = tlsClient.GetKeyExchange(); connection_state = CS_SERVER_HELLO_RECEIVED; break; default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } break; case HandshakeType.server_hello_done: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: case CS_SERVER_KEY_EXCHANGE_RECEIVED: case CS_CERTIFICATE_REQUEST_RECEIVED: // NB: Original code used case label fall-through if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) { // There was no server key exchange message; check it's OK this.keyExchange.SkipServerKeyExchange(); } AssertEmpty(inStr); connection_state = CS_SERVER_HELLO_DONE_RECEIVED; TlsCredentials clientCreds = null; if (certificateRequest == null) { this.keyExchange.SkipClientCredentials(); } else { clientCreds = this.authentication.GetClientCredentials(certificateRequest); Certificate clientCert; if (clientCreds == null) { this.keyExchange.SkipClientCredentials(); clientCert = Certificate.EmptyChain; } else { this.keyExchange.ProcessClientCredentials(clientCreds); clientCert = clientCreds.Certificate; } SendClientCertificate(clientCert); } /* * Send the client key exchange message, depending on the key * exchange we are using in our CipherSuite. */ SendClientKeyExchange(); connection_state = CS_CLIENT_KEY_EXCHANGE_SEND; if (clientCreds != null && clientCreds is TlsSignerCredentials) { TlsSignerCredentials signerCreds = (TlsSignerCredentials)clientCreds; byte[] md5andsha1 = rs.GetCurrentHash(); byte[] clientCertificateSignature = signerCreds.GenerateCertificateSignature( md5andsha1); SendCertificateVerify(clientCertificateSignature); connection_state = CS_CERTIFICATE_VERIFY_SEND; } /* * Now, we send change cipher state */ byte[] cmessage = new byte[1]; cmessage[0] = 1; rs.WriteMessage(ContentType.change_cipher_spec, cmessage, 0, cmessage.Length); connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND; /* * Calculate the master_secret */ byte[] pms = this.keyExchange.GeneratePremasterSecret(); securityParameters.masterSecret = TlsUtilities.PRF(pms, "master secret", TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom), 48); // TODO Is there a way to ensure the data is really overwritten? /* * RFC 2246 8.1. The pre_master_secret should be deleted from * memory once the master_secret has been computed. */ Array.Clear(pms, 0, pms.Length); /* * Initialize our cipher suite */ rs.ClientCipherSpecDecided(tlsClient.GetCompression(), tlsClient.GetCipher()); /* * Send our finished message. */ byte[] clientVerifyData = TlsUtilities.PRF(securityParameters.masterSecret, "client finished", rs.GetCurrentHash(), 12); MemoryStream bos = new MemoryStream(); TlsUtilities.WriteUint8((byte)HandshakeType.finished, bos); TlsUtilities.WriteOpaque24(clientVerifyData, bos); byte[] message = bos.ToArray(); rs.WriteMessage(ContentType.handshake, message, 0, message.Length); this.connection_state = CS_CLIENT_FINISHED_SEND; break; default: this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); break; } break; case HandshakeType.server_key_exchange: { switch (connection_state) { case CS_SERVER_HELLO_RECEIVED: case CS_SERVER_CERTIFICATE_RECEIVED: { // NB: Original code used case label fall-through if (connection_state == CS_SERVER_HELLO_RECEIVED) { // There was no server certificate message; check it's OK this.keyExchange.SkipServerCertificate(); this.authentication = null; } this.keyExchange.ProcessServerKeyExchange(inStr); AssertEmpty(inStr); break; } default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED; break; } case HandshakeType.certificate_request: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: case CS_SERVER_KEY_EXCHANGE_RECEIVED: { // NB: Original code used case label fall-through if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) { // There was no server key exchange message; check it's OK this.keyExchange.SkipServerKeyExchange(); } if (this.authentication == null) { /* * RFC 2246 7.4.4. It is a fatal handshake_failure alert * for an anonymous server to request client identification. */ this.FailWithError(AlertLevel.fatal, AlertDescription.handshake_failure); } int numTypes = TlsUtilities.ReadUint8(inStr); ClientCertificateType[] certificateTypes = new ClientCertificateType[numTypes]; for (int i = 0; i < numTypes; ++i) { certificateTypes[i] = (ClientCertificateType)TlsUtilities.ReadUint8(inStr); } byte[] authorities = TlsUtilities.ReadOpaque16(inStr); AssertEmpty(inStr); IList authorityDNs = Platform.CreateArrayList(); MemoryStream bis = new MemoryStream(authorities, false); while (bis.Position < bis.Length) { byte[] dnBytes = TlsUtilities.ReadOpaque16(bis); // TODO Switch to X500Name when available authorityDNs.Add(X509Name.GetInstance(Asn1Object.FromByteArray(dnBytes))); } this.certificateRequest = new CertificateRequest(certificateTypes, authorityDNs); this.keyExchange.ValidateCertificateRequest(this.certificateRequest); break; } default: this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED; break; case HandshakeType.hello_request: /* * 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 (connection_state == CS_DONE) { // Renegotiation not supported yet SendAlert(AlertLevel.warning, AlertDescription.no_renegotiation); } break; case HandshakeType.client_key_exchange: case HandshakeType.certificate_verify: case HandshakeType.client_hello: default: // We do not support this! this.FailWithError(AlertLevel.fatal, AlertDescription.unexpected_message); break; } }
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); } }
private void ProcessHandshakeMessage(short type, byte[] buf) { MemoryStream inStr = new MemoryStream(buf, false); /* * Check the type. */ switch (type) { case HP_CERTIFICATE: { switch (connection_state) { case CS_SERVER_HELLO_RECEIVED: { // Parse the Certificate message and send to cipher suite Certificate serverCertificate = Certificate.Parse(inStr); AssertEmpty(inStr); this.keyExchange.ProcessServerCertificate(serverCertificate); break; } default: this.FailWithError(AL_fatal, AP_unexpected_message); break; } connection_state = CS_SERVER_CERTIFICATE_RECEIVED; break; } case HP_FINISHED: switch (connection_state) { case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED: /* * Read the checksum from the finished message, it has always 12 bytes. */ byte[] serverVerifyData = new byte[12]; TlsUtilities.ReadFully(serverVerifyData, inStr); AssertEmpty(inStr); /* * Calculate our own checksum. */ byte[] expectedServerVerifyData = TlsUtilities.PRF( securityParameters.masterSecret, "server finished", rs.GetCurrentHash(), 12); /* * Compare both checksums. */ if (!Arrays.ConstantTimeAreEqual(expectedServerVerifyData, serverVerifyData)) { /* * Wrong checksum in the finished message. */ this.FailWithError(AL_fatal, AP_handshake_failure); } connection_state = CS_DONE; /* * We are now ready to receive application data. */ this.appDataReady = true; break; default: this.FailWithError(AL_fatal, AP_unexpected_message); break; } break; case HP_SERVER_HELLO: switch (connection_state) { case CS_CLIENT_HELLO_SEND: /* * Read the server hello message */ TlsUtilities.CheckVersion(inStr, this); /* * Read the server random */ securityParameters.serverRandom = new byte[32]; TlsUtilities.ReadFully(securityParameters.serverRandom, inStr); /* * Currently, we don't support session ids */ byte[] sessionID = TlsUtilities.ReadOpaque8(inStr); if (sessionID.Length > 32) { this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter); } this.tlsClient.NotifySessionID(sessionID); /* * Find out which ciphersuite the server has chosen and check that * it was one of the offered ones. */ int selectedCipherSuite = TlsUtilities.ReadUint16(inStr); if (!WasCipherSuiteOffered(selectedCipherSuite)) { this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter); } this.tlsClient.NotifySelectedCipherSuite(selectedCipherSuite); /* * We support only the null compression which means no * compression. */ short compressionMethod = TlsUtilities.ReadUint8(inStr); if (compressionMethod != 0) { this.FailWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter); } /* * RFC4366 2.2 The extended server hello message format MAY be * sent in place of the server hello message when the client has * requested extended functionality via the extended client hello * message specified in Section 2.1. */ if (extendedClientHello) { // Integer -> byte[] Hashtable serverExtensions = new Hashtable(); if (inStr.Position < inStr.Length) { // Process extensions from extended server hello byte[] extBytes = TlsUtilities.ReadOpaque16(inStr); MemoryStream ext = new MemoryStream(extBytes, false); while (ext.Position < ext.Length) { int extType = TlsUtilities.ReadUint16(ext); byte[] extValue = TlsUtilities.ReadOpaque16(ext); serverExtensions.Add(extType, extValue); } } // TODO[RFC 5746] If renegotiation_info was sent in client hello, check here tlsClient.ProcessServerExtensions(serverExtensions); } AssertEmpty(inStr); this.keyExchange = tlsClient.CreateKeyExchange(); connection_state = CS_SERVER_HELLO_RECEIVED; break; default: this.FailWithError(AL_fatal, AP_unexpected_message); break; } break; case HP_SERVER_HELLO_DONE: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: case CS_SERVER_KEY_EXCHANGE_RECEIVED: case CS_CERTIFICATE_REQUEST_RECEIVED: // NB: Original code used case label fall-through if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) { // There was no server key exchange message; check it's OK this.keyExchange.SkipServerKeyExchange(); } AssertEmpty(inStr); bool isClientCertificateRequested = (connection_state == CS_CERTIFICATE_REQUEST_RECEIVED); connection_state = CS_SERVER_HELLO_DONE_RECEIVED; if (isClientCertificateRequested) { SendClientCertificate(tlsClient.GetCertificate()); } /* * Send the client key exchange message, depending on the key * exchange we are using in our ciphersuite. */ SendClientKeyExchange(this.keyExchange.GenerateClientKeyExchange()); connection_state = CS_CLIENT_KEY_EXCHANGE_SEND; if (isClientCertificateRequested) { byte[] clientCertificateSignature = tlsClient.GenerateCertificateSignature(rs.GetCurrentHash()); if (clientCertificateSignature != null) { SendCertificateVerify(clientCertificateSignature); connection_state = CS_CERTIFICATE_VERIFY_SEND; } } /* * Now, we send change cipher state */ byte[] cmessage = new byte[1]; cmessage[0] = 1; rs.WriteMessage(RL_CHANGE_CIPHER_SPEC, cmessage, 0, cmessage.Length); connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND; /* * Calculate the master_secret */ byte[] pms = this.keyExchange.GeneratePremasterSecret(); securityParameters.masterSecret = TlsUtilities.PRF(pms, "master secret", TlsUtilities.Concat(securityParameters.clientRandom, securityParameters.serverRandom), 48); // TODO Is there a way to ensure the data is really overwritten? /* * RFC 2246 8.1. "The pre_master_secret should be deleted from * memory once the master_secret has been computed." */ Array.Clear(pms, 0, pms.Length); /* * Initialize our cipher suite */ rs.ClientCipherSpecDecided(tlsClient.CreateCipher(securityParameters)); /* * Send our finished message. */ byte[] clientVerifyData = TlsUtilities.PRF(securityParameters.masterSecret, "client finished", rs.GetCurrentHash(), 12); MemoryStream bos = new MemoryStream(); TlsUtilities.WriteUint8(HP_FINISHED, bos); TlsUtilities.WriteOpaque24(clientVerifyData, bos); byte[] message = bos.ToArray(); rs.WriteMessage(RL_HANDSHAKE, message, 0, message.Length); this.connection_state = CS_CLIENT_FINISHED_SEND; break; default: this.FailWithError(AL_fatal, AP_handshake_failure); break; } break; case HP_SERVER_KEY_EXCHANGE: { switch (connection_state) { case CS_SERVER_HELLO_RECEIVED: case CS_SERVER_CERTIFICATE_RECEIVED: { // NB: Original code used case label fall-through if (connection_state == CS_SERVER_HELLO_RECEIVED) { // There was no server certificate message; check it's OK this.keyExchange.SkipServerCertificate(); } this.keyExchange.ProcessServerKeyExchange(inStr, securityParameters); AssertEmpty(inStr); break; } default: this.FailWithError(AL_fatal, AP_unexpected_message); break; } this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED; break; } case HP_CERTIFICATE_REQUEST: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: case CS_SERVER_KEY_EXCHANGE_RECEIVED: { // NB: Original code used case label fall-through if (connection_state == CS_SERVER_CERTIFICATE_RECEIVED) { // There was no server key exchange message; check it's OK this.keyExchange.SkipServerKeyExchange(); } byte[] types = TlsUtilities.ReadOpaque8(inStr); byte[] authorities = TlsUtilities.ReadOpaque16(inStr); AssertEmpty(inStr); ArrayList authorityDNs = new ArrayList(); MemoryStream bis = new MemoryStream(authorities, false); while (bis.Position < bis.Length) { byte[] dnBytes = TlsUtilities.ReadOpaque16(bis); authorityDNs.Add(X509Name.GetInstance(Asn1Object.FromByteArray(dnBytes))); } this.tlsClient.ProcessServerCertificateRequest(types, authorityDNs); break; } default: this.FailWithError(AL_fatal, AP_unexpected_message); break; } this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED; break; case HP_HELLO_REQUEST: /* * 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 (connection_state == CS_DONE) { // Renegotiation not supported yet SendAlert(AL_warning, AP_no_renegotiation); } break; case HP_CLIENT_KEY_EXCHANGE: case HP_CERTIFICATE_VERIFY: case HP_CLIENT_HELLO: default: // We do not support this! this.FailWithError(AL_fatal, AP_unexpected_message); break; } }
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); }