ReadVersion() 공개 정적인 메소드

public static ReadVersion ( Stream input ) : ProtocolVersion
input Stream
리턴 ProtocolVersion
예제 #1
0
        internal virtual void CheckRecordHeader(byte[] recordHeader)
        {
            byte type = TlsUtilities.ReadUint8(recordHeader, TLS_HEADER_TYPE_OFFSET);

            /*
             * RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
             * unexpected_message alert.
             */
            CheckType(type, AlertDescription.unexpected_message);

            if (!mRestrictReadVersion)
            {
                int version = TlsUtilities.ReadVersionRaw(recordHeader, TLS_HEADER_VERSION_OFFSET);
                if ((version & 0xffffff00) != 0x0300)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }
            }
            else
            {
                ProtocolVersion version = TlsUtilities.ReadVersion(recordHeader, TLS_HEADER_VERSION_OFFSET);
                if (mReadVersion == null)
                {
                    // Will be set later in 'readRecord'
                }
                else if (!version.Equals(mReadVersion))
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }
            }

            int length = TlsUtilities.ReadUint16(recordHeader, TLS_HEADER_LENGTH_OFFSET);

            CheckLength(length, mCiphertextLimit, AlertDescription.record_overflow);
        }
예제 #2
0
        protected virtual byte[] ProcessHelloVerifyRequest(ClientHandshakeState state, byte[] body)
        {
            MemoryStream buf = new MemoryStream(body, false);

            ProtocolVersion server_version = TlsUtilities.ReadVersion(buf);

            byte[] cookie = TlsUtilities.ReadOpaque8(buf);

            TlsProtocol.AssertEmpty(buf);

            // TODO Seems this behaviour is not yet in line with OpenSSL for DTLS 1.2
            //        reportServerVersion(state, server_version);
            if (!server_version.IsEqualOrEarlierVersionOf(state.clientContext.ClientVersion))
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            /*
             * RFC 6347 This specification increases the cookie size limit to 255 bytes for greater
             * future flexibility. The limit remains 32 for previous versions of DTLS.
             */
            if (!ProtocolVersion.DTLSv12.IsEqualOrEarlierVersionOf(server_version) && cookie.Length > 32)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            return(cookie);
        }
예제 #3
0
        protected virtual void ProcessClientHello(DtlsServerProtocol.ServerHandshakeState state, byte[] body)
        {
            MemoryStream    input           = new MemoryStream(body, false);
            ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(input);

            if (!protocolVersion.IsDtls)
            {
                throw new TlsFatalAlert(47);
            }
            byte[] clientRandom = TlsUtilities.ReadFully(32, input);
            byte[] array        = TlsUtilities.ReadOpaque8(input);
            if (array.Length > 32)
            {
                throw new TlsFatalAlert(47);
            }
            TlsUtilities.ReadOpaque8(input);
            int num = TlsUtilities.ReadUint16(input);

            if (num < 2 || (num & 1) != 0)
            {
                throw new TlsFatalAlert(50);
            }
            state.offeredCipherSuites = TlsUtilities.ReadUint16Array(num / 2, input);
            int num2 = (int)TlsUtilities.ReadUint8(input);

            if (num2 < 1)
            {
                throw new TlsFatalAlert(47);
            }
            state.offeredCompressionMethods = TlsUtilities.ReadUint8Array(num2, input);
            state.clientExtensions          = TlsProtocol.ReadExtensions(input);
            TlsServerContextImpl serverContext      = state.serverContext;
            SecurityParameters   securityParameters = serverContext.SecurityParameters;

            securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions);
            serverContext.SetClientVersion(protocolVersion);
            state.server.NotifyClientVersion(protocolVersion);
            state.server.NotifyFallback(Arrays.Contains(state.offeredCipherSuites, 22016));
            securityParameters.clientRandom = clientRandom;
            state.server.NotifyOfferedCipherSuites(state.offeredCipherSuites);
            state.server.NotifyOfferedCompressionMethods(state.offeredCompressionMethods);
            if (Arrays.Contains(state.offeredCipherSuites, 255))
            {
                state.secure_renegotiation = true;
            }
            byte[] extensionData = TlsUtilities.GetExtensionData(state.clientExtensions, 65281);
            if (extensionData != null)
            {
                state.secure_renegotiation = true;
                if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                {
                    throw new TlsFatalAlert(40);
                }
            }
            state.server.NotifySecureRenegotiation(state.secure_renegotiation);
            if (state.clientExtensions != null)
            {
                state.server.ProcessClientExtensions(state.clientExtensions);
            }
        }
예제 #4
0
        internal virtual bool ReadRecord()
        {
            byte[] buf = TlsUtilities.ReadAllOrNothing(5, this.mInput);
            if (buf == null)
            {
                return(false);
            }
            byte type = TlsUtilities.ReadUint8(buf, 0);

            CheckType(type, 10);
            if (!this.mRestrictReadVersion)
            {
                if ((TlsUtilities.ReadVersionRaw(buf, 1) & 0xffffff00L) != 0x300L)
                {
                    throw new TlsFatalAlert(0x2f);
                }
            }
            else
            {
                ProtocolVersion version = TlsUtilities.ReadVersion(buf, 1);
                if (this.mReadVersion == null)
                {
                    this.mReadVersion = version;
                }
                else if (!version.Equals(this.mReadVersion))
                {
                    throw new TlsFatalAlert(0x2f);
                }
            }
            int len = TlsUtilities.ReadUint16(buf, 3);

            byte[] buffer2 = this.DecodeAndVerify(type, this.mInput, len);
            this.mHandler.ProcessRecord(type, buffer2, 0, buffer2.Length);
            return(true);
        }
