// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tls

import (
	"context"
	"errors"
	"reflect"
	"testing"
)

type testQUICConn struct {
	t           *testing.T
	conn        *QUICConn
	readSecret  map[QUICEncryptionLevel]suiteSecret
	writeSecret map[QUICEncryptionLevel]suiteSecret
	gotParams   []byte
	complete    bool
}

func newTestQUICClient(t *testing.T, config *Config) *testQUICConn {
	q := &testQUICConn{t: t}
	q.conn = QUICClient(&QUICConfig{
		TLSConfig: config,
	})
	t.Cleanup(func() {
		q.conn.Close()
	})
	return q
}

func newTestQUICServer(t *testing.T, config *Config) *testQUICConn {
	q := &testQUICConn{t: t}
	q.conn = QUICServer(&QUICConfig{
		TLSConfig: config,
	})
	t.Cleanup(func() {
		q.conn.Close()
	})
	return q
}

type suiteSecret struct {
	suite  uint16
	secret []byte
}

func (q *testQUICConn) setReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
	if _, ok := q.writeSecret[level]; !ok {
		q.t.Errorf("SetReadSecret for level %v called before SetWriteSecret", level)
	}
	if level == QUICEncryptionLevelApplication && !q.complete {
		q.t.Errorf("SetReadSecret for level %v called before HandshakeComplete", level)
	}
	if _, ok := q.readSecret[level]; ok {
		q.t.Errorf("SetReadSecret for level %v called twice", level)
	}
	if q.readSecret == nil {
		q.readSecret = map[QUICEncryptionLevel]suiteSecret{}
	}
	switch level {
	case QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication:
		q.readSecret[level] = suiteSecret{suite, secret}
	default:
		q.t.Errorf("SetReadSecret for unexpected level %v", level)
	}
}

func (q *testQUICConn) setWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
	if _, ok := q.writeSecret[level]; ok {
		q.t.Errorf("SetWriteSecret for level %v called twice", level)
	}
	if q.writeSecret == nil {
		q.writeSecret = map[QUICEncryptionLevel]suiteSecret{}
	}
	switch level {
	case QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication:
		q.writeSecret[level] = suiteSecret{suite, secret}
	default:
		q.t.Errorf("SetWriteSecret for unexpected level %v", level)
	}
}

var errTransportParametersRequired = errors.New("transport parameters required")

func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onHandleCryptoData func()) error {
	a, b := cli, srv
	for _, c := range []*testQUICConn{a, b} {
		if !c.conn.conn.quic.started {
			if err := c.conn.Start(ctx); err != nil {
				return err
			}
		}
	}
	idleCount := 0
	for {
		e := a.conn.NextEvent()
		switch e.Kind {
		case QUICNoEvent:
			idleCount++
			if idleCount == 2 {
				if !a.complete || !b.complete {
					return errors.New("handshake incomplete")
				}
				return nil
			}
			a, b = b, a
		case QUICSetReadSecret:
			a.setReadSecret(e.Level, e.Suite, e.Data)
		case QUICSetWriteSecret:
			a.setWriteSecret(e.Level, e.Suite, e.Data)
		case QUICWriteData:
			if err := b.conn.HandleData(e.Level, e.Data); err != nil {
				return err
			}
		case QUICTransportParameters:
			a.gotParams = e.Data
			if a.gotParams == nil {
				a.gotParams = []byte{}
			}
		case QUICTransportParametersRequired:
			return errTransportParametersRequired
		case QUICHandshakeDone:
			a.complete = true
			if a == srv {
				if err := srv.conn.SendSessionTicket(false); err != nil {
					return err
				}
			}
		}
		if e.Kind != QUICNoEvent {
			idleCount = 0
		}
	}
}

func TestQUICConnection(t *testing.T) {
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13

	cli := newTestQUICClient(t, config)
	cli.conn.SetTransportParameters(nil)

	srv := newTestQUICServer(t, config)
	srv.conn.SetTransportParameters(nil)

	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
		t.Fatalf("error during connection handshake: %v", err)
	}

	if _, ok := cli.readSecret[QUICEncryptionLevelHandshake]; !ok {
		t.Errorf("client has no Handshake secret")
	}
	if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; !ok {
		t.Errorf("client has no Application secret")
	}
	if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; !ok {
		t.Errorf("server has no Handshake secret")
	}
	if _, ok := srv.readSecret[QUICEncryptionLevelApplication]; !ok {
		t.Errorf("server has no Application secret")
	}
	for _, level := range []QUICEncryptionLevel{QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication} {
		if _, ok := cli.readSecret[level]; !ok {
			t.Errorf("client has no %v read secret", level)
		}
		if _, ok := srv.readSecret[level]; !ok {
			t.Errorf("server has no %v read secret", level)
		}
		if !reflect.DeepEqual(cli.readSecret[level], srv.writeSecret[level]) {
			t.Errorf("client read secret does not match server write secret for level %v", level)
		}
		if !reflect.DeepEqual(cli.writeSecret[level], srv.readSecret[level]) {
			t.Errorf("client write secret does not match server read secret for level %v", level)
		}
	}
}

