Пример #1
0
        // This function will try to parse TLS hello frame and fill details in provided info structure.
        // If frame was fully processed without any error, function returns true.
        // Otherwise it returns false and info may have partial data.
        // It is OK to call it again if more data becomes available.
        // It is also possible to limit what information is processed.
        // If callback delegate is provided, it will be called on ALL extensions.
        public static bool TryGetFrameInfo(ReadOnlySpan <byte> frame, ref TlsFrameInfo info, ProcessingOptions options = ProcessingOptions.All, HelloExtensionCallback?callback = null)
        {
            const int HandshakeTypeOffset = 5;

            if (frame.Length < HeaderSize)
            {
                return(false);
            }

            // This will not fail since we have enough data.
            bool gotHeader = TryGetFrameHeader(frame, ref info.Header);

            Debug.Assert(gotHeader);

            info.SupportedVersions = info.Header.Version;

            if (info.Header.Type == TlsContentType.Alert)
            {
                TlsAlertLevel       level       = default;
                TlsAlertDescription description = default;
                if (TryGetAlertInfo(frame, ref level, ref description))
                {
                    info.AlertDescription = description;
                    return(true);
                }

                return(false);
            }

            if (info.Header.Type != TlsContentType.Handshake || frame.Length <= HandshakeTypeOffset)
            {
                return(false);
            }

            info.HandshakeType = (TlsHandshakeType)frame[HandshakeTypeOffset];

            // Check if we have full frame.
            bool isComplete = frame.Length >= HeaderSize + info.Header.Length;

#pragma warning disable SYSLIB0039 // TLS 1.0 and 1.1 are obsolete
            if (((int)info.Header.Version >= (int)SslProtocols.Tls) &&
#pragma warning restore SYSLIB0039
                (info.HandshakeType == TlsHandshakeType.ClientHello || info.HandshakeType == TlsHandshakeType.ServerHello))
            {
                if (!TryParseHelloFrame(frame.Slice(HeaderSize), ref info, options, callback))
                {
                    isComplete = false;
                }
            }

            return(isComplete);
        }
Пример #2
0
    // This function will parse TLS Alert message and it will return alert level and description.
    public static bool TryGetAlertInfo(ReadOnlySpan <byte> frame, ref TlsAlertLevel level, ref TlsAlertDescription description)
    {
        if (frame.Length < 7 || frame[0] != (byte)TlsContentType.Alert)
        {
            return(false);
        }

        level       = (TlsAlertLevel)frame[5];
        description = (TlsAlertDescription)frame[6];

        return(true);
    }
Пример #3
0
    // This function will try to parse TLS hello frame and fill details in provided info structure.
    // If frame was fully processed without any error, function returns true.
    // Otherwise it returns false and info may have partial data.
    // It is OK to call it again if more data becomes available.
    // It is also possible to limit what information is processed.
    // If callback delegate is provided, it will be called on ALL extensions.
    public static bool TryGetFrameInfo(ReadOnlySpan <byte> frame, ref TlsFrameInfo info, ProcessingOptions options = ProcessingOptions.All, HelloExtensionCallback?callback = null)
    {
        const int HandshakeTypeOffset = 5;

        if (frame.Length < HeaderSize)
        {
            return(false);
        }

        // This will not fail since we have enough data.
        bool gotHeader = TryGetFrameHeader(frame, ref info.Header);

        Debug.Assert(gotHeader);

        info.SupportedVersions = info.Header.Version;
#pragma warning disable CS0618 // Ssl2 and Ssl3 are obsolete
        if (info.Header.Version == SslProtocols.Ssl2)
        {
            // This is safe. We would not get here if the length is too small.
            info.SupportedVersions |= TlsMinorVersionToProtocol(frame[4]);
            // We only recognize Unified ClientHello at the moment.
            // This is needed to trigger certificate selection callback in SslStream.
            info.HandshakeType = TlsHandshakeType.ClientHello;
            // There is no more parsing for old protocols.
            return(true);
        }
#pragma warning restore CS0618

        if (info.Header.Type == TlsContentType.Alert)
        {
            TlsAlertLevel       level       = default;
            TlsAlertDescription description = default;
            if (TryGetAlertInfo(frame, ref level, ref description))
            {
                info.AlertDescription = description;
                return(true);
            }

            return(false);
        }

        if (info.Header.Type != TlsContentType.Handshake || frame.Length <= HandshakeTypeOffset)
        {
            return(false);
        }

        info.HandshakeType = (TlsHandshakeType)frame[HandshakeTypeOffset];

        // Check if we have full frame.
        bool isComplete = frame.Length >= HeaderSize + info.Header.Length;

        if (((int)info.Header.Version >= (int)SslProtocols.Tls) &&
            (info.HandshakeType == TlsHandshakeType.ClientHello || info.HandshakeType == TlsHandshakeType.ServerHello))
        {
            if (!TryParseHelloFrame(frame.Slice(HeaderSize), ref info, options, callback))
            {
                isComplete = false;
            }
        }

        return(isComplete);
    }