예제 #5
0
        protected virtual void ReceiveClientHelloMessage(MemoryStream buf)
        {
            ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(buf);

            this.mRecordStream.SetWriteVersion(protocolVersion);
            if (protocolVersion.IsDtls)
            {
                throw new TlsFatalAlert(47);
            }
            byte[] clientRandom = TlsUtilities.ReadFully(32, buf);
            byte[] array        = TlsUtilities.ReadOpaque8(buf);
            if (array.Length > 32)
            {
                throw new TlsFatalAlert(47);
            }
            int num = TlsUtilities.ReadUint16(buf);

            if (num < 2 || (num & 1) != 0)
            {
                throw new TlsFatalAlert(50);
            }
            this.mOfferedCipherSuites = TlsUtilities.ReadUint16Array(num / 2, buf);
            int num2 = (int)TlsUtilities.ReadUint8(buf);

            if (num2 < 1)
            {
                throw new TlsFatalAlert(47);
            }
            this.mOfferedCompressionMethods = TlsUtilities.ReadUint8Array(num2, buf);
            this.mClientExtensions          = TlsProtocol.ReadExtensions(buf);
            this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(this.mClientExtensions);
            this.ContextAdmin.SetClientVersion(protocolVersion);
            this.mTlsServer.NotifyClientVersion(protocolVersion);
            this.mTlsServer.NotifyFallback(Arrays.Contains(this.mOfferedCipherSuites, 22016));
            this.mSecurityParameters.clientRandom = clientRandom;
            this.mTlsServer.NotifyOfferedCipherSuites(this.mOfferedCipherSuites);
            this.mTlsServer.NotifyOfferedCompressionMethods(this.mOfferedCompressionMethods);
            if (Arrays.Contains(this.mOfferedCipherSuites, 255))
            {
                this.mSecureRenegotiation = true;
            }
            byte[] extensionData = TlsUtilities.GetExtensionData(this.mClientExtensions, 65281);
            if (extensionData != null)
            {
                this.mSecureRenegotiation = true;
                if (!Arrays.ConstantTimeAreEqual(extensionData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                {
                    throw new TlsFatalAlert(40);
                }
            }
            this.mTlsServer.NotifySecureRenegotiation(this.mSecureRenegotiation);
            if (this.mClientExtensions != null)
            {
                this.mTlsServer.ProcessClientExtensions(this.mClientExtensions);
            }
        }
예제 #6
0
        protected virtual byte[] ProcessHelloVerifyRequest(DtlsClientProtocol.ClientHandshakeState state, byte[] body)
        {
            MemoryStream    memoryStream    = new MemoryStream(body, false);
            ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(memoryStream);

            byte[] array = TlsUtilities.ReadOpaque8(memoryStream);
            TlsProtocol.AssertEmpty(memoryStream);
            if (!protocolVersion.IsEqualOrEarlierVersionOf(state.clientContext.ClientVersion))
            {
                throw new TlsFatalAlert(47);
            }
            if (!ProtocolVersion.DTLSv12.IsEqualOrEarlierVersionOf(protocolVersion) && array.Length > 32)
            {
                throw new TlsFatalAlert(47);
            }
            return(array);
        }
예제 #7
0
        internal virtual bool ReadRecord()
        {
            byte[] recordHeader = TlsUtilities.ReadAllOrNothing(TLS_HEADER_SIZE, mInput);
            if (recordHeader == null)
            {
                return(false);
            }

            byte type = TlsUtilities.ReadUint8(recordHeader, TLS_HEADER_TYPE_OFFSET);

            /*
             * RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
             * unexpected_message alert.
             */
            CheckType(type, AlertDescription.unexpected_message);

            if (!mRestrictReadVersion)
            {
                int version = TlsUtilities.ReadVersionRaw(recordHeader, TLS_HEADER_VERSION_OFFSET);
                if ((version & 0xffffff00) != 0x0300)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }
            }
            else
            {
                ProtocolVersion version = TlsUtilities.ReadVersion(recordHeader, TLS_HEADER_VERSION_OFFSET);
                if (mReadVersion == null)
                {
                    mReadVersion = version;
                }
                else if (!version.Equals(mReadVersion))
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }
            }

            int length = TlsUtilities.ReadUint16(recordHeader, TLS_HEADER_LENGTH_OFFSET);

            CheckLength(length, mCiphertextLimit, AlertDescription.record_overflow);

            byte[] plaintext = DecodeAndVerify(type, mInput, length);
            mHandler.ProcessRecord(type, plaintext, 0, plaintext.Length);
            return(true);
        }
예제 #8
0
        protected virtual byte[] ProcessHelloVerifyRequest(ClientHandshakeState state, byte[] body)
        {
            //IL_0002: Unknown result type (might be due to invalid IL or missing references)
            //IL_0008: Expected O, but got Unknown
            MemoryStream    val             = new MemoryStream(body, false);
            ProtocolVersion protocolVersion = TlsUtilities.ReadVersion((Stream)(object)val);

            byte[] array = TlsUtilities.ReadOpaque8((Stream)(object)val);
            TlsProtocol.AssertEmpty(val);
            if (!protocolVersion.IsEqualOrEarlierVersionOf(state.clientContext.ClientVersion))
            {
                throw new TlsFatalAlert(47);
            }
            if (!ProtocolVersion.DTLSv12.IsEqualOrEarlierVersionOf(protocolVersion) && array.Length > 32)
            {
                throw new TlsFatalAlert(47);
            }
            return(array);
        }
