protected virtual void SendCertificateMessage(Certificate certificate)
        {
            if (certificate == null)
            {
                certificate = Certificate.EmptyChain;
            }

            if (certificate.IsEmpty)
            {
                TlsContext context = Context;
                if (!context.IsServer)
                {
                    ProtocolVersion serverVersion = Context.ServerVersion;
                    if (serverVersion.IsSsl)
                    {
                        string errorMessage = serverVersion.ToString() + " client didn't provide credentials";
                        RaiseWarning(AlertDescription.no_certificate, errorMessage);
                        return;
                    }
                }
            }

            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate);

            certificate.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendClientKeyExchangeMessage()
        {
            HandshakeMessage handshakeMessage = new HandshakeMessage(16);

            mKeyExchange.GenerateClientKeyExchange((Stream)(object)handshakeMessage);
            handshakeMessage.WriteToRecordStream(this);
        }
        protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify)
        {
            HandshakeMessage handshakeMessage = new HandshakeMessage(15);

            certificateVerify.Encode((Stream)(object)handshakeMessage);
            handshakeMessage.WriteToRecordStream(this);
        }
Beispiel #4
0
    protected virtual void SendSupplementalDataMessage(IList supplementalData)
    {
        HandshakeMessage handshakeMessage = new HandshakeMessage(23);

        WriteSupplementalData(handshakeMessage, supplementalData);
        handshakeMessage.WriteToRecordStream(this);
    }
Beispiel #5
0
        protected virtual void SendCertificateMessage(Certificate certificate)
        {
            if (certificate == null)
            {
                certificate = Certificate.EmptyChain;
            }
            if (certificate.IsEmpty)
            {
                TlsContext context = Context;
                if (!context.IsServer)
                {
                    ProtocolVersion serverVersion = Context.ServerVersion;
                    if (serverVersion.IsSsl)
                    {
                        string message = serverVersion.ToString() + " client didn't provide credentials";
                        RaiseWarning(41, message);
                        return;
                    }
                }
            }
            HandshakeMessage handshakeMessage = new HandshakeMessage(11);

            certificate.Encode((Stream)(object)handshakeMessage);
            handshakeMessage.WriteToRecordStream(this);
        }
    protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus)
    {
        HandshakeMessage handshakeMessage = new HandshakeMessage(22);

        certificateStatus.Encode(handshakeMessage);
        handshakeMessage.WriteToRecordStream(this);
    }
Beispiel #7
0
        protected virtual void SendSupplementalDataMessage(global::System.Collections.IList supplementalData)
        {
            HandshakeMessage handshakeMessage = new HandshakeMessage(23);

            WriteSupplementalData((Stream)(object)handshakeMessage, supplementalData);
            handshakeMessage.WriteToRecordStream(this);
        }
Beispiel #8
0
        protected virtual void SendCertificateMessage(Certificate certificate)
        {
            if (certificate == null)
            {
                certificate = Certificate.EmptyChain;
            }

            if (certificate.IsEmpty)
            {
                TlsContext context = Context;
                if (!context.IsServer)
                {
                    ProtocolVersion serverVersion = Context.ServerVersion;
                    if (serverVersion.IsSsl)
                    {
                        string errorMessage = serverVersion.ToString() + " client didn't provide credentials";
                        RaiseWarning(AlertDescription.no_certificate, errorMessage);
                        return;
                    }
                }
            }

            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate);

            certificate.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendSupplementalDataMessage(IList supplementalData)
        {
            HandshakeMessage output = new HandshakeMessage(0x17);

            WriteSupplementalData(output, supplementalData);
            output.WriteToRecordStream(this);
        }
    protected virtual void SendCertificateRequestMessage(CertificateRequest certificateRequest)
    {
        HandshakeMessage handshakeMessage = new HandshakeMessage(13);

        certificateRequest.Encode(handshakeMessage);
        handshakeMessage.WriteToRecordStream(this);
    }
    protected virtual void SendServerKeyExchangeMessage(byte[] serverKeyExchange)
    {
        HandshakeMessage handshakeMessage = new HandshakeMessage(12, serverKeyExchange.Length);

        handshakeMessage.Write(serverKeyExchange);
        handshakeMessage.WriteToRecordStream(this);
    }
