// 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); }
// 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); }
// 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); }