예제 #9
0
        internal virtual bool ReadRecord()
        {
            byte[] array = TlsUtilities.ReadAllOrNothing(5, mInput);
            if (array == null)
            {
                return(false);
            }
            byte b = TlsUtilities.ReadUint8(array, 0);

            CheckType(b, 10);
            if (!mRestrictReadVersion)
            {
                int num = TlsUtilities.ReadVersionRaw(array, 1);
                if ((num & 4294967040u) != 768)
                {
                    throw new TlsFatalAlert(47);
                }
            }
            else
            {
                ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(array, 1);
                if (mReadVersion == null)
                {
                    mReadVersion = protocolVersion;
                }
                else if (!protocolVersion.Equals(mReadVersion))
                {
                    throw new TlsFatalAlert(47);
                }
            }
            int len = TlsUtilities.ReadUint16(array, 3);

            byte[] array2 = DecodeAndVerify(b, mInput, len);
            mHandler.ProcessRecord(b, array2, 0, array2.Length);
            return(true);
        }
예제 #10
0
        internal virtual bool ReadRecord()
        {
            byte[] array = TlsUtilities.ReadAllOrNothing(5, this.mInput);
            if (array == null)
            {
                return(false);
            }
            byte b = TlsUtilities.ReadUint8(array, 0);

            RecordStream.CheckType(b, 10);
            if (!this.mRestrictReadVersion)
            {
                int num = TlsUtilities.ReadVersionRaw(array, 1);
                if (((long)num & (long)((ulong)-256)) != 768L)
                {
                    throw new TlsFatalAlert(47);
                }
            }
            else
            {
                ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(array, 1);
                if (this.mReadVersion == null)
                {
                    this.mReadVersion = protocolVersion;
                }
                else if (!protocolVersion.Equals(this.mReadVersion))
                {
                    throw new TlsFatalAlert(47);
                }
            }
            int len = TlsUtilities.ReadUint16(array, 3);

            byte[] array2 = this.DecodeAndVerify(b, this.mInput, len);
            this.mHandler.ProcessRecord(b, array2, 0, array2.Length);
            return(true);
        }
예제 #11
0
        private int ProcessRecord(int received, byte[] record, byte[] buf, int off)
        {
            // NOTE: received < 0 (timeout) is covered by this first case
            if (received < RECORD_HEADER_LENGTH)
            {
                return(-1);
            }
            int length = TlsUtilities.ReadUint16(record, 11);

            if (received != (length + RECORD_HEADER_LENGTH))
            {
                return(-1);
            }

            byte type = TlsUtilities.ReadUint8(record, 0);

            switch (type)
            {
            case ContentType.alert:
            case ContentType.application_data:
            case ContentType.change_cipher_spec:
            case ContentType.handshake:
            case ContentType.heartbeat:
                break;

            default:
                return(-1);
            }

            int epoch = TlsUtilities.ReadUint16(record, 3);

            DtlsEpoch recordEpoch = null;

            if (epoch == mReadEpoch.Epoch)
            {
                recordEpoch = mReadEpoch;
            }
            else if (type == ContentType.handshake && mRetransmitEpoch != null &&
                     epoch == mRetransmitEpoch.Epoch)
            {
                recordEpoch = mRetransmitEpoch;
            }

            if (recordEpoch == null)
            {
                return(-1);
            }

            long seq = TlsUtilities.ReadUint48(record, 5);

            if (recordEpoch.ReplayWindow.ShouldDiscard(seq))
            {
                return(-1);
            }

            ProtocolVersion version = TlsUtilities.ReadVersion(record, 1);

            if (!version.IsDtls)
            {
                return(-1);
            }

            if (mReadVersion != null && !mReadVersion.Equals(version))
            {
                return(-1);
            }

            byte[] plaintext = recordEpoch.Cipher.DecodeCiphertext(
                GetMacSequenceNumber(recordEpoch.Epoch, seq), type, record, RECORD_HEADER_LENGTH,
                received - RECORD_HEADER_LENGTH);

            recordEpoch.ReplayWindow.ReportAuthenticated(seq);

            if (plaintext.Length > this.mPlaintextLimit)
            {
                return(-1);
            }

            if (mReadVersion == null)
            {
                mReadVersion = version;
            }

            switch (type)
            {
            case ContentType.alert:
            {
                if (plaintext.Length == 2)
                {
                    byte alertLevel       = plaintext[0];
                    byte alertDescription = plaintext[1];

                    mPeer.NotifyAlertReceived(alertLevel, alertDescription);

                    if (alertLevel == AlertLevel.fatal)
                    {
                        Failed();
                        throw new TlsFatalAlert(alertDescription);
                    }

                    // TODO Can close_notify be a fatal alert?
                    if (alertDescription == AlertDescription.close_notify)
                    {
                        CloseTransport();
                    }
                }

                return(-1);
            }

            case ContentType.application_data:
            {
                if (mInHandshake)
                {
                    // TODO Consider buffering application data for new epoch that arrives
                    // out-of-order with the Finished message
                    return(-1);
                }
                break;
            }

            case ContentType.change_cipher_spec:
            {
                // Implicitly receive change_cipher_spec and change to pending cipher state

                for (int i = 0; i < plaintext.Length; ++i)
                {
                    byte message = TlsUtilities.ReadUint8(plaintext, i);
                    if (message != ChangeCipherSpec.change_cipher_spec)
                    {
                        continue;
                    }

                    if (mPendingEpoch != null)
                    {
                        mReadEpoch = mPendingEpoch;
                    }
                }

                return(-1);
            }

            case ContentType.handshake:
            {
                if (!mInHandshake)
                {
                    if (mRetransmit != null)
                    {
                        mRetransmit.ReceivedHandshakeRecord(epoch, plaintext, 0, plaintext.Length);
                    }

                    // TODO Consider support for HelloRequest
                    return(-1);
                }
                break;
            }

            case ContentType.heartbeat:
            {
                // TODO[RFC 6520]
                return(-1);
            }
            }

            /*
             * NOTE: If we receive any non-handshake data in the new epoch implies the peer has
             * received our final flight.
             */
            if (!mInHandshake && mRetransmit != null)
            {
                this.mRetransmit        = null;
                this.mRetransmitEpoch   = null;
                this.mRetransmitTimeout = null;
            }

            Array.Copy(plaintext, 0, buf, off, plaintext.Length);
            return(plaintext.Length);
        }
