Initial import
This commit is contained in:
		
							
								
								
									
										64
									
								
								cmd/protodial/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								cmd/protodial/main.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"git.maze.io/go/dpi/protocol"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	acceptFlag := flag.String("accept", "", "comma separated list of accepted protocols")
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
 | 
			
		||||
	if flag.NArg() != 2 {
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "Usage: %s <host> <port>\n", os.Args[0])
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	accept := make(map[string]bool)
 | 
			
		||||
	acceptFlags := strings.Split(*acceptFlag, ",")
 | 
			
		||||
	if len(acceptFlags) == 0 {
 | 
			
		||||
		fmt.Fprintln(os.Stderr, "No -accept was provided, refusing all protocols!")
 | 
			
		||||
	} else {
 | 
			
		||||
		for _, proto := range acceptFlags {
 | 
			
		||||
			accept[proto] = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c, err := net.Dial("tcp", net.JoinHostPort(flag.Arg(0), flag.Arg(1)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalln(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c = protocol.Limit(c, func(dir protocol.Direction, p *protocol.Protocol) error {
 | 
			
		||||
		if p == nil {
 | 
			
		||||
			return errors.New("No protocol detected")
 | 
			
		||||
		}
 | 
			
		||||
		if !accept[p.Name] {
 | 
			
		||||
			return fmt.Errorf("Protocol %s is not accepted", p.Name)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "Accepting protocol %s version %s initiated by %s\n",
 | 
			
		||||
			p.Name, p.Version, dir)
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	defer c.Close()
 | 
			
		||||
 | 
			
		||||
	var wait sync.WaitGroup
 | 
			
		||||
	wait.Go(func() { multiplex(c, os.Stdin) })
 | 
			
		||||
	wait.Go(func() { multiplex(os.Stdout, c) })
 | 
			
		||||
	wait.Wait()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func multiplex(w io.Writer, r io.Reader) {
 | 
			
		||||
	if _, err := io.Copy(w, r); err != nil && !errors.Is(err, io.EOF) {
 | 
			
		||||
		log.Fatalln("Copy terminated:", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										89
									
								
								cmd/protoproxy/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								cmd/protoproxy/main.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.maze.io/go/dpi/protocol"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	listenFlag := flag.String("listen", "localhost:4080", "proxy listen address")
 | 
			
		||||
	targetFlag := flag.String("target", "localhost:22", "proxy target address")
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
 | 
			
		||||
	l, err := net.Listen("tcp", *listenFlag)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("listen error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Printf("listening on %s", l.Addr())
 | 
			
		||||
	for {
 | 
			
		||||
		c, err := l.Accept()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatalln("accept error:", err)
 | 
			
		||||
		}
 | 
			
		||||
		go proxy(c, *targetFlag)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func proxy(client net.Conn, target string) {
 | 
			
		||||
	log.Printf("new connection from %s", client.RemoteAddr())
 | 
			
		||||
 | 
			
		||||
	// Hangup client if we return
 | 
			
		||||
	defer func() {
 | 
			
		||||
		log.Printf("closing connection to %s: %v", client.RemoteAddr(), client.Close())
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	log.Printf("dialing %s", target)
 | 
			
		||||
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	var dialer net.Dialer
 | 
			
		||||
 | 
			
		||||
	server, err := dialer.DialContext(ctx, "tcp", target)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		cancel()
 | 
			
		||||
		log.Printf("error connecting to %s: %v", target, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	cancel()
 | 
			
		||||
 | 
			
		||||
	// Hangup server if we return
 | 
			
		||||
	defer func() {
 | 
			
		||||
		log.Printf("closing connection to %s: %v", server.RemoteAddr(), server.Close())
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// Setup interceptor and wrap the client and server connections.
 | 
			
		||||
	interceptor := protocol.NewInterceptor()
 | 
			
		||||
	client = interceptor.Client(client)
 | 
			
		||||
	server = interceptor.Server(server)
 | 
			
		||||
 | 
			
		||||
	// Request a return channel and start the detection before doing anything
 | 
			
		||||
	// else with the client and server connections.
 | 
			
		||||
	intercepted := interceptor.Detect(10 * time.Second)
 | 
			
		||||
 | 
			
		||||
	log.Printf("client %s connected to %s; proxying", client.RemoteAddr(), server.RemoteAddr())
 | 
			
		||||
 | 
			
		||||
	// Create a wait group and copy between client and server bidirectionally,
 | 
			
		||||
	// either side needs to generate data for the detection to work.
 | 
			
		||||
	var group sync.WaitGroup
 | 
			
		||||
	group.Go(func() { io.Copy(client, server) })
 | 
			
		||||
	group.Go(func() { io.Copy(server, client) })
 | 
			
		||||
 | 
			
		||||
	// Wait until the interceptor produces data.
 | 
			
		||||
	result := <-intercepted
 | 
			
		||||
	if result.Error != nil {
 | 
			
		||||
		log.Printf("protocol detection failed: %v", result.Error)
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("detected protocol %s version %s initiated by %s",
 | 
			
		||||
			result.Protocol.Name, result.Protocol.Version, result.Direction)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Wait for the multiplexing to finish.
 | 
			
		||||
	group.Wait()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								doc.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
// Package dpi contains helpers for performing deep packet inspection.
 | 
			
		||||
package dpi
 | 
			
		||||
							
								
								
									
										26
									
								
								error.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								error.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
package dpi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrInvalid = errors.New("invalid")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DecodeError struct {
 | 
			
		||||
	Reason string
 | 
			
		||||
	Err    error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err DecodeError) Error() string {
 | 
			
		||||
	if err.Reason != "" {
 | 
			
		||||
		return fmt.Sprintf("dpi: %s: %v", err.Reason, err.Err.Error())
 | 
			
		||||
	}
 | 
			
		||||
	return err.Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err DecodeError) Unwrap() error {
 | 
			
		||||
	return err.Err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
module git.maze.io/go/dpi
 | 
			
		||||
 | 
			
		||||
go 1.25
 | 
			
		||||
 | 
			
		||||
require golang.org/x/crypto v0.42.0 // indirect
 | 
			
		||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
 | 
			
		||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
 | 
			
		||||
							
								
								
									
										113
									
								
								protocol/detect.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								protocol/detect.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Strict mode requires a full, compliant packet to be captured. This is only
 | 
			
		||||
// implemented by some detectors.
 | 
			
		||||
var Strict bool
 | 
			
		||||
 | 
			
		||||
// Common errors.
 | 
			
		||||
var (
 | 
			
		||||
	ErrTimeout = errors.New("timeout")
 | 
			
		||||
	ErrUnknown = errors.New("unknown protocol")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Direction indicates the communcation direction.
 | 
			
		||||
type Direction int
 | 
			
		||||
 | 
			
		||||
// Directions supported by this package.
 | 
			
		||||
const (
 | 
			
		||||
	Unknown Direction = iota
 | 
			
		||||
	Client
 | 
			
		||||
	Server
 | 
			
		||||
	Both
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (dir Direction) Contains(other Direction) bool {
 | 
			
		||||
	switch dir {
 | 
			
		||||
	case Client:
 | 
			
		||||
		return other == Client || other == Both
 | 
			
		||||
	case Server:
 | 
			
		||||
		return other == Server || other == Both
 | 
			
		||||
	case Both:
 | 
			
		||||
		return other == Client || other == Server
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var directionName = map[Direction]string{
 | 
			
		||||
	Client: "client",
 | 
			
		||||
	Server: "server",
 | 
			
		||||
	Both:   "both",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dir Direction) String() string {
 | 
			
		||||
	if s, ok := directionName[dir]; ok {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("invalid (%d)", int(dir))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type format struct {
 | 
			
		||||
	dir    Direction
 | 
			
		||||
	magic  string
 | 
			
		||||
	detect DetectFunc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Formats is the list of registered formats.
 | 
			
		||||
var (
 | 
			
		||||
	formatsMu     sync.Mutex
 | 
			
		||||
	atomicFormats atomic.Value
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DetectFunc func(Direction, []byte) *Protocol
 | 
			
		||||
 | 
			
		||||
func Register(dir Direction, magic string, detect DetectFunc) {
 | 
			
		||||
	formatsMu.Lock()
 | 
			
		||||
	formats, _ := atomicFormats.Load().([]format)
 | 
			
		||||
	atomicFormats.Store(append(formats, format{dir, magic, detect}))
 | 
			
		||||
	formatsMu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func matchMagic(magic string, data []byte) bool {
 | 
			
		||||
	// Empty magic means the detector will always run.
 | 
			
		||||
	if len(magic) == 0 {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The buffer should contain at least the same number of bytes
 | 
			
		||||
	// as our magic.
 | 
			
		||||
	if len(data) < len(magic) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Match bytes in magic with bytes in data.
 | 
			
		||||
	for i, b := range []byte(magic) {
 | 
			
		||||
		if b != '?' && data[i] != b {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Detect a protocol based on the provided data.
 | 
			
		||||
func Detect(dir Direction, data []byte) (*Protocol, error) {
 | 
			
		||||
	formats, _ := atomicFormats.Load().([]format)
 | 
			
		||||
	for _, f := range formats {
 | 
			
		||||
		if f.dir.Contains(dir) {
 | 
			
		||||
			// Check the buffer to see if we have sufficient bytes
 | 
			
		||||
			if matchMagic(f.magic, data) {
 | 
			
		||||
				if p := f.detect(dir, data); p != nil {
 | 
			
		||||
					return p, nil
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil, ErrUnknown
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										94
									
								
								protocol/detect_http.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								protocol/detect_http.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	Register(Client, "", detectHTTPRequest)
 | 
			
		||||
	Register(Server, "HTTP/?.", detectHTTPResponse)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectHTTPRequest(dir Direction, data []byte) *Protocol {
 | 
			
		||||
	// A minimal request "GET / HTTP/1.0\r\n" is > 8 bytes.
 | 
			
		||||
	if len(data) < 8 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if Strict {
 | 
			
		||||
		var (
 | 
			
		||||
			b = append(data, '\r', '\n')
 | 
			
		||||
			r = bufio.NewReader(bytes.NewReader(b))
 | 
			
		||||
		)
 | 
			
		||||
		if request, err := http.ReadRequest(r); err == nil {
 | 
			
		||||
			return &Protocol{
 | 
			
		||||
				Name: ProtocolHTTP,
 | 
			
		||||
				Version: Version{
 | 
			
		||||
					Major: request.ProtoMajor,
 | 
			
		||||
					Minor: request.ProtoMinor,
 | 
			
		||||
					Patch: -1,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		r.Reset(bytes.NewReader(b))
 | 
			
		||||
		if response, err := http.ReadResponse(r, nil); err == nil {
 | 
			
		||||
			return &Protocol{
 | 
			
		||||
				Name: ProtocolHTTP,
 | 
			
		||||
				Version: Version{
 | 
			
		||||
					Major: response.ProtoMajor,
 | 
			
		||||
					Minor: response.ProtoMinor,
 | 
			
		||||
					Patch: -1,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	crlfIndex := bytes.IndexFunc(data, func(r rune) bool {
 | 
			
		||||
		return r == '\r' || r == '\n'
 | 
			
		||||
	})
 | 
			
		||||
	if crlfIndex == -1 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A request has three, space-separated parts.
 | 
			
		||||
	part := bytes.Split(data[:crlfIndex], []byte(" "))
 | 
			
		||||
	if len(part) != 3 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The last part starts with "HTTP/".
 | 
			
		||||
	if !bytes.HasPrefix(part[2], []byte("HTTP/1")) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var version = Version{Patch: -1}
 | 
			
		||||
	fmt.Sscanf(string(part[2]), "HTTP/%d.%d ", &version.Major, &version.Minor)
 | 
			
		||||
 | 
			
		||||
	return &Protocol{
 | 
			
		||||
		Name:    ProtocolHTTP,
 | 
			
		||||
		Version: version,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectHTTPResponse(dir Direction, data []byte) *Protocol {
 | 
			
		||||
	if !dir.Contains(Server) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A minimal response "HTTP/1.0 200 OK\r\n" is > 8 bytes.
 | 
			
		||||
	if len(data) < 8 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var version = Version{Patch: -1}
 | 
			
		||||
	fmt.Sscanf(string(data), "HTTP/%d.%d ", &version.Major, &version.Minor)
 | 
			
		||||
 | 
			
		||||
	return &Protocol{
 | 
			
		||||
		Name:    ProtocolHTTP,
 | 
			
		||||
		Version: version,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										154
									
								
								protocol/detect_http_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								protocol/detect_http_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestDetectHTTPRequest(t *testing.T) {
 | 
			
		||||
	atomicFormats.Store([]format{{Client, "", detectHTTPRequest}})
 | 
			
		||||
 | 
			
		||||
	// A valid HTTP/1.0 GET request
 | 
			
		||||
	http10Request := []byte("GET /old-page.html HTTP/1.0\r\nUser-Agent: NCSA_Mosaic/1.0\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	// A valid HTTP/1.1 GET request
 | 
			
		||||
	getRequest := []byte("GET /resource/item?id=123 HTTP/1.1\r\nHost: example.com\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	// An invalid HTTP request
 | 
			
		||||
	sshBanner := []byte("SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4\r\n")
 | 
			
		||||
 | 
			
		||||
	defer func() { Strict = false }()
 | 
			
		||||
	for _, strict := range []bool{false, true} {
 | 
			
		||||
		Strict = strict
 | 
			
		||||
 | 
			
		||||
		name := "loose"
 | 
			
		||||
		if strict {
 | 
			
		||||
			name = "strict"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		t.Run(name, func(t *testing.T) {
 | 
			
		||||
			t.Run("HTTP/1.0 GET", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Client, http10Request)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolHTTP {
 | 
			
		||||
					t.Fatalf("expected http protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("HTTP/1.1 GET", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Client, getRequest)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolHTTP {
 | 
			
		||||
					t.Fatalf("expected http protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("Invalid SSH", func(t *testing.T) {
 | 
			
		||||
				_, err := Detect(Server, sshBanner)
 | 
			
		||||
				if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
					t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
				} else {
 | 
			
		||||
					t.Logf("error %q, as expected", err)
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDetectHTTPResponse(t *testing.T) {
 | 
			
		||||
	atomicFormats.Store([]format{{Server, "HTTP/?.? ", detectHTTPResponse}})
 | 
			
		||||
 | 
			
		||||
	// A valid HTTP/1.0 403 Forbidden response
 | 
			
		||||
	http10Response := []byte("HTTP/1.0 403 Forbidden\r\nServer: CERN/3.0\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	// A valid HTTP/1.1 200 OK response
 | 
			
		||||
	responseOK := []byte("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html>...</html>")
 | 
			
		||||
 | 
			
		||||
	// A valid HTTP/1.1 404 Not Found response
 | 
			
		||||
	responseNotFound := []byte("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	// An invalid HTTP GET request
 | 
			
		||||
	getRequest := []byte("GET /resource/item?id=123 HTTP/1.1\r\nHost: example.com\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	// An invalid banner (SSH)
 | 
			
		||||
	sshBanner := []byte("SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4\r\n")
 | 
			
		||||
 | 
			
		||||
	defer func() { Strict = false }()
 | 
			
		||||
	for _, strict := range []bool{false, true} {
 | 
			
		||||
		Strict = strict
 | 
			
		||||
 | 
			
		||||
		name := "loose"
 | 
			
		||||
		if strict {
 | 
			
		||||
			name = "strict"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		t.Run(name, func(t *testing.T) {
 | 
			
		||||
			t.Run("HTTP/1.0 403", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Server, http10Response)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolHTTP {
 | 
			
		||||
					t.Fatalf("expected http protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("HTTP/1.1 200", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Server, responseOK)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolHTTP {
 | 
			
		||||
					t.Fatalf("expected http protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("HTTP/1.1 404", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Server, responseNotFound)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolHTTP {
 | 
			
		||||
					t.Fatalf("expected http protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("Invalid HTTP/1.1 GET", func(t *testing.T) {
 | 
			
		||||
				_, err := Detect(Server, getRequest)
 | 
			
		||||
				if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
					t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
				} else {
 | 
			
		||||
					t.Logf("error %q, as expected", err)
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("Invalid SSH", func(t *testing.T) {
 | 
			
		||||
				_, err := Detect(Server, sshBanner)
 | 
			
		||||
				if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
					t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
				} else {
 | 
			
		||||
					t.Logf("error %q, as expected", err)
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								protocol/detect_mysql.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								protocol/detect_mysql.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	Register(Server, "\x0a", detectMySQL)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectMySQL(dir Direction, data []byte) *Protocol {
 | 
			
		||||
	if len(data) < 7 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The first byte of the handshake packet is the protocol version.
 | 
			
		||||
	// For MySQL, this is 10 (0x0A).
 | 
			
		||||
	if data[0] != 0x0A {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// After the protocol version, there is a null-terminated server version string.
 | 
			
		||||
	// We search for the null byte starting from the second byte (index 1).
 | 
			
		||||
	nullIndex := bytes.IndexByte(data[1:], 0x00)
 | 
			
		||||
 | 
			
		||||
	// If no null byte is found, it's not a valid banner.
 | 
			
		||||
	if nullIndex == -1 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The position of the null byte is relative to the start of the whole slice.
 | 
			
		||||
	// It's 1 (for the protocol byte) + nullIndex.
 | 
			
		||||
	serverVersionEndPos := 1 + nullIndex
 | 
			
		||||
 | 
			
		||||
	// After the null-terminated version string, there must be at least 4 bytes
 | 
			
		||||
	// for the connection ID, plus more data for capabilities, auth, etc.
 | 
			
		||||
	// We'll check for the 4-byte connection ID as a minimum requirement.
 | 
			
		||||
	const connectionIDLength = 4
 | 
			
		||||
	if len(data) < serverVersionEndPos+1+connectionIDLength {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var version Version
 | 
			
		||||
	fmt.Sscanf(string(data[1:serverVersionEndPos]), "%d.%d.%d-%s", &version.Major, &version.Minor, &version.Patch, &version.Extra)
 | 
			
		||||
 | 
			
		||||
	return &Protocol{
 | 
			
		||||
		Name:    ProtocolMySQL,
 | 
			
		||||
		Version: version,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								protocol/detect_mysql_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								protocol/detect_mysql_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestDetectMySQL(t *testing.T) {
 | 
			
		||||
	atomicFormats.Store([]format{{Server, "\x0a", detectMySQL}})
 | 
			
		||||
 | 
			
		||||
	// 1. A valid MySQL 8.0 banner
 | 
			
		||||
	mysql8Banner := []byte{
 | 
			
		||||
		0x0a, 0x38, 0x2e, 0x30, 0x2e, 0x33, 0x32, 0x00, 0x0d, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x04, 0x5a, 0x56, 0x5f, 0x3e, 0x6e, 0x76, 0x27, 0x00, 0xff, 0xff, 0xff,
 | 
			
		||||
		0x02, 0x00, 0xff, 0xc7, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x63, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x73,
 | 
			
		||||
		0x68, 0x61, 0x32, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 2. A valid MariaDB banner (protocol-compatible)
 | 
			
		||||
	mariaDBBanner := []byte{
 | 
			
		||||
		0x0a, 0x35, 0x2e, 0x35, 0x2e, 0x35, 0x2d, 0x31, 0x30, 0x2e, 0x36, 0x2e,
 | 
			
		||||
		0x35, 0x2d, 0x4d, 0x61, 0x72, 0x69, 0x61, 0x44, 0x42, 0x2d, 0x6c, 0x6f,
 | 
			
		||||
		0x67, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x4e, 0x5c, 0x32, 0x7b, 0x45, 0x3b,
 | 
			
		||||
		0x40, 0x60, 0x00, 0xff, 0xf7, 0x08, 0x02, 0x00, 0xff, 0x81, 0x15, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x79, 0x73,
 | 
			
		||||
		0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61,
 | 
			
		||||
		0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 3. An invalid banner (e.g., an HTTP request)
 | 
			
		||||
	httpBanner := []byte("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	// 4. A short, invalid slice
 | 
			
		||||
	shortSlice := []byte{0x0a, 0x31, 0x32, 0x33}
 | 
			
		||||
 | 
			
		||||
	// 5. A slice that starts correctly but is malformed (no null terminator)
 | 
			
		||||
	malformedSlice := []byte{0x0a, 0x38, 0x2e, 0x30, 0x2e, 0x30, 0x01, 0x02, 0x03, 0x04, 0x05}
 | 
			
		||||
 | 
			
		||||
	t.Run("MySQL 8", func(t *testing.T) {
 | 
			
		||||
		p, _ := Detect(Server, mysql8Banner)
 | 
			
		||||
		if p == nil {
 | 
			
		||||
			t.Fatal("expected MySQL protocol, got nil")
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("MariaDB", func(t *testing.T) {
 | 
			
		||||
		p, _ := Detect(Server, mariaDBBanner)
 | 
			
		||||
		if p == nil {
 | 
			
		||||
			t.Fatal("expected MySQL protocol, got nil")
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Invalid HTTP", func(t *testing.T) {
 | 
			
		||||
		_, err := Detect(Server, httpBanner)
 | 
			
		||||
		if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
			t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
		} else {
 | 
			
		||||
			t.Logf("error %q, as expected", err)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Too short", func(t *testing.T) {
 | 
			
		||||
		_, err := Detect(Server, shortSlice)
 | 
			
		||||
		if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
			t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
		} else {
 | 
			
		||||
			t.Logf("error %q, as expected", err)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Malformed", func(t *testing.T) {
 | 
			
		||||
		_, err := Detect(Server, malformedSlice)
 | 
			
		||||
		if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
			t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
		} else {
 | 
			
		||||
			t.Logf("error %q, as expected", err)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								protocol/detect_postgres.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								protocol/detect_postgres.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	registerPostgreSQL()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func registerPostgreSQL() {
 | 
			
		||||
	Register(Server, "R\x00???", detectPostgreSQLServer)             // Authentication request
 | 
			
		||||
	Register(Server, "K\x00???", detectPostgreSQLServer)             // BackendKeyData
 | 
			
		||||
	Register(Server, "S\x00???", detectPostgreSQLServer)             // ParameterStatus
 | 
			
		||||
	Register(Server, "Z\x00???", detectPostgreSQLServer)             // ReadyForQuery
 | 
			
		||||
	Register(Server, "E\x00???", detectPostgreSQLServer)             // ErrorResponse
 | 
			
		||||
	Register(Server, "N\x00???", detectPostgreSQLServer)             // NoticeResponse
 | 
			
		||||
	Register(Client, "????\x00\x02\x00\x00", detectPostgreSQLClient) // Startup packet, protocol 2.0
 | 
			
		||||
	Register(Client, "????\x00\x03\x00\x00", detectPostgreSQLClient) // Startup packet, protocol 3.0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectPostgreSQLClient(dir Direction, data []byte) *Protocol {
 | 
			
		||||
	// A client startup message needs at least 8 bytes (length + protocol version).
 | 
			
		||||
	if len(data) < 8 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	length := int(binary.BigEndian.Uint32(data[0:]))
 | 
			
		||||
	if len(data) != length {
 | 
			
		||||
		log.Printf("not postgres %q: %d != %d", data, len(data), length)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	major := int(binary.BigEndian.Uint16(data[4:]))
 | 
			
		||||
	minor := int(binary.BigEndian.Uint16(data[6:]))
 | 
			
		||||
	if major == 2 || major == 3 {
 | 
			
		||||
		return &Protocol{
 | 
			
		||||
			Name: ProtocolPostgreSQL,
 | 
			
		||||
			Version: Version{
 | 
			
		||||
				Major: major,
 | 
			
		||||
				Minor: minor,
 | 
			
		||||
				Patch: -1,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectPostgreSQLServer(dir Direction, data []byte) *Protocol {
 | 
			
		||||
	// A server message needs at least 5 bytes (type + length).
 | 
			
		||||
	if len(data) < 5 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// All server messages (and subsequent client messages) are tagged with a single-byte type.
 | 
			
		||||
	firstByte := data[0]
 | 
			
		||||
	switch firstByte {
 | 
			
		||||
	case 'R', // Authentication request
 | 
			
		||||
		'K', // BackendKeyData
 | 
			
		||||
		'S', // ParameterStatus
 | 
			
		||||
		'Z', // ReadyForQuery
 | 
			
		||||
		'E', // ErrorResponse
 | 
			
		||||
		'N': // NoticeResponse
 | 
			
		||||
		return &Protocol{Name: ProtocolPostgreSQL}
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										94
									
								
								protocol/detect_postgres_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								protocol/detect_postgres_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestDetectPostgreSQLClient(t *testing.T) {
 | 
			
		||||
	atomicFormats.Store([]format{})
 | 
			
		||||
	registerPostgreSQL()
 | 
			
		||||
 | 
			
		||||
	// 1. A valid PostgreSQL client startup message
 | 
			
		||||
	// Format: len (4b), proto (4b), params (n-bytes)
 | 
			
		||||
	// Here, user=mazeio, database=test
 | 
			
		||||
	// The message is: "user\0mazeio\0database\0test\0\0"
 | 
			
		||||
	// Total length: 4 (len) + 4 (proto) + 27 (params) = 35 (0x23)
 | 
			
		||||
	pgClientStartup := []byte{
 | 
			
		||||
		0x00, 0x00, 0x00, 0x23, // Length: 35
 | 
			
		||||
		0x00, 0x03, 0x00, 0x00, // Protocol Version 3.0
 | 
			
		||||
		'u', 's', 'e', 'r', 0x00, 'm', 'a', 'z', 'e', 'i', 'o', 0x00,
 | 
			
		||||
		'd', 'a', 't', 'a', 'b', 'a', 's', 'e', 0x00, 't', 'e', 's', 't', 0x00, 0x00,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Run("Protocol 3.0", func(t *testing.T) {
 | 
			
		||||
		p, err := Detect(Client, pgClientStartup)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
		if p.Name != ProtocolPostgreSQL {
 | 
			
		||||
			t.Fatalf("expected postgres protocol, got %s", p.Name)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDetectPostgreSQLServer(t *testing.T) {
 | 
			
		||||
	atomicFormats.Store([]format{})
 | 
			
		||||
	registerPostgreSQL()
 | 
			
		||||
 | 
			
		||||
	// A valid PostgreSQL server AuthenticationOk response
 | 
			
		||||
	// Format: type (1b), len (4b), content (4b)
 | 
			
		||||
	pgServerAuthOK := []byte{
 | 
			
		||||
		'R',                    // Type: Authentication
 | 
			
		||||
		0x00, 0x00, 0x00, 0x08, // Length: 8
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00, // Auth OK (0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A valid PostgreSQL server ErrorResponse
 | 
			
		||||
	pgServerError := []byte{
 | 
			
		||||
		'E',                    // Type: ErrorResponse
 | 
			
		||||
		0x00, 0x00, 0x00, 0x31, // Length
 | 
			
		||||
		'S', 'E', 'R', 'R', 'O', 'R', 0x00, // ... and so on
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Invalid data (HTTP GET request)
 | 
			
		||||
	httpBanner := []byte("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	t.Run("AuthenticationOk", func(t *testing.T) {
 | 
			
		||||
		p, err := Detect(Server, pgServerAuthOK)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
		if p.Name != ProtocolPostgreSQL {
 | 
			
		||||
			t.Fatalf("expected postgres protocol, got %s", p.Name)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("ErrorResponse", func(t *testing.T) {
 | 
			
		||||
		p, err := Detect(Server, pgServerError)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
		if p.Name != ProtocolPostgreSQL {
 | 
			
		||||
			t.Fatalf("expected postgres protocol, got %s", p.Name)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Invalid HTTP", func(t *testing.T) {
 | 
			
		||||
		_, err := Detect(Server, httpBanner)
 | 
			
		||||
		if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
			t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
		} else {
 | 
			
		||||
			t.Logf("error %q, as expected", err)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								protocol/detect_ssh.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								protocol/detect_ssh.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// The required prefix for the SSH protocol identification line.
 | 
			
		||||
const (
 | 
			
		||||
	ssh199Prefix = "SSH-1.99-"
 | 
			
		||||
	ssh20Prefix  = "SSH-2.0-"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	Register(Both, "", detectSSH)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectSSH(dir Direction, data []byte) *Protocol {
 | 
			
		||||
	// The data must be at least as long as the prefix itself.
 | 
			
		||||
	if len(data) < len(ssh20Prefix) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The protocol allows for pre-banner text, so we have to check all lines.
 | 
			
		||||
	for _, line := range bytes.Split(data, []byte{'\n'}) {
 | 
			
		||||
		line = bytes.TrimSuffix(line, []byte{'\r'})
 | 
			
		||||
		if bytes.HasPrefix(line, []byte(ssh20Prefix)) {
 | 
			
		||||
			return &Protocol{
 | 
			
		||||
				Name: ProtocolSSH,
 | 
			
		||||
				Version: Version{
 | 
			
		||||
					Major: 2,
 | 
			
		||||
					Minor: 0,
 | 
			
		||||
					Patch: -1,
 | 
			
		||||
					Extra: string(line[len(ssh20Prefix):]),
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if bytes.HasPrefix(line, []byte(ssh199Prefix)) {
 | 
			
		||||
			return &Protocol{
 | 
			
		||||
				Name: ProtocolSSH,
 | 
			
		||||
				Version: Version{
 | 
			
		||||
					Major: 1,
 | 
			
		||||
					Minor: 99,
 | 
			
		||||
					Patch: -1,
 | 
			
		||||
					Extra: string(line[len(ssh20Prefix):]),
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										103
									
								
								protocol/detect_ssh_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								protocol/detect_ssh_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestDetectSSH(t *testing.T) {
 | 
			
		||||
	atomicFormats.Store([]format{{Both, "", detectSSH}})
 | 
			
		||||
 | 
			
		||||
	// 1. A standard OpenSSH banner
 | 
			
		||||
	openSSHBanner := []byte("SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4\r\n")
 | 
			
		||||
 | 
			
		||||
	// 2. An SSH banner with a pre-banner legal notice
 | 
			
		||||
	preBannerSSH := []byte(
 | 
			
		||||
		"*******************************************************************\r\n" +
 | 
			
		||||
			"* W A R N I N G                          *\r\n" +
 | 
			
		||||
			"* This system is for the use of authorized users only.          *\r\n" +
 | 
			
		||||
			"*******************************************************************\r\n" +
 | 
			
		||||
			"SSH-2.0-OpenSSH_7.6p1\r\n",
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// 3. A different SSH implementation (Dropbear)
 | 
			
		||||
	dropbearBanner := []byte("SSH-2.0-dropbear_2020.81\r\n")
 | 
			
		||||
 | 
			
		||||
	// 4. An invalid banner (e.g., the MySQL banner from the previous example)
 | 
			
		||||
	mysqlBanner := []byte{
 | 
			
		||||
		0x0a, 0x38, 0x2e, 0x30, 0x2e, 0x33, 0x32, 0x00, 0x0d, 0x00, 0x00, 0x00,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 5. A simple HTTP request
 | 
			
		||||
	httpBanner := []byte("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
 | 
			
		||||
 | 
			
		||||
	t.Run("OpenSSH client", func(t *testing.T) {
 | 
			
		||||
		p, err := Detect(Server, openSSHBanner)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
		if p.Name != ProtocolSSH {
 | 
			
		||||
			t.Fatalf("expected ssh protocol, got %s", p.Name)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("OpenSSH server", func(t *testing.T) {
 | 
			
		||||
		p, err := Detect(Server, openSSHBanner)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
		if p.Name != ProtocolSSH {
 | 
			
		||||
			t.Fatalf("expected ssh protocol, got %s", p.Name)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("OpenSSH server with banner", func(t *testing.T) {
 | 
			
		||||
		p, err := Detect(Server, preBannerSSH)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
		if p.Name != ProtocolSSH {
 | 
			
		||||
			t.Fatalf("expected ssh protocol, got %s", p.Name)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Dropbear server", func(t *testing.T) {
 | 
			
		||||
		p, err := Detect(Server, dropbearBanner)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
		if p.Name != ProtocolSSH {
 | 
			
		||||
			t.Fatalf("expected ssh protocol, got %s", p.Name)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Invalid MySQL banner", func(t *testing.T) {
 | 
			
		||||
		_, err := Detect(Server, mysqlBanner)
 | 
			
		||||
		if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
			t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
		} else {
 | 
			
		||||
			t.Logf("error %q, as expected", err)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Invalid HTTP banner", func(t *testing.T) {
 | 
			
		||||
		_, err := Detect(Server, httpBanner)
 | 
			
		||||
		if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
			t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
		} else {
 | 
			
		||||
			t.Logf("error %q, as expected", err)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								protocol/detect_tls.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								protocol/detect_tls.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"golang.org/x/crypto/cryptobyte"
 | 
			
		||||
 | 
			
		||||
	"git.maze.io/go/dpi"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	registerTLS()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func registerTLS() {
 | 
			
		||||
	Register(Both, "\x16\x03\x00", detectTLS) // SSLv3
 | 
			
		||||
	Register(Both, "\x16\x03\x01", detectTLS) // TLSv1.0
 | 
			
		||||
	Register(Both, "\x16\x03\x02", detectTLS) // TLSv1.1
 | 
			
		||||
	Register(Both, "\x16\x03\x03", detectTLS) // TLSv1.2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detectTLS(dir Direction, data []byte) *Protocol {
 | 
			
		||||
	stream := cryptobyte.String(data)
 | 
			
		||||
 | 
			
		||||
	// A TLS packet always has a content type (1 byte), version (2 bytes) and length (2 bytes).
 | 
			
		||||
	if len(stream) < 5 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check for TLS Handshake (type 22)
 | 
			
		||||
	var header struct {
 | 
			
		||||
		Type    uint8
 | 
			
		||||
		Version uint16
 | 
			
		||||
		Length  uint32
 | 
			
		||||
	}
 | 
			
		||||
	if !stream.ReadUint8(&header.Type) || header.Type != 0x16 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if !stream.ReadUint16(&header.Version) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if !stream.ReadUint24(&header.Length) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Detected SSL/TLS version
 | 
			
		||||
	var version dpi.TLSVersion
 | 
			
		||||
 | 
			
		||||
	// Attempt to decode the full TLS Client Hello handshake
 | 
			
		||||
	if version == 0 {
 | 
			
		||||
		if hello, err := dpi.DecodeTLSClientHelloHandshake(data); err == nil {
 | 
			
		||||
			version = hello.Version
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Attempt to decode the full TLS Server Hello handshake
 | 
			
		||||
	if version == 0 {
 | 
			
		||||
		if hello, err := dpi.DecodeTLSServerHello(data); err == nil {
 | 
			
		||||
			version = hello.Version
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Attempt to decode at least the handshake protocol and version.
 | 
			
		||||
	if version == 0 && !Strict {
 | 
			
		||||
		var handshakeType uint8
 | 
			
		||||
		if stream.ReadUint8(&handshakeType) && (handshakeType == 1 || handshakeType == 2) {
 | 
			
		||||
			var (
 | 
			
		||||
				length      uint32
 | 
			
		||||
				versionWord uint16
 | 
			
		||||
			)
 | 
			
		||||
			if stream.ReadUint24(&length) && stream.ReadUint16(&versionWord) {
 | 
			
		||||
				version = dpi.TLSVersion(versionWord)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Fall back to the version in the TLS record header, this is less accurate
 | 
			
		||||
	if version == 0 && !Strict {
 | 
			
		||||
		version = dpi.TLSVersion(header.Version)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// We're "multi protocol", in that SSL is its own protocol
 | 
			
		||||
	if version == dpi.VersionSSL30 {
 | 
			
		||||
		return &Protocol{
 | 
			
		||||
			Name:    ProtocolSSL,
 | 
			
		||||
			Version: Version{Major: 3, Minor: 0, Patch: -1},
 | 
			
		||||
		}
 | 
			
		||||
	} else if version >= dpi.VersionTLS10 && version <= dpi.VersionTLS13 {
 | 
			
		||||
		return &Protocol{
 | 
			
		||||
			Name:    ProtocolTLS,
 | 
			
		||||
			Version: Version{Major: 1, Minor: int(uint8(version) - 1), Patch: -1},
 | 
			
		||||
		}
 | 
			
		||||
	} else if version >= dpi.VersionTLS13Draft && version <= dpi.VersionTLS13Draft23 {
 | 
			
		||||
		return &Protocol{
 | 
			
		||||
			Name:    ProtocolTLS,
 | 
			
		||||
			Version: Version{Major: 1, Minor: 3, Patch: -1},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										280
									
								
								protocol/detect_tls_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								protocol/detect_tls_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,280 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestDetectTLS(t *testing.T) {
 | 
			
		||||
	atomicFormats.Store([]format{})
 | 
			
		||||
	registerTLS()
 | 
			
		||||
 | 
			
		||||
	// A SSLv3 Client Hello
 | 
			
		||||
	sslV3ClientHello := testMustDecodeHexString(`
 | 
			
		||||
		                  16 03 00 00 51 01 00 00 4d 03
 | 
			
		||||
		00 50 42 b2 29 1f cf 52 a0 94 87 05 e7 0b 63 08
 | 
			
		||||
		12 a2 6c 59 f7 f5 72 2b 57 14 a7 07 95 cb ce e5
 | 
			
		||||
		e4 00 00 26 00 04 00 05 00 2f 00 33 00 32 00 0a
 | 
			
		||||
		fe ff 00 16 00 13 00 66 00 09 fe fe 00 15 00 12
 | 
			
		||||
		00 03 00 08 00 06 00 14 00 11 01 00`)
 | 
			
		||||
 | 
			
		||||
	// A synthesized TLS 1.1 ClientHello
 | 
			
		||||
	tls11ClientHello := []byte{
 | 
			
		||||
		// --- Record Layer (5 bytes) ---
 | 
			
		||||
		0x16,       // Content Type: Handshake (22)
 | 
			
		||||
		0x03, 0x02, // Version: TLS 1.1 (Major=3, Minor=2)
 | 
			
		||||
		0x00, 0x45, // Length of the handshake message below (69 bytes)
 | 
			
		||||
 | 
			
		||||
		// --- Handshake Protocol: ClientHello (69 bytes) ---
 | 
			
		||||
		0x01,             // Handshake Type: ClientHello (1)
 | 
			
		||||
		0x00, 0x00, 0x41, // Length of the rest of the message (65 bytes)
 | 
			
		||||
		0x03, 0x02, // Client Version: TLS 1.1 (Major=3, Minor=2)
 | 
			
		||||
 | 
			
		||||
		// Random (32 bytes):
 | 
			
		||||
		// In TLS 1.1+, the entire 32 bytes are fully random.
 | 
			
		||||
		// The timestamp structure from SSLv3 is removed.
 | 
			
		||||
		0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
 | 
			
		||||
		0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00,
 | 
			
		||||
		0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
 | 
			
		||||
		0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00,
 | 
			
		||||
 | 
			
		||||
		// Session ID
 | 
			
		||||
		0x00, // Session ID Length: 0 (new session)
 | 
			
		||||
 | 
			
		||||
		// Cipher Suites
 | 
			
		||||
		0x00, 0x04, // Cipher Suites Length: 4 bytes (2 suites)
 | 
			
		||||
		0x00, 0x2F, // Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA
 | 
			
		||||
		0x00, 0x35, // Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA
 | 
			
		||||
 | 
			
		||||
		// Compression Methods
 | 
			
		||||
		0x01, // Compression Methods Length: 1 byte
 | 
			
		||||
		0x00, // Compression Method: NULL (0)
 | 
			
		||||
 | 
			
		||||
		// --- Extensions (20 bytes) ---
 | 
			
		||||
		0x00, 0x14, // Extensions Length: 20 bytes
 | 
			
		||||
		// Extension: Server Name Indication (SNI)
 | 
			
		||||
		0x00, 0x00, // Extension Type: server_name (0)
 | 
			
		||||
		0x00, 0x10, // Extension Length: 16 bytes
 | 
			
		||||
		0x00, 0x0E, // Server Name List Length: 14 bytes
 | 
			
		||||
		0x00,       // Server Name Type: host_name (0)
 | 
			
		||||
		0x00, 0x0B, // Server Name Length: 11 bytes
 | 
			
		||||
		// Server Name: "example.com"
 | 
			
		||||
		'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A synthesized partial TLS 1.1 ClientHello
 | 
			
		||||
	tls11ClientHelloPartial := []byte{
 | 
			
		||||
		// --- Record Layer (5 bytes) ---
 | 
			
		||||
		0x16,       // Content Type: Handshake (22)
 | 
			
		||||
		0x03, 0x02, // Version: TLS 1.1 (Major=3, Minor=2)
 | 
			
		||||
		0x00, 0x45, // Length of the handshake message below (69 bytes)
 | 
			
		||||
 | 
			
		||||
		// --- Handshake Protocol: ClientHello (69 bytes) ---
 | 
			
		||||
		0x01,             // Handshake Type: ClientHello (1)
 | 
			
		||||
		0x00, 0x00, 0x41, // Length of the rest of the message (65 bytes)
 | 
			
		||||
		0x03, 0x02, // Client Version: TLS 1.1 (Major=3, Minor=2)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A synthesized TLSv1.2 ClientHello
 | 
			
		||||
	tls12ClientHello := []byte{
 | 
			
		||||
		// --- Record Layer (5 bytes) ---
 | 
			
		||||
		0x16,       // Content Type: Handshake (22)
 | 
			
		||||
		0x03, 0x03, // Version: TLS 1.2 (Major=3, Minor=3)
 | 
			
		||||
		0x00, 0x61, // Length of handshake message below (97 bytes)
 | 
			
		||||
 | 
			
		||||
		// --- Handshake Protocol: ClientHello (97 bytes) ---
 | 
			
		||||
		0x01,             // Handshake Type: ClientHello (1)
 | 
			
		||||
		0x00, 0x00, 0x5D, // Length of the rest of the message (93 bytes)
 | 
			
		||||
		0x03, 0x03, // Client Version: TLS 1.2 (Major=3, Minor=3)
 | 
			
		||||
 | 
			
		||||
		// Random (32 bytes)
 | 
			
		||||
		0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11,
 | 
			
		||||
		0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
 | 
			
		||||
		0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11,
 | 
			
		||||
		0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
 | 
			
		||||
 | 
			
		||||
		// Session ID
 | 
			
		||||
		0x00, // Session ID Length: 0 (new session)
 | 
			
		||||
 | 
			
		||||
		// Cipher Suites (using modern GCM suites)
 | 
			
		||||
		0x00, 0x04, // Cipher Suites Length: 4 bytes (2 suites)
 | 
			
		||||
		0xC0, 0x2F, // Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 | 
			
		||||
		0xC0, 0x30, // Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 | 
			
		||||
 | 
			
		||||
		// Compression Methods
 | 
			
		||||
		0x01, // Compression Methods Length: 1 byte
 | 
			
		||||
		0x00, // Compression Method: NULL (0)
 | 
			
		||||
 | 
			
		||||
		// --- Extensions (48 bytes) ---
 | 
			
		||||
		0x00, 0x30, // Extensions Length: 48 bytes
 | 
			
		||||
		// Extension: Server Name Indication (SNI) (20 bytes)
 | 
			
		||||
		0x00, 0x00, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x0B,
 | 
			
		||||
		'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm',
 | 
			
		||||
		// Extension: Signature Algorithms (10 bytes) - CRITICAL for TLS 1.2
 | 
			
		||||
		0x00, 0x0D, // Extension Type: signature_algorithms (13)
 | 
			
		||||
		0x00, 0x06, // Extension Length: 6 bytes
 | 
			
		||||
		0x00, 0x04, // Hash/Signature Algorithm List Length: 4 bytes
 | 
			
		||||
		0x04, 0x01, // Algorithm: rsa_pkcs1_sha256
 | 
			
		||||
		0x05, 0x01, // Algorithm: rsa_pkcs1_sha384
 | 
			
		||||
		// Extension: Application-Layer Protocol Negotiation (ALPN) (18 bytes)
 | 
			
		||||
		0x00, 0x10, // Extension Type: application_layer_protocol_negotiation (16)
 | 
			
		||||
		0x00, 0x0E, // Extension Length: 14 bytes
 | 
			
		||||
		0x00, 0x0C, // ALPN Extension Length: 12 bytes
 | 
			
		||||
		// ALPN Protocol: "h2" (HTTP/2)
 | 
			
		||||
		0x02, 'h', '2',
 | 
			
		||||
		// ALPN Protocol: "http/1.1"
 | 
			
		||||
		0x08, 'h', 't', 't', 'p', '/', '1', '.', '1',
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A valid TLS 1.3 Client Hello (captured from a real connection)
 | 
			
		||||
	tls13ClientHello := []byte{
 | 
			
		||||
		0x16,       // Content Type: Handshake (22)
 | 
			
		||||
		0x03, 0x01, // Version: TLS 1.0 (for compatibility in a 1.3 hello)
 | 
			
		||||
		0x01, 0x3a, // Length
 | 
			
		||||
		0x01, 0x00, 0x01, 0x36, 0x03, 0x03, 0xb1,
 | 
			
		||||
		0x40, 0xd3, 0xf1, 0x7d, 0xa3, 0xb8, 0x33, 0xac, 0xad, 0x21, 0x79, 0x9c,
 | 
			
		||||
		0xbe, 0x39, 0x96, 0x08, 0x49, 0x3b, 0x53, 0x75, 0xa0, 0x1b, 0xee, 0x6e,
 | 
			
		||||
		0x6a, 0xbe, 0x6c, 0x41, 0xdf, 0x6c, 0xf4, 0x20, 0xa4, 0xaa, 0x0c, 0xca,
 | 
			
		||||
		0xd4, 0x37, 0x76, 0x5f, 0x49, 0xc6, 0x06, 0x9b, 0xac, 0x90, 0x89, 0x76,
 | 
			
		||||
		0x1c, 0xc7, 0xc4, 0x12, 0xb4, 0x4a, 0xe0, 0x27, 0x72, 0x89, 0x97, 0x85,
 | 
			
		||||
		0x76, 0xf8, 0xc8, 0x83, 0x00, 0x62, 0x13, 0x03, 0x13, 0x02, 0x13, 0x01,
 | 
			
		||||
		0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28,
 | 
			
		||||
		0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39,
 | 
			
		||||
		0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, 0x00, 0x3d,
 | 
			
		||||
		0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27,
 | 
			
		||||
		0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, 0x00, 0x33,
 | 
			
		||||
		0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba,
 | 
			
		||||
		0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12,
 | 
			
		||||
		0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x8b,
 | 
			
		||||
		0x00, 0x2b, 0x00, 0x09, 0x08, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x03,
 | 
			
		||||
		0x01, 0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x2c,
 | 
			
		||||
		0x4b, 0xaa, 0xb4, 0xb3, 0xc8, 0x93, 0xcd, 0x5c, 0x24, 0xb9, 0x9b, 0xd4,
 | 
			
		||||
		0x59, 0x04, 0xfe, 0x69, 0xaf, 0x68, 0xb9, 0xa6, 0x36, 0xbb, 0xab, 0x87,
 | 
			
		||||
		0xfa, 0x15, 0x59, 0xea, 0xdd, 0x38, 0x68, 0x00, 0x00, 0x00, 0x0e, 0x00,
 | 
			
		||||
		0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
 | 
			
		||||
		0x74, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00,
 | 
			
		||||
		0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0d, 0x00,
 | 
			
		||||
		0x18, 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, 0x08, 0x05, 0x05,
 | 
			
		||||
		0x01, 0x05, 0x03, 0x08, 0x04, 0x04, 0x01, 0x04, 0x03, 0x02, 0x01, 0x02,
 | 
			
		||||
		0x03, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08, 0x68,
 | 
			
		||||
		0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Invalid data (Postgres client startup)
 | 
			
		||||
	pgClientStartup := []byte{
 | 
			
		||||
		0x00, 0x00, 0x00, 0x25, 0x00, 0x03, 0x00, 0x00,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() { Strict = false }()
 | 
			
		||||
	for _, strict := range []bool{false, true} {
 | 
			
		||||
		Strict = strict
 | 
			
		||||
 | 
			
		||||
		name := "loose"
 | 
			
		||||
		if strict {
 | 
			
		||||
			name = "strict"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		t.Run(name, func(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
			t.Run("SSLv3 Client Hello", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Client, sslV3ClientHello)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolSSL {
 | 
			
		||||
					t.Fatalf("expected ssl protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("TLS 1.1 Client Hello", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Client, tls11ClientHello)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolTLS {
 | 
			
		||||
					t.Fatalf("expected tls protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("TLS 1.1 partial Client Hello", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Client, tls11ClientHelloPartial)
 | 
			
		||||
				if strict {
 | 
			
		||||
					if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
						t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
					} else {
 | 
			
		||||
						t.Logf("error %q, as expected", err)
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						t.Fatal(err)
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
					t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
					if p.Name != ProtocolTLS {
 | 
			
		||||
						t.Fatalf("expected tls protocol, got %s", p.Name)
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("TLS 1.2 Client Hello", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Client, tls12ClientHello)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolTLS {
 | 
			
		||||
					t.Fatalf("expected tls protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("TLS 1.3 Client Hello", func(t *testing.T) {
 | 
			
		||||
				p, err := Detect(Client, tls13ClientHello)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatal(err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t.Logf("detected %s version %s", p.Name, p.Version)
 | 
			
		||||
				if p.Name != ProtocolTLS {
 | 
			
		||||
					t.Fatalf("expected tls protocol, got %s", p.Name)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			t.Run("Invalid PostgreSQL", func(t *testing.T) {
 | 
			
		||||
				_, err := Detect(Server, pgClientStartup)
 | 
			
		||||
				if !errors.Is(err, ErrUnknown) {
 | 
			
		||||
					t.Fatalf("expected unknown format, got error %T: %q", err, err)
 | 
			
		||||
				} else {
 | 
			
		||||
					t.Logf("error %q, as expected", err)
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testDecodeHexString(s string) ([]byte, error) {
 | 
			
		||||
	s = strings.TrimSpace(s)
 | 
			
		||||
	s = strings.ReplaceAll(s, " ", "")
 | 
			
		||||
	s = strings.ReplaceAll(s, "\n", "")
 | 
			
		||||
	s = strings.ReplaceAll(s, "\t", "")
 | 
			
		||||
	return hex.DecodeString(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testMustDecodeHexString(s string) []byte {
 | 
			
		||||
	b, err := testDecodeHexString(s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return b
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										128
									
								
								protocol/intercept.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								protocol/intercept.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Intercepted is the result returned by [Interceptor.Detect].
 | 
			
		||||
type Intercepted struct {
 | 
			
		||||
	Direction Direction
 | 
			
		||||
	Protocol  *Protocol
 | 
			
		||||
	Error     error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Interceptor intercepts reads from client or server.
 | 
			
		||||
type Interceptor struct {
 | 
			
		||||
	clientBytes  chan []byte
 | 
			
		||||
	clientReader *readInterceptor
 | 
			
		||||
	serverBytes  chan []byte
 | 
			
		||||
	serverReader *readInterceptor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewInterceptor creates a new (transparent) protocol interceptor.
 | 
			
		||||
func NewInterceptor() *Interceptor {
 | 
			
		||||
	return &Interceptor{
 | 
			
		||||
		clientBytes: make(chan []byte, 1),
 | 
			
		||||
		serverBytes: make(chan []byte, 1),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type readInterceptor struct {
 | 
			
		||||
	net.Conn
 | 
			
		||||
	bytes chan []byte
 | 
			
		||||
	once  atomic.Bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newReadInterceptor(c net.Conn, bytes chan []byte) *readInterceptor {
 | 
			
		||||
	return &readInterceptor{
 | 
			
		||||
		Conn:  c,
 | 
			
		||||
		bytes: bytes,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Cancel any future Read interceptions and closes the channel.
 | 
			
		||||
func (r *readInterceptor) Cancel() {
 | 
			
		||||
	if r == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	r.once.Store(true)
 | 
			
		||||
	close(r.bytes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *readInterceptor) Read(p []byte) (n int, err error) {
 | 
			
		||||
	if r.once.CompareAndSwap(false, true) {
 | 
			
		||||
		if n, err = r.Conn.Read(p); n > 0 {
 | 
			
		||||
			// We create a copy, since the Read caller may modify p
 | 
			
		||||
			// immediately after reading.
 | 
			
		||||
			data := make([]byte, n)
 | 
			
		||||
			copy(data, p[:n])
 | 
			
		||||
			// Buffer the bytes in the channel.
 | 
			
		||||
			r.bytes <- data
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return r.Conn.Read(p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client binds the client connection to the interceptor.
 | 
			
		||||
func (i *Interceptor) Client(c net.Conn) net.Conn {
 | 
			
		||||
	if ri, ok := c.(*readInterceptor); ok {
 | 
			
		||||
		return ri
 | 
			
		||||
	}
 | 
			
		||||
	i.clientReader = newReadInterceptor(c, i.clientBytes)
 | 
			
		||||
	return i.clientReader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Server binds the server connection to the interceptor.
 | 
			
		||||
func (i *Interceptor) Server(c net.Conn) net.Conn {
 | 
			
		||||
	if ri, ok := c.(*readInterceptor); ok {
 | 
			
		||||
		return ri
 | 
			
		||||
	}
 | 
			
		||||
	i.serverReader = newReadInterceptor(c, i.serverBytes)
 | 
			
		||||
	return i.serverReader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Detect runs protocol detection on the previously bound Client and Server connection.
 | 
			
		||||
//
 | 
			
		||||
// It waits until either the client or the server performs a read operation,
 | 
			
		||||
// which is then used for running protocol detection. If the read operation
 | 
			
		||||
// takes longer than timeout, an error is returned.
 | 
			
		||||
//
 | 
			
		||||
// The returned channel always yields one result and is then closed.
 | 
			
		||||
func (i *Interceptor) Detect(timeout time.Duration) <-chan *Intercepted {
 | 
			
		||||
	var interceptc = make(chan *Intercepted, 1)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		// Make sure all channels are closed once we finish processing.
 | 
			
		||||
		defer close(interceptc)
 | 
			
		||||
		defer i.clientReader.Cancel()
 | 
			
		||||
		defer i.serverReader.Cancel()
 | 
			
		||||
 | 
			
		||||
		select {
 | 
			
		||||
		case <-time.After(timeout): // timeout
 | 
			
		||||
			interceptc <- &Intercepted{
 | 
			
		||||
				Error: ErrTimeout,
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case data := <-i.clientBytes: // client sent banner
 | 
			
		||||
			p, err := Detect(Client, data)
 | 
			
		||||
			interceptc <- &Intercepted{
 | 
			
		||||
				Direction: Client,
 | 
			
		||||
				Protocol:  p,
 | 
			
		||||
				Error:     err,
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case data := <-i.serverBytes: // server sent banner
 | 
			
		||||
			p, err := Detect(Server, data)
 | 
			
		||||
			interceptc <- &Intercepted{
 | 
			
		||||
				Direction: Server,
 | 
			
		||||
				Protocol:  p,
 | 
			
		||||
				Error:     err,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return interceptc
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								protocol/limit.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								protocol/limit.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AcceptFunc receives a direction and a detected protocol.
 | 
			
		||||
type AcceptFunc func(Direction, *Protocol) error
 | 
			
		||||
 | 
			
		||||
// Limit the connection protocol, by running a detection after either side sends
 | 
			
		||||
// a banner within timeout.
 | 
			
		||||
//
 | 
			
		||||
// If no protocol could be detected, the accept function is called with a nil
 | 
			
		||||
// argument to check if we should proceed.
 | 
			
		||||
//
 | 
			
		||||
// If the accept function returns false, the connection will be closed.
 | 
			
		||||
func Limit(conn net.Conn, accept AcceptFunc) net.Conn {
 | 
			
		||||
	if accept == nil {
 | 
			
		||||
		// Nothing to do here.
 | 
			
		||||
		return conn
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &connLimiter{
 | 
			
		||||
		Conn:   conn,
 | 
			
		||||
		accept: accept,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type connLimiter struct {
 | 
			
		||||
	net.Conn
 | 
			
		||||
	accept      AcceptFunc
 | 
			
		||||
	acceptOnce  sync.Once
 | 
			
		||||
	acceptError atomic.Value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *connLimiter) init(readData, writeData []byte) {
 | 
			
		||||
	l.acceptOnce.Do(func() {
 | 
			
		||||
		var (
 | 
			
		||||
			dir  Direction
 | 
			
		||||
			data []byte
 | 
			
		||||
		)
 | 
			
		||||
		if readData != nil {
 | 
			
		||||
			// init called by initial read
 | 
			
		||||
			dir, data = Server, readData
 | 
			
		||||
		} else {
 | 
			
		||||
			// init called by initial write
 | 
			
		||||
			dir, data = Client, writeData
 | 
			
		||||
		}
 | 
			
		||||
		protocol, _ := Detect(dir, data)
 | 
			
		||||
		if err := l.accept(dir, protocol); err != nil {
 | 
			
		||||
			l.acceptError.Store(err)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *connLimiter) Read(p []byte) (n int, err error) {
 | 
			
		||||
	var ok bool
 | 
			
		||||
	if err, ok = l.acceptError.Load().(error); ok && err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if n, err = l.Conn.Read(p); n > 0 {
 | 
			
		||||
		l.init(p[:n], nil)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *connLimiter) Write(p []byte) (n int, err error) {
 | 
			
		||||
	l.init(nil, p)
 | 
			
		||||
	var ok bool
 | 
			
		||||
	if err, ok = l.acceptError.Load().(error); ok && err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return l.Conn.Write(p)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								protocol/protocol.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								protocol/protocol.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
package protocol
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Protocols supported by this package.
 | 
			
		||||
const (
 | 
			
		||||
	ProtocolDNS        = "dns"
 | 
			
		||||
	ProtocolHTTP       = "http"
 | 
			
		||||
	ProtocolMySQL      = "mysql"
 | 
			
		||||
	ProtocolPostgreSQL = "postgresql"
 | 
			
		||||
	ProtocolSSH        = "ssh"
 | 
			
		||||
	ProtocolSSL        = "ssl"
 | 
			
		||||
	ProtocolTLS        = "tls"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Protocol struct {
 | 
			
		||||
	Name    string
 | 
			
		||||
	Version Version
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Version struct {
 | 
			
		||||
	Major int
 | 
			
		||||
	Minor int
 | 
			
		||||
	Patch int
 | 
			
		||||
	Extra string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v Version) String() string {
 | 
			
		||||
	p := make([]string, 0, 3)
 | 
			
		||||
	if v.Major >= 0 {
 | 
			
		||||
		p = append(p, strconv.Itoa(v.Major))
 | 
			
		||||
		if v.Minor >= 0 {
 | 
			
		||||
			p = append(p, strconv.Itoa(v.Minor))
 | 
			
		||||
			if v.Patch >= 0 {
 | 
			
		||||
				p = append(p, strconv.Itoa(v.Patch))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	s := strings.Join(p, ".")
 | 
			
		||||
	if v.Extra != "" {
 | 
			
		||||
		return s + "-" + v.Extra
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								testdata/tls13-clienthello.bin
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								testdata/tls13-clienthello.bin
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										455
									
								
								tls.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								tls.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,455 @@
 | 
			
		||||
package dpi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/cryptobyte"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TLSExtension is a TLS extension.
 | 
			
		||||
type TLSExtension struct {
 | 
			
		||||
	Type uint16
 | 
			
		||||
	Data []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TLSRecord is a TLS record.
 | 
			
		||||
type TLSRecord struct {
 | 
			
		||||
	Raw     []byte
 | 
			
		||||
	Type    uint8
 | 
			
		||||
	Version uint16
 | 
			
		||||
	Length  uint16
 | 
			
		||||
	Data    []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DecodeTLSRecord(data []byte) (*TLSRecord, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		stream = cryptobyte.String(data)
 | 
			
		||||
		record = &TLSRecord{Raw: data}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if !stream.ReadUint8(&record.Type) ||
 | 
			
		||||
		!stream.ReadUint16(&record.Version) ||
 | 
			
		||||
		!stream.ReadUint16(&record.Length) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "invalid TLS record header",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !stream.ReadBytes(&record.Data, int(record.Length)) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "invalid TLS record data",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !stream.Empty() {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "extraneous data after TLS record",
 | 
			
		||||
			Err:    ErrInvalid,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return record, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TLSClientHello is a TLS ClientHello packet as part of the TLS handshake.
 | 
			
		||||
type TLSClientHello struct {
 | 
			
		||||
	Raw                          []byte
 | 
			
		||||
	Version                      TLSVersion
 | 
			
		||||
	Random                       []byte
 | 
			
		||||
	SessionID                    []byte
 | 
			
		||||
	CipherSuites                 []uint16
 | 
			
		||||
	CompressionMethods           []uint8
 | 
			
		||||
	Extensions                   []TLSExtension
 | 
			
		||||
	ServerName                   string
 | 
			
		||||
	SupportedCurves              []uint16             // aka "Supported Groups"
 | 
			
		||||
	SupportedSignatureAlgorithms []TLSSignatureScheme // RFC 5246, Section 7.4.1.4.1
 | 
			
		||||
	ALPNProtocols                []string             // RFC 7301, Section 3.1
 | 
			
		||||
	SupportedVersions            []TLSVersion         // RFC 8446, Section 4.2.1z
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DecodeTLSClientHello(data []byte) (*TLSClientHello, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		stream = cryptobyte.String(data)
 | 
			
		||||
		hello  = &TLSClientHello{Raw: data}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Read header (4 bytes)
 | 
			
		||||
	var handshakeType uint8
 | 
			
		||||
	if !stream.ReadUint8(&handshakeType) || handshakeType != tlsTypeClientHello {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: fmt.Sprintf("expected a TLS ClientHello (0x%02X), got 0x%02X", tlsTypeClientHello, handshakeType),
 | 
			
		||||
			Err:    ErrInvalid,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var record cryptobyte.String
 | 
			
		||||
	if !stream.ReadUint24LengthPrefixed(&record) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS record",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !stream.Empty() {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "invalid TLS record length",
 | 
			
		||||
			Err:    ErrInvalid,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parser client version.
 | 
			
		||||
	var version uint16
 | 
			
		||||
	if !record.ReadUint16(&version) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS version",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	hello.Version = TLSVersion(version)
 | 
			
		||||
 | 
			
		||||
	// Parse random (32 bytes)
 | 
			
		||||
	if !record.ReadBytes(&hello.Random, 32) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS random bytes",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse session ID
 | 
			
		||||
	var sessionID cryptobyte.String
 | 
			
		||||
	if !record.ReadUint8LengthPrefixed(&sessionID) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS session ID",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	hello.SessionID = sessionID
 | 
			
		||||
 | 
			
		||||
	// Parse cipher suites
 | 
			
		||||
	var cipherSuites cryptobyte.String
 | 
			
		||||
	if !record.ReadUint16LengthPrefixed(&cipherSuites) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS cipher suites bytes",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for !cipherSuites.Empty() {
 | 
			
		||||
		var cipherSuite uint16
 | 
			
		||||
		if !cipherSuites.ReadUint16(&cipherSuite) {
 | 
			
		||||
			return nil, DecodeError{
 | 
			
		||||
				Reason: "incomplete TLS cipher suite",
 | 
			
		||||
				Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		hello.CipherSuites = append(hello.CipherSuites, cipherSuite)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse compression methods
 | 
			
		||||
	var compressionMethods cryptobyte.String
 | 
			
		||||
	if !record.ReadUint8LengthPrefixed(&compressionMethods) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS compression methods bytes",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	hello.CompressionMethods = compressionMethods
 | 
			
		||||
 | 
			
		||||
	// Parse extensions (optional)
 | 
			
		||||
	if record.Empty() {
 | 
			
		||||
		return hello, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var extensions cryptobyte.String
 | 
			
		||||
	if !record.ReadUint16LengthPrefixed(&extensions) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS extensions",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !record.Empty() {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "extraneous TLS extension data",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for !extensions.Empty() {
 | 
			
		||||
		var (
 | 
			
		||||
			extension     TLSExtension
 | 
			
		||||
			extensionData = cryptobyte.String(extension.Data)
 | 
			
		||||
		)
 | 
			
		||||
		if !extensions.ReadUint16(&extension.Type) || !extensions.ReadUint16LengthPrefixed(&extensionData) {
 | 
			
		||||
			return nil, DecodeError{
 | 
			
		||||
				Reason: "incomplete TLS extension record data",
 | 
			
		||||
				Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		hello.Extensions = append(hello.Extensions, extension)
 | 
			
		||||
 | 
			
		||||
		switch extension.Type {
 | 
			
		||||
		case tlsExtensionServerName:
 | 
			
		||||
			// RFC 6066, Section 3
 | 
			
		||||
			if !readTLSServerName(extensionData, &hello.ServerName) {
 | 
			
		||||
				return nil, DecodeError{
 | 
			
		||||
					Reason: "invalid TLS server name extension data",
 | 
			
		||||
					Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case tlsExtensionSupportedGroups:
 | 
			
		||||
			// RFC 4492, Section 5.1.1
 | 
			
		||||
			// RFC 8446, Section 4.2.7
 | 
			
		||||
			if !readTLSSupportedGroups(extensionData, &hello.SupportedCurves) {
 | 
			
		||||
				return nil, DecodeError{
 | 
			
		||||
					Reason: "invalid TLS supported groups extension data",
 | 
			
		||||
					Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case tlsExtensionSignatureAlgorithms:
 | 
			
		||||
			// RFC 5246, Section 7.4.1
 | 
			
		||||
			if !readTLSSignatureAlgorithms(extensionData, &hello.SupportedSignatureAlgorithms) {
 | 
			
		||||
				return nil, DecodeError{
 | 
			
		||||
					Reason: "invalid TLS supported signature algorithms extension data",
 | 
			
		||||
					Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case tlsExtensionALPN:
 | 
			
		||||
			if !readTLSALPN(extensionData, &hello.ALPNProtocols) {
 | 
			
		||||
				return nil, DecodeError{
 | 
			
		||||
					Reason: "invalid TLS ALPN extension data",
 | 
			
		||||
					Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case tlsExtensionSupportedVersions:
 | 
			
		||||
			if !readTLSSupportedVersions(extensionData, &hello.SupportedVersions) {
 | 
			
		||||
				return nil, DecodeError{
 | 
			
		||||
					Reason: "invalid TLS supported versions extension data",
 | 
			
		||||
					Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hello, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DecodeTLSClientHelloHandshake(data []byte) (*TLSClientHello, error) {
 | 
			
		||||
	record, err := DecodeTLSRecord(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if record.Type != tlsRecordTypeHandshake {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: fmt.Sprintf("expected TLS handshake record type (0x%02X), got 0x%02X", tlsRecordTypeHandshake, record.Type),
 | 
			
		||||
			Err:    ErrInvalid,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return DecodeTLSClientHello(record.Data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TLSServerHello is a TLS ServerHello packet as part of the TLS handshake.
 | 
			
		||||
type TLSServerHello struct {
 | 
			
		||||
	Raw               []byte
 | 
			
		||||
	Version           TLSVersion
 | 
			
		||||
	RandomTimestamp   time.Time
 | 
			
		||||
	Random            []byte
 | 
			
		||||
	SessionID         []byte
 | 
			
		||||
	CipherSuite       uint16
 | 
			
		||||
	CompressionMethod uint8
 | 
			
		||||
	Extensions        []TLSExtension
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DecodeTLSServerHello(data []byte) (*TLSServerHello, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		stream = cryptobyte.String(data)
 | 
			
		||||
		hello  = &TLSServerHello{Raw: data}
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Read header (4 bytes)
 | 
			
		||||
	var handshakeType uint8
 | 
			
		||||
	if !stream.ReadUint8(&handshakeType) || handshakeType != tlsTypeServerHello {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: fmt.Sprintf("expected a TLS ServerHello (0x%02X), got 0x%02X", tlsTypeServerHello, handshakeType),
 | 
			
		||||
			Err:    ErrInvalid,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var record cryptobyte.String
 | 
			
		||||
	if !stream.ReadUint24LengthPrefixed(&record) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS record",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !stream.Empty() {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "invalid TLS record length",
 | 
			
		||||
			Err:    ErrInvalid,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parser server version.
 | 
			
		||||
	var version uint16
 | 
			
		||||
	if !record.ReadUint16(&version) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS version",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	hello.Version = TLSVersion(version)
 | 
			
		||||
 | 
			
		||||
	// Parse random (32 bytes)
 | 
			
		||||
	if !record.ReadBytes(&hello.Random, 32) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS random bytes",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	hello.RandomTimestamp = time.Unix(int64(binary.BigEndian.Uint32(hello.Random)), 0)
 | 
			
		||||
 | 
			
		||||
	// Parse session ID
 | 
			
		||||
	var sessionID cryptobyte.String
 | 
			
		||||
	if !record.ReadUint8LengthPrefixed(&sessionID) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS session ID",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	hello.SessionID = sessionID
 | 
			
		||||
 | 
			
		||||
	// Parse cipher suite
 | 
			
		||||
	if !record.ReadUint16(&hello.CipherSuite) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS cipher suite",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse compression method
 | 
			
		||||
	if !record.ReadUint8(&hello.CompressionMethod) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS compression method",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse extensions (optional)
 | 
			
		||||
	if record.Empty() {
 | 
			
		||||
		return hello, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var extensions cryptobyte.String
 | 
			
		||||
	if !record.ReadUint16LengthPrefixed(&extensions) {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "incomplete TLS extensions",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !record.Empty() {
 | 
			
		||||
		return nil, DecodeError{
 | 
			
		||||
			Reason: "extraneous TLS extension data",
 | 
			
		||||
			Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for !extensions.Empty() {
 | 
			
		||||
		var (
 | 
			
		||||
			extension     TLSExtension
 | 
			
		||||
			extensionData = cryptobyte.String(extension.Data)
 | 
			
		||||
		)
 | 
			
		||||
		if !extensions.ReadUint16(&extension.Type) || !extensions.ReadUint16LengthPrefixed(&extensionData) {
 | 
			
		||||
			return nil, DecodeError{
 | 
			
		||||
				Reason: "incomplete TLS extension record data",
 | 
			
		||||
				Err:    io.ErrUnexpectedEOF,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		hello.Extensions = append(hello.Extensions, extension)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hello, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readTLSServerName(data cryptobyte.String, serverName *string) bool {
 | 
			
		||||
	var list cryptobyte.String
 | 
			
		||||
	if !data.ReadUint16LengthPrefixed(&list) || list.Empty() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for !list.Empty() {
 | 
			
		||||
		var (
 | 
			
		||||
			nameType uint8
 | 
			
		||||
			name     cryptobyte.String
 | 
			
		||||
		)
 | 
			
		||||
		if !list.ReadUint8(&nameType) || !list.ReadUint16LengthPrefixed(&name) || name.Empty() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if nameType != 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if *serverName == "" {
 | 
			
		||||
			*serverName = string(name)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readTLSSupportedGroups(data cryptobyte.String, supported *[]uint16) bool {
 | 
			
		||||
	var groups cryptobyte.String
 | 
			
		||||
	if !data.ReadUint16LengthPrefixed(&groups) || groups.Empty() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for !groups.Empty() {
 | 
			
		||||
		var group uint16
 | 
			
		||||
		if !groups.ReadUint16(&group) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		*supported = append(*supported, group)
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readTLSSignatureAlgorithms(data cryptobyte.String, supported *[]TLSSignatureScheme) bool {
 | 
			
		||||
	var algorithms cryptobyte.String
 | 
			
		||||
	if !data.ReadUint16LengthPrefixed(&algorithms) || algorithms.Empty() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for !algorithms.Empty() {
 | 
			
		||||
		var algorithm uint16
 | 
			
		||||
		if !algorithms.ReadUint16(&algorithm) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		*supported = append(*supported, TLSSignatureScheme(algorithm))
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readTLSALPN(data cryptobyte.String, alpnProtocols *[]string) bool {
 | 
			
		||||
	var list cryptobyte.String
 | 
			
		||||
	if !data.ReadUint16LengthPrefixed(&list) || list.Empty() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for !list.Empty() {
 | 
			
		||||
		var proto cryptobyte.String
 | 
			
		||||
		if !list.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		*alpnProtocols = append(*alpnProtocols, string(proto))
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readTLSSupportedVersions(data cryptobyte.String, versions *[]TLSVersion) bool {
 | 
			
		||||
	var list cryptobyte.String
 | 
			
		||||
	if !data.ReadUint8LengthPrefixed(&list) || list.Empty() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for !list.Empty() {
 | 
			
		||||
		var version uint16
 | 
			
		||||
		if !list.ReadUint16(&version) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		*versions = append(*versions, TLSVersion(version))
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										525
									
								
								tls_const.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										525
									
								
								tls_const.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,525 @@
 | 
			
		||||
package dpi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:generate stringer -linecomment -type=TLSCipherSuite,TLSSignatureScheme -output=tls_const_string.go
 | 
			
		||||
 | 
			
		||||
// TLS Version
 | 
			
		||||
type TLSVersion uint16
 | 
			
		||||
 | 
			
		||||
func (version TLSVersion) String() string {
 | 
			
		||||
	return TLSVersionName(version)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TLS versions.
 | 
			
		||||
const (
 | 
			
		||||
	VersionSSL30        TLSVersion = 0x0300           // SSLv3
 | 
			
		||||
	VersionTLS10        TLSVersion = tls.VersionTLS10 // TLS 1.0
 | 
			
		||||
	VersionTLS11        TLSVersion = tls.VersionTLS11 // TLS 1.1
 | 
			
		||||
	VersionTLS12        TLSVersion = tls.VersionTLS12 // TLS 1.2
 | 
			
		||||
	VersionTLS13        TLSVersion = tls.VersionTLS13 // TLS 1.3
 | 
			
		||||
	VersionTLS13Draft   TLSVersion = 0x7F00           // TLS 1.3 (draft)
 | 
			
		||||
	VersionTLS13Draft18 TLSVersion = 0x7F12           // TLS 1.3 (draft 18)
 | 
			
		||||
	VersionTLS13Draft19 TLSVersion = 0x7F13           // TLS 1.3 (draft 19)
 | 
			
		||||
	VersionTLS13Draft20 TLSVersion = 0x7F14           // TLS 1.3 (draft 20)
 | 
			
		||||
	VersionTLS13Draft21 TLSVersion = 0x7F15           // TLS 1.3 (draft 21)
 | 
			
		||||
	VersionTLS13Draft22 TLSVersion = 0x7F16           // TLS 1.3 (draft 22)
 | 
			
		||||
	VersionTLS13Draft23 TLSVersion = 0x7F17           // TLS 1.3 (draft 23)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var tlsVersionName = map[TLSVersion]string{
 | 
			
		||||
	VersionSSL30:        "SSLv3",
 | 
			
		||||
	VersionTLS10:        "TLS 1.0",
 | 
			
		||||
	VersionTLS11:        "TLS 1.1",
 | 
			
		||||
	VersionTLS12:        "TLS 1.2",
 | 
			
		||||
	VersionTLS13:        "TLS 1.3",
 | 
			
		||||
	VersionTLS13Draft:   "TLS 1.3 (draft)",
 | 
			
		||||
	VersionTLS13Draft18: "TLS 1.3 (draft 18)",
 | 
			
		||||
	VersionTLS13Draft19: "TLS 1.3 (draft 19)",
 | 
			
		||||
	VersionTLS13Draft20: "TLS 1.3 (draft 20)",
 | 
			
		||||
	VersionTLS13Draft21: "TLS 1.3 (draft 21)",
 | 
			
		||||
	VersionTLS13Draft22: "TLS 1.3 (draft 22)",
 | 
			
		||||
	VersionTLS13Draft23: "TLS 1.3 (draft 23)",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TLSVersionName(version TLSVersion) string {
 | 
			
		||||
	if s, ok := tlsVersionName[version]; ok {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	return "TLSVersion(0x" + strconv.FormatUint(uint64(version), 16) + ")"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	tlsRecordTypeChangeCipherSpec uint8 = 20
 | 
			
		||||
	tlsRecordTypeAlert            uint8 = 21
 | 
			
		||||
	tlsRecordTypeHandshake        uint8 = 22
 | 
			
		||||
	tlsRecordTypeApplicationData  uint8 = 23
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TLS handshake message types.
 | 
			
		||||
const (
 | 
			
		||||
	tlsTypeHelloRequest        uint8 = 0
 | 
			
		||||
	tlsTypeClientHello         uint8 = 1
 | 
			
		||||
	tlsTypeServerHello         uint8 = 2
 | 
			
		||||
	tlsTypeNewSessionTicket    uint8 = 4
 | 
			
		||||
	tlsTypeEndOfEarlyData      uint8 = 5
 | 
			
		||||
	tlsTypeEncryptedExtensions uint8 = 8
 | 
			
		||||
	tlsTypeCertificate         uint8 = 11
 | 
			
		||||
	tlsTypeServerKeyExchange   uint8 = 12
 | 
			
		||||
	tlsTypeCertificateRequest  uint8 = 13
 | 
			
		||||
	tlsTypeServerHelloDone     uint8 = 14
 | 
			
		||||
	tlsTypeCertificateVerify   uint8 = 15
 | 
			
		||||
	tlsTypeClientKeyExchange   uint8 = 16
 | 
			
		||||
	tlsTypeFinished            uint8 = 20
 | 
			
		||||
	tlsTypeCertificateStatus   uint8 = 22
 | 
			
		||||
	tlsTypeKeyUpdate           uint8 = 24
 | 
			
		||||
	tlsTypeMessageHash         uint8 = 254
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TLS extensions.
 | 
			
		||||
const (
 | 
			
		||||
	tlsExtensionServerName              uint16 = 0
 | 
			
		||||
	tlsExtensionStatusRequest           uint16 = 5
 | 
			
		||||
	tlsExtensionSupportedGroups         uint16 = 10
 | 
			
		||||
	tlsExtensionSupportedPoints         uint16 = 11
 | 
			
		||||
	tlsExtensionSignatureAlgorithms     uint16 = 13
 | 
			
		||||
	tlsExtensionALPN                    uint16 = 16
 | 
			
		||||
	tlsExtensionStatusRequestV2         uint16 = 17
 | 
			
		||||
	tlsExtensionSCT                     uint16 = 18
 | 
			
		||||
	tlsExtensionExtendedMasterSecret    uint16 = 23
 | 
			
		||||
	tlsExtensionDelegatedCredentials    uint16 = 34
 | 
			
		||||
	tlsExtensionSessionTicket           uint16 = 35
 | 
			
		||||
	tlsExtensionPreSharedKey            uint16 = 41
 | 
			
		||||
	tlsExtensionEarlyData               uint16 = 42
 | 
			
		||||
	tlsExtensionSupportedVersions       uint16 = 43
 | 
			
		||||
	tlsExtensionCookie                  uint16 = 44
 | 
			
		||||
	tlsExtensionPSKModes                uint16 = 45
 | 
			
		||||
	tlsExtensionCertificateAuthorities  uint16 = 47
 | 
			
		||||
	tlsExtensionSignatureAlgorithmsCert uint16 = 50
 | 
			
		||||
	tlsExtensionKeyShare                uint16 = 51
 | 
			
		||||
	tlsExtensionQUICTransportParameters uint16 = 57
 | 
			
		||||
	tlsExtensionRenegotiationInfo       uint16 = 0xff01
 | 
			
		||||
	tlsExtensionECHOuterExtensions      uint16 = 0xfd00
 | 
			
		||||
	tlsExtensionEncryptedClientHello    uint16 = 0xfe0d
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TLS cipher suite.
 | 
			
		||||
type TLSCipherSuite uint16
 | 
			
		||||
 | 
			
		||||
// TLS cipher suites.
 | 
			
		||||
//
 | 
			
		||||
// See https://www.iana.org/assignments/tls-parameters/tls-parameters.xml
 | 
			
		||||
const (
 | 
			
		||||
	TLS_NULL_WITH_NULL_NULL                       TLSCipherSuite = 0x0000
 | 
			
		||||
	TLS_RSA_WITH_NULL_MD5                         TLSCipherSuite = 0x0001 // RFC5246
 | 
			
		||||
	TLS_RSA_WITH_NULL_SHA                         TLSCipherSuite = 0x0002 // RFC5246
 | 
			
		||||
	TLS_RSA_EXPORT_WITH_RC4_40_MD5                TLSCipherSuite = 0x0003 // RFC4346 RFC6347
 | 
			
		||||
	TLS_RSA_WITH_RC4_128_MD5                      TLSCipherSuite = 0x0004 // RFC5246 RFC6347
 | 
			
		||||
	TLS_RSA_WITH_RC4_128_SHA                      TLSCipherSuite = 0x0005 // RFC5246 RFC6347
 | 
			
		||||
	TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5            TLSCipherSuite = 0x0006 // RFC4346
 | 
			
		||||
	TLS_RSA_WITH_IDEA_CBC_SHA                     TLSCipherSuite = 0x0007 // RFC8996
 | 
			
		||||
	TLS_RSA_EXPORT_WITH_DES40_CBC_SHA             TLSCipherSuite = 0x0008 // RFC4346
 | 
			
		||||
	TLS_RSA_WITH_DES_CBC_SHA                      TLSCipherSuite = 0x0009 // RFC8996
 | 
			
		||||
	TLS_RSA_WITH_3DES_EDE_CBC_SHA                 TLSCipherSuite = 0x000A // RFC5246
 | 
			
		||||
	TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA          TLSCipherSuite = 0x000B // RFC4346
 | 
			
		||||
	TLS_DH_DSS_WITH_DES_CBC_SHA                   TLSCipherSuite = 0x000C // RFC8996
 | 
			
		||||
	TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA              TLSCipherSuite = 0x000D // RFC5246
 | 
			
		||||
	TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA          TLSCipherSuite = 0x000E // RFC4346
 | 
			
		||||
	TLS_DH_RSA_WITH_DES_CBC_SHA                   TLSCipherSuite = 0x000F // RFC8996
 | 
			
		||||
	TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA              TLSCipherSuite = 0x0010 // RFC5246
 | 
			
		||||
	TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA         TLSCipherSuite = 0x0011 // RFC4346
 | 
			
		||||
	TLS_DHE_DSS_WITH_DES_CBC_SHA                  TLSCipherSuite = 0x0012 // RFC8996
 | 
			
		||||
	TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA             TLSCipherSuite = 0x0013 // RFC5246
 | 
			
		||||
	TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA         TLSCipherSuite = 0x0014 // RFC4346
 | 
			
		||||
	TLS_DHE_RSA_WITH_DES_CBC_SHA                  TLSCipherSuite = 0x0015 // RFC8996
 | 
			
		||||
	TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA             TLSCipherSuite = 0x0016 // RFC5246
 | 
			
		||||
	TLS_DH_anon_EXPORT_WITH_RC4_40_MD5            TLSCipherSuite = 0x0017 // RFC4346 RFC6347
 | 
			
		||||
	TLS_DH_anon_WITH_RC4_128_MD5                  TLSCipherSuite = 0x0018 // RFC5246 RFC6347
 | 
			
		||||
	TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA         TLSCipherSuite = 0x0019 // RFC4346
 | 
			
		||||
	TLS_DH_anon_WITH_DES_CBC_SHA                  TLSCipherSuite = 0x001A // RFC8996
 | 
			
		||||
	TLS_DH_anon_WITH_3DES_EDE_CBC_SHA             TLSCipherSuite = 0x001B // RFC5246
 | 
			
		||||
	TLS_KRB5_WITH_DES_CBC_SHA                     TLSCipherSuite = 0x001E // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_WITH_3DES_EDE_CBC_SHA                TLSCipherSuite = 0x001F // RFC2712
 | 
			
		||||
	TLS_KRB5_WITH_RC4_128_SHA                     TLSCipherSuite = 0x0020 // RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_WITH_IDEA_CBC_SHA                    TLSCipherSuite = 0x0021 // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_WITH_DES_CBC_MD5                     TLSCipherSuite = 0x0022 // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_WITH_3DES_EDE_CBC_MD5                TLSCipherSuite = 0x0023 // RFC2712
 | 
			
		||||
	TLS_KRB5_WITH_RC4_128_MD5                     TLSCipherSuite = 0x0024 // RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_WITH_IDEA_CBC_MD5                    TLSCipherSuite = 0x0025 // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA           TLSCipherSuite = 0x0026 // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA           TLSCipherSuite = 0x0027 // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_EXPORT_WITH_RC4_40_SHA               TLSCipherSuite = 0x0028 // RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5           TLSCipherSuite = 0x0029 // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5           TLSCipherSuite = 0x002A // RFC2712 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_KRB5_EXPORT_WITH_RC4_40_MD5               TLSCipherSuite = 0x002B // RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_PSK_WITH_NULL_SHA                         TLSCipherSuite = 0x002C // RFC4785 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_DHE_PSK_WITH_NULL_SHA                     TLSCipherSuite = 0x002D // RFC4785
 | 
			
		||||
	TLS_RSA_PSK_WITH_NULL_SHA                     TLSCipherSuite = 0x002E // RFC4785
 | 
			
		||||
	TLS_RSA_WITH_AES_128_CBC_SHA                  TLSCipherSuite = 0x002F // RFC5246
 | 
			
		||||
	TLS_DH_DSS_WITH_AES_128_CBC_SHA               TLSCipherSuite = 0x0030 // RFC5246
 | 
			
		||||
	TLS_DH_RSA_WITH_AES_128_CBC_SHA               TLSCipherSuite = 0x0031 // RFC5246
 | 
			
		||||
	TLS_DHE_DSS_WITH_AES_128_CBC_SHA              TLSCipherSuite = 0x0032 // RFC5246
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_128_CBC_SHA              TLSCipherSuite = 0x0033 // RFC5246
 | 
			
		||||
	TLS_DH_anon_WITH_AES_128_CBC_SHA              TLSCipherSuite = 0x0034 // RFC5246
 | 
			
		||||
	TLS_RSA_WITH_AES_256_CBC_SHA                  TLSCipherSuite = 0x0035 // RFC5246
 | 
			
		||||
	TLS_DH_DSS_WITH_AES_256_CBC_SHA               TLSCipherSuite = 0x0036 // RFC5246
 | 
			
		||||
	TLS_DH_RSA_WITH_AES_256_CBC_SHA               TLSCipherSuite = 0x0037 // RFC5246
 | 
			
		||||
	TLS_DHE_DSS_WITH_AES_256_CBC_SHA              TLSCipherSuite = 0x0038 // RFC5246
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_256_CBC_SHA              TLSCipherSuite = 0x0039 // RFC5246
 | 
			
		||||
	TLS_DH_anon_WITH_AES_256_CBC_SHA              TLSCipherSuite = 0x003A // RFC5246
 | 
			
		||||
	TLS_RSA_WITH_NULL_SHA256                      TLSCipherSuite = 0x003B // RFC5246
 | 
			
		||||
	TLS_RSA_WITH_AES_128_CBC_SHA256               TLSCipherSuite = 0x003C // RFC5246
 | 
			
		||||
	TLS_RSA_WITH_AES_256_CBC_SHA256               TLSCipherSuite = 0x003D // RFC5246
 | 
			
		||||
	TLS_DH_DSS_WITH_AES_128_CBC_SHA256            TLSCipherSuite = 0x003E // RFC5246
 | 
			
		||||
	TLS_DH_RSA_WITH_AES_128_CBC_SHA256            TLSCipherSuite = 0x003F // RFC5246
 | 
			
		||||
	TLS_DHE_DSS_WITH_AES_128_CBC_SHA256           TLSCipherSuite = 0x0040 // RFC5246
 | 
			
		||||
	TLS_RSA_WITH_CAMELLIA_128_CBC_SHA             TLSCipherSuite = 0x0041 // RFC5932
 | 
			
		||||
	TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA          TLSCipherSuite = 0x0042 // RFC5932
 | 
			
		||||
	TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA          TLSCipherSuite = 0x0043 // RFC5932
 | 
			
		||||
	TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA         TLSCipherSuite = 0x0044 // RFC5932
 | 
			
		||||
	TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA         TLSCipherSuite = 0x0045 // RFC5932
 | 
			
		||||
	TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA         TLSCipherSuite = 0x0046 // RFC5932
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_128_CBC_SHA256           TLSCipherSuite = 0x0067 // RFC5246
 | 
			
		||||
	TLS_DH_DSS_WITH_AES_256_CBC_SHA256            TLSCipherSuite = 0x0068 // RFC5246
 | 
			
		||||
	TLS_DH_RSA_WITH_AES_256_CBC_SHA256            TLSCipherSuite = 0x0069 // RFC5246
 | 
			
		||||
	TLS_DHE_DSS_WITH_AES_256_CBC_SHA256           TLSCipherSuite = 0x006A // RFC5246
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_256_CBC_SHA256           TLSCipherSuite = 0x006B // RFC5246
 | 
			
		||||
	TLS_DH_anon_WITH_AES_128_CBC_SHA256           TLSCipherSuite = 0x006C // RFC5246
 | 
			
		||||
	TLS_DH_anon_WITH_AES_256_CBC_SHA256           TLSCipherSuite = 0x006D // RFC5246
 | 
			
		||||
	TLS_RSA_WITH_CAMELLIA_256_CBC_SHA             TLSCipherSuite = 0x0084 // RFC5932
 | 
			
		||||
	TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA          TLSCipherSuite = 0x0085 // RFC5932
 | 
			
		||||
	TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA          TLSCipherSuite = 0x0086 // RFC5932
 | 
			
		||||
	TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA         TLSCipherSuite = 0x0087 // RFC5932
 | 
			
		||||
	TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA         TLSCipherSuite = 0x0088 // RFC5932
 | 
			
		||||
	TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA         TLSCipherSuite = 0x0089 // RFC5932
 | 
			
		||||
	TLS_PSK_WITH_RC4_128_SHA                      TLSCipherSuite = 0x008A // RFC4279 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_PSK_WITH_3DES_EDE_CBC_SHA                 TLSCipherSuite = 0x008B // RFC4279
 | 
			
		||||
	TLS_PSK_WITH_AES_128_CBC_SHA                  TLSCipherSuite = 0x008C // RFC4279
 | 
			
		||||
	TLS_PSK_WITH_AES_256_CBC_SHA                  TLSCipherSuite = 0x008D // RFC4279
 | 
			
		||||
	TLS_DHE_PSK_WITH_RC4_128_SHA                  TLSCipherSuite = 0x008E // RFC4279 RFC6347
 | 
			
		||||
	TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA             TLSCipherSuite = 0x008F // RFC4279
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_128_CBC_SHA              TLSCipherSuite = 0x0090 // RFC4279
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_256_CBC_SHA              TLSCipherSuite = 0x0091 // RFC4279
 | 
			
		||||
	TLS_RSA_PSK_WITH_RC4_128_SHA                  TLSCipherSuite = 0x0092 // RFC4279 RFC6347
 | 
			
		||||
	TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA             TLSCipherSuite = 0x0093 // RFC4279
 | 
			
		||||
	TLS_RSA_PSK_WITH_AES_128_CBC_SHA              TLSCipherSuite = 0x0094 // RFC4279
 | 
			
		||||
	TLS_RSA_PSK_WITH_AES_256_CBC_SHA              TLSCipherSuite = 0x0095 // RFC4279
 | 
			
		||||
	TLS_RSA_WITH_SEED_CBC_SHA                     TLSCipherSuite = 0x0096 // RFC4162
 | 
			
		||||
	TLS_DH_DSS_WITH_SEED_CBC_SHA                  TLSCipherSuite = 0x0097 // RFC4162
 | 
			
		||||
	TLS_DH_RSA_WITH_SEED_CBC_SHA                  TLSCipherSuite = 0x0098 // RFC4162
 | 
			
		||||
	TLS_DHE_DSS_WITH_SEED_CBC_SHA                 TLSCipherSuite = 0x0099 // RFC4162
 | 
			
		||||
	TLS_DHE_RSA_WITH_SEED_CBC_SHA                 TLSCipherSuite = 0x009A // RFC4162
 | 
			
		||||
	TLS_DH_anon_WITH_SEED_CBC_SHA                 TLSCipherSuite = 0x009B // RFC4162
 | 
			
		||||
	TLS_RSA_WITH_AES_128_GCM_SHA256               TLSCipherSuite = 0x009C // RFC5288
 | 
			
		||||
	TLS_RSA_WITH_AES_256_GCM_SHA384               TLSCipherSuite = 0x009D // RFC5288
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_128_GCM_SHA256           TLSCipherSuite = 0x009E // RFC5288
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_256_GCM_SHA384           TLSCipherSuite = 0x009F // RFC5288
 | 
			
		||||
	TLS_DH_RSA_WITH_AES_128_GCM_SHA256            TLSCipherSuite = 0x00A0 // RFC5288
 | 
			
		||||
	TLS_DH_RSA_WITH_AES_256_GCM_SHA384            TLSCipherSuite = 0x00A1 // RFC5288
 | 
			
		||||
	TLS_DHE_DSS_WITH_AES_128_GCM_SHA256           TLSCipherSuite = 0x00A2 // RFC5288
 | 
			
		||||
	TLS_DHE_DSS_WITH_AES_256_GCM_SHA384           TLSCipherSuite = 0x00A3 // RFC5288
 | 
			
		||||
	TLS_DH_DSS_WITH_AES_128_GCM_SHA256            TLSCipherSuite = 0x00A4 // RFC5288
 | 
			
		||||
	TLS_DH_DSS_WITH_AES_256_GCM_SHA384            TLSCipherSuite = 0x00A5 // RFC5288
 | 
			
		||||
	TLS_DH_anon_WITH_AES_128_GCM_SHA256           TLSCipherSuite = 0x00A6 // RFC5288
 | 
			
		||||
	TLS_DH_anon_WITH_AES_256_GCM_SHA384           TLSCipherSuite = 0x00A7 // RFC5288
 | 
			
		||||
	TLS_PSK_WITH_AES_128_GCM_SHA256               TLSCipherSuite = 0x00A8 // RFC5487
 | 
			
		||||
	TLS_PSK_WITH_AES_256_GCM_SHA384               TLSCipherSuite = 0x00A9 // RFC5487
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_128_GCM_SHA256           TLSCipherSuite = 0x00AA // RFC5487
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_256_GCM_SHA384           TLSCipherSuite = 0x00AB // RFC5487
 | 
			
		||||
	TLS_RSA_PSK_WITH_AES_128_GCM_SHA256           TLSCipherSuite = 0x00AC // RFC5487
 | 
			
		||||
	TLS_RSA_PSK_WITH_AES_256_GCM_SHA384           TLSCipherSuite = 0x00AD // RFC5487
 | 
			
		||||
	TLS_PSK_WITH_AES_128_CBC_SHA256               TLSCipherSuite = 0x00AE // RFC5487
 | 
			
		||||
	TLS_PSK_WITH_AES_256_CBC_SHA384               TLSCipherSuite = 0x00AF // RFC5487
 | 
			
		||||
	TLS_PSK_WITH_NULL_SHA256                      TLSCipherSuite = 0x00B0 // RFC5487 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_PSK_WITH_NULL_SHA384                      TLSCipherSuite = 0x00B1 // RFC5487 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_128_CBC_SHA256           TLSCipherSuite = 0x00B2 // RFC5487
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_256_CBC_SHA384           TLSCipherSuite = 0x00B3 // RFC5487
 | 
			
		||||
	TLS_DHE_PSK_WITH_NULL_SHA256                  TLSCipherSuite = 0x00B4 // RFC5487
 | 
			
		||||
	TLS_DHE_PSK_WITH_NULL_SHA384                  TLSCipherSuite = 0x00B5 // RFC5487
 | 
			
		||||
	TLS_RSA_PSK_WITH_AES_128_CBC_SHA256           TLSCipherSuite = 0x00B6 // RFC5487
 | 
			
		||||
	TLS_RSA_PSK_WITH_AES_256_CBC_SHA384           TLSCipherSuite = 0x00B7 // RFC5487
 | 
			
		||||
	TLS_RSA_PSK_WITH_NULL_SHA256                  TLSCipherSuite = 0x00B8 // RFC5487
 | 
			
		||||
	TLS_RSA_PSK_WITH_NULL_SHA384                  TLSCipherSuite = 0x00B9 // RFC5487
 | 
			
		||||
	TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256          TLSCipherSuite = 0x00BA // RFC5932
 | 
			
		||||
	TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256       TLSCipherSuite = 0x00BB // RFC5932
 | 
			
		||||
	TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256       TLSCipherSuite = 0x00BC // RFC5932
 | 
			
		||||
	TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256      TLSCipherSuite = 0x00BD // RFC5932
 | 
			
		||||
	TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256      TLSCipherSuite = 0x00BE // RFC5932
 | 
			
		||||
	TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256      TLSCipherSuite = 0x00BF // RFC5932
 | 
			
		||||
	TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256          TLSCipherSuite = 0x00C0 // RFC5932
 | 
			
		||||
	TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256       TLSCipherSuite = 0x00C1 // RFC5932
 | 
			
		||||
	TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256       TLSCipherSuite = 0x00C2 // RFC5932
 | 
			
		||||
	TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256      TLSCipherSuite = 0x00C3 // RFC5932
 | 
			
		||||
	TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256      TLSCipherSuite = 0x00C4 // RFC5932
 | 
			
		||||
	TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256      TLSCipherSuite = 0x00C5 // RFC5932
 | 
			
		||||
	TLS_SM4_GCM_SM3                               TLSCipherSuite = 0x00C6 // RFC8998
 | 
			
		||||
	TLS_SM4_CCM_SM3                               TLSCipherSuite = 0x00C7 // RFC8998
 | 
			
		||||
	TLS_EMPTY_RENEGOTIATION_INFO_SCSV             TLSCipherSuite = 0x00FF
 | 
			
		||||
	TLS_AES_128_GCM_SHA256                        TLSCipherSuite = 0x1301 // RFC-ietf-tls-rfc8446bis-13
 | 
			
		||||
	TLS_AES_256_GCM_SHA384                        TLSCipherSuite = 0x1302 // RFC-ietf-tls-rfc8446bis-13
 | 
			
		||||
	TLS_CHACHA20_POLY1305_SHA256                  TLSCipherSuite = 0x1303 // RFC-ietf-tls-rfc8446bis-13
 | 
			
		||||
	TLS_AES_128_CCM_SHA256                        TLSCipherSuite = 0x1304 // RFC-ietf-tls-rfc8446bis-13
 | 
			
		||||
	TLS_AES_128_CCM_8_SHA256                      TLSCipherSuite = 0x1305 // RFC-ietf-tls-rfc8446bis-13 IESG Action 2018-08-16
 | 
			
		||||
	TLS_AEGIS_256_SHA512                          TLSCipherSuite = 0x1306 // draft-irtf-cfrg-aegis-aead-08]
 | 
			
		||||
	TLS_AEGIS_128L_SHA256                         TLSCipherSuite = 0x1307
 | 
			
		||||
	TLS_FALLBACK_SCSV                             TLSCipherSuite = 0x5600
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_NULL_SHA                  TLSCipherSuite = 0xC001 // RFC8422
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_RC4_128_SHA               TLSCipherSuite = 0xC002 // RFC8422 RFC6347
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA          TLSCipherSuite = 0xC003 // RFC8422
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA           TLSCipherSuite = 0xC004 // RFC8422
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA           TLSCipherSuite = 0xC005 // RFC8422
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_NULL_SHA                 TLSCipherSuite = 0xC006 // RFC8422 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_RC4_128_SHA              TLSCipherSuite = 0xC007 // RFC8422 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA         TLSCipherSuite = 0xC008 // RFC8422
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA          TLSCipherSuite = 0xC009 // RFC8422
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA          TLSCipherSuite = 0xC00A // RFC8422
 | 
			
		||||
	TLS_ECDH_RSA_WITH_NULL_SHA                    TLSCipherSuite = 0xC00B // RFC8422
 | 
			
		||||
	TLS_ECDH_RSA_WITH_RC4_128_SHA                 TLSCipherSuite = 0xC00C // RFC8422 RFC6347
 | 
			
		||||
	TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA            TLSCipherSuite = 0xC00D // RFC8422
 | 
			
		||||
	TLS_ECDH_RSA_WITH_AES_128_CBC_SHA             TLSCipherSuite = 0xC00E // RFC8422
 | 
			
		||||
	TLS_ECDH_RSA_WITH_AES_256_CBC_SHA             TLSCipherSuite = 0xC00F // RFC8422
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_NULL_SHA                   TLSCipherSuite = 0xC010 // RFC8422 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_RC4_128_SHA                TLSCipherSuite = 0xC011 // RFC8422 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA           TLSCipherSuite = 0xC012 // RFC8422
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA            TLSCipherSuite = 0xC013 // RFC8422
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA            TLSCipherSuite = 0xC014 // RFC8422
 | 
			
		||||
	TLS_ECDH_anon_WITH_NULL_SHA                   TLSCipherSuite = 0xC015 // RFC8422
 | 
			
		||||
	TLS_ECDH_anon_WITH_RC4_128_SHA                TLSCipherSuite = 0xC016 // RFC8422 RFC6347
 | 
			
		||||
	TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA           TLSCipherSuite = 0xC017 // RFC8422
 | 
			
		||||
	TLS_ECDH_anon_WITH_AES_128_CBC_SHA            TLSCipherSuite = 0xC018 // RFC8422
 | 
			
		||||
	TLS_ECDH_anon_WITH_AES_256_CBC_SHA            TLSCipherSuite = 0xC019 // RFC8422
 | 
			
		||||
	TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA             TLSCipherSuite = 0xC01A // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA         TLSCipherSuite = 0xC01B // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA         TLSCipherSuite = 0xC01C // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_WITH_AES_128_CBC_SHA              TLSCipherSuite = 0xC01D // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA          TLSCipherSuite = 0xC01E // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA          TLSCipherSuite = 0xC01F // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_WITH_AES_256_CBC_SHA              TLSCipherSuite = 0xC020 // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA          TLSCipherSuite = 0xC021 // RFC5054
 | 
			
		||||
	TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA          TLSCipherSuite = 0xC022 // RFC5054
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256       TLSCipherSuite = 0xC023 // RFC5289
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384       TLSCipherSuite = 0xC024 // RFC5289
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256        TLSCipherSuite = 0xC025 // RFC5289
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384        TLSCipherSuite = 0xC026 // RFC5289
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256         TLSCipherSuite = 0xC027 // RFC5289
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384         TLSCipherSuite = 0xC028 // RFC5289
 | 
			
		||||
	TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256          TLSCipherSuite = 0xC029 // RFC5289
 | 
			
		||||
	TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384          TLSCipherSuite = 0xC02A // RFC5289
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256       TLSCipherSuite = 0xC02B // RFC5289
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384       TLSCipherSuite = 0xC02C // RFC5289
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256        TLSCipherSuite = 0xC02D // RFC5289
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384        TLSCipherSuite = 0xC02E // RFC5289
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256         TLSCipherSuite = 0xC02F // RFC5289
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384         TLSCipherSuite = 0xC030 // RFC5289
 | 
			
		||||
	TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256          TLSCipherSuite = 0xC031 // RFC5289
 | 
			
		||||
	TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384          TLSCipherSuite = 0xC032 // RFC5289
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_RC4_128_SHA                TLSCipherSuite = 0xC033 // RFC5489 RFC6347 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA           TLSCipherSuite = 0xC034 // RFC5489
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA            TLSCipherSuite = 0xC035 // RFC5489
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA            TLSCipherSuite = 0xC036 // RFC5489
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256         TLSCipherSuite = 0xC037 // RFC5489
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384         TLSCipherSuite = 0xC038 // RFC5489
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_NULL_SHA                   TLSCipherSuite = 0xC039 // RFC5489 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_NULL_SHA256                TLSCipherSuite = 0xC03A // RFC5489 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_NULL_SHA384                TLSCipherSuite = 0xC03B // RFC5489 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_RSA_WITH_ARIA_128_CBC_SHA256              TLSCipherSuite = 0xC03C // RFC6209
 | 
			
		||||
	TLS_RSA_WITH_ARIA_256_CBC_SHA384              TLSCipherSuite = 0xC03D // RFC6209
 | 
			
		||||
	TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256           TLSCipherSuite = 0xC03E // RFC6209
 | 
			
		||||
	TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384           TLSCipherSuite = 0xC03F // RFC6209
 | 
			
		||||
	TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256           TLSCipherSuite = 0xC040 // RFC6209
 | 
			
		||||
	TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384           TLSCipherSuite = 0xC041 // RFC6209
 | 
			
		||||
	TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256          TLSCipherSuite = 0xC042 // RFC6209
 | 
			
		||||
	TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384          TLSCipherSuite = 0xC043 // RFC6209
 | 
			
		||||
	TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256          TLSCipherSuite = 0xC044 // RFC6209
 | 
			
		||||
	TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384          TLSCipherSuite = 0xC045 // RFC6209
 | 
			
		||||
	TLS_DH_anon_WITH_ARIA_128_CBC_SHA256          TLSCipherSuite = 0xC046 // RFC6209
 | 
			
		||||
	TLS_DH_anon_WITH_ARIA_256_CBC_SHA384          TLSCipherSuite = 0xC047 // RFC6209
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256      TLSCipherSuite = 0xC048 // RFC6209
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384      TLSCipherSuite = 0xC049 // RFC6209
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256       TLSCipherSuite = 0xC04A // RFC6209
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384       TLSCipherSuite = 0xC04B // RFC6209
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256        TLSCipherSuite = 0xC04C // RFC6209
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384        TLSCipherSuite = 0xC04D // RFC6209
 | 
			
		||||
	TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256         TLSCipherSuite = 0xC04E // RFC6209
 | 
			
		||||
	TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384         TLSCipherSuite = 0xC04F // RFC6209
 | 
			
		||||
	TLS_RSA_WITH_ARIA_128_GCM_SHA256              TLSCipherSuite = 0xC050 // RFC6209
 | 
			
		||||
	TLS_RSA_WITH_ARIA_256_GCM_SHA384              TLSCipherSuite = 0xC051 // RFC6209
 | 
			
		||||
	TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256          TLSCipherSuite = 0xC052 // RFC6209
 | 
			
		||||
	TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384          TLSCipherSuite = 0xC053 // RFC6209
 | 
			
		||||
	TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256           TLSCipherSuite = 0xC054 // RFC6209
 | 
			
		||||
	TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384           TLSCipherSuite = 0xC055 // RFC6209
 | 
			
		||||
	TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256          TLSCipherSuite = 0xC056 // RFC6209
 | 
			
		||||
	TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384          TLSCipherSuite = 0xC057 // RFC6209
 | 
			
		||||
	TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256           TLSCipherSuite = 0xC058 // RFC6209
 | 
			
		||||
	TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384           TLSCipherSuite = 0xC059 // RFC6209
 | 
			
		||||
	TLS_DH_anon_WITH_ARIA_128_GCM_SHA256          TLSCipherSuite = 0xC05A // RFC6209
 | 
			
		||||
	TLS_DH_anon_WITH_ARIA_256_GCM_SHA384          TLSCipherSuite = 0xC05B // RFC6209
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256      TLSCipherSuite = 0xC05C // RFC6209
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384      TLSCipherSuite = 0xC05D // RFC6209
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256       TLSCipherSuite = 0xC05E // RFC6209
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384       TLSCipherSuite = 0xC05F // RFC6209
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256        TLSCipherSuite = 0xC060 // RFC6209
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384        TLSCipherSuite = 0xC061 // RFC6209
 | 
			
		||||
	TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256         TLSCipherSuite = 0xC062 // RFC6209
 | 
			
		||||
	TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384         TLSCipherSuite = 0xC063 // RFC6209
 | 
			
		||||
	TLS_PSK_WITH_ARIA_128_CBC_SHA256              TLSCipherSuite = 0xC064 // RFC6209
 | 
			
		||||
	TLS_PSK_WITH_ARIA_256_CBC_SHA384              TLSCipherSuite = 0xC065 // RFC6209
 | 
			
		||||
	TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256          TLSCipherSuite = 0xC066 // RFC6209
 | 
			
		||||
	TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384          TLSCipherSuite = 0xC067 // RFC6209
 | 
			
		||||
	TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256          TLSCipherSuite = 0xC068 // RFC6209
 | 
			
		||||
	TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384          TLSCipherSuite = 0xC069 // RFC6209
 | 
			
		||||
	TLS_PSK_WITH_ARIA_128_GCM_SHA256              TLSCipherSuite = 0xC06A // RFC6209
 | 
			
		||||
	TLS_PSK_WITH_ARIA_256_GCM_SHA384              TLSCipherSuite = 0xC06B // RFC6209
 | 
			
		||||
	TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256          TLSCipherSuite = 0xC06C // RFC6209
 | 
			
		||||
	TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384          TLSCipherSuite = 0xC06D // RFC6209
 | 
			
		||||
	TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256          TLSCipherSuite = 0xC06E // RFC6209
 | 
			
		||||
	TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384          TLSCipherSuite = 0xC06F // RFC6209
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256        TLSCipherSuite = 0xC070 // RFC6209
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384        TLSCipherSuite = 0xC071 // RFC6209
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256  TLSCipherSuite = 0xC072 // RFC6367
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384  TLSCipherSuite = 0xC073 // RFC6367
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256   TLSCipherSuite = 0xC074 // RFC6367
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384   TLSCipherSuite = 0xC075 // RFC6367
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256    TLSCipherSuite = 0xC076 // RFC6367
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384    TLSCipherSuite = 0xC077 // RFC6367
 | 
			
		||||
	TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256     TLSCipherSuite = 0xC078 // RFC6367
 | 
			
		||||
	TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384     TLSCipherSuite = 0xC079 // RFC6367
 | 
			
		||||
	TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256          TLSCipherSuite = 0xC07A // RFC6367
 | 
			
		||||
	TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384          TLSCipherSuite = 0xC07B // RFC6367
 | 
			
		||||
	TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256      TLSCipherSuite = 0xC07C // RFC6367
 | 
			
		||||
	TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384      TLSCipherSuite = 0xC07D // RFC6367
 | 
			
		||||
	TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256       TLSCipherSuite = 0xC07E // RFC6367
 | 
			
		||||
	TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384       TLSCipherSuite = 0xC07F // RFC6367
 | 
			
		||||
	TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256      TLSCipherSuite = 0xC080 // RFC6367
 | 
			
		||||
	TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384      TLSCipherSuite = 0xC081 // RFC6367
 | 
			
		||||
	TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256       TLSCipherSuite = 0xC082 // RFC6367
 | 
			
		||||
	TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384       TLSCipherSuite = 0xC083 // RFC6367
 | 
			
		||||
	TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256      TLSCipherSuite = 0xC084 // RFC6367
 | 
			
		||||
	TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384      TLSCipherSuite = 0xC085 // RFC6367
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256  TLSCipherSuite = 0xC086 // RFC6367
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384  TLSCipherSuite = 0xC087 // RFC6367
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256   TLSCipherSuite = 0xC088 // RFC6367
 | 
			
		||||
	TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384   TLSCipherSuite = 0xC089 // RFC6367
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256    TLSCipherSuite = 0xC08A // RFC6367
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384    TLSCipherSuite = 0xC08B // RFC6367
 | 
			
		||||
	TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256     TLSCipherSuite = 0xC08C // RFC6367
 | 
			
		||||
	TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384     TLSCipherSuite = 0xC08D // RFC6367
 | 
			
		||||
	TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256          TLSCipherSuite = 0xC08E // RFC6367
 | 
			
		||||
	TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384          TLSCipherSuite = 0xC08F // RFC6367
 | 
			
		||||
	TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256      TLSCipherSuite = 0xC090 // RFC6367
 | 
			
		||||
	TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384      TLSCipherSuite = 0xC091 // RFC6367
 | 
			
		||||
	TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256      TLSCipherSuite = 0xC092 // RFC6367
 | 
			
		||||
	TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384      TLSCipherSuite = 0xC093 // RFC6367
 | 
			
		||||
	TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256          TLSCipherSuite = 0xC094 // RFC6367
 | 
			
		||||
	TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384          TLSCipherSuite = 0xC095 // RFC6367
 | 
			
		||||
	TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256      TLSCipherSuite = 0xC096 // RFC6367
 | 
			
		||||
	TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384      TLSCipherSuite = 0xC097 // RFC6367
 | 
			
		||||
	TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256      TLSCipherSuite = 0xC098 // RFC6367
 | 
			
		||||
	TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384      TLSCipherSuite = 0xC099 // RFC6367
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256    TLSCipherSuite = 0xC09A // RFC6367
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384    TLSCipherSuite = 0xC09B // RFC6367
 | 
			
		||||
	TLS_RSA_WITH_AES_128_CCM                      TLSCipherSuite = 0xC09C // RFC6655
 | 
			
		||||
	TLS_RSA_WITH_AES_256_CCM                      TLSCipherSuite = 0xC09D // RFC6655
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_128_CCM                  TLSCipherSuite = 0xC09E // RFC6655
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_256_CCM                  TLSCipherSuite = 0xC09F // RFC6655
 | 
			
		||||
	TLS_RSA_WITH_AES_128_CCM_8                    TLSCipherSuite = 0xC0A0 // RFC6655
 | 
			
		||||
	TLS_RSA_WITH_AES_256_CCM_8                    TLSCipherSuite = 0xC0A1 // RFC6655
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_128_CCM_8                TLSCipherSuite = 0xC0A2 // RFC6655
 | 
			
		||||
	TLS_DHE_RSA_WITH_AES_256_CCM_8                TLSCipherSuite = 0xC0A3 // RFC6655
 | 
			
		||||
	TLS_PSK_WITH_AES_128_CCM                      TLSCipherSuite = 0xC0A4 // RFC6655
 | 
			
		||||
	TLS_PSK_WITH_AES_256_CCM                      TLSCipherSuite = 0xC0A5 // RFC6655
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_128_CCM                  TLSCipherSuite = 0xC0A6 // RFC6655
 | 
			
		||||
	TLS_DHE_PSK_WITH_AES_256_CCM                  TLSCipherSuite = 0xC0A7 // RFC6655
 | 
			
		||||
	TLS_PSK_WITH_AES_128_CCM_8                    TLSCipherSuite = 0xC0A8 // RFC6655
 | 
			
		||||
	TLS_PSK_WITH_AES_256_CCM_8                    TLSCipherSuite = 0xC0A9 // RFC6655
 | 
			
		||||
	TLS_PSK_DHE_WITH_AES_128_CCM_8                TLSCipherSuite = 0xC0AA // RFC6655
 | 
			
		||||
	TLS_PSK_DHE_WITH_AES_256_CCM_8                TLSCipherSuite = 0xC0AB // RFC6655
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_128_CCM              TLSCipherSuite = 0xC0AC // RFC7251
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_256_CCM              TLSCipherSuite = 0xC0AD // RFC7251
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8            TLSCipherSuite = 0xC0AE // RFC7251
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8            TLSCipherSuite = 0xC0AF // RFC7251
 | 
			
		||||
	TLS_ECCPWD_WITH_AES_128_GCM_SHA256            TLSCipherSuite = 0xC0B0 // RFC8492
 | 
			
		||||
	TLS_ECCPWD_WITH_AES_256_GCM_SHA384            TLSCipherSuite = 0xC0B1 // RFC8492
 | 
			
		||||
	TLS_ECCPWD_WITH_AES_128_CCM_SHA256            TLSCipherSuite = 0xC0B2 // RFC8492
 | 
			
		||||
	TLS_ECCPWD_WITH_AES_256_CCM_SHA384            TLSCipherSuite = 0xC0B3 // RFC8492
 | 
			
		||||
	TLS_SHA256_SHA256                             TLSCipherSuite = 0xC0B4 // RFC9150 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_SHA384_SHA384                             TLSCipherSuite = 0xC0B5 // RFC9150 RFC-ietf-tls-rfc8447bis-14
 | 
			
		||||
	TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC  TLSCipherSuite = 0xC100 // RFC9189
 | 
			
		||||
	TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC       TLSCipherSuite = 0xC101 // RFC9189
 | 
			
		||||
	TLS_GOSTR341112_256_WITH_28147_CNT_IMIT       TLSCipherSuite = 0xC102 // RFC9189
 | 
			
		||||
	TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L     TLSCipherSuite = 0xC103 // RFC9367
 | 
			
		||||
	TLS_GOSTR341112_256_WITH_MAGMA_MGM_L          TLSCipherSuite = 0xC104 // RFC9367
 | 
			
		||||
	TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S     TLSCipherSuite = 0xC105 // RFC9367
 | 
			
		||||
	TLS_GOSTR341112_256_WITH_MAGMA_MGM_S          TLSCipherSuite = 0xC106 // RFC9367
 | 
			
		||||
	TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   TLSCipherSuite = 0xCCA8 // RFC7905
 | 
			
		||||
	TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLSCipherSuite = 0xCCA9 // RFC7905
 | 
			
		||||
	TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     TLSCipherSuite = 0xCCAA // RFC7905
 | 
			
		||||
	TLS_PSK_WITH_CHACHA20_POLY1305_SHA256         TLSCipherSuite = 0xCCAB // RFC7905
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   TLSCipherSuite = 0xCCAC // RFC7905
 | 
			
		||||
	TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     TLSCipherSuite = 0xCCAD // RFC7905
 | 
			
		||||
	TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256     TLSCipherSuite = 0xCCAE // RFC7905
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256         TLSCipherSuite = 0xD001 // RFC8442
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384         TLSCipherSuite = 0xD002 // RFC8442
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256       TLSCipherSuite = 0xD003 // RFC8442
 | 
			
		||||
	TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256         TLSCipherSuite = 0xD005
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TLSCipherSuiteName(suite TLSCipherSuite) string {
 | 
			
		||||
	return suite.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TLS compression methods
 | 
			
		||||
//
 | 
			
		||||
// See https://www.iana.org/assignments/comp-meth-ids/comp-meth-ids.xhtml
 | 
			
		||||
const (
 | 
			
		||||
	TLS_COMPRESS_NULL    uint8 = 0
 | 
			
		||||
	TLS_COMPRESS_DEFLATE uint8 = 1
 | 
			
		||||
	TLS_COMPRESS_LSZ     uint8 = 64
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var tlsCompressionMethodNames = map[uint8]string{
 | 
			
		||||
	TLS_COMPRESS_NULL:    "NULL",
 | 
			
		||||
	TLS_COMPRESS_DEFLATE: "DEFLATE",
 | 
			
		||||
	TLS_COMPRESS_LSZ:     "LSZ",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TLSCompressionMethodName(method uint8) string {
 | 
			
		||||
	if s, ok := tlsCompressionMethodNames[method]; ok {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("0x%02X", method)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TLS signature scheme.
 | 
			
		||||
type TLSSignatureScheme uint16
 | 
			
		||||
 | 
			
		||||
// TLS signature schemes.
 | 
			
		||||
//
 | 
			
		||||
// See RFC 8446, Section 4.2.3
 | 
			
		||||
const (
 | 
			
		||||
	// RSASSA-PKCS1-v1_5 algorithms.
 | 
			
		||||
	PKCS1WithSHA256 TLSSignatureScheme = 0x0401
 | 
			
		||||
	PKCS1WithSHA384 TLSSignatureScheme = 0x0501
 | 
			
		||||
	PKCS1WithSHA512 TLSSignatureScheme = 0x0601
 | 
			
		||||
 | 
			
		||||
	// RSASSA-PSS algorithms with public key OID rsaEncryption.
 | 
			
		||||
	PSSWithSHA256 TLSSignatureScheme = 0x0804
 | 
			
		||||
	PSSWithSHA384 TLSSignatureScheme = 0x0805
 | 
			
		||||
	PSSWithSHA512 TLSSignatureScheme = 0x0806
 | 
			
		||||
 | 
			
		||||
	// ECDSA algorithms. Only constrained to a specific curve in TLS 1.3.
 | 
			
		||||
	ECDSAWithP256AndSHA256 TLSSignatureScheme = 0x0403
 | 
			
		||||
	ECDSAWithP384AndSHA384 TLSSignatureScheme = 0x0503
 | 
			
		||||
	ECDSAWithP521AndSHA512 TLSSignatureScheme = 0x0603
 | 
			
		||||
 | 
			
		||||
	// EdDSA algorithms.
 | 
			
		||||
	Ed25519 TLSSignatureScheme = 0x0807
 | 
			
		||||
 | 
			
		||||
	// Legacy signature and hash algorithms for TLS 1.2.
 | 
			
		||||
	PKCS1WithSHA1 TLSSignatureScheme = 0x0201
 | 
			
		||||
	ECDSAWithSHA1 TLSSignatureScheme = 0x0203
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										786
									
								
								tls_const_string.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										786
									
								
								tls_const_string.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,786 @@
 | 
			
		||||
// Code generated by "stringer -linecomment -type=TLSCipherSuite,TLSSignatureScheme -output=tls_const_string.go"; DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package dpi
 | 
			
		||||
 | 
			
		||||
import "strconv"
 | 
			
		||||
 | 
			
		||||
func _() {
 | 
			
		||||
	// An "invalid array index" compiler error signifies that the constant values have changed.
 | 
			
		||||
	// Re-run the stringer command to generate them again.
 | 
			
		||||
	var x [1]struct{}
 | 
			
		||||
	_ = x[TLS_NULL_WITH_NULL_NULL-0]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_NULL_MD5-1]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_NULL_SHA-2]
 | 
			
		||||
	_ = x[TLS_RSA_EXPORT_WITH_RC4_40_MD5-3]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_RC4_128_MD5-4]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_RC4_128_SHA-5]
 | 
			
		||||
	_ = x[TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5-6]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_IDEA_CBC_SHA-7]
 | 
			
		||||
	_ = x[TLS_RSA_EXPORT_WITH_DES40_CBC_SHA-8]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_DES_CBC_SHA-9]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_3DES_EDE_CBC_SHA-10]
 | 
			
		||||
	_ = x[TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA-11]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_DES_CBC_SHA-12]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA-13]
 | 
			
		||||
	_ = x[TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA-14]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_DES_CBC_SHA-15]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA-16]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA-17]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_DES_CBC_SHA-18]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA-19]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA-20]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_DES_CBC_SHA-21]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA-22]
 | 
			
		||||
	_ = x[TLS_DH_anon_EXPORT_WITH_RC4_40_MD5-23]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_RC4_128_MD5-24]
 | 
			
		||||
	_ = x[TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA-25]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_DES_CBC_SHA-26]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_3DES_EDE_CBC_SHA-27]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_DES_CBC_SHA-30]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_3DES_EDE_CBC_SHA-31]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_RC4_128_SHA-32]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_IDEA_CBC_SHA-33]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_DES_CBC_MD5-34]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_3DES_EDE_CBC_MD5-35]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_RC4_128_MD5-36]
 | 
			
		||||
	_ = x[TLS_KRB5_WITH_IDEA_CBC_MD5-37]
 | 
			
		||||
	_ = x[TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA-38]
 | 
			
		||||
	_ = x[TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA-39]
 | 
			
		||||
	_ = x[TLS_KRB5_EXPORT_WITH_RC4_40_SHA-40]
 | 
			
		||||
	_ = x[TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5-41]
 | 
			
		||||
	_ = x[TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5-42]
 | 
			
		||||
	_ = x[TLS_KRB5_EXPORT_WITH_RC4_40_MD5-43]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_NULL_SHA-44]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_NULL_SHA-45]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_NULL_SHA-46]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_128_CBC_SHA-47]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_AES_128_CBC_SHA-48]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_AES_128_CBC_SHA-49]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_AES_128_CBC_SHA-50]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_128_CBC_SHA-51]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_AES_128_CBC_SHA-52]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_256_CBC_SHA-53]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_AES_256_CBC_SHA-54]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_AES_256_CBC_SHA-55]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_AES_256_CBC_SHA-56]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_256_CBC_SHA-57]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_AES_256_CBC_SHA-58]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_NULL_SHA256-59]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_128_CBC_SHA256-60]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_256_CBC_SHA256-61]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_AES_128_CBC_SHA256-62]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_AES_128_CBC_SHA256-63]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_AES_128_CBC_SHA256-64]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_CAMELLIA_128_CBC_SHA-65]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA-66]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA-67]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA-68]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA-69]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA-70]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_128_CBC_SHA256-103]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_AES_256_CBC_SHA256-104]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_AES_256_CBC_SHA256-105]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_AES_256_CBC_SHA256-106]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_256_CBC_SHA256-107]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_AES_128_CBC_SHA256-108]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_AES_256_CBC_SHA256-109]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_CAMELLIA_256_CBC_SHA-132]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA-133]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA-134]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA-135]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA-136]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA-137]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_RC4_128_SHA-138]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_3DES_EDE_CBC_SHA-139]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_128_CBC_SHA-140]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_256_CBC_SHA-141]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_RC4_128_SHA-142]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA-143]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_128_CBC_SHA-144]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_256_CBC_SHA-145]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_RC4_128_SHA-146]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA-147]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_AES_128_CBC_SHA-148]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_AES_256_CBC_SHA-149]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_SEED_CBC_SHA-150]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_SEED_CBC_SHA-151]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_SEED_CBC_SHA-152]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_SEED_CBC_SHA-153]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_SEED_CBC_SHA-154]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_SEED_CBC_SHA-155]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_128_GCM_SHA256-156]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_256_GCM_SHA384-157]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_128_GCM_SHA256-158]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_256_GCM_SHA384-159]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_AES_128_GCM_SHA256-160]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_AES_256_GCM_SHA384-161]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_AES_128_GCM_SHA256-162]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_AES_256_GCM_SHA384-163]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_AES_128_GCM_SHA256-164]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_AES_256_GCM_SHA384-165]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_AES_128_GCM_SHA256-166]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_AES_256_GCM_SHA384-167]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_128_GCM_SHA256-168]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_256_GCM_SHA384-169]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_128_GCM_SHA256-170]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_256_GCM_SHA384-171]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_AES_128_GCM_SHA256-172]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_AES_256_GCM_SHA384-173]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_128_CBC_SHA256-174]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_256_CBC_SHA384-175]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_NULL_SHA256-176]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_NULL_SHA384-177]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_128_CBC_SHA256-178]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_256_CBC_SHA384-179]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_NULL_SHA256-180]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_NULL_SHA384-181]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_AES_128_CBC_SHA256-182]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_AES_256_CBC_SHA384-183]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_NULL_SHA256-184]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_NULL_SHA384-185]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256-186]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256-187]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256-188]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256-189]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256-190]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256-191]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256-192]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256-193]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256-194]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256-195]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256-196]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256-197]
 | 
			
		||||
	_ = x[TLS_SM4_GCM_SM3-198]
 | 
			
		||||
	_ = x[TLS_SM4_CCM_SM3-199]
 | 
			
		||||
	_ = x[TLS_EMPTY_RENEGOTIATION_INFO_SCSV-255]
 | 
			
		||||
	_ = x[TLS_AES_128_GCM_SHA256-4865]
 | 
			
		||||
	_ = x[TLS_AES_256_GCM_SHA384-4866]
 | 
			
		||||
	_ = x[TLS_CHACHA20_POLY1305_SHA256-4867]
 | 
			
		||||
	_ = x[TLS_AES_128_CCM_SHA256-4868]
 | 
			
		||||
	_ = x[TLS_AES_128_CCM_8_SHA256-4869]
 | 
			
		||||
	_ = x[TLS_AEGIS_256_SHA512-4870]
 | 
			
		||||
	_ = x[TLS_AEGIS_128L_SHA256-4871]
 | 
			
		||||
	_ = x[TLS_FALLBACK_SCSV-22016]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_NULL_SHA-49153]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_RC4_128_SHA-49154]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA-49155]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA-49156]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA-49157]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_NULL_SHA-49158]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_RC4_128_SHA-49159]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA-49160]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA-49161]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA-49162]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_NULL_SHA-49163]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_RC4_128_SHA-49164]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA-49165]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_AES_128_CBC_SHA-49166]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_AES_256_CBC_SHA-49167]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_NULL_SHA-49168]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_RC4_128_SHA-49169]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA-49170]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA-49171]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA-49172]
 | 
			
		||||
	_ = x[TLS_ECDH_anon_WITH_NULL_SHA-49173]
 | 
			
		||||
	_ = x[TLS_ECDH_anon_WITH_RC4_128_SHA-49174]
 | 
			
		||||
	_ = x[TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA-49175]
 | 
			
		||||
	_ = x[TLS_ECDH_anon_WITH_AES_128_CBC_SHA-49176]
 | 
			
		||||
	_ = x[TLS_ECDH_anon_WITH_AES_256_CBC_SHA-49177]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA-49178]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA-49179]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA-49180]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_WITH_AES_128_CBC_SHA-49181]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA-49182]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA-49183]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_WITH_AES_256_CBC_SHA-49184]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA-49185]
 | 
			
		||||
	_ = x[TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA-49186]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256-49187]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384-49188]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256-49189]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384-49190]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256-49191]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384-49192]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256-49193]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384-49194]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256-49195]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384-49196]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256-49197]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384-49198]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256-49199]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384-49200]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256-49201]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384-49202]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_RC4_128_SHA-49203]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA-49204]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA-49205]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA-49206]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256-49207]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384-49208]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_NULL_SHA-49209]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_NULL_SHA256-49210]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_NULL_SHA384-49211]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_ARIA_128_CBC_SHA256-49212]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_ARIA_256_CBC_SHA384-49213]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256-49214]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384-49215]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256-49216]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384-49217]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256-49218]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384-49219]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256-49220]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384-49221]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_ARIA_128_CBC_SHA256-49222]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_ARIA_256_CBC_SHA384-49223]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256-49224]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384-49225]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256-49226]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384-49227]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256-49228]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384-49229]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256-49230]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384-49231]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_ARIA_128_GCM_SHA256-49232]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_ARIA_256_GCM_SHA384-49233]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256-49234]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384-49235]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256-49236]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384-49237]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256-49238]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384-49239]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256-49240]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384-49241]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_ARIA_128_GCM_SHA256-49242]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_ARIA_256_GCM_SHA384-49243]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256-49244]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384-49245]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256-49246]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384-49247]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256-49248]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384-49249]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256-49250]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384-49251]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_ARIA_128_CBC_SHA256-49252]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_ARIA_256_CBC_SHA384-49253]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256-49254]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384-49255]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256-49256]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384-49257]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_ARIA_128_GCM_SHA256-49258]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_ARIA_256_GCM_SHA384-49259]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256-49260]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384-49261]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256-49262]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384-49263]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256-49264]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384-49265]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256-49266]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384-49267]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256-49268]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384-49269]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256-49270]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384-49271]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256-49272]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384-49273]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256-49274]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384-49275]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256-49276]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384-49277]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256-49278]
 | 
			
		||||
	_ = x[TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384-49279]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256-49280]
 | 
			
		||||
	_ = x[TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384-49281]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256-49282]
 | 
			
		||||
	_ = x[TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384-49283]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256-49284]
 | 
			
		||||
	_ = x[TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384-49285]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256-49286]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384-49287]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256-49288]
 | 
			
		||||
	_ = x[TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384-49289]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256-49290]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384-49291]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256-49292]
 | 
			
		||||
	_ = x[TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384-49293]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256-49294]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384-49295]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256-49296]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384-49297]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256-49298]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384-49299]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256-49300]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384-49301]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256-49302]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384-49303]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256-49304]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384-49305]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256-49306]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384-49307]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_128_CCM-49308]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_256_CCM-49309]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_128_CCM-49310]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_256_CCM-49311]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_128_CCM_8-49312]
 | 
			
		||||
	_ = x[TLS_RSA_WITH_AES_256_CCM_8-49313]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_128_CCM_8-49314]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_AES_256_CCM_8-49315]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_128_CCM-49316]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_256_CCM-49317]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_128_CCM-49318]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_AES_256_CCM-49319]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_128_CCM_8-49320]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_AES_256_CCM_8-49321]
 | 
			
		||||
	_ = x[TLS_PSK_DHE_WITH_AES_128_CCM_8-49322]
 | 
			
		||||
	_ = x[TLS_PSK_DHE_WITH_AES_256_CCM_8-49323]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_128_CCM-49324]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_256_CCM-49325]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8-49326]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8-49327]
 | 
			
		||||
	_ = x[TLS_ECCPWD_WITH_AES_128_GCM_SHA256-49328]
 | 
			
		||||
	_ = x[TLS_ECCPWD_WITH_AES_256_GCM_SHA384-49329]
 | 
			
		||||
	_ = x[TLS_ECCPWD_WITH_AES_128_CCM_SHA256-49330]
 | 
			
		||||
	_ = x[TLS_ECCPWD_WITH_AES_256_CCM_SHA384-49331]
 | 
			
		||||
	_ = x[TLS_SHA256_SHA256-49332]
 | 
			
		||||
	_ = x[TLS_SHA384_SHA384-49333]
 | 
			
		||||
	_ = x[TLS_GOSTR341112_256_WITH_KUZNYECHIK_CTR_OMAC-49408]
 | 
			
		||||
	_ = x[TLS_GOSTR341112_256_WITH_MAGMA_CTR_OMAC-49409]
 | 
			
		||||
	_ = x[TLS_GOSTR341112_256_WITH_28147_CNT_IMIT-49410]
 | 
			
		||||
	_ = x[TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L-49411]
 | 
			
		||||
	_ = x[TLS_GOSTR341112_256_WITH_MAGMA_MGM_L-49412]
 | 
			
		||||
	_ = x[TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S-49413]
 | 
			
		||||
	_ = x[TLS_GOSTR341112_256_WITH_MAGMA_MGM_S-49414]
 | 
			
		||||
	_ = x[TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256-52392]
 | 
			
		||||
	_ = x[TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256-52393]
 | 
			
		||||
	_ = x[TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256-52394]
 | 
			
		||||
	_ = x[TLS_PSK_WITH_CHACHA20_POLY1305_SHA256-52395]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256-52396]
 | 
			
		||||
	_ = x[TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256-52397]
 | 
			
		||||
	_ = x[TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256-52398]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256-53249]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384-53250]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256-53251]
 | 
			
		||||
	_ = x[TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256-53253]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const _TLSCipherSuite_name = "TLS_NULL_WITH_NULL_NULLRFC5246RFC5246RFC4346 RFC6347RFC5246 RFC6347RFC5246 RFC6347RFC4346RFC8996RFC4346RFC8996RFC5246RFC4346RFC8996RFC5246RFC4346RFC8996RFC5246RFC4346RFC8996RFC5246RFC4346RFC8996RFC5246RFC4346 RFC6347RFC5246 RFC6347RFC4346RFC8996RFC5246RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC-ietf-tls-rfc8447bis-14RFC2712 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC4785 RFC-ietf-tls-rfc8447bis-14RFC4785RFC4785RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5246RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC4279 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC4279RFC4279RFC4279RFC4279 RFC6347RFC4279RFC4279RFC4279RFC4279 RFC6347RFC4279RFC4279RFC4279RFC4162RFC4162RFC4162RFC4162RFC4162RFC4162RFC5288RFC5288RFC5288RFC5288RFC5288RFC5288RFC5288RFC5288RFC5288RFC5288RFC5288RFC5288RFC5487RFC5487RFC5487RFC5487RFC5487RFC5487RFC5487RFC5487RFC5487 RFC-ietf-tls-rfc8447bis-14RFC5487 RFC-ietf-tls-rfc8447bis-14RFC5487RFC5487RFC5487RFC5487RFC5487RFC5487RFC5487RFC5487RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC5932RFC8998RFC8998TLS_EMPTY_RENEGOTIATION_INFO_SCSVRFC-ietf-tls-rfc8446bis-13RFC-ietf-tls-rfc8446bis-13RFC-ietf-tls-rfc8446bis-13RFC-ietf-tls-rfc8446bis-13RFC-ietf-tls-rfc8446bis-13 IESG Action 2018-08-16draft-irtf-cfrg-aegis-aead-08]TLS_AEGIS_128L_SHA256TLS_FALLBACK_SCSVRFC8422RFC8422 RFC6347RFC8422RFC8422RFC8422RFC8422 RFC-ietf-tls-rfc8447bis-14RFC8422 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC8422RFC8422RFC8422RFC8422RFC8422 RFC6347RFC8422RFC8422RFC8422RFC8422 RFC-ietf-tls-rfc8447bis-14RFC8422 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC8422RFC8422RFC8422RFC8422RFC8422 RFC6347RFC8422RFC8422RFC8422RFC5054RFC5054RFC5054RFC5054RFC5054RFC5054RFC5054RFC5054RFC5054RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5289RFC5489 RFC6347 RFC-ietf-tls-rfc8447bis-14RFC5489RFC5489RFC5489RFC5489RFC5489RFC5489 RFC-ietf-tls-rfc8447bis-14RFC5489 RFC-ietf-tls-rfc8447bis-14RFC5489 RFC-ietf-tls-rfc8447bis-14RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6209RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6367RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC6655RFC7251RFC7251RFC7251RFC7251RFC8492RFC8492RFC8492RFC8492RFC9150 RFC-ietf-tls-rfc8447bis-14RFC9150 RFC-ietf-tls-rfc8447bis-14RFC9189RFC9189RFC9189RFC9367RFC9367RFC9367RFC9367RFC7905RFC7905RFC7905RFC7905RFC7905RFC7905RFC7905RFC8442RFC8442RFC8442TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256"
 | 
			
		||||
 | 
			
		||||
