Source file src/crypto/tls/bogo_shim_test.go

     1  package tls
     2  
     3  import (
     4  	"crypto/x509"
     5  	"encoding/binary"
     6  	"encoding/json"
     7  	"encoding/pem"
     8  	"flag"
     9  	"fmt"
    10  	"internal/testenv"
    11  	"io"
    12  	"log"
    13  	"net"
    14  	"os"
    15  	"os/exec"
    16  	"path/filepath"
    17  	"runtime"
    18  	"testing"
    19  )
    20  
    21  var (
    22  	port   = flag.String("port", "", "")
    23  	server = flag.Bool("server", false, "")
    24  
    25  	isHandshakerSupported = flag.Bool("is-handshaker-supported", false, "")
    26  
    27  	keyfile  = flag.String("key-file", "", "")
    28  	certfile = flag.String("cert-file", "", "")
    29  
    30  	trustCert = flag.String("trust-cert", "", "")
    31  
    32  	minVersion = flag.Int("min-version", VersionSSL30, "")
    33  	maxVersion = flag.Int("max-version", VersionTLS13, "")
    34  
    35  	noTLS13 = flag.Bool("no-tls13", false, "")
    36  
    37  	requireAnyClientCertificate = flag.Bool("require-any-client-certificate", false, "")
    38  
    39  	shimWritesFirst = flag.Bool("shim-writes-first", false, "")
    40  
    41  	resumeCount = flag.Int("resume-count", 0, "")
    42  
    43  	shimID = flag.Uint64("shim-id", 0, "")
    44  	_      = flag.Bool("ipv6", false, "")
    45  
    46  	// Unimplemented flags
    47  	// -advertise-alpn
    48  	// -advertise-npn
    49  	// -allow-hint-mismatch
    50  	// -async
    51  	// -check-close-notify
    52  	// -cipher
    53  	// -curves
    54  	// -delegated-credential
    55  	// -dtls
    56  	// -ech-config-list
    57  	// -ech-server-config
    58  	// -enable-channel-id
    59  	// -enable-early-data
    60  	// -enable-ech-grease
    61  	// -enable-grease
    62  	// -enable-ocsp-stapling
    63  	// -enable-signed-cert-timestamps
    64  	// -expect-advertised-alpn
    65  	// -expect-certificate-types
    66  	// -expect-channel-id
    67  	// -expect-cipher-aes
    68  	// -expect-client-ca-list
    69  	// -expect-curve-id
    70  	// -expect-early-data-reason
    71  	// -expect-extended-master-secret
    72  	// -expect-hrr
    73  	// -expect-key-usage-invalid
    74  	// -expect-msg-callback
    75  	// -expect-no-session
    76  	// -expect-peer-cert-file
    77  	// -expect-peer-signature-algorithm
    78  	// -expect-peer-verify-pref
    79  	// -expect-secure-renegotiation
    80  	// -expect-server-name
    81  	// -expect-ticket-supports-early-data
    82  	// -export-keying-material
    83  	// -export-traffic-secrets
    84  	// -fail-cert-callback
    85  	// -fail-early-callback
    86  	// -fallback-scsv
    87  	// -false-start
    88  	// -forbid-renegotiation-after-handshake
    89  	// -handshake-twice
    90  	// -host-name
    91  	// -ignore-rsa-key-usage
    92  	// -implicit-handshake
    93  	// -install-cert-compression-algs
    94  	// -install-ddos-callback
    95  	// -install-one-cert-compression-alg
    96  	// -jdk11-workaround
    97  	// -key-update
    98  	// -max-cert-list
    99  	// -max-send-fragment
   100  	// -no-ticket
   101  	// -no-tls1
   102  	// -no-tls11
   103  	// -no-tls12
   104  	// -ocsp-response
   105  	// -on-resume-expect-accept-early-data
   106  	// -on-resume-expect-reject-early-data
   107  	// -on-shim-cipher
   108  	// -on-shim-curves
   109  	// -peek-then-read
   110  	// -psk
   111  	// -read-with-unfinished-write
   112  	// -reject-alpn
   113  	// -renegotiate-explicit
   114  	// -renegotiate-freely
   115  	// -renegotiate-ignore
   116  	// -renegotiate-once
   117  	// -select-alpn
   118  	// -select-next-proto
   119  	// -send-alert
   120  	// -send-channel-id
   121  	// -server-preference
   122  	// -shim-shuts-down
   123  	// -signed-cert-timestamps
   124  	// -signing-prefs
   125  	// -srtp-profiles
   126  	// -tls-unique
   127  	// -use-client-ca-list
   128  	// -use-ocsp-callback
   129  	// -use-old-client-cert-callback
   130  	// -verify-fail
   131  	// -verify-peer
   132  	// -verify-prefs
   133  )
   134  
   135  func bogoShim() {
   136  	if *isHandshakerSupported {
   137  		fmt.Println("No")
   138  		return
   139  	}
   140  
   141  	cfg := &Config{
   142  		ServerName: "test",
   143  
   144  		MinVersion: uint16(*minVersion),
   145  		MaxVersion: uint16(*maxVersion),
   146  
   147  		ClientSessionCache: NewLRUClientSessionCache(0),
   148  	}
   149  
   150  	if *noTLS13 && cfg.MaxVersion == VersionTLS13 {
   151  		cfg.MaxVersion = VersionTLS12
   152  	}
   153  
   154  	if *keyfile != "" || *certfile != "" {
   155  		pair, err := LoadX509KeyPair(*certfile, *keyfile)
   156  		if err != nil {
   157  			log.Fatalf("load key-file err: %s", err)
   158  		}
   159  		cfg.Certificates = []Certificate{pair}
   160  	}
   161  	if *trustCert != "" {
   162  		pool := x509.NewCertPool()
   163  		certFile, err := os.ReadFile(*trustCert)
   164  		if err != nil {
   165  			log.Fatalf("load trust-cert err: %s", err)
   166  		}
   167  		block, _ := pem.Decode(certFile)
   168  		cert, err := x509.ParseCertificate(block.Bytes)
   169  		if err != nil {
   170  			log.Fatalf("parse trust-cert err: %s", err)
   171  		}
   172  		pool.AddCert(cert)
   173  		cfg.RootCAs = pool
   174  	}
   175  
   176  	if *requireAnyClientCertificate {
   177  		cfg.ClientAuth = RequireAnyClientCert
   178  	}
   179  
   180  	for i := 0; i < *resumeCount+1; i++ {
   181  		conn, err := net.Dial("tcp", net.JoinHostPort("localhost", *port))
   182  		if err != nil {
   183  			log.Fatalf("dial err: %s", err)
   184  		}
   185  		defer conn.Close()
   186  
   187  		// Write the shim ID we were passed as a little endian uint64
   188  		shimIDBytes := make([]byte, 8)
   189  		binary.LittleEndian.PutUint64(shimIDBytes, *shimID)
   190  		if _, err := conn.Write(shimIDBytes); err != nil {
   191  			log.Fatalf("failed to write shim id: %s", err)
   192  		}
   193  
   194  		var tlsConn *Conn
   195  		if *server {
   196  			tlsConn = Server(conn, cfg)
   197  		} else {
   198  			tlsConn = Client(conn, cfg)
   199  		}
   200  
   201  		if *shimWritesFirst {
   202  			if _, err := tlsConn.Write([]byte("hello")); err != nil {
   203  				log.Fatalf("write err: %s", err)
   204  			}
   205  		}
   206  
   207  		for {
   208  			buf := make([]byte, 500)
   209  			n, err := tlsConn.Read(buf)
   210  			if err == io.EOF {
   211  				break
   212  			}
   213  			if err != nil {
   214  				log.Fatalf("read err: %s", err)
   215  			}
   216  			buf = buf[:n]
   217  			for i := range buf {
   218  				buf[i] ^= 0xff
   219  			}
   220  			if _, err := tlsConn.Write(buf); err != nil {
   221  				log.Fatalf("write err: %s", err)
   222  			}
   223  		}
   224  	}
   225  }
   226  
   227  func TestBogoSuite(t *testing.T) {
   228  	testenv.SkipIfShortAndSlow(t)
   229  	testenv.MustHaveExternalNetwork(t)
   230  	testenv.MustHaveGoRun(t)
   231  	testenv.MustHaveExec(t)
   232  
   233  	if testing.Short() {
   234  		t.Skip("skipping in short mode")
   235  	}
   236  
   237  	if testenv.Builder() != "" && runtime.GOOS == "windows" {
   238  		t.Skip("#66913: windows network connections are flakey on builders")
   239  	}
   240  
   241  	const boringsslModVer = "v0.0.0-20240412155355-1c6e10495e4f"
   242  	output, err := exec.Command("go", "mod", "download", "-json", "github.com/google/boringssl@"+boringsslModVer).CombinedOutput()
   243  	if err != nil {
   244  		t.Fatalf("failed to download boringssl: %s", err)
   245  	}
   246  	var j struct {
   247  		Dir string
   248  	}
   249  	if err := json.Unmarshal(output, &j); err != nil {
   250  		t.Fatalf("failed to parse 'go mod download' output: %s", err)
   251  	}
   252  
   253  	cwd, err := os.Getwd()
   254  	if err != nil {
   255  		t.Fatal(err)
   256  	}
   257  
   258  	args := []string{
   259  		"test",
   260  		".",
   261  		fmt.Sprintf("-shim-config=%s", filepath.Join(cwd, "bogo_config.json")),
   262  		fmt.Sprintf("-shim-path=%s", os.Args[0]),
   263  		"-shim-extra-flags=-bogo-mode",
   264  		"-allow-unimplemented",
   265  		"-loose-errors", // TODO(roland): this should be removed eventually
   266  	}
   267  	if *bogoFilter != "" {
   268  		args = append(args, fmt.Sprintf("-test=%s", *bogoFilter))
   269  	}
   270  
   271  	goCmd, err := testenv.GoTool()
   272  	if err != nil {
   273  		t.Fatal(err)
   274  	}
   275  	cmd := exec.Command(goCmd, args...)
   276  	cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
   277  	cmd.Dir = filepath.Join(j.Dir, "ssl/test/runner")
   278  	err = cmd.Run()
   279  	if err != nil {
   280  		t.Fatalf("bogo failed: %s", err)
   281  	}
   282  }
   283  

View as plain text