예제 #12
0
        protected virtual void ReceiveClientHelloMessage(MemoryStream buf)
        {
            ProtocolVersion client_version = TlsUtilities.ReadVersion(buf);

            mRecordStream.SetWriteVersion(client_version);

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

            byte[] client_random = TlsUtilities.ReadFully(32, buf);

            /*
             * TODO RFC 5077 3.4. If a ticket is presented by the client, the server MUST NOT attempt to
             * use the Session ID in the ClientHello for stateful session resumption.
             */
            byte[] sessionID = TlsUtilities.ReadOpaque8(buf);
            if (sessionID.Length > 32)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            /*
             * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session
             * resumption request), this vector MUST include at least the cipher_suite from that
             * session.
             */
            int cipher_suites_length = TlsUtilities.ReadUint16(buf);

            if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0)
            {
                throw new TlsFatalAlert(AlertDescription.decode_error);
            }

            this.mOfferedCipherSuites = TlsUtilities.ReadUint16Array(cipher_suites_length / 2, buf);

            /*
             * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session
             * resumption request), it MUST include the compression_method from that session.
             */
            int compression_methods_length = TlsUtilities.ReadUint8(buf);

            if (compression_methods_length < 1)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            this.mOfferedCompressionMethods = TlsUtilities.ReadUint8Array(compression_methods_length, buf);

            /*
             * 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.
             */
            this.mClientExtensions = ReadExtensions(buf);

            /*
             * 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)
             */
            this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(mClientExtensions);

            ContextAdmin.SetClientVersion(client_version);

            mTlsServer.NotifyClientVersion(client_version);
            mTlsServer.NotifyFallback(Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_FALLBACK_SCSV));

            mSecurityParameters.clientRandom = client_random;

            mTlsServer.NotifyOfferedCipherSuites(mOfferedCipherSuites);
            mTlsServer.NotifyOfferedCompressionMethods(mOfferedCompressionMethods);

            /*
             * RFC 5746 3.6. Server Behavior: Initial Handshake
             */
            {
                /*
                 * 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.
                 */

                /*
                 * When a ClientHello is received, the server MUST check if it includes the
                 * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
                 * to TRUE.
                 */
                if (Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
                {
                    this.mSecureRenegotiation = true;
                }

                /*
                 * The server MUST check if the "renegotiation_info" extension is included in the
                 * ClientHello.
                 */
                byte[] renegExtData = TlsUtilities.GetExtensionData(mClientExtensions, ExtensionType.renegotiation_info);
                if (renegExtData != null)
                {
                    /*
                     * If the extension is present, set secure_renegotiation flag to TRUE. The
                     * server MUST then verify that the length of the "renegotiated_connection"
                     * field is zero, and if it is not, MUST abort the handshake.
                     */
                    this.mSecureRenegotiation = true;

                    if (!Arrays.ConstantTimeAreEqual(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                    {
                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
                    }
                }
            }

            mTlsServer.NotifySecureRenegotiation(this.mSecureRenegotiation);

            if (mClientExtensions != null)
            {
                mTlsServer.ProcessClientExtensions(mClientExtensions);
            }
        }
예제 #13
0
        protected virtual void ProcessClientHello(ServerHandshakeState state, byte[] body)
        {
            MemoryStream buf = new MemoryStream(body, false);

            // TODO Read RFCs for guidance on the expected record layer version number
            ProtocolVersion client_version = TlsUtilities.ReadVersion(buf);

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

            /*
             * Read the client random
             */
            byte[] client_random = TlsUtilities.ReadFully(32, buf);

            byte[] sessionID = TlsUtilities.ReadOpaque8(buf);
            if (sessionID.Length > 32)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            // TODO RFC 4347 has the cookie length restricted to 32, but not in RFC 6347
            byte[] cookie = TlsUtilities.ReadOpaque8(buf);

            int cipher_suites_length = TlsUtilities.ReadUint16(buf);

            if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0)
            {
                throw new TlsFatalAlert(AlertDescription.decode_error);
            }

            /*
             * NOTE: "If the session_id field is not empty (implying a session resumption request) this
             * vector must include at least the cipher_suite from that session."
             */
            state.offeredCipherSuites = TlsUtilities.ReadUint16Array(cipher_suites_length / 2, buf);

            int compression_methods_length = TlsUtilities.ReadUint8(buf);

            if (compression_methods_length < 1)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            state.offeredCompressionMethods = TlsUtilities.ReadUint8Array(compression_methods_length, buf);

            /*
             * 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.
             */
            state.clientExtensions = TlsProtocol.ReadExtensions(buf);

            TlsServerContextImpl context            = state.serverContext;
            SecurityParameters   securityParameters = context.SecurityParameters;

            /*
             * 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)
             */
            securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.clientExtensions);

            context.SetClientVersion(client_version);

            state.server.NotifyClientVersion(client_version);
            state.server.NotifyFallback(Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV));

            securityParameters.clientRandom = client_random;

            state.server.NotifyOfferedCipherSuites(state.offeredCipherSuites);
            state.server.NotifyOfferedCompressionMethods(state.offeredCompressionMethods);

            /*
             * RFC 5746 3.6. Server Behavior: Initial Handshake
             */
            {
                /*
                 * 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.
                 */

                /*
                 * When a ClientHello is received, the server MUST check if it includes the
                 * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
                 * to TRUE.
                 */
                if (Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
                {
                    state.secure_renegotiation = true;
                }

                /*
                 * The server MUST check if the "renegotiation_info" extension is included in the
                 * ClientHello.
                 */
                byte[] renegExtData = TlsUtilities.GetExtensionData(state.clientExtensions, ExtensionType.renegotiation_info);
                if (renegExtData != null)
                {
                    /*
                     * If the extension is present, set secure_renegotiation flag to TRUE. The
                     * server MUST then verify that the length of the "renegotiated_connection"
                     * field is zero, and if it is not, MUST abort the handshake.
                     */
                    state.secure_renegotiation = true;

                    if (!Arrays.ConstantTimeAreEqual(renegExtData, TlsProtocol.CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                    {
                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
                    }
                }
            }

            state.server.NotifySecureRenegotiation(state.secure_renegotiation);

            if (state.clientExtensions != null)
            {
                // NOTE: Validates the padding extension data, if present
                TlsExtensionsUtilities.GetPaddingExtension(state.clientExtensions);

                state.server.ProcessClientExtensions(state.clientExtensions);
            }
        }
예제 #14
0
        public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
        {
            byte[] record = null;

            for (;;)
            {
                int receiveLimit = System.Math.Min(len, GetReceiveLimit()) + RECORD_HEADER_LENGTH;
                if (record == null || record.Length < receiveLimit)
                {
                    record = new byte[receiveLimit];
                }

                try
                {
                    if (mRetransmit != null && DateTimeUtilities.CurrentUnixMs() > mRetransmitExpiry)
                    {
                        mRetransmit      = null;
                        mRetransmitEpoch = null;
                    }

                    int received = ReceiveRecord(record, 0, receiveLimit, waitMillis);
                    if (received < 0)
                    {
                        return(received);
                    }
                    if (received < RECORD_HEADER_LENGTH)
                    {
                        continue;
                    }
                    int length = TlsUtilities.ReadUint16(record, 11);
                    if (received != (length + RECORD_HEADER_LENGTH))
                    {
                        continue;
                    }

                    byte type = TlsUtilities.ReadUint8(record, 0);

                    // TODO Support user-specified custom protocols?
                    switch (type)
                    {
                    case ContentType.alert:
                    case ContentType.application_data:
                    case ContentType.change_cipher_spec:
                    case ContentType.handshake:
                    case ContentType.heartbeat:
                        break;

                    default:
                        // TODO Exception?
                        continue;
                    }

                    int epoch = TlsUtilities.ReadUint16(record, 3);

                    DtlsEpoch recordEpoch = null;
                    if (epoch == mReadEpoch.Epoch)
                    {
                        recordEpoch = mReadEpoch;
                    }
                    else if (type == ContentType.handshake && mRetransmitEpoch != null &&
                             epoch == mRetransmitEpoch.Epoch)
                    {
                        recordEpoch = mRetransmitEpoch;
                    }

                    if (recordEpoch == null)
                    {
                        continue;
                    }

                    long seq = TlsUtilities.ReadUint48(record, 5);
                    if (recordEpoch.ReplayWindow.ShouldDiscard(seq))
                    {
                        continue;
                    }

                    ProtocolVersion version = TlsUtilities.ReadVersion(record, 1);
                    if (!version.IsDtls)
                    {
                        continue;
                    }

                    if (mReadVersion != null && !mReadVersion.Equals(version))
                    {
                        continue;
                    }

                    byte[] plaintext = recordEpoch.Cipher.DecodeCiphertext(
                        GetMacSequenceNumber(recordEpoch.Epoch, seq), type, record, RECORD_HEADER_LENGTH,
                        received - RECORD_HEADER_LENGTH);

                    recordEpoch.ReplayWindow.ReportAuthenticated(seq);

                    if (plaintext.Length > this.mPlaintextLimit)
                    {
                        continue;
                    }

                    if (mReadVersion == null)
                    {
                        mReadVersion = version;
                    }

                    switch (type)
                    {
                    case ContentType.alert:
                    {
                        if (plaintext.Length == 2)
                        {
                            byte alertLevel       = plaintext[0];
                            byte alertDescription = plaintext[1];

                            mPeer.NotifyAlertReceived(alertLevel, alertDescription);

                            if (alertLevel == AlertLevel.fatal)
                            {
                                Failed();
                                throw new TlsFatalAlert(alertDescription);
                            }

                            // TODO Can close_notify be a fatal alert?
                            if (alertDescription == AlertDescription.close_notify)
                            {
                                CloseTransport();
                            }
                        }

                        continue;
                    }

                    case ContentType.application_data:
                    {
                        if (mInHandshake)
                        {
                            // TODO Consider buffering application data for new epoch that arrives
                            // out-of-order with the Finished message
                            continue;
                        }
                        break;
                    }

                    case ContentType.change_cipher_spec:
                    {
                        // Implicitly receive change_cipher_spec and change to pending cipher state

                        for (int i = 0; i < plaintext.Length; ++i)
                        {
                            byte message = TlsUtilities.ReadUint8(plaintext, i);
                            if (message != ChangeCipherSpec.change_cipher_spec)
                            {
                                continue;
                            }

                            if (mPendingEpoch != null)
                            {
                                mReadEpoch = mPendingEpoch;
                            }
                        }

                        continue;
                    }

                    case ContentType.handshake:
                    {
                        if (!mInHandshake)
                        {
                            if (mRetransmit != null)
                            {
                                mRetransmit.ReceivedHandshakeRecord(epoch, plaintext, 0, plaintext.Length);
                            }

                            // TODO Consider support for HelloRequest
                            continue;
                        }
                        break;
                    }

                    case ContentType.heartbeat:
                    {
                        // TODO[RFC 6520]
                        continue;
                    }
                    }

                    /*
                     * NOTE: If we receive any non-handshake data in the new epoch implies the peer has
                     * received our final flight.
                     */
                    if (!mInHandshake && mRetransmit != null)
                    {
                        this.mRetransmit      = null;
                        this.mRetransmitEpoch = null;
                    }

                    Array.Copy(plaintext, 0, buf, off, plaintext.Length);
                    return(plaintext.Length);
                }
                catch (IOException e)
                {
                    // NOTE: Assume this is a timeout for the moment
                    throw e;
                }
            }
        }
예제 #15
0
        protected virtual void ReceiveServerHelloMessage(MemoryStream buf)
        {
            {
                ProtocolVersion server_version = TlsUtilities.ReadVersion(buf);
                if (server_version.IsDtls)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                // Check that this matches what the server is Sending in the record layer
                if (!server_version.Equals(this.mRecordStream.ReadVersion))
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                ProtocolVersion client_version = Context.ClientVersion;
                if (!server_version.IsEqualOrEarlierVersionOf(client_version))
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                this.mRecordStream.SetWriteVersion(server_version);
                ContextAdmin.SetServerVersion(server_version);
                this.mTlsClient.NotifyServerVersion(server_version);
            }

            /*
             * Read the server random
             */
            this.mSecurityParameters.serverRandom = TlsUtilities.ReadFully(32, buf);

            this.mSelectedSessionID = TlsUtilities.ReadOpaque8(buf);
            if (this.mSelectedSessionID.Length > 32)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }
            this.mTlsClient.NotifySessionID(this.mSelectedSessionID);
            this.mResumedSession = this.mSelectedSessionID.Length > 0 && this.mTlsSession != null &&
                                   Arrays.AreEqual(this.mSelectedSessionID, this.mTlsSession.SessionID);

            /*
             * Find out which CipherSuite the server has chosen and check that it was one of the offered
             * ones, and is a valid selection for the negotiated version.
             */
            int selectedCipherSuite = TlsUtilities.ReadUint16(buf);

            if (!Arrays.Contains(this.mOfferedCipherSuites, selectedCipherSuite) ||
                selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL ||
                CipherSuite.IsScsv(selectedCipherSuite) ||
                !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, Context.ServerVersion))
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }
            this.mTlsClient.NotifySelectedCipherSuite(selectedCipherSuite);

            /*
             * Find out which CompressionMethod the server has chosen and check that it was one of the
             * offered ones.
             */
            byte selectedCompressionMethod = TlsUtilities.ReadUint8(buf);

            if (!Arrays.Contains(this.mOfferedCompressionMethods, selectedCompressionMethod))
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }
            this.mTlsClient.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.
             */
            this.mServerExtensions = 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 (this.mServerExtensions != null)
            {
                foreach (int extType in this.mServerExtensions.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(this.mClientExtensions, 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 (this.mResumedSession)
                    {
                        // 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(this.mServerExtensions, 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).
                     */
                    this.mSecureRenegotiation = true;

                    if (!Arrays.ConstantTimeAreEqual(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
                    {
                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
                    }
                }
            }

            // TODO[compat-gnutls] GnuTLS test server fails to Send renegotiation_info extension when resuming
            this.mTlsClient.NotifySecureRenegotiation(this.mSecureRenegotiation);

            IDictionary sessionClientExtensions = mClientExtensions, sessionServerExtensions = mServerExtensions;

            if (this.mResumedSession)
            {
                if (selectedCipherSuite != this.mSessionParameters.CipherSuite ||
                    selectedCompressionMethod != this.mSessionParameters.CompressionAlgorithm)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                sessionClientExtensions = null;
                sessionServerExtensions = this.mSessionParameters.ReadServerExtensions();
            }

            this.mSecurityParameters.cipherSuite          = selectedCipherSuite;
            this.mSecurityParameters.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(selectedCipherSuite))
                    {
                        throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                    }

                    this.mSecurityParameters.encryptThenMac = serverSentEncryptThenMAC;
                }

                this.mSecurityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(sessionServerExtensions);

                this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(sessionClientExtensions,
                                                                                               sessionServerExtensions, AlertDescription.illegal_parameter);

                this.mSecurityParameters.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.
                 */
                this.mAllowCertificateStatus = !this.mResumedSession &&
                                               TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.status_request,
                                                                                          AlertDescription.illegal_parameter);

                this.mExpectSessionTicket = !this.mResumedSession &&
                                            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)
            {
                this.mTlsClient.ProcessServerExtensions(sessionServerExtensions);
            }

            this.mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, this.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.
             */
            this.mSecurityParameters.verifyDataLength = 12;
        }