Beispiel #12
0
    protected virtual void SendFinishedMessage()
    {
        byte[]           array            = CreateVerifyData(Context.IsServer);
        HandshakeMessage handshakeMessage = new HandshakeMessage(20, array.Length);

        handshakeMessage.Write(array, 0, array.Length);
        handshakeMessage.WriteToRecordStream(this);
    }
Beispiel #13
0
        protected virtual void SendCertificateRequestMessage(CertificateRequest certificateRequest)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_request);

            certificateRequest.Encode(message);

            message.WriteToRecordStream(this);
        }
Beispiel #14
0
        protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_status);

            certificateStatus.Encode(message);

            message.WriteToRecordStream(this);
        }
Beispiel #15
0
        protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_verify);

            certificateVerify.Encode(message);

            message.WriteToRecordStream(this);
        }
Beispiel #16
0
        protected virtual void SendServerKeyExchangeMessage(byte[] serverKeyExchange)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.server_key_exchange, serverKeyExchange.Length);

            message.Write(serverKeyExchange);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendFinishedMessage()
        {
            byte[]           buffer  = this.CreateVerifyData(this.Context.IsServer);
            HandshakeMessage message = new HandshakeMessage(20, buffer.Length);

            message.Write(buffer, 0, buffer.Length);
            message.WriteToRecordStream(this);
        }
Beispiel #18
0
        protected virtual void SendSupplementalDataMessage(IList supplementalData)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.supplemental_data);

            WriteSupplementalData(message, supplementalData);

            message.WriteToRecordStream(this);
        }
Beispiel #19
0
        protected virtual void SendClientKeyExchangeMessage()
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.client_key_exchange);

            this.mKeyExchange.GenerateClientKeyExchange(message);

            message.WriteToRecordStream(this);
        }
Beispiel #20
0
        protected virtual void SendFinishedMessage()
        {
            byte[] verify_data = CreateVerifyData(Context.IsServer);

            HandshakeMessage message = new HandshakeMessage(HandshakeType.finished, verify_data.Length);

            message.Write(verify_data, 0, verify_data.Length);

            message.WriteToRecordStream(this);
        }
    protected virtual void SendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
    {
        if (newSessionTicket == null)
        {
            throw new TlsFatalAlert(80);
        }
        HandshakeMessage handshakeMessage = new HandshakeMessage(4);

        newSessionTicket.Encode(handshakeMessage);
        handshakeMessage.WriteToRecordStream(this);
    }
        protected virtual void SendClientHelloMessage()
        {
            mRecordStream.SetWriteVersion(mTlsClient.ClientHelloRecordLayerVersion);
            ProtocolVersion clientVersion = mTlsClient.ClientVersion;

            if (clientVersion.IsDtls)
            {
                throw new TlsFatalAlert(80);
            }
            ContextAdmin.SetClientVersion(clientVersion);
            byte[] array = TlsUtilities.EmptyBytes;
            if (mTlsSession != null)
            {
                array = mTlsSession.SessionID;
                if (array == null || array.Length > 32)
                {
                    array = TlsUtilities.EmptyBytes;
                }
            }
            bool isFallback = mTlsClient.IsFallback;

            mOfferedCipherSuites       = mTlsClient.GetCipherSuites();
            mOfferedCompressionMethods = mTlsClient.GetCompressionMethods();
            if (array.Length > 0 && mSessionParameters != null && (!Arrays.Contains(mOfferedCipherSuites, mSessionParameters.CipherSuite) || !Arrays.Contains(mOfferedCompressionMethods, mSessionParameters.CompressionAlgorithm)))
            {
                array = TlsUtilities.EmptyBytes;
            }
            mClientExtensions = mTlsClient.GetClientExtensions();
            HandshakeMessage handshakeMessage = new HandshakeMessage(1);

            TlsUtilities.WriteVersion(clientVersion, (Stream)(object)handshakeMessage);
            handshakeMessage.Write(mSecurityParameters.ClientRandom);
            TlsUtilities.WriteOpaque8(array, (Stream)(object)handshakeMessage);
            byte[] extensionData = TlsUtilities.GetExtensionData(mClientExtensions, 65281);
            bool   flag          = null == extensionData;
            bool   flag2         = !Arrays.Contains(mOfferedCipherSuites, 255);

            if (flag && flag2)
            {
                mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, 255);
            }
            if (isFallback && !Arrays.Contains(mOfferedCipherSuites, 22016))
            {
                mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, 22016);
            }
            TlsUtilities.WriteUint16ArrayWithUint16Length(mOfferedCipherSuites, (Stream)(object)handshakeMessage);
            TlsUtilities.WriteUint8ArrayWithUint8Length(mOfferedCompressionMethods, (Stream)(object)handshakeMessage);
            if (mClientExtensions != null)
            {
                TlsProtocol.WriteExtensions((Stream)(object)handshakeMessage, mClientExtensions);
            }
            handshakeMessage.WriteToRecordStream(this);
        }