var _TLSCipherSuite_map = map[TLSCipherSuite]string{
 | 
			
		||||
	0:     _TLSCipherSuite_name[0:23],
 | 
			
		||||
	1:     _TLSCipherSuite_name[23:30],
 | 
			
		||||
	2:     _TLSCipherSuite_name[30:37],
 | 
			
		||||
	3:     _TLSCipherSuite_name[37:52],
 | 
			
		||||
	4:     _TLSCipherSuite_name[52:67],
 | 
			
		||||
	5:     _TLSCipherSuite_name[67:82],
 | 
			
		||||
	6:     _TLSCipherSuite_name[82:89],
 | 
			
		||||
	7:     _TLSCipherSuite_name[89:96],
 | 
			
		||||
	8:     _TLSCipherSuite_name[96:103],
 | 
			
		||||
	9:     _TLSCipherSuite_name[103:110],
 | 
			
		||||
	10:    _TLSCipherSuite_name[110:117],
 | 
			
		||||
	11:    _TLSCipherSuite_name[117:124],
 | 
			
		||||
	12:    _TLSCipherSuite_name[124:131],
 | 
			
		||||
	13:    _TLSCipherSuite_name[131:138],
 | 
			
		||||
	14:    _TLSCipherSuite_name[138:145],
 | 
			
		||||
	15:    _TLSCipherSuite_name[145:152],
 | 
			
		||||
	16:    _TLSCipherSuite_name[152:159],
 | 
			
		||||
	17:    _TLSCipherSuite_name[159:166],
 | 
			
		||||
	18:    _TLSCipherSuite_name[166:173],
 | 
			
		||||
	19:    _TLSCipherSuite_name[173:180],
 | 
			
		||||
	20:    _TLSCipherSuite_name[180:187],
 | 
			
		||||
	21:    _TLSCipherSuite_name[187:194],
 | 
			
		||||
	22:    _TLSCipherSuite_name[194:201],
 | 
			
		||||
	23:    _TLSCipherSuite_name[201:216],
 | 
			
		||||
	24:    _TLSCipherSuite_name[216:231],
 | 
			
		||||
	25:    _TLSCipherSuite_name[231:238],
 | 
			
		||||
	26:    _TLSCipherSuite_name[238:245],
 | 
			
		||||
	27:    _TLSCipherSuite_name[245:252],
 | 
			
		||||
	30:    _TLSCipherSuite_name[252:286],
 | 
			
		||||
	31:    _TLSCipherSuite_name[286:293],
 | 
			
		||||
	32:    _TLSCipherSuite_name[293:335],
 | 
			
		||||
	33:    _TLSCipherSuite_name[335:369],
 | 
			
		||||
	34:    _TLSCipherSuite_name[369:403],
 | 
			
		||||
	35:    _TLSCipherSuite_name[403:410],
 | 
			
		||||
	36:    _TLSCipherSuite_name[410:452],
 | 
			
		||||
	37:    _TLSCipherSuite_name[452:486],
 | 
			
		||||
	38:    _TLSCipherSuite_name[486:520],
 | 
			
		||||
	39:    _TLSCipherSuite_name[520:554],
 | 
			
		||||
	40:    _TLSCipherSuite_name[554:596],
 | 
			
		||||
	41:    _TLSCipherSuite_name[596:630],
 | 
			
		||||
	42:    _TLSCipherSuite_name[630:664],
 | 
			
		||||
	43:    _TLSCipherSuite_name[664:706],
 | 
			
		||||
	44:    _TLSCipherSuite_name[706:740],
 | 
			
		||||
	45:    _TLSCipherSuite_name[740:747],
 | 
			
		||||
	46:    _TLSCipherSuite_name[747:754],
 | 
			
		||||
	47:    _TLSCipherSuite_name[754:761],
 | 
			
		||||
	48:    _TLSCipherSuite_name[761:768],
 | 
			
		||||
	49:    _TLSCipherSuite_name[768:775],
 | 
			
		||||
	50:    _TLSCipherSuite_name[775:782],
 | 
			
		||||
	51:    _TLSCipherSuite_name[782:789],
 | 
			
		||||
	52:    _TLSCipherSuite_name[789:796],
 | 
			
		||||
	53:    _TLSCipherSuite_name[796:803],
 | 
			
		||||
	54:    _TLSCipherSuite_name[803:810],
 | 
			
		||||
	55:    _TLSCipherSuite_name[810:817],
 | 
			
		||||
	56:    _TLSCipherSuite_name[817:824],
 | 
			
		||||
	57:    _TLSCipherSuite_name[824:831],
 | 
			
		||||
	58:    _TLSCipherSuite_name[831:838],
 | 
			
		||||
	59:    _TLSCipherSuite_name[838:845],
 | 
			
		||||
	60:    _TLSCipherSuite_name[845:852],
 | 
			
		||||
	61:    _TLSCipherSuite_name[852:859],
 | 
			
		||||
	62:    _TLSCipherSuite_name[859:866],
 | 
			
		||||
	63:    _TLSCipherSuite_name[866:873],
 | 
			
		||||
	64:    _TLSCipherSuite_name[873:880],
 | 
			
		||||
	65:    _TLSCipherSuite_name[880:887],
 | 
			
		||||
	66:    _TLSCipherSuite_name[887:894],
 | 
			
		||||
	67:    _TLSCipherSuite_name[894:901],
 | 
			
		||||
	68:    _TLSCipherSuite_name[901:908],
 | 
			
		||||
	69:    _TLSCipherSuite_name[908:915],
 | 
			
		||||
	70:    _TLSCipherSuite_name[915:922],
 | 
			
		||||
	103:   _TLSCipherSuite_name[922:929],
 | 
			
		||||
	104:   _TLSCipherSuite_name[929:936],
 | 
			
		||||
	105:   _TLSCipherSuite_name[936:943],
 | 
			
		||||
	106:   _TLSCipherSuite_name[943:950],
 | 
			
		||||
	107:   _TLSCipherSuite_name[950:957],
 | 
			
		||||
	108:   _TLSCipherSuite_name[957:964],
 | 
			
		||||
	109:   _TLSCipherSuite_name[964:971],
 | 
			
		||||
	132:   _TLSCipherSuite_name[971:978],
 | 
			
		||||
	133:   _TLSCipherSuite_name[978:985],
 | 
			
		||||
	134:   _TLSCipherSuite_name[985:992],
 | 
			
		||||
	135:   _TLSCipherSuite_name[992:999],
 | 
			
		||||
	136:   _TLSCipherSuite_name[999:1006],
 | 
			
		||||
	137:   _TLSCipherSuite_name[1006:1013],
 | 
			
		||||
	138:   _TLSCipherSuite_name[1013:1055],
 | 
			
		||||
	139:   _TLSCipherSuite_name[1055:1062],
 | 
			
		||||
	140:   _TLSCipherSuite_name[1062:1069],
 | 
			
		||||
	141:   _TLSCipherSuite_name[1069:1076],
 | 
			
		||||
	142:   _TLSCipherSuite_name[1076:1091],
 | 
			
		||||
	143:   _TLSCipherSuite_name[1091:1098],
 | 
			
		||||
	144:   _TLSCipherSuite_name[1098:1105],
 | 
			
		||||
	145:   _TLSCipherSuite_name[1105:1112],
 | 
			
		||||
	146:   _TLSCipherSuite_name[1112:1127],
 | 
			
		||||
	147:   _TLSCipherSuite_name[1127:1134],
 | 
			
		||||
	148:   _TLSCipherSuite_name[1134:1141],
 | 
			
		||||
	149:   _TLSCipherSuite_name[1141:1148],
 | 
			
		||||
	150:   _TLSCipherSuite_name[1148:1155],
 | 
			
		||||
	151:   _TLSCipherSuite_name[1155:1162],
 | 
			
		||||
	152:   _TLSCipherSuite_name[1162:1169],
 | 
			
		||||
	153:   _TLSCipherSuite_name[1169:1176],
 | 
			
		||||
	154:   _TLSCipherSuite_name[1176:1183],
 | 
			
		||||
	155:   _TLSCipherSuite_name[1183:1190],
 | 
			
		||||
	156:   _TLSCipherSuite_name[1190:1197],
 | 
			
		||||
	157:   _TLSCipherSuite_name[1197:1204],
 | 
			
		||||
	158:   _TLSCipherSuite_name[1204:1211],
 | 
			
		||||
	159:   _TLSCipherSuite_name[1211:1218],
 | 
			
		||||
	160:   _TLSCipherSuite_name[1218:1225],
 | 
			
		||||
	161:   _TLSCipherSuite_name[1225:1232],
 | 
			
		||||
	162:   _TLSCipherSuite_name[1232:1239],
 | 
			
		||||
	163:   _TLSCipherSuite_name[1239:1246],
 | 
			
		||||
	164:   _TLSCipherSuite_name[1246:1253],
 | 
			
		||||
	165:   _TLSCipherSuite_name[1253:1260],
 | 
			
		||||
	166:   _TLSCipherSuite_name[1260:1267],
 | 
			
		||||
	167:   _TLSCipherSuite_name[1267:1274],
 | 
			
		||||
	168:   _TLSCipherSuite_name[1274:1281],
 | 
			
		||||
	169:   _TLSCipherSuite_name[1281:1288],
 | 
			
		||||
	170:   _TLSCipherSuite_name[1288:1295],
 | 
			
		||||
	171:   _TLSCipherSuite_name[1295:1302],
 | 
			
		||||
	172:   _TLSCipherSuite_name[1302:1309],
 | 
			
		||||
	173:   _TLSCipherSuite_name[1309:1316],
 | 
			
		||||
	174:   _TLSCipherSuite_name[1316:1323],
 | 
			
		||||
	175:   _TLSCipherSuite_name[1323:1330],
 | 
			
		||||
	176:   _TLSCipherSuite_name[1330:1364],
 | 
			
		||||
	177:   _TLSCipherSuite_name[1364:1398],
 | 
			
		||||
	178:   _TLSCipherSuite_name[1398:1405],
 | 
			
		||||
	179:   _TLSCipherSuite_name[1405:1412],
 | 
			
		||||
	180:   _TLSCipherSuite_name[1412:1419],
 | 
			
		||||
	181:   _TLSCipherSuite_name[1419:1426],
 | 
			
		||||
	182:   _TLSCipherSuite_name[1426:1433],
 | 
			
		||||
	183:   _TLSCipherSuite_name[1433:1440],
 | 
			
		||||
	184:   _TLSCipherSuite_name[1440:1447],
 | 
			
		||||
	185:   _TLSCipherSuite_name[1447:1454],
 | 
			
		||||
	186:   _TLSCipherSuite_name[1454:1461],
 | 
			
		||||
	187:   _TLSCipherSuite_name[1461:1468],
 | 
			
		||||
	188:   _TLSCipherSuite_name[1468:1475],
 | 
			
		||||
	189:   _TLSCipherSuite_name[1475:1482],
 | 
			
		||||
	190:   _TLSCipherSuite_name[1482:1489],
 | 
			
		||||
	191:   _TLSCipherSuite_name[1489:1496],
 | 
			
		||||
	192:   _TLSCipherSuite_name[1496:1503],
 | 
			
		||||
	193:   _TLSCipherSuite_name[1503:1510],
 | 
			
		||||
	194:   _TLSCipherSuite_name[1510:1517],
 | 
			
		||||
	195:   _TLSCipherSuite_name[1517:1524],
 | 
			
		||||
	196:   _TLSCipherSuite_name[1524:1531],
 | 
			
		||||
	197:   _TLSCipherSuite_name[1531:1538],
 | 
			
		||||
	198:   _TLSCipherSuite_name[1538:1545],
 | 
			
		||||
	199:   _TLSCipherSuite_name[1545:1552],
 | 
			
		||||
	255:   _TLSCipherSuite_name[1552:1585],
 | 
			
		||||
	4865:  _TLSCipherSuite_name[1585:1611],
 | 
			
		||||
	4866:  _TLSCipherSuite_name[1611:1637],
 | 
			
		||||
	4867:  _TLSCipherSuite_name[1637:1663],
 | 
			
		||||
	4868:  _TLSCipherSuite_name[1663:1689],
 | 
			
		||||
	4869:  _TLSCipherSuite_name[1689:1738],
 | 
			
		||||
	4870:  _TLSCipherSuite_name[1738:1768],
 | 
			
		||||
	4871:  _TLSCipherSuite_name[1768:1789],
 | 
			
		||||
	22016: _TLSCipherSuite_name[1789:1806],
 | 
			
		||||
	49153: _TLSCipherSuite_name[1806:1813],
 | 
			
		||||
	49154: _TLSCipherSuite_name[1813:1828],
 | 
			
		||||
	49155: _TLSCipherSuite_name[1828:1835],
 | 
			
		||||
	49156: _TLSCipherSuite_name[1835:1842],
 | 
			
		||||
	49157: _TLSCipherSuite_name[1842:1849],
 | 
			
		||||
	49158: _TLSCipherSuite_name[1849:1883],
 | 
			
		||||
	49159: _TLSCipherSuite_name[1883:1925],
 | 
			
		||||
	49160: _TLSCipherSuite_name[1925:1932],
 | 
			
		||||
	49161: _TLSCipherSuite_name[1932:1939],
 | 
			
		||||
	49162: _TLSCipherSuite_name[1939:1946],
 | 
			
		||||
	49163: _TLSCipherSuite_name[1946:1953],
 | 
			
		||||
	49164: _TLSCipherSuite_name[1953:1968],
 | 
			
		||||
	49165: _TLSCipherSuite_name[1968:1975],
 | 
			
		||||
	49166: _TLSCipherSuite_name[1975:1982],
 | 
			
		||||
	49167: _TLSCipherSuite_name[1982:1989],
 | 
			
		||||
	49168: _TLSCipherSuite_name[1989:2023],
 | 
			
		||||
	49169: _TLSCipherSuite_name[2023:2065],
 | 
			
		||||
	49170: _TLSCipherSuite_name[2065:2072],
 | 
			
		||||
	49171: _TLSCipherSuite_name[2072:2079],
 | 
			
		||||
	49172: _TLSCipherSuite_name[2079:2086],
 | 
			
		||||
	49173: _TLSCipherSuite_name[2086:2093],
 | 
			
		||||
	49174: _TLSCipherSuite_name[2093:2108],
 | 
			
		||||
	49175: _TLSCipherSuite_name[2108:2115],
 | 
			
		||||
	49176: _TLSCipherSuite_name[2115:2122],
 | 
			
		||||
	49177: _TLSCipherSuite_name[2122:2129],
 | 
			
		||||
	49178: _TLSCipherSuite_name[2129:2136],
 | 
			
		||||
	49179: _TLSCipherSuite_name[2136:2143],
 | 
			
		||||
	49180: _TLSCipherSuite_name[2143:2150],
 | 
			
		||||
	49181: _TLSCipherSuite_name[2150:2157],
 | 
			
		||||
	49182: _TLSCipherSuite_name[2157:2164],
 | 
			
		||||
	49183: _TLSCipherSuite_name[2164:2171],
 | 
			
		||||
	49184: _TLSCipherSuite_name[2171:2178],
 | 
			
		||||
	49185: _TLSCipherSuite_name[2178:2185],
 | 
			
		||||
	49186: _TLSCipherSuite_name[2185:2192],
 | 
			
		||||
	49187: _TLSCipherSuite_name[2192:2199],
 | 
			
		||||
	49188: _TLSCipherSuite_name[2199:2206],
 | 
			
		||||
	49189: _TLSCipherSuite_name[2206:2213],
 | 
			
		||||
	49190: _TLSCipherSuite_name[2213:2220],
 | 
			
		||||
	49191: _TLSCipherSuite_name[2220:2227],
 | 
			
		||||
	49192: _TLSCipherSuite_name[2227:2234],
 | 
			
		||||
	49193: _TLSCipherSuite_name[2234:2241],
 | 
			
		||||
	49194: _TLSCipherSuite_name[2241:2248],
 | 
			
		||||
	49195: _TLSCipherSuite_name[2248:2255],
 | 
			
		||||
	49196: _TLSCipherSuite_name[2255:2262],
 | 
			
		||||
	49197: _TLSCipherSuite_name[2262:2269],
 | 
			
		||||
	49198: _TLSCipherSuite_name[2269:2276],
 | 
			
		||||
	49199: _TLSCipherSuite_name[2276:2283],
 | 
			
		||||
	49200: _TLSCipherSuite_name[2283:2290],
 | 
			
		||||
	49201: _TLSCipherSuite_name[2290:2297],
 | 
			
		||||
	49202: _TLSCipherSuite_name[2297:2304],
 | 
			
		||||
	49203: _TLSCipherSuite_name[2304:2346],
 | 
			
		||||
	49204: _TLSCipherSuite_name[2346:2353],
 | 
			
		||||
	49205: _TLSCipherSuite_name[2353:2360],
 | 
			
		||||
	49206: _TLSCipherSuite_name[2360:2367],
 | 
			
		||||
	49207: _TLSCipherSuite_name[2367:2374],
 | 
			
		||||
	49208: _TLSCipherSuite_name[2374:2381],
 | 
			
		||||
	49209: _TLSCipherSuite_name[2381:2415],
 | 
			
		||||
	49210: _TLSCipherSuite_name[2415:2449],
 | 
			
		||||
	49211: _TLSCipherSuite_name[2449:2483],
 | 
			
		||||
	49212: _TLSCipherSuite_name[2483:2490],
 | 
			
		||||
	49213: _TLSCipherSuite_name[2490:2497],
 | 
			
		||||
	49214: _TLSCipherSuite_name[2497:2504],
 | 
			
		||||
	49215: _TLSCipherSuite_name[2504:2511],
 | 
			
		||||
	49216: _TLSCipherSuite_name[2511:2518],
 | 
			
		||||
	49217: _TLSCipherSuite_name[2518:2525],
 | 
			
		||||
	49218: _TLSCipherSuite_name[2525:2532],
 | 
			
		||||
	49219: _TLSCipherSuite_name[2532:2539],
 | 
			
		||||
	49220: _TLSCipherSuite_name[2539:2546],
 | 
			
		||||
	49221: _TLSCipherSuite_name[2546:2553],
 | 
			
		||||
	49222: _TLSCipherSuite_name[2553:2560],
 | 
			
		||||
	49223: _TLSCipherSuite_name[2560:2567],
 | 
			
		||||
	49224: _TLSCipherSuite_name[2567:2574],
 | 
			
		||||
	49225: _TLSCipherSuite_name[2574:2581],
 | 
			
		||||
	49226: _TLSCipherSuite_name[2581:2588],
 | 
			
		||||
	49227: _TLSCipherSuite_name[2588:2595],
 | 
			
		||||
	49228: _TLSCipherSuite_name[2595:2602],
 | 
			
		||||
	49229: _TLSCipherSuite_name[2602:2609],
 | 
			
		||||
	49230: _TLSCipherSuite_name[2609:2616],
 | 
			
		||||
	49231: _TLSCipherSuite_name[2616:2623],
 | 
			
		||||
	49232: _TLSCipherSuite_name[2623:2630],
 | 
			
		||||
	49233: _TLSCipherSuite_name[2630:2637],
 | 
			
		||||
	49234: _TLSCipherSuite_name[2637:2644],
 | 
			
		||||
	49235: _TLSCipherSuite_name[2644:2651],
 | 
			
		||||
	49236: _TLSCipherSuite_name[2651:2658],
 | 
			
		||||
	49237: _TLSCipherSuite_name[2658:2665],
 | 
			
		||||
	49238: _TLSCipherSuite_name[2665:2672],
 | 
			
		||||
	49239: _TLSCipherSuite_name[2672:2679],
 | 
			
		||||
	49240: _TLSCipherSuite_name[2679:2686],
 | 
			
		||||
	49241: _TLSCipherSuite_name[2686:2693],
 | 
			
		||||
	49242: _TLSCipherSuite_name[2693:2700],
 | 
			
		||||
	49243: _TLSCipherSuite_name[2700:2707],
 | 
			
		||||
	49244: _TLSCipherSuite_name[2707:2714],
 | 
			
		||||
	49245: _TLSCipherSuite_name[2714:2721],
 | 
			
		||||
	49246: _TLSCipherSuite_name[2721:2728],
 | 
			
		||||
	49247: _TLSCipherSuite_name[2728:2735],
 | 
			
		||||
	49248: _TLSCipherSuite_name[2735:2742],
 | 
			
		||||
	49249: _TLSCipherSuite_name[2742:2749],
 | 
			
		||||
	49250: _TLSCipherSuite_name[2749:2756],
 | 
			
		||||
	49251: _TLSCipherSuite_name[2756:2763],
 | 
			
		||||
	49252: _TLSCipherSuite_name[2763:2770],
 | 
			
		||||
	49253: _TLSCipherSuite_name[2770:2777],
 | 
			
		||||
	49254: _TLSCipherSuite_name[2777:2784],
 | 
			
		||||
	49255: _TLSCipherSuite_name[2784:2791],
 | 
			
		||||
	49256: _TLSCipherSuite_name[2791:2798],
 | 
			
		||||
	49257: _TLSCipherSuite_name[2798:2805],
 | 
			
		||||
	49258: _TLSCipherSuite_name[2805:2812],
 | 
			
		||||
	49259: _TLSCipherSuite_name[2812:2819],
 | 
			
		||||
	49260: _TLSCipherSuite_name[2819:2826],
 | 
			
		||||
	49261: _TLSCipherSuite_name[2826:2833],
 | 
			
		||||
	49262: _TLSCipherSuite_name[2833:2840],
 | 
			
		||||
	49263: _TLSCipherSuite_name[2840:2847],
 | 
			
		||||
	49264: _TLSCipherSuite_name[2847:2854],
 | 
			
		||||
	49265: _TLSCipherSuite_name[2854:2861],
 | 
			
		||||
	49266: _TLSCipherSuite_name[2861:2868],
 | 
			
		||||
	49267: _TLSCipherSuite_name[2868:2875],
 | 
			
		||||
	49268: _TLSCipherSuite_name[2875:2882],
 | 
			
		||||
	49269: _TLSCipherSuite_name[2882:2889],
 | 
			
		||||
	49270: _TLSCipherSuite_name[2889:2896],
 | 
			
		||||
	49271: _TLSCipherSuite_name[2896:2903],
 | 
			
		||||
	49272: _TLSCipherSuite_name[2903:2910],
 | 
			
		||||
	49273: _TLSCipherSuite_name[2910:2917],
 | 
			
		||||
	49274: _TLSCipherSuite_name[2917:2924],
 | 
			
		||||
	49275: _TLSCipherSuite_name[2924:2931],
 | 
			
		||||
	49276: _TLSCipherSuite_name[2931:2938],
 | 
			
		||||
	49277: _TLSCipherSuite_name[2938:2945],
 | 
			
		||||
	49278: _TLSCipherSuite_name[2945:2952],
 | 
			
		||||
	49279: _TLSCipherSuite_name[2952:2959],
 | 
			
		||||
	49280: _TLSCipherSuite_name[2959:2966],
 | 
			
		||||
	49281: _TLSCipherSuite_name[2966:2973],
 | 
			
		||||
	49282: _TLSCipherSuite_name[2973:2980],
 | 
			
		||||
	49283: _TLSCipherSuite_name[2980:2987],
 | 
			
		||||
	49284: _TLSCipherSuite_name[2987:2994],
 | 
			
		||||
	49285: _TLSCipherSuite_name[2994:3001],
 | 
			
		||||
	49286: _TLSCipherSuite_name[3001:3008],
 | 
			
		||||
	49287: _TLSCipherSuite_name[3008:3015],
 | 
			
		||||
	49288: _TLSCipherSuite_name[3015:3022],
 | 
			
		||||
	49289: _TLSCipherSuite_name[3022:3029],
 | 
			
		||||
	49290: _TLSCipherSuite_name[3029:3036],
 | 
			
		||||
	49291: _TLSCipherSuite_name[3036:3043],
 | 
			
		||||
	49292: _TLSCipherSuite_name[3043:3050],
 | 
			
		||||
	49293: _TLSCipherSuite_name[3050:3057],
 | 
			
		||||
	49294: _TLSCipherSuite_name[3057:3064],
 | 
			
		||||
	49295: _TLSCipherSuite_name[3064:3071],
 | 
			
		||||
	49296: _TLSCipherSuite_name[3071:3078],
 | 
			
		||||
	49297: _TLSCipherSuite_name[3078:3085],
 | 
			
		||||
	49298: _TLSCipherSuite_name[3085:3092],
 | 
			
		||||
	49299: _TLSCipherSuite_name[3092:3099],
 | 
			
		||||
	49300: _TLSCipherSuite_name[3099:3106],
 | 
			
		||||
	49301: _TLSCipherSuite_name[3106:3113],
 | 
			
		||||
	49302: _TLSCipherSuite_name[3113:3120],
 | 
			
		||||
	49303: _TLSCipherSuite_name[3120:3127],
 | 
			
		||||
	49304: _TLSCipherSuite_name[3127:3134],
 | 
			
		||||
	49305: _TLSCipherSuite_name[3134:3141],
 | 
			
		||||
	49306: _TLSCipherSuite_name[3141:3148],
 | 
			
		||||
	49307: _TLSCipherSuite_name[3148:3155],
 | 
			
		||||
	49308: _TLSCipherSuite_name[3155:3162],
 | 
			
		||||
	49309: _TLSCipherSuite_name[3162:3169],
 | 
			
		||||
	49310: _TLSCipherSuite_name[3169:3176],
 | 
			
		||||
	49311: _TLSCipherSuite_name[3176:3183],
 | 
			
		||||
	49312: _TLSCipherSuite_name[3183:3190],
 | 
			
		||||
	49313: _TLSCipherSuite_name[3190:3197],
 | 
			
		||||
	49314: _TLSCipherSuite_name[3197:3204],
 | 
			
		||||
	49315: _TLSCipherSuite_name[3204:3211],
 | 
			
		||||
	49316: _TLSCipherSuite_name[3211:3218],
 | 
			
		||||
	49317: _TLSCipherSuite_name[3218:3225],
 | 
			
		||||
	49318: _TLSCipherSuite_name[3225:3232],
 | 
			
		||||
	49319: _TLSCipherSuite_name[3232:3239],
 | 
			
		||||
	49320: _TLSCipherSuite_name[3239:3246],
 | 
			
		||||
	49321: _TLSCipherSuite_name[3246:3253],
 | 
			
		||||
	49322: _TLSCipherSuite_name[3253:3260],
 | 
			
		||||
	49323: _TLSCipherSuite_name[3260:3267],
 | 
			
		||||
	49324: _TLSCipherSuite_name[3267:3274],
 | 
			
		||||
	49325: _TLSCipherSuite_name[3274:3281],
 | 
			
		||||
	49326: _TLSCipherSuite_name[3281:3288],
 | 
			
		||||
	49327: _TLSCipherSuite_name[3288:3295],
 | 
			
		||||
	49328: _TLSCipherSuite_name[3295:3302],
 | 
			
		||||
	49329: _TLSCipherSuite_name[3302:3309],
 | 
			
		||||
	49330: _TLSCipherSuite_name[3309:3316],
 | 
			
		||||
	49331: _TLSCipherSuite_name[3316:3323],
 | 
			
		||||
	49332: _TLSCipherSuite_name[3323:3357],
 | 
			
		||||
	49333: _TLSCipherSuite_name[3357:3391],
 | 
			
		||||
	49408: _TLSCipherSuite_name[3391:3398],
 | 
			
		||||
	49409: _TLSCipherSuite_name[3398:3405],
 | 
			
		||||
	49410: _TLSCipherSuite_name[3405:3412],
 | 
			
		||||
	49411: _TLSCipherSuite_name[3412:3419],
 | 
			
		||||
	49412: _TLSCipherSuite_name[3419:3426],
 | 
			
		||||
	49413: _TLSCipherSuite_name[3426:3433],
 | 
			
		||||
	49414: _TLSCipherSuite_name[3433:3440],
 | 
			
		||||
	52392: _TLSCipherSuite_name[3440:3447],
 | 
			
		||||
	52393: _TLSCipherSuite_name[3447:3454],
 | 
			
		||||
	52394: _TLSCipherSuite_name[3454:3461],
 | 
			
		||||
	52395: _TLSCipherSuite_name[3461:3468],
 | 
			
		||||
	52396: _TLSCipherSuite_name[3468:3475],
 | 
			
		||||
	52397: _TLSCipherSuite_name[3475:3482],
 | 
			
		||||
	52398: _TLSCipherSuite_name[3482:3489],
 | 
			
		||||
	53249: _TLSCipherSuite_name[3489:3496],
 | 
			
		||||
	53250: _TLSCipherSuite_name[3496:3503],
 | 
			
		||||
	53251: _TLSCipherSuite_name[3503:3510],
 | 
			
		||||
	53253: _TLSCipherSuite_name[3510:3547],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i TLSCipherSuite) String() string {
 | 
			
		||||
	if str, ok := _TLSCipherSuite_map[i]; ok {
 | 
			
		||||
		return str
 | 
			
		||||
	}
 | 
			
		||||
	return "TLSCipherSuite(" + strconv.FormatInt(int64(i), 10) + ")"
 | 
			
		||||
}
 | 
			
		||||