예제 #16
0
        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;
        }
예제 #17
0
        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;
        }
예제 #18
0
        public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
        {
            byte[] array = null;
            int    result;

            while (true)
            {
                int num = Math.Min(len, this.GetReceiveLimit()) + 13;
                if (array == null || array.Length < num)
                {
                    array = new byte[num];
                }
                try
                {
                    if (this.mRetransmit != null && DateTimeUtilities.CurrentUnixMs() > this.mRetransmitExpiry)
                    {
                        this.mRetransmit      = null;
                        this.mRetransmitEpoch = null;
                    }
                    int num2 = this.ReceiveRecord(array, 0, num, waitMillis);
                    if (num2 < 0)
                    {
                        result = num2;
                    }
                    else
                    {
                        if (num2 < 13)
                        {
                            continue;
                        }
                        int num3 = TlsUtilities.ReadUint16(array, 11);
                        if (num2 != num3 + 13)
                        {
                            continue;
                        }
                        byte b = TlsUtilities.ReadUint8(array, 0);
                        switch (b)
                        {
                        case 20:
                        case 21:
                        case 22:
                        case 23:
                        case 24:
                        {
                            int       num4      = TlsUtilities.ReadUint16(array, 3);
                            DtlsEpoch dtlsEpoch = null;
                            if (num4 == this.mReadEpoch.Epoch)
                            {
                                dtlsEpoch = this.mReadEpoch;
                            }
                            else if (b == 22 && this.mRetransmitEpoch != null && num4 == this.mRetransmitEpoch.Epoch)
                            {
                                dtlsEpoch = this.mRetransmitEpoch;
                            }
                            if (dtlsEpoch == null)
                            {
                                continue;
                            }
                            long num5 = TlsUtilities.ReadUint48(array, 5);
                            if (dtlsEpoch.ReplayWindow.ShouldDiscard(num5))
                            {
                                continue;
                            }
                            ProtocolVersion other = TlsUtilities.ReadVersion(array, 1);
                            if (this.mDiscoveredPeerVersion != null && !this.mDiscoveredPeerVersion.Equals(other))
                            {
                                continue;
                            }
                            byte[] array2 = dtlsEpoch.Cipher.DecodeCiphertext(DtlsRecordLayer.GetMacSequenceNumber(dtlsEpoch.Epoch, num5), b, array, 13, num2 - 13);
                            dtlsEpoch.ReplayWindow.ReportAuthenticated(num5);
                            if (array2.Length > this.mPlaintextLimit)
                            {
                                continue;
                            }
                            if (this.mDiscoveredPeerVersion == null)
                            {
                                this.mDiscoveredPeerVersion = other;
                            }
                            switch (b)
                            {
                            case 20:
                                for (int i = 0; i < array2.Length; i++)
                                {
                                    byte b2 = TlsUtilities.ReadUint8(array2, i);
                                    if (b2 == 1 && this.mPendingEpoch != null)
                                    {
                                        this.mReadEpoch = this.mPendingEpoch;
                                    }
                                }
                                continue;

                            case 21:
                                if (array2.Length == 2)
                                {
                                    byte b3 = array2[0];
                                    byte b4 = array2[1];
                                    this.mPeer.NotifyAlertReceived(b3, b4);
                                    if (b3 == 2)
                                    {
                                        this.Fail(b4);
                                        throw new TlsFatalAlert(b4);
                                    }
                                    if (b4 == 0)
                                    {
                                        this.CloseTransport();
                                    }
                                }
                                continue;

                            case 22:
                                if (!this.mInHandshake)
                                {
                                    if (this.mRetransmit != null)
                                    {
                                        this.mRetransmit.ReceivedHandshakeRecord(num4, array2, 0, array2.Length);
                                    }
                                    continue;
                                }
                                break;

                            case 23:
                                if (this.mInHandshake)
                                {
                                    continue;
                                }
                                break;

                            case 24:
                                continue;
                            }
                            if (!this.mInHandshake && this.mRetransmit != null)
                            {
                                this.mRetransmit      = null;
                                this.mRetransmitEpoch = null;
                            }
                            Array.Copy(array2, 0, buf, off, array2.Length);
                            result = array2.Length;
                            break;
                        }

                        default:
                            continue;
                        }
                    }
                }
                catch (IOException ex)
                {
                    throw ex;
                }
                break;
            }
            return(result);
        }
