package tls import ( "crypto/x509" "encoding/json" "encoding/pem" "flag" "fmt" "internal/byteorder" "internal/testenv" "io" "log" "net" "os" "os/exec" "path/filepath" "runtime" "testing" ) var ( port = flag.String("port", "", "") server = flag.Bool("server", false, "") isHandshakerSupported = flag.Bool("is-handshaker-supported", false, "") keyfile = flag.String("key-file", "", "") certfile = flag.String("cert-file", "", "") trustCert = flag.String("trust-cert", "", "") minVersion = flag.Int("min-version", VersionSSL30, "") maxVersion = flag.Int("max-version", VersionTLS13, "") noTLS13 = flag.Bool("no-tls13", false, "") requireAnyClientCertificate = flag.Bool("require-any-client-certificate", false, "") shimWritesFirst = flag.Bool("shim-writes-first", false, "") resumeCount = flag.Int("resume-count", 0, "") shimID = flag.Uint64("shim-id", 0, "") _ = flag.Bool("ipv6", false, "") // Unimplemented flags // -advertise-alpn // -advertise-npn // -allow-hint-mismatch // -async // -check-close-notify // -cipher // -curves // -delegated-credential // -dtls // -ech-config-list // -ech-server-config // -enable-channel-id // -enable-early-data // -enable-ech-grease // -enable-grease // -enable-ocsp-stapling // -enable-signed-cert-timestamps // -expect-advertised-alpn // -expect-certificate-types // -expect-channel-id // -expect-cipher-aes // -expect-client-ca-list // -expect-curve-id // -expect-early-data-reason // -expect-extended-master-secret // -expect-hrr // -expect-key-usage-invalid // -expect-msg-callback // -expect-no-session // -expect-peer-cert-file // -expect-peer-signature-algorithm // -expect-peer-verify-pref // -expect-secure-renegotiation // -expect-server-name // -expect-ticket-supports-early-data // -export-keying-material // -export-traffic-secrets // -fail-cert-callback // -fail-early-callback // -fallback-scsv // -false-start // -forbid-renegotiation-after-handshake // -handshake-twice // -host-name // -ignore-rsa-key-usage // -implicit-handshake // -install-cert-compression-algs // -install-ddos-callback // -install-one-cert-compression-alg // -jdk11-workaround // -key-update // -max-cert-list // -max-send-fragment // -no-ticket // -no-tls1 // -no-tls11 // -no-tls12 // -ocsp-response // -on-resume-expect-accept-early-data // -on-resume-expect-reject-early-data // -on-shim-cipher // -on-shim-curves // -peek-then-read // -psk // -read-with-unfinished-write // -reject-alpn // -renegotiate-explicit // -renegotiate-freely // -renegotiate-ignore // -renegotiate-once // -select-alpn // -select-next-proto // -send-alert // -send-channel-id // -server-preference // -shim-shuts-down // -signed-cert-timestamps // -signing-prefs // -srtp-profiles // -tls-unique // -use-client-ca-list // -use-ocsp-callback // -use-old-client-cert-callback // -verify-fail // -verify-peer // -verify-prefs ) func bogoShim() { if *isHandshakerSupported { fmt.Println("No") return } cfg := &Config{ ServerName: "test", MinVersion: uint16(*minVersion), MaxVersion: uint16(*maxVersion), ClientSessionCache: NewLRUClientSessionCache(0), } if *noTLS13 && cfg.MaxVersion == VersionTLS13 { cfg.MaxVersion = VersionTLS12 } if *keyfile != "" || *certfile != "" { pair, err := LoadX509KeyPair(*certfile, *keyfile) if err != nil { log.Fatalf("load key-file err: %s", err) } cfg.Certificates = []Certificate{pair} } if *trustCert != "" { pool := x509.NewCertPool() certFile, err := os.ReadFile(*trustCert) if err != nil { log.Fatalf("load trust-cert err: %s", err) } block, _ := pem.Decode(certFile) cert, err := x509.ParseCertificate(block.Bytes) if err != nil { log.Fatalf("parse trust-cert err: %s", err) } pool.AddCert(cert) cfg.RootCAs = pool } if *requireAnyClientCertificate { cfg.ClientAuth = RequireAnyClientCert } for i := 0; i < *resumeCount+1; i++ { conn, err := net.Dial("tcp", net.JoinHostPort("localhost", *port)) if err != nil { log.Fatalf("dial err: %s", err) } defer conn.Close() // Write the shim ID we were passed as a little endian uint64 shimIDBytes := make([]byte, 8) byteorder.LePutUint64(shimIDBytes, *shimID) if _, err := conn.Write(shimIDBytes); err != nil { log.Fatalf("failed to write shim id: %s", err) } var tlsConn *Conn if *server { tlsConn = Server(conn, cfg) } else { tlsConn = Client(conn, cfg) } if *shimWritesFirst { if _, err := tlsConn.Write([]byte("hello")); err != nil { log.Fatalf("write err: %s", err) } } for { buf := make([]byte, 500) n, err := tlsConn.Read(buf) if err == io.EOF { break } if err != nil { log.Fatalf("read err: %s", err) } buf = buf[:n] for i := range buf { buf[i] ^= 0xff } if _, err := tlsConn.Write(buf); err != nil { log.Fatalf("write err: %s", err) } } } } func TestBogoSuite(t *testing.T) { testenv.SkipIfShortAndSlow(t) testenv.MustHaveExternalNetwork(t) testenv.MustHaveGoRun(t) testenv.MustHaveExec(t) if testing.Short() { t.Skip("skipping in short mode") } if testenv.Builder() != "" && runtime.GOOS == "windows" { t.Skip("#66913: windows network connections are flakey on builders") } const boringsslModVer = "v0.0.0-20240412155355-1c6e10495e4f" output, err := exec.Command("go", "mod", "download", "-json", "github.com/google/boringssl@"+boringsslModVer).CombinedOutput() if err != nil { t.Fatalf("failed to download boringssl: %s", err) } var j struct { Dir string } if err := json.Unmarshal(output, &j); err != nil { t.Fatalf("failed to parse 'go mod download' output: %s", err) } cwd, err := os.Getwd() if err != nil { t.Fatal(err) } args := []string{ "test", ".", fmt.Sprintf("-shim-config=%s", filepath.Join(cwd, "bogo_config.json")), fmt.Sprintf("-shim-path=%s", os.Args[0]), "-shim-extra-flags=-bogo-mode", "-allow-unimplemented", "-loose-errors", // TODO(roland): this should be removed eventually } if *bogoFilter != "" { args = append(args, fmt.Sprintf("-test=%s", *bogoFilter)) } goCmd, err := testenv.GoTool() if err != nil { t.Fatal(err) } cmd := exec.Command(goCmd, args...) cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr cmd.Dir = filepath.Join(j.Dir, "ssl/test/runner") err = cmd.Run() if err != nil { t.Fatalf("bogo failed: %s", err) } }