Initial import

This commit is contained in:
2025-10-08 20:53:56 +02:00
commit 2081d684ed
25 changed files with 3486 additions and 0 deletions

64
cmd/protodial/main.go Normal file
View 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
View 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
View File

@@ -0,0 +1,2 @@
// Package dpi contains helpers for performing deep packet inspection.
package dpi

26
error.go Normal file
View 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
View 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
View 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
View 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
View 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,
}
}

View 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
View 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,
}
}

View 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)
}
})
}

View 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
}
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

455
tls.go Normal file
View 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
View 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
View 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
View 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)
}