예제 #19
0
        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;
        }
예제 #20
0
        public virtual int Receive(byte[] buf, int off, int len, int waitMillis)
        {
            //IL_02c8: Expected O, but got Unknown
            byte[] array = null;
            while (true)
            {
                int num = Math.Min(len, GetReceiveLimit()) + 13;
                if (array == null || array.Length < num)
                {
                    array = new byte[num];
                }
                try
                {
                    if (mRetransmit != null && DateTimeUtilities.CurrentUnixMs() > mRetransmitExpiry)
                    {
                        mRetransmit      = null;
                        mRetransmitEpoch = null;
                    }
                    int num2 = ReceiveRecord(array, 0, num, waitMillis);
                    if (num2 < 0)
                    {
                        return(num2);
                    }
                    if (num2 < 13)
                    {
                        continue;
                    }
                    int num3 = TlsUtilities.ReadUint16(array, 11);
                    if (num2 != num3 + 13)
                    {
                        continue;
                    }
                    byte b = TlsUtilities.ReadUint8(array, 0);
                    switch (b)
                    {
                    case 20:
                    case 21:
                    case 22:
                    case 23:
                    case 24:
                    {
                        int       num4      = TlsUtilities.ReadUint16(array, 3);
                        DtlsEpoch dtlsEpoch = null;
                        if (num4 == mReadEpoch.Epoch)
                        {
                            dtlsEpoch = mReadEpoch;
                        }
                        else if (b == 22 && mRetransmitEpoch != null && num4 == mRetransmitEpoch.Epoch)
                        {
                            dtlsEpoch = mRetransmitEpoch;
                        }
                        if (dtlsEpoch == null)
                        {
                            break;
                        }
                        long num5 = TlsUtilities.ReadUint48(array, 5);
                        if (dtlsEpoch.ReplayWindow.ShouldDiscard(num5))
                        {
                            break;
                        }
                        ProtocolVersion protocolVersion = TlsUtilities.ReadVersion(array, 1);
                        if (!protocolVersion.IsDtls || (mReadVersion != null && !mReadVersion.Equals(protocolVersion)))
                        {
                            break;
                        }
                        byte[] array2 = dtlsEpoch.Cipher.DecodeCiphertext(GetMacSequenceNumber(dtlsEpoch.Epoch, num5), b, array, 13, num2 - 13);
                        dtlsEpoch.ReplayWindow.ReportAuthenticated(num5);
                        if (array2.Length > mPlaintextLimit)
                        {
                            break;
                        }
                        if (mReadVersion == null)
                        {
                            mReadVersion = protocolVersion;
                        }
                        switch (b)
                        {
                        case 21:
                            if (array2.Length == 2)
                            {
                                byte b2 = array2[0];
                                byte b3 = array2[1];
                                mPeer.NotifyAlertReceived(b2, b3);
                                if (b2 == 2)
                                {
                                    Fail(b3);
                                    throw new TlsFatalAlert(b3);
                                }
                                if (b3 == 0)
                                {
                                    CloseTransport();
                                }
                            }
                            goto end_IL_0022;

                        case 23:
                            if (!mInHandshake)
                            {
                                break;
                            }
                            goto end_IL_0022;

                        case 20:
                        {
                            for (int i = 0; i < array2.Length; i++)
                            {
                                byte b4 = TlsUtilities.ReadUint8(array2, i);
                                if (b4 == 1 && mPendingEpoch != null)
                                {
                                    mReadEpoch = mPendingEpoch;
                                }
                            }
                            goto end_IL_0022;
                        }

                        case 22:
                            if (mInHandshake)
                            {
                                break;
                            }
                            if (mRetransmit != null)
                            {
                                mRetransmit.ReceivedHandshakeRecord(num4, array2, 0, array2.Length);
                            }
                            goto end_IL_0022;

                        case 24:
                            goto end_IL_0022;
                        }
                        if (!mInHandshake && mRetransmit != null)
                        {
                            mRetransmit      = null;
                            mRetransmitEpoch = null;
                        }
                        global::System.Array.Copy((global::System.Array)array2, 0, (global::System.Array)buf, off, array2.Length);
                        return(array2.Length);
                    }
                    }
                    end_IL_0022 :;
                }
                catch (IOException val)
                {
                    IOException val2 = val;
                    throw val2;
                }
            }
        }