func TestQUICSessionResumption(t *testing.T) {
	clientConfig := testConfig.Clone()
	clientConfig.MinVersion = VersionTLS13
	clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
	clientConfig.ServerName = "example.go.dev"

	serverConfig := testConfig.Clone()
	serverConfig.MinVersion = VersionTLS13

	cli := newTestQUICClient(t, clientConfig)
	cli.conn.SetTransportParameters(nil)
	srv := newTestQUICServer(t, serverConfig)
	srv.conn.SetTransportParameters(nil)
	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
		t.Fatalf("error during first connection handshake: %v", err)
	}
	if cli.conn.ConnectionState().DidResume {
		t.Errorf("first connection unexpectedly used session resumption")
	}

	cli2 := newTestQUICClient(t, clientConfig)
	cli2.conn.SetTransportParameters(nil)
	srv2 := newTestQUICServer(t, serverConfig)
	srv2.conn.SetTransportParameters(nil)
	if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil {
		t.Fatalf("error during second connection handshake: %v", err)
	}
	if !cli2.conn.ConnectionState().DidResume {
		t.Errorf("second connection did not use session resumption")
	}
}

func TestQUICPostHandshakeClientAuthentication(t *testing.T) {
	// RFC 9001, Section 4.4.
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13
	cli := newTestQUICClient(t, config)
	cli.conn.SetTransportParameters(nil)
	srv := newTestQUICServer(t, config)
	srv.conn.SetTransportParameters(nil)
	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
		t.Fatalf("error during connection handshake: %v", err)
	}

	certReq := new(certificateRequestMsgTLS13)
	certReq.ocspStapling = true
	certReq.scts = true
	certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
	certReqBytes, err := certReq.marshal()
	if err != nil {
		t.Fatal(err)
	}
	if err := cli.conn.HandleData(QUICEncryptionLevelApplication, append([]byte{
		byte(typeCertificateRequest),
		byte(0), byte(0), byte(len(certReqBytes)),
	}, certReqBytes...)); err == nil {
		t.Fatalf("post-handshake authentication request: got no error, want one")
	}
}

func TestQUICPostHandshakeKeyUpdate(t *testing.T) {
	// RFC 9001, Section 6.
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13
	cli := newTestQUICClient(t, config)
	cli.conn.SetTransportParameters(nil)
	srv := newTestQUICServer(t, config)
	srv.conn.SetTransportParameters(nil)
	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
		t.Fatalf("error during connection handshake: %v", err)
	}

	keyUpdate := new(keyUpdateMsg)
	keyUpdateBytes, err := keyUpdate.marshal()
	if err != nil {
		t.Fatal(err)
	}
	if err := cli.conn.HandleData(QUICEncryptionLevelApplication, append([]byte{
		byte(typeKeyUpdate),
		byte(0), byte(0), byte(len(keyUpdateBytes)),
	}, keyUpdateBytes...)); !errors.Is(err, alertUnexpectedMessage) {
		t.Fatalf("key update request: got error %v, want alertUnexpectedMessage", err)
	}
}

func TestQUICHandshakeError(t *testing.T) {
	clientConfig := testConfig.Clone()
	clientConfig.MinVersion = VersionTLS13
	clientConfig.InsecureSkipVerify = false
	clientConfig.ServerName = "name"

	serverConfig := testConfig.Clone()
	serverConfig.MinVersion = VersionTLS13

	cli := newTestQUICClient(t, clientConfig)
	cli.conn.SetTransportParameters(nil)
	srv := newTestQUICServer(t, serverConfig)
	srv.conn.SetTransportParameters(nil)
	err := runTestQUICConnection(context.Background(), cli, srv, nil)
	if !errors.Is(err, AlertError(alertBadCertificate)) {
		t.Errorf("connection handshake terminated with error %q, want alertBadCertificate", err)
	}
	var e *CertificateVerificationError
	if !errors.As(err, &e) {
		t.Errorf("connection handshake terminated with error %q, want CertificateVerificationError", err)
	}
}