Beispiel #23
0
        protected virtual void SendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
        {
            if (newSessionTicket == null)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            HandshakeMessage message = new HandshakeMessage(HandshakeType.session_ticket);

            newSessionTicket.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendClientKeyExchangeMessage()
        {
            if (HTTPManager.Logger.Level <= Loglevels.All)
            {
                HTTPManager.Logger.Verbose("TlsClientProtocol", "SendClientKeyExchangeMessage", this.LoggingContext);
            }

            HandshakeMessage message = new HandshakeMessage(HandshakeType.client_key_exchange);

            this.mKeyExchange.GenerateClientKeyExchange(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify)
        {
            if (HTTPManager.Logger.Level <= Loglevels.All)
            {
                HTTPManager.Logger.Verbose("TlsClientProtocol", "SendCertificateVerifyMessage", this.LoggingContext);
            }

            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_verify);

            certificateVerify.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendCertificateMessage(Certificate certificate)
        {
            if (certificate == null)
            {
                certificate = Certificate.EmptyChain;
            }
            if (certificate.IsEmpty && !this.Context.IsServer)
            {
                ProtocolVersion serverVersion = this.Context.ServerVersion;
                if (serverVersion.IsSsl)
                {
                    string message = serverVersion.ToString() + " client didn't provide credentials";
                    this.RaiseWarning(0x29, message);
                    return;
                }
            }
            HandshakeMessage output = new HandshakeMessage(11);

            certificate.Encode(output);
            output.WriteToRecordStream(this);
        }
        protected virtual void SendFinishedMessage()
        {
            byte[] verify_data = CreateVerifyData(Context.IsServer);

            HandshakeMessage message = new HandshakeMessage(HandshakeType.finished, verify_data.Length);

            message.Write(verify_data, 0, verify_data.Length);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendSupplementalDataMessage(IList supplementalData)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.supplemental_data);

            WriteSupplementalData(message, supplementalData);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendClientHelloMessage()
        {
            this.mRecordStream.SetWriteVersion(this.mTlsClient.ClientHelloRecordLayerVersion);

            ProtocolVersion client_version = this.mTlsClient.ClientVersion;
            if (client_version.IsDtls)
                throw new TlsFatalAlert(AlertDescription.internal_error);

            ContextAdmin.SetClientVersion(client_version);

            /*
             * TODO RFC 5077 3.4. When presenting a ticket, the client MAY generate and include a
             * Session ID in the TLS ClientHello.
             */
            byte[] session_id = TlsUtilities.EmptyBytes;
            if (this.mTlsSession != null)
            {
                session_id = this.mTlsSession.SessionID;
                if (session_id == null || session_id.Length > 32)
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }

            bool fallback = this.mTlsClient.IsFallback;

            this.mOfferedCipherSuites = this.mTlsClient.GetCipherSuites();

            this.mOfferedCompressionMethods = this.mTlsClient.GetCompressionMethods();

            if (session_id.Length > 0 && this.mSessionParameters != null)
            {
                if (!Arrays.Contains(this.mOfferedCipherSuites, mSessionParameters.CipherSuite)
                    || !Arrays.Contains(this.mOfferedCompressionMethods, mSessionParameters.CompressionAlgorithm))
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }

            this.mClientExtensions = this.mTlsClient.GetClientExtensions();

            HandshakeMessage message = new HandshakeMessage(HandshakeType.client_hello);

            TlsUtilities.WriteVersion(client_version, message);

            message.Write(this.mSecurityParameters.ClientRandom);

            TlsUtilities.WriteOpaque8(session_id, message);

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
                 * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
                 * ClientHello. Including both is NOT RECOMMENDED.
                 */
                byte[] renegExtData = TlsUtilities.GetExtensionData(mClientExtensions, ExtensionType.renegotiation_info);
                bool noRenegExt = (null == renegExtData);

                bool noRenegScsv = !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);

                if (noRenegExt && noRenegScsv)
                {
                    // TODO Consider whether to default to a client extension instead
    //                this.mClientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(this.mClientExtensions);
    //                this.mClientExtensions[ExtensionType.renegotiation_info] = CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
                    this.mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
                }

                /*
                 * draft-ietf-tls-downgrade-scsv-00 4. If a client sends a ClientHello.client_version
                 * containing a lower value than the latest (highest-valued) version supported by the
                 * client, it SHOULD include the TLS_FALLBACK_SCSV cipher suite value in
                 * ClientHello.cipher_suites.
                 */
                if (fallback && !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV))
                {
                    this.mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV);
                }

                TlsUtilities.WriteUint16ArrayWithUint16Length(mOfferedCipherSuites, message);
            }

            TlsUtilities.WriteUint8ArrayWithUint8Length(mOfferedCompressionMethods, message);

            if (mClientExtensions != null)
            {
                WriteExtensions(message, mClientExtensions);
            }

            message.WriteToRecordStream(this);
        }
        protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_verify);

            certificateVerify.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendCertificateRequestMessage(CertificateRequest certificateRequest)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_request);

            certificateRequest.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendClientKeyExchangeMessage()
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.client_key_exchange);

            this.mKeyExchange.GenerateClientKeyExchange(message);

            message.WriteToRecordStream(this);
        }