예제 #21
0
        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 (CompressionMethod.cls_null != 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 7627 4. Clients and servers SHOULD NOT accept handshakes that do not use the extended
             * master secret [..]. (and see 5.2, 5.3)
             */
            securityParameters.extendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(state.serverExtensions);

            if (!securityParameters.IsExtendedMasterSecret &&
                (state.resumedSession || state.client.RequiresExtendedMasterSecret()))
            {
                throw new TlsFatalAlert(AlertDescription.handshake_failure);
            }

            /*
             * 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 && sessionServerExtensions.Count > 0)
            {
                {
                    /*
                     * 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.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);

                short s = TlsExtensionsUtilities.GetServerCertificateTypeExtensionServer(sessionServerExtensions);
                if (s != -1)
                {
                    state.serverCertificateType = s;
                }

                s = TlsExtensionsUtilities.GetClientCertificateTypeExtensionServer(sessionServerExtensions);
                if (s != -1)
                {
                    state.clientCertificateType = s;
                }
            }

            if (sessionClientExtensions != null)
            {
                state.client.ProcessServerExtensions(sessionServerExtensions);
            }

            securityParameters.prfAlgorithm = TlsProtocol.GetPrfAlgorithm(state.clientContext,
                                                                          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;
        }
예제 #22
0
        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;
        }
예제 #23
0
        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.selectedCipherSuite = TlsUtilities.ReadUint16(buf);
            if (!Arrays.Contains(state.offeredCipherSuites, state.selectedCipherSuite) ||
                state.selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL ||
                CipherSuite.IsScsv(state.selectedCipherSuite) ||
                !TlsUtilities.IsValidCipherSuiteForVersion(state.selectedCipherSuite, server_version))
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            ValidateSelectedCipherSuite(state.selectedCipherSuite, AlertDescription.illegal_parameter);

            state.client.NotifySelectedCipherSuite(state.selectedCipherSuite);

            state.selectedCompressionMethod = TlsUtilities.ReadUint8(buf);
            if (!Arrays.Contains(state.offeredCompressionMethods, (byte)state.selectedCompressionMethod))
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }
            state.client.NotifySelectedCompressionMethod((byte)state.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[]
            IDictionary serverExtensions = TlsProtocol.ReadExtensions(buf);

            /*
             * draft-ietf-tls-session-hash-01 5.2. If a server receives the "extended_master_secret"
             * extension, it MUST include the "extended_master_secret" extension in its ServerHello
             * message.
             */
            bool serverSentExtendedMasterSecret = TlsExtensionsUtilities.HasExtendedMasterSecretExtension(serverExtensions);

            if (serverSentExtendedMasterSecret != securityParameters.extendedMasterSecret)
            {
                throw new TlsFatalAlert(AlertDescription.handshake_failure);
            }

            /*
             * 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 (serverExtensions != null)
            {
                foreach (int extType in 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);
                    }

                    /*
                     * draft-ietf-tls-session-hash-01 5.2. Implementation note: if the server decides to
                     * proceed with resumption, the extension does not have any effect. Requiring the
                     * extension to be included anyway makes the extension negotiation logic easier,
                     * because it does not depend on whether resumption is accepted or not.
                     */
                    if (extType == ExtensionType.extended_master_secret)
                    {
                        continue;
                    }

                    /*
                     * 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[.]
                     */
                    // TODO[sessions]
                    //                if (this.mResumedSession)
                    //                {
                    //                    // 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 = (byte[])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);
                        }
                    }
                }

                /*
                 * 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(serverExtensions);
                if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(state.selectedCipherSuite))
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                securityParameters.encryptThenMac = serverSentEncryptThenMAC;

                state.maxFragmentLength = EvaluateMaxFragmentLengthExtension(state.clientExtensions, serverExtensions,
                                                                             AlertDescription.illegal_parameter);

                securityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(serverExtensions);

                state.allowCertificateStatus = TlsUtilities.HasExpectedEmptyExtensionData(serverExtensions,
                                                                                          ExtensionType.status_request, AlertDescription.illegal_parameter);

                state.expectSessionTicket = TlsUtilities.HasExpectedEmptyExtensionData(serverExtensions,
                                                                                       ExtensionType.session_ticket, AlertDescription.illegal_parameter);
            }

            state.client.NotifySecureRenegotiation(state.secure_renegotiation);

            if (state.clientExtensions != null)
            {
                state.client.ProcessServerExtensions(serverExtensions);
            }
        }
예제 #24
0
        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;
        }