// Test that QUICConn.ConnectionState can be used during the handshake,
// and that it reports the application protocol as soon as it has been
// negotiated.
func TestQUICConnectionState(t *testing.T) {
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13
	config.NextProtos = []string{"h3"}
	cli := newTestQUICClient(t, config)
	cli.conn.SetTransportParameters(nil)
	srv := newTestQUICServer(t, config)
	srv.conn.SetTransportParameters(nil)
	onHandleCryptoData := func() {
		cliCS := cli.conn.ConnectionState()
		cliWantALPN := ""
		if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; ok {
			cliWantALPN = "h3"
		}
		if want, got := cliCS.NegotiatedProtocol, cliWantALPN; want != got {
			t.Errorf("cli.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
		}

		srvCS := srv.conn.ConnectionState()
		srvWantALPN := ""
		if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; ok {
			srvWantALPN = "h3"
		}
		if want, got := srvCS.NegotiatedProtocol, srvWantALPN; want != got {
			t.Errorf("srv.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
		}
	}
	if err := runTestQUICConnection(context.Background(), cli, srv, onHandleCryptoData); err != nil {
		t.Fatalf("error during connection handshake: %v", err)
	}
}

func TestQUICStartContextPropagation(t *testing.T) {
	const key = "key"
	const value = "value"
	ctx := context.WithValue(context.Background(), key, value)
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13
	calls := 0
	config.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) {
		calls++
		got, _ := info.Context().Value(key).(string)
		if got != value {
			t.Errorf("GetConfigForClient context key %q has value %q, want %q", key, got, value)
		}
		return nil, nil
	}
	cli := newTestQUICClient(t, config)
	cli.conn.SetTransportParameters(nil)
	srv := newTestQUICServer(t, config)
	srv.conn.SetTransportParameters(nil)
	if err := runTestQUICConnection(ctx, cli, srv, nil); err != nil {
		t.Fatalf("error during connection handshake: %v", err)
	}
	if calls != 1 {
		t.Errorf("GetConfigForClient called %v times, want 1", calls)
	}
}

func TestQUICDelayedTransportParameters(t *testing.T) {
	clientConfig := testConfig.Clone()
	clientConfig.MinVersion = VersionTLS13
	clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
	clientConfig.ServerName = "example.go.dev"

	serverConfig := testConfig.Clone()
	serverConfig.MinVersion = VersionTLS13

	cliParams := "client params"
	srvParams := "server params"

	cli := newTestQUICClient(t, clientConfig)
	srv := newTestQUICServer(t, serverConfig)
	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
		t.Fatalf("handshake with no client parameters: %v; want errTransportParametersRequired", err)
	}
	cli.conn.SetTransportParameters([]byte(cliParams))
	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
		t.Fatalf("handshake with no server parameters: %v; want errTransportParametersRequired", err)
	}
	srv.conn.SetTransportParameters([]byte(srvParams))
	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
		t.Fatalf("error during connection handshake: %v", err)
	}

	if got, want := string(cli.gotParams), srvParams; got != want {
		t.Errorf("client got transport params: %q, want %q", got, want)
	}
	if got, want := string(srv.gotParams), cliParams; got != want {
		t.Errorf("server got transport params: %q, want %q", got, want)
	}
}

func TestQUICEmptyTransportParameters(t *testing.T) {
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13

	cli := newTestQUICClient(t, config)
	cli.conn.SetTransportParameters(nil)
	srv := newTestQUICServer(t, config)
	srv.conn.SetTransportParameters(nil)
	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
		t.Fatalf("error during connection handshake: %v", err)
	}

	if cli.gotParams == nil {
		t.Errorf("client did not get transport params")
	}
	if srv.gotParams == nil {
		t.Errorf("server did not get transport params")
	}
	if len(cli.gotParams) != 0 {
		t.Errorf("client got transport params: %v, want empty", cli.gotParams)
	}
	if len(srv.gotParams) != 0 {
		t.Errorf("server got transport params: %v, want empty", srv.gotParams)
	}
}

func TestQUICCanceledWaitingForData(t *testing.T) {
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13
	cli := newTestQUICClient(t, config)
	cli.conn.SetTransportParameters(nil)
	cli.conn.Start(context.Background())
	for cli.conn.NextEvent().Kind != QUICNoEvent {
	}
	err := cli.conn.Close()
	if !errors.Is(err, alertCloseNotify) {
		t.Errorf("conn.Close() = %v, want alertCloseNotify", err)
	}
}

func TestQUICCanceledWaitingForTransportParams(t *testing.T) {
	config := testConfig.Clone()
	config.MinVersion = VersionTLS13
	cli := newTestQUICClient(t, config)
	cli.conn.Start(context.Background())
	for cli.conn.NextEvent().Kind != QUICTransportParametersRequired {
	}
	err := cli.conn.Close()
	if !errors.Is(err, alertCloseNotify) {
		t.Errorf("conn.Close() = %v, want alertCloseNotify", err)
	}
}