Beispiel #33
0
        protected virtual void SendServerHelloMessage()
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.server_hello);

            {
                ProtocolVersion server_version = mTlsServer.GetServerVersion();
                if (!server_version.IsEqualOrEarlierVersionOf(Context.ClientVersion))
                {
                    throw new TlsFatalAlert(AlertDescription.internal_error);
                }

                mRecordStream.ReadVersion = server_version;
                mRecordStream.SetWriteVersion(server_version);
                mRecordStream.SetRestrictReadVersion(true);
                ContextAdmin.SetServerVersion(server_version);

                TlsUtilities.WriteVersion(server_version, message);
            }

            message.Write(this.mSecurityParameters.serverRandom);

            /*
             * 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, message);

            int selectedCipherSuite = mTlsServer.GetSelectedCipherSuite();

            if (!Arrays.Contains(mOfferedCipherSuites, selectedCipherSuite) ||
                selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL ||
                CipherSuite.IsScsv(selectedCipherSuite) ||
                !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, Context.ServerVersion))
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }
            mSecurityParameters.cipherSuite = selectedCipherSuite;

            byte selectedCompressionMethod = mTlsServer.GetSelectedCompressionMethod();

            if (!Arrays.Contains(mOfferedCompressionMethods, selectedCompressionMethod))
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }
            mSecurityParameters.compressionAlgorithm = selectedCompressionMethod;

            TlsUtilities.WriteUint16(selectedCipherSuite, message);
            TlsUtilities.WriteUint8(selectedCompressionMethod, message);

            this.mServerExtensions = mTlsServer.GetServerExtensions();

            /*
             * RFC 5746 3.6. Server Behavior: Initial Handshake
             */
            if (this.mSecureRenegotiation)
            {
                byte[] renegExtData = TlsUtilities.GetExtensionData(this.mServerExtensions, 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.
                     */
                    this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
                    this.mServerExtensions[ExtensionType.renegotiation_info] = CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
                }
            }

            if (mSecurityParameters.extendedMasterSecret)
            {
                this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
                TlsExtensionsUtilities.AddExtendedMasterSecretExtension(mServerExtensions);
            }

            /*
             * 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 (this.mServerExtensions != null)
            {
                this.mSecurityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(mServerExtensions);

                this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(mClientExtensions,
                                                                                               mServerExtensions, AlertDescription.internal_error);

                this.mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(mServerExtensions);

                /*
                 * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in
                 * a session resumption handshake.
                 */
                this.mAllowCertificateStatus = !mResumedSession &&
                                               TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, ExtensionType.status_request,
                                                                                          AlertDescription.internal_error);

                this.mExpectSessionTicket = !mResumedSession &&
                                            TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, ExtensionType.session_ticket,
                                                                                       AlertDescription.internal_error);

                WriteExtensions(message, this.mServerExtensions);
            }

            mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, mSecurityParameters.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.
             */
            mSecurityParameters.verifyDataLength = 12;

            ApplyMaxFragmentLengthExtension();

            message.WriteToRecordStream(this);
        }
        protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_status);

            certificateStatus.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
        {
            if (newSessionTicket == null)
                throw new TlsFatalAlert(AlertDescription.internal_error);

            HandshakeMessage message = new HandshakeMessage(HandshakeType.session_ticket);

            newSessionTicket.Encode(message);

            message.WriteToRecordStream(this);
        }
        protected virtual void SendServerHelloMessage()
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.server_hello);

            {
                ProtocolVersion server_version = mTlsServer.GetServerVersion();
                if (!server_version.IsEqualOrEarlierVersionOf(Context.ClientVersion))
                    throw new TlsFatalAlert(AlertDescription.internal_error);

                mRecordStream.ReadVersion = server_version;
                mRecordStream.SetWriteVersion(server_version);
                mRecordStream.SetRestrictReadVersion(true);
                ContextAdmin.SetServerVersion(server_version);

                TlsUtilities.WriteVersion(server_version, message);
            }

            message.Write(this.mSecurityParameters.serverRandom);

            /*
             * 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, message);

            int selectedCipherSuite = mTlsServer.GetSelectedCipherSuite();
            if (!Arrays.Contains(mOfferedCipherSuites, selectedCipherSuite)
                || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
                || CipherSuite.IsScsv(selectedCipherSuite)
                || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, Context.ServerVersion))
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }
            mSecurityParameters.cipherSuite = selectedCipherSuite;

            byte selectedCompressionMethod = mTlsServer.GetSelectedCompressionMethod();
            if (!Arrays.Contains(mOfferedCompressionMethods, selectedCompressionMethod))
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }
            mSecurityParameters.compressionAlgorithm = selectedCompressionMethod;

            TlsUtilities.WriteUint16(selectedCipherSuite, message);
            TlsUtilities.WriteUint8(selectedCompressionMethod, message);

            this.mServerExtensions = mTlsServer.GetServerExtensions();

            /*
             * RFC 5746 3.6. Server Behavior: Initial Handshake
             */
            if (this.mSecureRenegotiation)
            {
                byte[] renegExtData = TlsUtilities.GetExtensionData(this.mServerExtensions, 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.
                     */
                    this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
                    this.mServerExtensions[ExtensionType.renegotiation_info] = CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
                }
            }

            if (mSecurityParameters.extendedMasterSecret)
            {
                this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
                TlsExtensionsUtilities.AddExtendedMasterSecretExtension(mServerExtensions);
            }

            /*
             * 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 (this.mServerExtensions != null)
            {
                this.mSecurityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(mServerExtensions);

                this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(mClientExtensions,
                    mServerExtensions, AlertDescription.internal_error);

                this.mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(mServerExtensions);

                /*
                 * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in
                 * a session resumption handshake.
                 */
                this.mAllowCertificateStatus = !mResumedSession
                    && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, ExtensionType.status_request,
                        AlertDescription.internal_error);

                this.mExpectSessionTicket = !mResumedSession
                    && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, ExtensionType.session_ticket,
                        AlertDescription.internal_error);

                WriteExtensions(message, this.mServerExtensions);
            }

            mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, mSecurityParameters.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.
             */
            mSecurityParameters.verifyDataLength = 12;

            ApplyMaxFragmentLengthExtension();

            message.WriteToRecordStream(this);
        }
        protected virtual void SendServerKeyExchangeMessage(byte[] serverKeyExchange)
        {
            HandshakeMessage message = new HandshakeMessage(HandshakeType.server_key_exchange, serverKeyExchange.Length);

            message.Write(serverKeyExchange);

            message.WriteToRecordStream(this);
        }
    protected virtual void SendServerHelloMessage()
    {
        HandshakeMessage handshakeMessage = new HandshakeMessage(2);
        ProtocolVersion  serverVersion    = mTlsServer.GetServerVersion();

        if (!serverVersion.IsEqualOrEarlierVersionOf(Context.ClientVersion))
        {
            throw new TlsFatalAlert(80);
        }
        mRecordStream.ReadVersion = serverVersion;
        mRecordStream.SetWriteVersion(serverVersion);
        mRecordStream.SetRestrictReadVersion(enabled: true);
        ContextAdmin.SetServerVersion(serverVersion);
        TlsUtilities.WriteVersion(serverVersion, handshakeMessage);
        handshakeMessage.Write(mSecurityParameters.serverRandom);
        TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, handshakeMessage);
        int selectedCipherSuite = mTlsServer.GetSelectedCipherSuite();

        if (!Arrays.Contains(mOfferedCipherSuites, selectedCipherSuite) || selectedCipherSuite == 0 || CipherSuite.IsScsv(selectedCipherSuite) || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, Context.ServerVersion))
        {
            throw new TlsFatalAlert(80);
        }
        mSecurityParameters.cipherSuite = selectedCipherSuite;
        byte selectedCompressionMethod = mTlsServer.GetSelectedCompressionMethod();

        if (!Arrays.Contains(mOfferedCompressionMethods, selectedCompressionMethod))
        {
            throw new TlsFatalAlert(80);
        }
        mSecurityParameters.compressionAlgorithm = selectedCompressionMethod;
        TlsUtilities.WriteUint16(selectedCipherSuite, handshakeMessage);
        TlsUtilities.WriteUint8(selectedCompressionMethod, handshakeMessage);
        mServerExtensions = mTlsServer.GetServerExtensions();
        if (mSecureRenegotiation)
        {
            byte[] extensionData = TlsUtilities.GetExtensionData(mServerExtensions, 65281);
            if (null == extensionData)
            {
                mServerExtensions        = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
                mServerExtensions[65281] = TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
            }
        }
        if (mSecurityParameters.extendedMasterSecret)
        {
            mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
            TlsExtensionsUtilities.AddExtendedMasterSecretExtension(mServerExtensions);
        }
        if (mServerExtensions != null)
        {
            mSecurityParameters.encryptThenMac    = TlsExtensionsUtilities.HasEncryptThenMacExtension(mServerExtensions);
            mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(mClientExtensions, mServerExtensions, 80);
            mSecurityParameters.truncatedHMac     = TlsExtensionsUtilities.HasTruncatedHMacExtension(mServerExtensions);
            mAllowCertificateStatus = (!mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, 5, 80));
            mExpectSessionTicket    = (!mResumedSession && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, 35, 80));
            TlsProtocol.WriteExtensions(handshakeMessage, mServerExtensions);
        }
        mSecurityParameters.prfAlgorithm     = TlsProtocol.GetPrfAlgorithm(Context, mSecurityParameters.CipherSuite);
        mSecurityParameters.verifyDataLength = 12;
        ApplyMaxFragmentLengthExtension();
        handshakeMessage.WriteToRecordStream(this);
    }
