protected static GetPrfAlgorithm ( TlsContext context, int ciphersuite ) : int | ||
context | TlsContext | |
ciphersuite | int | |
return | int |
protected virtual byte[] GenerateServerHello(DtlsServerProtocol.ServerHandshakeState state) { SecurityParameters securityParameters = state.serverContext.SecurityParameters; MemoryStream memoryStream = new MemoryStream(); ProtocolVersion serverVersion = state.server.GetServerVersion(); if (!serverVersion.IsEqualOrEarlierVersionOf(state.serverContext.ClientVersion)) { throw new TlsFatalAlert(80); } state.serverContext.SetServerVersion(serverVersion); TlsUtilities.WriteVersion(state.serverContext.ServerVersion, memoryStream); memoryStream.Write(securityParameters.ServerRandom, 0, securityParameters.ServerRandom.Length); TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, memoryStream); int selectedCipherSuite = state.server.GetSelectedCipherSuite(); if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == 0 || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.serverContext.ServerVersion)) { throw new TlsFatalAlert(80); } DtlsProtocol.ValidateSelectedCipherSuite(selectedCipherSuite, 80); securityParameters.cipherSuite = selectedCipherSuite; byte selectedCompressionMethod = state.server.GetSelectedCompressionMethod(); if (!Arrays.Contains(state.offeredCompressionMethods, selectedCompressionMethod)) { throw new TlsFatalAlert(80); } securityParameters.compressionAlgorithm = selectedCompressionMethod; TlsUtilities.WriteUint16(selectedCipherSuite, memoryStream); TlsUtilities.WriteUint8(selectedCompressionMethod, memoryStream); state.serverExtensions = state.server.GetServerExtensions(); if (state.secure_renegotiation) { byte[] extensionData = TlsUtilities.GetExtensionData(state.serverExtensions, 65281); bool flag = null == extensionData; if (flag) { state.serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(state.serverExtensions); state.serverExtensions[65281] = TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes); } } if (securityParameters.extendedMasterSecret) { state.serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(state.serverExtensions); TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.serverExtensions); } if (state.serverExtensions != null) { securityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(state.serverExtensions); securityParameters.maxFragmentLength = DtlsProtocol.EvaluateMaxFragmentLengthExtension(state.resumedSession, state.clientExtensions, state.serverExtensions, 80); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(state.serverExtensions); state.allowCertificateStatus = (!state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, 5, 80)); state.expectSessionTicket = (!state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, 35, 80)); TlsProtocol.WriteExtensions(memoryStream, state.serverExtensions); } securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.serverContext, securityParameters.CipherSuite); securityParameters.verifyDataLength = 12; return(memoryStream.ToArray()); }
internal virtual DtlsTransport ClientHandshake(ClientHandshakeState state, DtlsRecordLayer recordLayer) { SecurityParameters securityParameters = state.clientContext.SecurityParameters; DtlsReliableHandshake handshake = new DtlsReliableHandshake(state.clientContext, recordLayer); byte[] clientHelloBody = GenerateClientHello(state, state.client); handshake.SendMessage(HandshakeType.client_hello, clientHelloBody); DtlsReliableHandshake.Message serverMessage = handshake.ReceiveMessage(); while (serverMessage.Type == HandshakeType.hello_verify_request) { ProtocolVersion recordLayerVersion = recordLayer.ResetDiscoveredPeerVersion(); ProtocolVersion client_version = state.clientContext.ClientVersion; /* * RFC 6347 4.2.1 DTLS 1.2 server implementations SHOULD use DTLS version 1.0 regardless of * the version of TLS that is expected to be negotiated. DTLS 1.2 and 1.0 clients MUST use * the version solely to indicate packet formatting (which is the same in both DTLS 1.2 and * 1.0) and not as part of version negotiation. */ if (!recordLayerVersion.IsEqualOrEarlierVersionOf(client_version)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } byte[] cookie = ProcessHelloVerifyRequest(state, serverMessage.Body); byte[] patched = PatchClientHelloWithCookie(clientHelloBody, cookie); handshake.ResetHandshakeMessagesDigest(); handshake.SendMessage(HandshakeType.client_hello, patched); serverMessage = handshake.ReceiveMessage(); } if (serverMessage.Type == HandshakeType.server_hello) { ReportServerVersion(state, recordLayer.DiscoveredPeerVersion); ProcessServerHello(state, serverMessage.Body); } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } if (state.maxFragmentLength >= 0) { int plainTextLimit = 1 << (8 + state.maxFragmentLength); recordLayer.SetPlaintextLimit(plainTextLimit); } securityParameters.cipherSuite = state.selectedCipherSuite; securityParameters.compressionAlgorithm = (byte)state.selectedCompressionMethod; securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, state.selectedCipherSuite); /* * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has * a verify_data_length equal to 12. This includes all existing cipher suites. */ securityParameters.verifyDataLength = 12; handshake.NotifyHelloComplete(); bool resumedSession = state.selectedSessionID.Length > 0 && state.tlsSession != null && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID); if (resumedSession) { if (securityParameters.CipherSuite != state.sessionParameters.CipherSuite || securityParameters.CompressionAlgorithm != state.sessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } IDictionary sessionServerExtensions = state.sessionParameters.ReadServerExtensions(); securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); securityParameters.masterSecret = Arrays.Clone(state.sessionParameters.MasterSecret); recordLayer.InitPendingEpoch(state.client.GetCipher()); // NOTE: Calculated exclusive of the actual Finished message from the server byte[] resExpectedServerVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext, ExporterLabel.server_finished, TlsProtocol.GetCurrentPrfHash(state.clientContext, handshake.HandshakeHash, null)); ProcessFinished(handshake.ReceiveMessageBody(HandshakeType.finished), resExpectedServerVerifyData); // NOTE: Calculated exclusive of the Finished message itself byte[] resClientVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext, ExporterLabel.client_finished, TlsProtocol.GetCurrentPrfHash(state.clientContext, handshake.HandshakeHash, null)); handshake.SendMessage(HandshakeType.finished, resClientVerifyData); handshake.Finish(); state.clientContext.SetResumableSession(state.tlsSession); state.client.NotifyHandshakeComplete(); return(new DtlsTransport(recordLayer)); } InvalidateSession(state); if (state.selectedSessionID.Length > 0) { state.tlsSession = new TlsSessionImpl(state.selectedSessionID, null); } serverMessage = handshake.ReceiveMessage(); if (serverMessage.Type == HandshakeType.supplemental_data) { ProcessServerSupplementalData(state, serverMessage.Body); serverMessage = handshake.ReceiveMessage(); } else { state.client.ProcessServerSupplementalData(null); } state.keyExchange = state.client.GetKeyExchange(); state.keyExchange.Init(state.clientContext); Certificate serverCertificate = null; if (serverMessage.Type == HandshakeType.certificate) { serverCertificate = ProcessServerCertificate(state, serverMessage.Body); serverMessage = handshake.ReceiveMessage(); } else { // Okay, Certificate is optional state.keyExchange.SkipServerCredentials(); } // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus if (serverCertificate == null || serverCertificate.IsEmpty) { state.allowCertificateStatus = false; } if (serverMessage.Type == HandshakeType.certificate_status) { ProcessCertificateStatus(state, serverMessage.Body); serverMessage = handshake.ReceiveMessage(); } else { // Okay, CertificateStatus is optional } if (serverMessage.Type == HandshakeType.server_key_exchange) { ProcessServerKeyExchange(state, serverMessage.Body); serverMessage = handshake.ReceiveMessage(); } else { // Okay, ServerKeyExchange is optional state.keyExchange.SkipServerKeyExchange(); } if (serverMessage.Type == HandshakeType.certificate_request) { ProcessCertificateRequest(state, serverMessage.Body); /* * TODO Give the client a chance to immediately select the CertificateVerify hash * algorithm here to avoid tracking the other hash algorithms unnecessarily? */ TlsUtilities.TrackHashAlgorithms(handshake.HandshakeHash, state.certificateRequest.SupportedSignatureAlgorithms); serverMessage = handshake.ReceiveMessage(); } else { // Okay, CertificateRequest is optional } if (serverMessage.Type == HandshakeType.server_hello_done) { if (serverMessage.Body.Length != 0) { throw new TlsFatalAlert(AlertDescription.decode_error); } } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } handshake.HandshakeHash.SealHashAlgorithms(); IList clientSupplementalData = state.client.GetClientSupplementalData(); if (clientSupplementalData != null) { byte[] supplementalDataBody = GenerateSupplementalData(clientSupplementalData); handshake.SendMessage(HandshakeType.supplemental_data, supplementalDataBody); } if (state.certificateRequest != null) { state.clientCredentials = state.authentication.GetClientCredentials(state.certificateRequest); /* * 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. */ Certificate clientCertificate = null; if (state.clientCredentials != null) { clientCertificate = state.clientCredentials.Certificate; } if (clientCertificate == null) { clientCertificate = Certificate.EmptyChain; } byte[] certificateBody = GenerateCertificate(clientCertificate); handshake.SendMessage(HandshakeType.certificate, certificateBody); } if (state.clientCredentials != null) { state.keyExchange.ProcessClientCredentials(state.clientCredentials); } else { state.keyExchange.SkipClientCredentials(); } byte[] clientKeyExchangeBody = GenerateClientKeyExchange(state); handshake.SendMessage(HandshakeType.client_key_exchange, clientKeyExchangeBody); TlsHandshakeHash prepareFinishHash = handshake.PrepareToFinish(); securityParameters.sessionHash = TlsProtocol.GetCurrentPrfHash(state.clientContext, prepareFinishHash, null); TlsProtocol.EstablishMasterSecret(state.clientContext, state.keyExchange); recordLayer.InitPendingEpoch(state.client.GetCipher()); if (state.clientCredentials != null && state.clientCredentials is TlsSignerCredentials) { TlsSignerCredentials signerCredentials = (TlsSignerCredentials)state.clientCredentials; /* * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2 */ SignatureAndHashAlgorithm signatureAndHashAlgorithm; byte[] hash; if (TlsUtilities.IsTlsV12(state.clientContext)) { signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm; if (signatureAndHashAlgorithm == null) { throw new TlsFatalAlert(AlertDescription.internal_error); } hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash); } else { signatureAndHashAlgorithm = null; hash = securityParameters.SessionHash; } byte[] signature = signerCredentials.GenerateCertificateSignature(hash); DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature); byte[] certificateVerifyBody = GenerateCertificateVerify(state, certificateVerify); handshake.SendMessage(HandshakeType.certificate_verify, certificateVerifyBody); } // NOTE: Calculated exclusive of the Finished message itself byte[] clientVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext, ExporterLabel.client_finished, TlsProtocol.GetCurrentPrfHash(state.clientContext, handshake.HandshakeHash, null)); handshake.SendMessage(HandshakeType.finished, clientVerifyData); if (state.expectSessionTicket) { serverMessage = handshake.ReceiveMessage(); if (serverMessage.Type == HandshakeType.session_ticket) { ProcessNewSessionTicket(state, serverMessage.Body); } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } } // NOTE: Calculated exclusive of the actual Finished message from the server byte[] expectedServerVerifyData = TlsUtilities.CalculateVerifyData(state.clientContext, ExporterLabel.server_finished, TlsProtocol.GetCurrentPrfHash(state.clientContext, handshake.HandshakeHash, null)); ProcessFinished(handshake.ReceiveMessageBody(HandshakeType.finished), expectedServerVerifyData); handshake.Finish(); if (state.tlsSession != null) { state.sessionParameters = new SessionParameters.Builder() .SetCipherSuite(securityParameters.cipherSuite) .SetCompressionAlgorithm(securityParameters.compressionAlgorithm) .SetMasterSecret(securityParameters.masterSecret) .SetPeerCertificate(serverCertificate) .SetPskIdentity(securityParameters.pskIdentity) .Build(); state.tlsSession = TlsUtilities.ImportSession(state.tlsSession.SessionID, state.sessionParameters); state.clientContext.SetResumableSession(state.tlsSession); } state.client.NotifyHandshakeComplete(); return(new DtlsTransport(recordLayer)); }
protected virtual byte[] GenerateServerHello(ServerHandshakeState state) { SecurityParameters securityParameters = state.serverContext.SecurityParameters; MemoryStream buf = new MemoryStream(); { ProtocolVersion server_version = state.server.GetServerVersion(); if (!server_version.IsEqualOrEarlierVersionOf(state.serverContext.ClientVersion)) { throw new TlsFatalAlert(AlertDescription.internal_error); } // TODO Read RFCs for guidance on the expected record layer version number // recordStream.setReadVersion(server_version); // recordStream.setWriteVersion(server_version); // recordStream.setRestrictReadVersion(true); state.serverContext.SetServerVersion(server_version); TlsUtilities.WriteVersion(state.serverContext.ServerVersion, buf); } buf.Write(securityParameters.ServerRandom, 0, securityParameters.ServerRandom.Length); /* * The server may return an empty session_id to indicate that the session will not be cached * and therefore cannot be resumed. */ TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, buf); int selectedCipherSuite = state.server.GetSelectedCipherSuite(); if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.serverContext.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.internal_error); } ValidateSelectedCipherSuite(selectedCipherSuite, AlertDescription.internal_error); securityParameters.cipherSuite = selectedCipherSuite; byte selectedCompressionMethod = state.server.GetSelectedCompressionMethod(); if (!Arrays.Contains(state.offeredCompressionMethods, selectedCompressionMethod)) { throw new TlsFatalAlert(AlertDescription.internal_error); } securityParameters.compressionAlgorithm = selectedCompressionMethod; TlsUtilities.WriteUint16(selectedCipherSuite, buf); TlsUtilities.WriteUint8(selectedCompressionMethod, buf); state.serverExtensions = state.server.GetServerExtensions(); /* * RFC 5746 3.6. Server Behavior: Initial Handshake */ if (state.secure_renegotiation) { byte[] renegExtData = TlsUtilities.GetExtensionData(state.serverExtensions, ExtensionType.renegotiation_info); bool noRenegExt = (null == renegExtData); if (noRenegExt) { /* * Note that sending a "renegotiation_info" extension in response to a ClientHello * containing only the SCSV is an explicit exception to the prohibition in RFC 5246, * Section 7.4.1.4, on the server sending unsolicited extensions and is only allowed * because the client is signaling its willingness to receive the extension via the * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. */ /* * If the secure_renegotiation flag is set to TRUE, the server MUST include an empty * "renegotiation_info" extension in the ServerHello message. */ state.serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(state.serverExtensions); state.serverExtensions[ExtensionType.renegotiation_info] = TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes); } } if (securityParameters.extendedMasterSecret) { state.serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(state.serverExtensions); TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.serverExtensions); } /* * 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. */ if (state.serverExtensions != null) { securityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(state.serverExtensions); securityParameters.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.resumedSession, state.clientExtensions, state.serverExtensions, AlertDescription.internal_error); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(state.serverExtensions); /* * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in * a session resumption handshake. */ state.allowCertificateStatus = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, ExtensionType.status_request, AlertDescription.internal_error); state.expectSessionTicket = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, ExtensionType.session_ticket, AlertDescription.internal_error); TlsProtocol.WriteExtensions(buf, state.serverExtensions); } securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.serverContext, securityParameters.CipherSuite); /* * RFC 5246 7.4.9. Any cipher suite which does not explicitly specify verify_data_length * has a verify_data_length equal to 12. This includes all existing cipher suites. */ securityParameters.verifyDataLength = 12; return(buf.ToArray()); }
protected virtual void SendServerHelloMessage() { TlsProtocol.HandshakeMessage handshakeMessage = new TlsProtocol.HandshakeMessage(2); ProtocolVersion serverVersion = this.mTlsServer.GetServerVersion(); if (!serverVersion.IsEqualOrEarlierVersionOf(this.Context.ClientVersion)) { throw new TlsFatalAlert(80); } this.mRecordStream.ReadVersion = serverVersion; this.mRecordStream.SetWriteVersion(serverVersion); this.mRecordStream.SetRestrictReadVersion(true); this.ContextAdmin.SetServerVersion(serverVersion); TlsUtilities.WriteVersion(serverVersion, handshakeMessage); handshakeMessage.Write(this.mSecurityParameters.serverRandom); TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, handshakeMessage); int selectedCipherSuite = this.mTlsServer.GetSelectedCipherSuite(); if (!Arrays.Contains(this.mOfferedCipherSuites, selectedCipherSuite) || selectedCipherSuite == 0 || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, this.Context.ServerVersion)) { throw new TlsFatalAlert(80); } this.mSecurityParameters.cipherSuite = selectedCipherSuite; byte selectedCompressionMethod = this.mTlsServer.GetSelectedCompressionMethod(); if (!Arrays.Contains(this.mOfferedCompressionMethods, selectedCompressionMethod)) { throw new TlsFatalAlert(80); } this.mSecurityParameters.compressionAlgorithm = selectedCompressionMethod; TlsUtilities.WriteUint16(selectedCipherSuite, handshakeMessage); TlsUtilities.WriteUint8(selectedCompressionMethod, handshakeMessage); this.mServerExtensions = this.mTlsServer.GetServerExtensions(); if (this.mSecureRenegotiation) { byte[] extensionData = TlsUtilities.GetExtensionData(this.mServerExtensions, 65281); bool flag = null == extensionData; if (flag) { this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(this.mServerExtensions); this.mServerExtensions[65281] = TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes); } } if (this.mSecurityParameters.extendedMasterSecret) { this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(this.mServerExtensions); TlsExtensionsUtilities.AddExtendedMasterSecretExtension(this.mServerExtensions); } if (this.mServerExtensions != null) { this.mSecurityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(this.mServerExtensions); this.mSecurityParameters.maxFragmentLength = this.ProcessMaxFragmentLengthExtension(this.mClientExtensions, this.mServerExtensions, 80); this.mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(this.mServerExtensions); this.mAllowCertificateStatus = (!this.mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(this.mServerExtensions, 5, 80)); this.mExpectSessionTicket = (!this.mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(this.mServerExtensions, 35, 80)); TlsProtocol.WriteExtensions(handshakeMessage, this.mServerExtensions); } this.mSecurityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(this.Context, this.mSecurityParameters.CipherSuite); this.mSecurityParameters.verifyDataLength = 12; this.ApplyMaxFragmentLengthExtension(); handshakeMessage.WriteToRecordStream(this); }
protected virtual void ProcessServerHello(ClientHandshakeState state, byte[] body) { SecurityParameters securityParameters = state.clientContext.SecurityParameters; MemoryStream buf = new MemoryStream(body, false); { ProtocolVersion server_version = TlsUtilities.ReadVersion(buf); ReportServerVersion(state, server_version); } securityParameters.serverRandom = TlsUtilities.ReadFully(32, buf); state.selectedSessionID = TlsUtilities.ReadOpaque8(buf); if (state.selectedSessionID.Length > 32) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } state.client.NotifySessionID(state.selectedSessionID); state.resumedSession = state.selectedSessionID.Length > 0 && state.tlsSession != null && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID); int selectedCipherSuite = TlsUtilities.ReadUint16(buf); if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.clientContext.ServerVersion)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } ValidateSelectedCipherSuite(selectedCipherSuite, AlertDescription.illegal_parameter); state.client.NotifySelectedCipherSuite(selectedCipherSuite); byte selectedCompressionMethod = TlsUtilities.ReadUint8(buf); if (!Arrays.Contains(state.offeredCompressionMethods, selectedCompressionMethod)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } state.client.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. */ // Integer -> byte[] state.serverExtensions = TlsProtocol.ReadExtensions(buf); /* * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an * extended client hello message. However, see RFC 5746 exception below. We always include * the SCSV, so an Extended Server Hello is always allowed. */ if (state.serverExtensions != null) { foreach (int extType in state.serverExtensions.Keys) { /* * RFC 5746 3.6. Note that sending a "renegotiation_info" extension in response to a * ClientHello containing only the SCSV is an explicit exception to the prohibition * in RFC 5246, Section 7.4.1.4, on the server sending unsolicited extensions and is * only allowed because the client is signaling its willingness to receive the * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. */ if (extType == ExtensionType.renegotiation_info) { continue; } /* * RFC 5246 7.4.1.4 An extension type MUST NOT appear in the ServerHello unless the * same extension type appeared in the corresponding ClientHello. If a client * receives an extension type in ServerHello that it did not request in the * associated ClientHello, it MUST abort the handshake with an unsupported_extension * fatal alert. */ if (null == TlsUtilities.GetExtensionData(state.clientExtensions, extType)) { throw new TlsFatalAlert(AlertDescription.unsupported_extension); } /* * 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[.] */ if (state.resumedSession) { // TODO[compat-gnutls] GnuTLS test server sends server extensions e.g. ec_point_formats // TODO[compat-openssl] OpenSSL test server sends server extensions e.g. ec_point_formats // TODO[compat-polarssl] PolarSSL test server sends server extensions e.g. ec_point_formats //throw new TlsFatalAlert(AlertDescription.illegal_parameter); } } } /* * RFC 5746 3.4. Client Behavior: Initial Handshake */ { /* * When a ServerHello is received, the client MUST check if it includes the * "renegotiation_info" extension: */ byte[] renegExtData = TlsUtilities.GetExtensionData(state.serverExtensions, ExtensionType.renegotiation_info); if (renegExtData != null) { /* * 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). */ state.secure_renegotiation = true; if (!Arrays.ConstantTimeAreEqual(renegExtData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } } } // TODO[compat-gnutls] GnuTLS test server fails to send renegotiation_info extension when resuming state.client.NotifySecureRenegotiation(state.secure_renegotiation); IDictionary sessionClientExtensions = state.clientExtensions, sessionServerExtensions = state.serverExtensions; if (state.resumedSession) { if (selectedCipherSuite != state.sessionParameters.CipherSuite || selectedCompressionMethod != state.sessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } sessionClientExtensions = null; sessionServerExtensions = state.sessionParameters.ReadServerExtensions(); } securityParameters.cipherSuite = selectedCipherSuite; securityParameters.compressionAlgorithm = selectedCompressionMethod; if (sessionServerExtensions != null) { { /* * RFC 7366 3. If a server receives an encrypt-then-MAC request extension from a client * and then selects a stream or Authenticated Encryption with Associated Data (AEAD) * ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the * client. */ bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(sessionServerExtensions); if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite)) { throw new TlsFatalAlert(AlertDescription.illegal_parameter); } securityParameters.encryptThenMac = serverSentEncryptThenMAC; } securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions); securityParameters.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.resumedSession, sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(sessionServerExtensions); /* * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be * sent in a session resumption handshake. */ state.allowCertificateStatus = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.status_request, AlertDescription.illegal_parameter); state.expectSessionTicket = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.session_ticket, AlertDescription.illegal_parameter); } /* * TODO[session-hash] * * draft-ietf-tls-session-hash-04 4. Clients and servers SHOULD NOT accept handshakes * that do not use the extended master secret [..]. (and see 5.2, 5.3) */ if (sessionClientExtensions != null) { state.client.ProcessServerExtensions(sessionServerExtensions); } securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, securityParameters.CipherSuite); /* * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has * a verify_data_length equal to 12. This includes all existing cipher suites. */ securityParameters.verifyDataLength = 12; }
protected virtual byte[] GenerateServerHello(ServerHandshakeState state) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown SecurityParameters securityParameters = state.serverContext.SecurityParameters; MemoryStream val = new MemoryStream(); ProtocolVersion serverVersion = state.server.GetServerVersion(); if (!serverVersion.IsEqualOrEarlierVersionOf(state.serverContext.ClientVersion)) { throw new TlsFatalAlert(80); } state.serverContext.SetServerVersion(serverVersion); TlsUtilities.WriteVersion(state.serverContext.ServerVersion, (Stream)(object)val); ((Stream)val).Write(securityParameters.ServerRandom, 0, securityParameters.ServerRandom.Length); TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, (Stream)(object)val); int selectedCipherSuite = state.server.GetSelectedCipherSuite(); if (!Arrays.Contains(state.offeredCipherSuites, selectedCipherSuite) || selectedCipherSuite == 0 || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, state.serverContext.ServerVersion)) { throw new TlsFatalAlert(80); } DtlsProtocol.ValidateSelectedCipherSuite(selectedCipherSuite, 80); securityParameters.cipherSuite = selectedCipherSuite; byte selectedCompressionMethod = state.server.GetSelectedCompressionMethod(); if (!Arrays.Contains(state.offeredCompressionMethods, selectedCompressionMethod)) { throw new TlsFatalAlert(80); } securityParameters.compressionAlgorithm = selectedCompressionMethod; TlsUtilities.WriteUint16(selectedCipherSuite, (Stream)(object)val); TlsUtilities.WriteUint8(selectedCompressionMethod, (Stream)(object)val); state.serverExtensions = state.server.GetServerExtensions(); if (state.secure_renegotiation) { byte[] extensionData = TlsUtilities.GetExtensionData(state.serverExtensions, 65281); if (null == extensionData) { state.serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(state.serverExtensions); state.serverExtensions.set_Item((object)65281, (object)TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)); } } if (securityParameters.extendedMasterSecret) { state.serverExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(state.serverExtensions); TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.serverExtensions); } if (state.serverExtensions != null) { securityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(state.serverExtensions); securityParameters.maxFragmentLength = DtlsProtocol.EvaluateMaxFragmentLengthExtension(state.resumedSession, state.clientExtensions, state.serverExtensions, 80); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(state.serverExtensions); state.allowCertificateStatus = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, 5, 80); state.expectSessionTicket = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(state.serverExtensions, 35, 80); TlsProtocol.WriteExtensions((Stream)(object)val, state.serverExtensions); } securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.serverContext, securityParameters.CipherSuite); securityParameters.verifyDataLength = 12; return(val.ToArray()); }
protected virtual void ProcessServerHello(DtlsClientProtocol.ClientHandshakeState state, byte[] body) { SecurityParameters securityParameters = state.clientContext.SecurityParameters; MemoryStream input = new MemoryStream(body, false); ProtocolVersion server_version = TlsUtilities.ReadVersion(input); this.ReportServerVersion(state, server_version); securityParameters.serverRandom = TlsUtilities.ReadFully(32, input); state.selectedSessionID = TlsUtilities.ReadOpaque8(input); if (state.selectedSessionID.Length > 32) { throw new TlsFatalAlert(47); } state.client.NotifySessionID(state.selectedSessionID); state.resumedSession = (state.selectedSessionID.Length > 0 && state.tlsSession != null && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID)); int num = TlsUtilities.ReadUint16(input); if (!Arrays.Contains(state.offeredCipherSuites, num) || num == 0 || CipherSuite.IsScsv(num) || !TlsUtilities.IsValidCipherSuiteForVersion(num, state.clientContext.ServerVersion)) { throw new TlsFatalAlert(47); } DtlsProtocol.ValidateSelectedCipherSuite(num, 47); state.client.NotifySelectedCipherSuite(num); byte b = TlsUtilities.ReadUint8(input); if (!Arrays.Contains(state.offeredCompressionMethods, b)) { throw new TlsFatalAlert(47); } state.client.NotifySelectedCompressionMethod(b); state.serverExtensions = TlsProtocol.ReadExtensions(input); if (state.serverExtensions != null) { foreach (int num2 in state.serverExtensions.Keys) { if (num2 != 65281) { if (TlsUtilities.GetExtensionData(state.clientExtensions, num2) == null) { throw new TlsFatalAlert(110); } bool arg_16B_0 = state.resumedSession; } } } byte[] extensionData = TlsUtilities.GetExtensionData(state.serverExtensions, 65281); if (extensionData != null) { state.secure_renegotiation = true; if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(40); } } state.client.NotifySecureRenegotiation(state.secure_renegotiation); IDictionary dictionary = state.clientExtensions; IDictionary dictionary2 = state.serverExtensions; if (state.resumedSession) { if (num != state.sessionParameters.CipherSuite || b != state.sessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(47); } dictionary = null; dictionary2 = state.sessionParameters.ReadServerExtensions(); } securityParameters.cipherSuite = num; securityParameters.compressionAlgorithm = b; if (dictionary2 != null) { bool flag = TlsExtensionsUtilities.HasEncryptThenMacExtension(dictionary2); if (flag && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite)) { throw new TlsFatalAlert(47); } securityParameters.encryptThenMac = flag; securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(dictionary2); securityParameters.maxFragmentLength = DtlsProtocol.EvaluateMaxFragmentLengthExtension(state.resumedSession, dictionary, dictionary2, 47); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(dictionary2); state.allowCertificateStatus = (!state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 5, 47)); state.expectSessionTicket = (!state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 35, 47)); } if (dictionary != null) { state.client.ProcessServerExtensions(dictionary2); } securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, securityParameters.CipherSuite); securityParameters.verifyDataLength = 12; }
protected virtual void ProcessServerHello(ClientHandshakeState state, byte[] body) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown SecurityParameters securityParameters = state.clientContext.SecurityParameters; MemoryStream input = new MemoryStream(body, false); ProtocolVersion server_version = TlsUtilities.ReadVersion((Stream)(object)input); ReportServerVersion(state, server_version); securityParameters.serverRandom = TlsUtilities.ReadFully(32, (Stream)(object)input); state.selectedSessionID = TlsUtilities.ReadOpaque8((Stream)(object)input); if (state.selectedSessionID.Length > 32) { throw new TlsFatalAlert(47); } state.client.NotifySessionID(state.selectedSessionID); state.resumedSession = state.selectedSessionID.Length > 0 && state.tlsSession != null && Arrays.AreEqual(state.selectedSessionID, state.tlsSession.SessionID); int num = TlsUtilities.ReadUint16((Stream)(object)input); if (!Arrays.Contains(state.offeredCipherSuites, num) || num == 0 || CipherSuite.IsScsv(num) || !TlsUtilities.IsValidCipherSuiteForVersion(num, state.clientContext.ServerVersion)) { throw new TlsFatalAlert(47); } DtlsProtocol.ValidateSelectedCipherSuite(num, 47); state.client.NotifySelectedCipherSuite(num); byte b = TlsUtilities.ReadUint8((Stream)(object)input); if (!Arrays.Contains(state.offeredCompressionMethods, b)) { throw new TlsFatalAlert(47); } state.client.NotifySelectedCompressionMethod(b); state.serverExtensions = TlsProtocol.ReadExtensions(input); if (state.serverExtensions != null) { { global::System.Collections.IEnumerator enumerator = ((global::System.Collections.IEnumerable)state.serverExtensions.get_Keys()).GetEnumerator(); try { while (enumerator.MoveNext()) { int num2 = (int)enumerator.get_Current(); if (num2 != 65281) { if (TlsUtilities.GetExtensionData(state.clientExtensions, num2) == null) { throw new TlsFatalAlert(110); } _ = state.resumedSession; } } } finally { global::System.IDisposable disposable = enumerator as global::System.IDisposable; if (disposable != null) { disposable.Dispose(); } } } } byte[] extensionData = TlsUtilities.GetExtensionData(state.serverExtensions, 65281); if (extensionData != null) { state.secure_renegotiation = true; if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(40); } } state.client.NotifySecureRenegotiation(state.secure_renegotiation); IDictionary val = state.clientExtensions; IDictionary val2 = state.serverExtensions; if (state.resumedSession) { if (num != state.sessionParameters.CipherSuite || b != state.sessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(47); } val = null; val2 = state.sessionParameters.ReadServerExtensions(); } securityParameters.cipherSuite = num; securityParameters.compressionAlgorithm = b; if (val2 != null) { bool flag = TlsExtensionsUtilities.HasEncryptThenMacExtension(val2); if (flag && !TlsUtilities.IsBlockCipherSuite(securityParameters.CipherSuite)) { throw new TlsFatalAlert(47); } securityParameters.encryptThenMac = flag; securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(val2); securityParameters.maxFragmentLength = DtlsProtocol.EvaluateMaxFragmentLengthExtension(state.resumedSession, val, val2, 47); securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(val2); state.allowCertificateStatus = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(val2, 5, 47); state.expectSessionTicket = !state.resumedSession && TlsUtilities.HasExpectedEmptyExtensionData(val2, 35, 47); } if (val != null) { state.client.ProcessServerExtensions(val2); } securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext, securityParameters.CipherSuite); securityParameters.verifyDataLength = 12; }
protected virtual void ReceiveServerHelloMessage(MemoryStream buf) { ProtocolVersion protocolVersion = TlsUtilities.ReadVersion((Stream)(object)buf); if (protocolVersion.IsDtls) { throw new TlsFatalAlert(47); } if (!protocolVersion.Equals(mRecordStream.ReadVersion)) { throw new TlsFatalAlert(47); } ProtocolVersion clientVersion = Context.ClientVersion; if (!protocolVersion.IsEqualOrEarlierVersionOf(clientVersion)) { throw new TlsFatalAlert(47); } mRecordStream.SetWriteVersion(protocolVersion); ContextAdmin.SetServerVersion(protocolVersion); mTlsClient.NotifyServerVersion(protocolVersion); mSecurityParameters.serverRandom = TlsUtilities.ReadFully(32, (Stream)(object)buf); mSelectedSessionID = TlsUtilities.ReadOpaque8((Stream)(object)buf); if (mSelectedSessionID.Length > 32) { throw new TlsFatalAlert(47); } mTlsClient.NotifySessionID(mSelectedSessionID); mResumedSession = mSelectedSessionID.Length > 0 && mTlsSession != null && Arrays.AreEqual(mSelectedSessionID, mTlsSession.SessionID); int num = TlsUtilities.ReadUint16((Stream)(object)buf); if (!Arrays.Contains(mOfferedCipherSuites, num) || num == 0 || CipherSuite.IsScsv(num) || !TlsUtilities.IsValidCipherSuiteForVersion(num, Context.ServerVersion)) { throw new TlsFatalAlert(47); } mTlsClient.NotifySelectedCipherSuite(num); byte b = TlsUtilities.ReadUint8((Stream)(object)buf); if (!Arrays.Contains(mOfferedCompressionMethods, b)) { throw new TlsFatalAlert(47); } mTlsClient.NotifySelectedCompressionMethod(b); mServerExtensions = TlsProtocol.ReadExtensions(buf); if (mServerExtensions != null) { { global::System.Collections.IEnumerator enumerator = ((global::System.Collections.IEnumerable)mServerExtensions.get_Keys()).GetEnumerator(); try { while (enumerator.MoveNext()) { int num2 = (int)enumerator.get_Current(); if (num2 != 65281) { if (TlsUtilities.GetExtensionData(mClientExtensions, num2) == null) { throw new TlsFatalAlert(110); } _ = mResumedSession; } } } finally { global::System.IDisposable disposable = enumerator as global::System.IDisposable; if (disposable != null) { disposable.Dispose(); } } } } byte[] extensionData = TlsUtilities.GetExtensionData(mServerExtensions, 65281); if (extensionData != null) { mSecureRenegotiation = true; if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(40); } } mTlsClient.NotifySecureRenegotiation(mSecureRenegotiation); IDictionary val = mClientExtensions; IDictionary val2 = mServerExtensions; if (mResumedSession) { if (num != mSessionParameters.CipherSuite || b != mSessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(47); } val = null; val2 = mSessionParameters.ReadServerExtensions(); } mSecurityParameters.cipherSuite = num; mSecurityParameters.compressionAlgorithm = b; if (val2 != null) { bool flag = TlsExtensionsUtilities.HasEncryptThenMacExtension(val2); if (flag && !TlsUtilities.IsBlockCipherSuite(num)) { throw new TlsFatalAlert(47); } mSecurityParameters.encryptThenMac = flag; mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(val2); mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(val, val2, 47); mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(val2); mAllowCertificateStatus = !mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(val2, 5, 47); mExpectSessionTicket = !mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(val2, 35, 47); } if (val != null) { mTlsClient.ProcessServerExtensions(val2); } mSecurityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(Context, mSecurityParameters.CipherSuite); mSecurityParameters.verifyDataLength = 12; }
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: After receiving a record from the client, we discover the record layer version ProtocolVersion client_version = recordLayer.DiscoveredPeerVersion; // TODO Read RFCs for guidance on the expected record layer version number state.serverContext.SetClientVersion(client_version); } if (clientMessage.Type == HandshakeType.client_hello) { ProcessClientHello(state, clientMessage.Body); } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } { byte[] serverHelloBody = GenerateServerHello(state); if (state.maxFragmentLength >= 0) { int plainTextLimit = 1 << (8 + state.maxFragmentLength); recordLayer.SetPlaintextLimit(plainTextLimit); } securityParameters.cipherSuite = state.selectedCipherSuite; securityParameters.compressionAlgorithm = (byte)state.selectedCompressionMethod; securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.serverContext, state.selectedCipherSuite); /* * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length * has a verify_data_length equal to 12. This includes all existing cipher suites. */ securityParameters.verifyDataLength = 12; 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) { 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 virtual void ReceiveServerHelloMessage(MemoryStream buf) { ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(buf); if (protocolVersion.IsDtls) { throw new TlsFatalAlert(47); } if (!protocolVersion.Equals(mRecordStream.ReadVersion)) { throw new TlsFatalAlert(47); } ProtocolVersion clientVersion = Context.ClientVersion; if (!protocolVersion.IsEqualOrEarlierVersionOf(clientVersion)) { throw new TlsFatalAlert(47); } mRecordStream.SetWriteVersion(protocolVersion); ContextAdmin.SetServerVersion(protocolVersion); mTlsClient.NotifyServerVersion(protocolVersion); mSecurityParameters.serverRandom = TlsUtilities.ReadFully(32, buf); mSelectedSessionID = TlsUtilities.ReadOpaque8(buf); if (mSelectedSessionID.Length > 32) { throw new TlsFatalAlert(47); } mTlsClient.NotifySessionID(mSelectedSessionID); mResumedSession = (mSelectedSessionID.Length > 0 && mTlsSession != null && Arrays.AreEqual(mSelectedSessionID, mTlsSession.SessionID)); int num = TlsUtilities.ReadUint16(buf); if (!Arrays.Contains(mOfferedCipherSuites, num) || num == 0 || CipherSuite.IsScsv(num) || !TlsUtilities.IsValidCipherSuiteForVersion(num, Context.ServerVersion)) { throw new TlsFatalAlert(47); } mTlsClient.NotifySelectedCipherSuite(num); byte b = TlsUtilities.ReadUint8(buf); if (!Arrays.Contains(mOfferedCompressionMethods, b)) { throw new TlsFatalAlert(47); } mTlsClient.NotifySelectedCompressionMethod(b); mServerExtensions = TlsProtocol.ReadExtensions(buf); if (mServerExtensions != null) { foreach (int key in mServerExtensions.Keys) { if (key != 65281) { if (TlsUtilities.GetExtensionData(mClientExtensions, key) == null) { throw new TlsFatalAlert(110); } if (!mResumedSession) { } } } } byte[] extensionData = TlsUtilities.GetExtensionData(mServerExtensions, 65281); if (extensionData != null) { mSecureRenegotiation = true; if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(40); } } mTlsClient.NotifySecureRenegotiation(mSecureRenegotiation); IDictionary dictionary = mClientExtensions; IDictionary dictionary2 = mServerExtensions; if (mResumedSession) { if (num != mSessionParameters.CipherSuite || b != mSessionParameters.CompressionAlgorithm) { throw new TlsFatalAlert(47); } dictionary = null; dictionary2 = mSessionParameters.ReadServerExtensions(); } mSecurityParameters.cipherSuite = num; mSecurityParameters.compressionAlgorithm = b; if (dictionary2 != null) { bool flag = TlsExtensionsUtilities.HasEncryptThenMacExtension(dictionary2); if (flag && !TlsUtilities.IsBlockCipherSuite(num)) { throw new TlsFatalAlert(47); } mSecurityParameters.encryptThenMac = flag; mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(dictionary2); mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(dictionary, dictionary2, 47); mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(dictionary2); mAllowCertificateStatus = (!mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 5, 47)); mExpectSessionTicket = (!mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(dictionary2, 35, 47)); } if (dictionary != null) { mTlsClient.ProcessServerExtensions(dictionary2); } mSecurityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(Context, mSecurityParameters.CipherSuite); mSecurityParameters.verifyDataLength = 12; }
protected virtual void ReceiveServerHelloMessage(MemoryStream buf) { ProtocolVersion writeVersion = TlsUtilities.ReadVersion(buf); if (writeVersion.IsDtls) { throw new TlsFatalAlert(0x2f); } if (!writeVersion.Equals(base.mRecordStream.ReadVersion)) { throw new TlsFatalAlert(0x2f); } ProtocolVersion clientVersion = this.Context.ClientVersion; if (!writeVersion.IsEqualOrEarlierVersionOf(clientVersion)) { throw new TlsFatalAlert(0x2f); } base.mRecordStream.SetWriteVersion(writeVersion); this.ContextAdmin.SetServerVersion(writeVersion); this.mTlsClient.NotifyServerVersion(writeVersion); base.mSecurityParameters.serverRandom = TlsUtilities.ReadFully(0x20, buf); this.mSelectedSessionID = TlsUtilities.ReadOpaque8(buf); if (this.mSelectedSessionID.Length > 0x20) { throw new TlsFatalAlert(0x2f); } this.mTlsClient.NotifySessionID(this.mSelectedSessionID); base.mResumedSession = ((this.mSelectedSessionID.Length > 0) && (base.mTlsSession != null)) && Arrays.AreEqual(this.mSelectedSessionID, base.mTlsSession.SessionID); int n = TlsUtilities.ReadUint16(buf); if ((!Arrays.Contains(base.mOfferedCipherSuites, n) || (n == 0)) || (CipherSuite.IsScsv(n) || !TlsUtilities.IsValidCipherSuiteForVersion(n, this.Context.ServerVersion))) { throw new TlsFatalAlert(0x2f); } this.mTlsClient.NotifySelectedCipherSuite(n); byte num2 = TlsUtilities.ReadUint8(buf); if (!Arrays.Contains(base.mOfferedCompressionMethods, num2)) { throw new TlsFatalAlert(0x2f); } this.mTlsClient.NotifySelectedCompressionMethod(num2); base.mServerExtensions = TlsProtocol.ReadExtensions(buf); if (base.mServerExtensions != null) { IEnumerator enumerator = base.mServerExtensions.Keys.GetEnumerator(); try { while (enumerator.MoveNext()) { int current = (int)enumerator.Current; if (current != 0xff01) { if (TlsUtilities.GetExtensionData(base.mClientExtensions, current) == null) { throw new TlsFatalAlert(110); } if (base.mResumedSession) { } } } } finally { if (enumerator is IDisposable disposable) { IDisposable disposable; disposable.Dispose(); } } } byte[] extensionData = TlsUtilities.GetExtensionData(base.mServerExtensions, 0xff01); if (extensionData != null) { base.mSecureRenegotiation = true; if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes))) { throw new TlsFatalAlert(40); } } this.mTlsClient.NotifySecureRenegotiation(base.mSecureRenegotiation); IDictionary mClientExtensions = base.mClientExtensions; IDictionary mServerExtensions = base.mServerExtensions; if (base.mResumedSession) { if ((n != base.mSessionParameters.CipherSuite) || (num2 != base.mSessionParameters.CompressionAlgorithm)) { throw new TlsFatalAlert(0x2f); } mClientExtensions = null; mServerExtensions = base.mSessionParameters.ReadServerExtensions(); } base.mSecurityParameters.cipherSuite = n; base.mSecurityParameters.compressionAlgorithm = num2; if (mServerExtensions != null) { bool flag = TlsExtensionsUtilities.HasEncryptThenMacExtension(mServerExtensions); if (flag && !TlsUtilities.IsBlockCipherSuite(n)) { throw new TlsFatalAlert(0x2f); } base.mSecurityParameters.encryptThenMac = flag; base.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mServerExtensions); base.mSecurityParameters.maxFragmentLength = this.ProcessMaxFragmentLengthExtension(mClientExtensions, mServerExtensions, 0x2f); base.mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(mServerExtensions); base.mAllowCertificateStatus = !base.mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, 5, 0x2f); base.mExpectSessionTicket = !base.mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, 0x23, 0x2f); } if (mClientExtensions != null) { this.mTlsClient.ProcessServerExtensions(mServerExtensions); } base.mSecurityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(this.Context, base.mSecurityParameters.CipherSuite); base.mSecurityParameters.verifyDataLength = 12; }