func _() {
 | 
			
		||||
	// An "invalid array index" compiler error signifies that the constant values have changed.
 | 
			
		||||
	// Re-run the stringer command to generate them again.
 | 
			
		||||
	var x [1]struct{}
 | 
			
		||||
	_ = x[PKCS1WithSHA256-1025]
 | 
			
		||||
	_ = x[PKCS1WithSHA384-1281]
 | 
			
		||||
	_ = x[PKCS1WithSHA512-1537]
 | 
			
		||||
	_ = x[PSSWithSHA256-2052]
 | 
			
		||||
	_ = x[PSSWithSHA384-2053]
 | 
			
		||||
	_ = x[PSSWithSHA512-2054]
 | 
			
		||||
	_ = x[ECDSAWithP256AndSHA256-1027]
 | 
			
		||||
	_ = x[ECDSAWithP384AndSHA384-1283]
 | 
			
		||||
	_ = x[ECDSAWithP521AndSHA512-1539]
 | 
			
		||||
	_ = x[Ed25519-2055]
 | 
			
		||||
	_ = x[PKCS1WithSHA1-513]
 | 
			
		||||
	_ = x[ECDSAWithSHA1-515]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_TLSSignatureScheme_name_0 = "PKCS1WithSHA1"
 | 
			
		||||
	_TLSSignatureScheme_name_1 = "ECDSAWithSHA1"
 | 
			
		||||
	_TLSSignatureScheme_name_2 = "PKCS1WithSHA256"
 | 
			
		||||
	_TLSSignatureScheme_name_3 = "ECDSAWithP256AndSHA256"
 | 
			
		||||
	_TLSSignatureScheme_name_4 = "PKCS1WithSHA384"
 | 
			
		||||
	_TLSSignatureScheme_name_5 = "ECDSAWithP384AndSHA384"
 | 
			
		||||
	_TLSSignatureScheme_name_6 = "PKCS1WithSHA512"
 | 
			
		||||
	_TLSSignatureScheme_name_7 = "ECDSAWithP521AndSHA512"
 | 
			
		||||
	_TLSSignatureScheme_name_8 = "PSSWithSHA256PSSWithSHA384PSSWithSHA512Ed25519"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	_TLSSignatureScheme_index_8 = [...]uint8{0, 13, 26, 39, 46}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (i TLSSignatureScheme) String() string {
 | 
			
		||||
	switch {
 | 
			
		||||
	case i == 513:
 | 
			
		||||
		return _TLSSignatureScheme_name_0
 | 
			
		||||
	case i == 515:
 | 
			
		||||
		return _TLSSignatureScheme_name_1
 | 
			
		||||
	case i == 1025:
 | 
			
		||||
		return _TLSSignatureScheme_name_2
 | 
			
		||||
	case i == 1027:
 | 
			
		||||
		return _TLSSignatureScheme_name_3
 | 
			
		||||
	case i == 1281:
 | 
			
		||||
		return _TLSSignatureScheme_name_4
 | 
			
		||||
	case i == 1283:
 | 
			
		||||
		return _TLSSignatureScheme_name_5
 | 
			
		||||
	case i == 1537:
 | 
			
		||||
		return _TLSSignatureScheme_name_6
 | 
			
		||||
	case i == 1539:
 | 
			
		||||
		return _TLSSignatureScheme_name_7
 | 
			
		||||
	case 2052 <= i && i <= 2055:
 | 
			
		||||
		i -= 2052
 | 
			
		||||
		return _TLSSignatureScheme_name_8[_TLSSignatureScheme_index_8[i]:_TLSSignatureScheme_index_8[i+1]]
 | 
			
		||||
	default:
 | 
			
		||||
		return "TLSSignatureScheme(" + strconv.FormatInt(int64(i), 10) + ")"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								tls_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								tls_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
package dpi
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestDecodeTLSClientHello(t *testing.T) {
 | 
			
		||||
	// Taken from a random PCAP on the internet
 | 
			
		||||
	clientHelloBytes, err := testDecodeHexString(`
 | 
			
		||||
		     1603 0100 c801 0000 c403 03ec 12dd
 | 
			
		||||
		1764 a439 fd7e 8c85 46b8 4d1e a06e b3d7
 | 
			
		||||
		a051 f03c b817 470d 4c54 c5df 7200 001c
 | 
			
		||||
		eaea c02b c02f c02c c030 cca9 cca8 c013
 | 
			
		||||
		c014 009c 009d 002f 0035 000a 0100 007f
 | 
			
		||||
		dada 0000 ff01 0001 0000 0000 1600 1400
 | 
			
		||||
		0011 7777 772e 7769 6b69 7065 6469 612e
 | 
			
		||||
		6f72 6700 1700 0000 2300 0000 0d00 1400
 | 
			
		||||
		1204 0308 0404 0105 0308 0505 0108 0606
 | 
			
		||||
		0102 0100 0500 0501 0000 0000 0012 0000
 | 
			
		||||
		0010 000e 000c 0268 3208 6874 7470 2f31
 | 
			
		||||
		2e31 7550 0000 000b 0002 0100 000a 000a
 | 
			
		||||
		0008 1a1a 001d 0017 0018 1a1a 0001 00
 | 
			
		||||
	`)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("failed to decode test ClientHello: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Taken from RFC8443 TLS 1.3 traces example:
 | 
			
		||||
	rfc8443ClientHelloBytes, err := testDecodeHexString(`
 | 
			
		||||
		                            16 03 01 00 c4 01 00 00 c0 03 03 cb
 | 
			
		||||
         34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12
 | 
			
		||||
         ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00
 | 
			
		||||
         00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01
 | 
			
		||||
         00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02
 | 
			
		||||
         01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d
 | 
			
		||||
         e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d
 | 
			
		||||
         54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e
 | 
			
		||||
         04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02
 | 
			
		||||
         01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01
 | 
			
		||||
	`)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("failed to decode test ClientHello: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Run("Client Hello", func(t *testing.T) {
 | 
			
		||||
		hello, err := DecodeTLSClientHelloHandshake(clientHelloBytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		hello.Raw = nil
 | 
			
		||||
		t.Logf("%#v", hello)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("TLS 1.3 Client Hello", func(t *testing.T) {
 | 
			
		||||
		hello, err := DecodeTLSClientHelloHandshake(rfc8443ClientHelloBytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		hello.Raw = nil
 | 
			
		||||
		t.Logf("%#v", hello)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDecodeTLSServerHello(t *testing.T) {
 | 
			
		||||
	serverHelloBytes, err := hex.DecodeString("02000030030300000000000000000000000000000000000000000000000000000000000000000000000000080005000000050000")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("failed to decode test ServerHello: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Run("Server Hello", func(t *testing.T) {
 | 
			
		||||
		hello, err := DecodeTLSServerHello(serverHelloBytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("%#+v", hello)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testDecodeHexString(s string) ([]byte, error) {
 | 
			
		||||
	s = strings.TrimSpace(s)
 | 
			
		||||
	s = strings.ReplaceAll(s, " ", "")
 | 
			
		||||
	s = strings.ReplaceAll(s, "\n", "")
 | 
			
		||||
	s = strings.ReplaceAll(s, "\t", "")
 | 
			
		||||
	return hex.DecodeString(s)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user