Beispiel #39
0
        protected virtual void SendClientHelloMessage()
        {
            this.mRecordStream.SetWriteVersion(this.mTlsClient.ClientHelloRecordLayerVersion);

            ProtocolVersion client_version = this.mTlsClient.ClientVersion;

            if (client_version.IsDtls)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            ContextAdmin.SetClientVersion(client_version);

            /*
             * TODO RFC 5077 3.4. When presenting a ticket, the client MAY generate and include a
             * Session ID in the TLS ClientHello.
             */
            byte[] session_id = TlsUtilities.EmptyBytes;
            if (this.mTlsSession != null)
            {
                session_id = this.mTlsSession.SessionID;
                if (session_id == null || session_id.Length > 32)
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }

            bool fallback = this.mTlsClient.IsFallback;

            this.mOfferedCipherSuites = this.mTlsClient.GetCipherSuites();

            this.mOfferedCompressionMethods = this.mTlsClient.GetCompressionMethods();

            if (session_id.Length > 0 && this.mSessionParameters != null)
            {
                if (!Arrays.Contains(this.mOfferedCipherSuites, mSessionParameters.CipherSuite) ||
                    !Arrays.Contains(this.mOfferedCompressionMethods, mSessionParameters.CompressionAlgorithm))
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }

            this.mClientExtensions = this.mTlsClient.GetClientExtensions();

            HandshakeMessage message = new HandshakeMessage(HandshakeType.client_hello);

            TlsUtilities.WriteVersion(client_version, message);

            message.Write(this.mSecurityParameters.ClientRandom);

            TlsUtilities.WriteOpaque8(session_id, message);

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
                 * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
                 * ClientHello. Including both is NOT RECOMMENDED.
                 */
                byte[] renegExtData = TlsUtilities.GetExtensionData(mClientExtensions, ExtensionType.renegotiation_info);
                bool   noRenegExt   = (null == renegExtData);

                bool noRenegScsv = !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);

                if (noRenegExt && noRenegScsv)
                {
                    // TODO Consider whether to default to a client extension instead
                    //                this.mClientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(this.mClientExtensions);
                    //                this.mClientExtensions[ExtensionType.renegotiation_info] = CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
                    this.mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
                }

                /*
                 * draft-ietf-tls-downgrade-scsv-00 4. If a client sends a ClientHello.client_version
                 * containing a lower value than the latest (highest-valued) version supported by the
                 * client, it SHOULD include the TLS_FALLBACK_SCSV cipher suite value in
                 * ClientHello.cipher_suites.
                 */
                if (fallback && !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV))
                {
                    this.mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV);
                }

                TlsUtilities.WriteUint16ArrayWithUint16Length(mOfferedCipherSuites, message);
            }

            TlsUtilities.WriteUint8ArrayWithUint8Length(mOfferedCompressionMethods, message);

            if (mClientExtensions != null)
            {
                WriteExtensions(message, mClientExtensions);
            }

            message.WriteToRecordStream(this);
        }