Source file src/crypto/tls/quic_test.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tls
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"errors"
    11  	"fmt"
    12  	"reflect"
    13  	"strings"
    14  	"sync"
    15  	"testing"
    16  )
    17  
    18  type testQUICConn struct {
    19  	t                 *testing.T
    20  	conn              *QUICConn
    21  	readSecret        map[QUICEncryptionLevel]suiteSecret
    22  	writeSecret       map[QUICEncryptionLevel]suiteSecret
    23  	ticketOpts        QUICSessionTicketOptions
    24  	onResumeSession   func(*SessionState)
    25  	gotParams         []byte
    26  	gotError          error
    27  	earlyDataRejected bool
    28  	complete          bool
    29  }
    30  
    31  func newTestQUICClient(t *testing.T, config *QUICConfig) *testQUICConn {
    32  	q := &testQUICConn{
    33  		t:    t,
    34  		conn: QUICClient(config),
    35  	}
    36  	t.Cleanup(func() {
    37  		q.conn.Close()
    38  	})
    39  	return q
    40  }
    41  
    42  func newTestQUICServer(t *testing.T, config *QUICConfig) *testQUICConn {
    43  	q := &testQUICConn{
    44  		t:    t,
    45  		conn: QUICServer(config),
    46  	}
    47  	t.Cleanup(func() {
    48  		q.conn.Close()
    49  	})
    50  	return q
    51  }
    52  
    53  type suiteSecret struct {
    54  	suite  uint16
    55  	secret []byte
    56  }
    57  
    58  func (q *testQUICConn) setReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
    59  	if _, ok := q.writeSecret[level]; !ok && level != QUICEncryptionLevelEarly {
    60  		q.t.Errorf("SetReadSecret for level %v called before SetWriteSecret", level)
    61  	}
    62  	if level == QUICEncryptionLevelApplication && !q.complete {
    63  		q.t.Errorf("SetReadSecret for level %v called before HandshakeComplete", level)
    64  	}
    65  	if _, ok := q.readSecret[level]; ok {
    66  		q.t.Errorf("SetReadSecret for level %v called twice", level)
    67  	}
    68  	if q.readSecret == nil {
    69  		q.readSecret = map[QUICEncryptionLevel]suiteSecret{}
    70  	}
    71  	switch level {
    72  	case QUICEncryptionLevelHandshake,
    73  		QUICEncryptionLevelEarly,
    74  		QUICEncryptionLevelApplication:
    75  		q.readSecret[level] = suiteSecret{suite, secret}
    76  	default:
    77  		q.t.Errorf("SetReadSecret for unexpected level %v", level)
    78  	}
    79  }
    80  
    81  func (q *testQUICConn) setWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
    82  	if _, ok := q.writeSecret[level]; ok {
    83  		q.t.Errorf("SetWriteSecret for level %v called twice", level)
    84  	}
    85  	if q.writeSecret == nil {
    86  		q.writeSecret = map[QUICEncryptionLevel]suiteSecret{}
    87  	}
    88  	switch level {
    89  	case QUICEncryptionLevelHandshake,
    90  		QUICEncryptionLevelEarly,
    91  		QUICEncryptionLevelApplication:
    92  		q.writeSecret[level] = suiteSecret{suite, secret}
    93  	default:
    94  		q.t.Errorf("SetWriteSecret for unexpected level %v", level)
    95  	}
    96  }
    97  
    98  var errTransportParametersRequired = errors.New("transport parameters required")
    99  
   100  func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onEvent func(e QUICEvent, src, dst *testQUICConn) bool) error {
   101  	a, b := cli, srv
   102  	for _, c := range []*testQUICConn{a, b} {
   103  		if !c.conn.conn.quic.started {
   104  			if err := c.conn.Start(ctx); err != nil {
   105  				return err
   106  			}
   107  		}
   108  	}
   109  	idleCount := 0
   110  	for {
   111  		e := a.conn.NextEvent()
   112  		if onEvent != nil && onEvent(e, a, b) {
   113  			continue
   114  		}
   115  		if a.gotError != nil && e.Kind != QUICNoEvent {
   116  			return fmt.Errorf("unexpected event %v after QUICErrorEvent", e.Kind)
   117  		}
   118  		switch e.Kind {
   119  		case QUICNoEvent:
   120  			idleCount++
   121  			if idleCount == 2 {
   122  				if !a.complete || !b.complete {
   123  					return errors.New("handshake incomplete")
   124  				}
   125  				return nil
   126  			}
   127  			a, b = b, a
   128  		case QUICSetReadSecret:
   129  			a.setReadSecret(e.Level, e.Suite, e.Data)
   130  		case QUICSetWriteSecret:
   131  			a.setWriteSecret(e.Level, e.Suite, e.Data)
   132  		case QUICWriteData:
   133  			if err := b.conn.HandleData(e.Level, e.Data); err != nil {
   134  				return err
   135  			}
   136  		case QUICTransportParameters:
   137  			a.gotParams = e.Data
   138  			if a.gotParams == nil {
   139  				a.gotParams = []byte{}
   140  			}
   141  		case QUICTransportParametersRequired:
   142  			return errTransportParametersRequired
   143  		case QUICHandshakeDone:
   144  			a.complete = true
   145  			if a == srv {
   146  				if err := srv.conn.SendSessionTicket(srv.ticketOpts); err != nil {
   147  					return err
   148  				}
   149  			}
   150  		case QUICStoreSession:
   151  			if a != cli {
   152  				return errors.New("unexpected QUICStoreSession event received by server")
   153  			}
   154  			a.conn.StoreSession(e.SessionState)
   155  		case QUICResumeSession:
   156  			if a.onResumeSession != nil {
   157  				a.onResumeSession(e.SessionState)
   158  			}
   159  		case QUICRejectedEarlyData:
   160  			a.earlyDataRejected = true
   161  		case QUICErrorEvent:
   162  			if e.Err == nil {
   163  				return errors.New("unexpected QUICErrorEvent with no Err")
   164  			}
   165  			a.gotError = e.Err
   166  		}
   167  		if e.Kind != QUICNoEvent {
   168  			idleCount = 0
   169  		}
   170  	}
   171  }
   172  
   173  func TestQUICConnection(t *testing.T) {
   174  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   175  	config.TLSConfig.MinVersion = VersionTLS13
   176  
   177  	cli := newTestQUICClient(t, config)
   178  	cli.conn.SetTransportParameters(nil)
   179  
   180  	srv := newTestQUICServer(t, config)
   181  	srv.conn.SetTransportParameters(nil)
   182  
   183  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   184  		t.Fatalf("error during connection handshake: %v", err)
   185  	}
   186  
   187  	if _, ok := cli.readSecret[QUICEncryptionLevelHandshake]; !ok {
   188  		t.Errorf("client has no Handshake secret")
   189  	}
   190  	if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; !ok {
   191  		t.Errorf("client has no Application secret")
   192  	}
   193  	if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; !ok {
   194  		t.Errorf("server has no Handshake secret")
   195  	}
   196  	if _, ok := srv.readSecret[QUICEncryptionLevelApplication]; !ok {
   197  		t.Errorf("server has no Application secret")
   198  	}
   199  	for _, level := range []QUICEncryptionLevel{QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication} {
   200  		if _, ok := cli.readSecret[level]; !ok {
   201  			t.Errorf("client has no %v read secret", level)
   202  		}
   203  		if _, ok := srv.readSecret[level]; !ok {
   204  			t.Errorf("server has no %v read secret", level)
   205  		}
   206  		if !reflect.DeepEqual(cli.readSecret[level], srv.writeSecret[level]) {
   207  			t.Errorf("client read secret does not match server write secret for level %v", level)
   208  		}
   209  		if !reflect.DeepEqual(cli.writeSecret[level], srv.readSecret[level]) {
   210  			t.Errorf("client write secret does not match server read secret for level %v", level)
   211  		}
   212  	}
   213  }
   214  
   215  func TestQUICSessionResumption(t *testing.T) {
   216  	clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   217  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   218  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   219  	clientConfig.TLSConfig.ServerName = "example.go.dev"
   220  
   221  	serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   222  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   223  
   224  	cli := newTestQUICClient(t, clientConfig)
   225  	cli.conn.SetTransportParameters(nil)
   226  	srv := newTestQUICServer(t, serverConfig)
   227  	srv.conn.SetTransportParameters(nil)
   228  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   229  		t.Fatalf("error during first connection handshake: %v", err)
   230  	}
   231  	if cli.conn.ConnectionState().DidResume {
   232  		t.Errorf("first connection unexpectedly used session resumption")
   233  	}
   234  
   235  	cli2 := newTestQUICClient(t, clientConfig)
   236  	cli2.conn.SetTransportParameters(nil)
   237  	srv2 := newTestQUICServer(t, serverConfig)
   238  	srv2.conn.SetTransportParameters(nil)
   239  	if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil {
   240  		t.Fatalf("error during second connection handshake: %v", err)
   241  	}
   242  	if !cli2.conn.ConnectionState().DidResume {
   243  		t.Errorf("second connection did not use session resumption")
   244  	}
   245  
   246  	clientConfig.TLSConfig.SessionTicketsDisabled = true
   247  	cli3 := newTestQUICClient(t, clientConfig)
   248  	cli3.conn.SetTransportParameters(nil)
   249  	srv3 := newTestQUICServer(t, serverConfig)
   250  	srv3.conn.SetTransportParameters(nil)
   251  	if err := runTestQUICConnection(context.Background(), cli3, srv3, nil); err != nil {
   252  		t.Fatalf("error during third connection handshake: %v", err)
   253  	}
   254  	if cli3.conn.ConnectionState().DidResume {
   255  		t.Errorf("third connection unexpectedly used session resumption")
   256  	}
   257  }
   258  
   259  func TestQUICFragmentaryData(t *testing.T) {
   260  	clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   261  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   262  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   263  	clientConfig.TLSConfig.ServerName = "example.go.dev"
   264  
   265  	serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   266  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   267  
   268  	cli := newTestQUICClient(t, clientConfig)
   269  	cli.conn.SetTransportParameters(nil)
   270  	srv := newTestQUICServer(t, serverConfig)
   271  	srv.conn.SetTransportParameters(nil)
   272  	onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
   273  		if e.Kind == QUICWriteData {
   274  			// Provide the data one byte at a time.
   275  			for i := range e.Data {
   276  				if err := dst.conn.HandleData(e.Level, e.Data[i:i+1]); err != nil {
   277  					t.Errorf("HandleData: %v", err)
   278  					break
   279  				}
   280  			}
   281  			return true
   282  		}
   283  		return false
   284  	}
   285  	if err := runTestQUICConnection(context.Background(), cli, srv, onEvent); err != nil {
   286  		t.Fatalf("error during first connection handshake: %v", err)
   287  	}
   288  }
   289  
   290  func TestQUICPostHandshakeClientAuthentication(t *testing.T) {
   291  	// RFC 9001, Section 4.4.
   292  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   293  	config.TLSConfig.MinVersion = VersionTLS13
   294  	cli := newTestQUICClient(t, config)
   295  	cli.conn.SetTransportParameters(nil)
   296  	srv := newTestQUICServer(t, config)
   297  	srv.conn.SetTransportParameters(nil)
   298  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   299  		t.Fatalf("error during connection handshake: %v", err)
   300  	}
   301  
   302  	certReq := new(certificateRequestMsgTLS13)
   303  	certReq.ocspStapling = true
   304  	certReq.scts = true
   305  	certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS13)
   306  	certReqBytes, err := certReq.marshal()
   307  	if err != nil {
   308  		t.Fatal(err)
   309  	}
   310  	if err := cli.conn.HandleData(QUICEncryptionLevelApplication, append([]byte{
   311  		byte(typeCertificateRequest),
   312  		byte(0), byte(0), byte(len(certReqBytes)),
   313  	}, certReqBytes...)); err == nil {
   314  		t.Fatalf("post-handshake authentication request: got no error, want one")
   315  	}
   316  }
   317  
   318  func TestQUICPostHandshakeKeyUpdate(t *testing.T) {
   319  	// RFC 9001, Section 6.
   320  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   321  	config.TLSConfig.MinVersion = VersionTLS13
   322  	cli := newTestQUICClient(t, config)
   323  	cli.conn.SetTransportParameters(nil)
   324  	srv := newTestQUICServer(t, config)
   325  	srv.conn.SetTransportParameters(nil)
   326  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   327  		t.Fatalf("error during connection handshake: %v", err)
   328  	}
   329  
   330  	keyUpdate := new(keyUpdateMsg)
   331  	keyUpdateBytes, err := keyUpdate.marshal()
   332  	if err != nil {
   333  		t.Fatal(err)
   334  	}
   335  	expectedErr := "unexpected key update message"
   336  	if err = cli.conn.HandleData(QUICEncryptionLevelApplication, keyUpdateBytes); err == nil {
   337  		t.Fatalf("key update request: expected error from post-handshake key update, got nil")
   338  	} else if !strings.Contains(err.Error(), expectedErr) {
   339  		t.Fatalf("key update request: got error %v, expected substring %q", err, expectedErr)
   340  	}
   341  }
   342  
   343  func TestQUICPostHandshakeMessageTooLarge(t *testing.T) {
   344  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   345  	config.TLSConfig.MinVersion = VersionTLS13
   346  	cli := newTestQUICClient(t, config)
   347  	cli.conn.SetTransportParameters(nil)
   348  	srv := newTestQUICServer(t, config)
   349  	srv.conn.SetTransportParameters(nil)
   350  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   351  		t.Fatalf("error during connection handshake: %v", err)
   352  	}
   353  
   354  	size := maxHandshake + 1
   355  	if err := cli.conn.HandleData(QUICEncryptionLevelApplication, []byte{
   356  		byte(typeNewSessionTicket),
   357  		byte(size >> 16),
   358  		byte(size >> 8),
   359  		byte(size),
   360  	}); err == nil {
   361  		t.Fatalf("%v-byte post-handshake message: got no error, want one", size)
   362  	}
   363  }
   364  
   365  func TestQUICHandshakeError(t *testing.T) {
   366  	clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   367  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   368  	clientConfig.TLSConfig.InsecureSkipVerify = false
   369  	clientConfig.TLSConfig.ServerName = "name"
   370  
   371  	serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   372  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   373  
   374  	cli := newTestQUICClient(t, clientConfig)
   375  	cli.conn.SetTransportParameters(nil)
   376  	srv := newTestQUICServer(t, serverConfig)
   377  	srv.conn.SetTransportParameters(nil)
   378  	err := runTestQUICConnection(context.Background(), cli, srv, nil)
   379  	if !errors.Is(err, AlertError(alertBadCertificate)) {
   380  		t.Errorf("connection handshake terminated with error %q, want alertBadCertificate", err)
   381  	}
   382  	if _, ok := errors.AsType[*CertificateVerificationError](err); !ok {
   383  		t.Errorf("connection handshake terminated with error %q, want CertificateVerificationError", err)
   384  	}
   385  
   386  	ev := cli.conn.NextEvent()
   387  	if ev.Kind != QUICErrorEvent {
   388  		t.Errorf("client.NextEvent: no QUICErrorEvent, want one")
   389  	}
   390  	if ev.Err != err {
   391  		t.Errorf("client.NextEvent: want same error returned by Start, got %v", ev.Err)
   392  	}
   393  }
   394  
   395  // Test that we can report an error produced by the GetEncryptedClientHelloKeys function.
   396  func TestQUICECHKeyError(t *testing.T) {
   397  	getECHKeysError := errors.New("error returned by GetEncryptedClientHelloKeys")
   398  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   399  	config.TLSConfig.MinVersion = VersionTLS13
   400  	config.TLSConfig.NextProtos = []string{"h3"}
   401  	config.TLSConfig.GetEncryptedClientHelloKeys = func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error) {
   402  		return nil, getECHKeysError
   403  	}
   404  	cli := newTestQUICClient(t, config)
   405  	cli.conn.SetTransportParameters(nil)
   406  	srv := newTestQUICServer(t, config)
   407  
   408  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
   409  		t.Fatalf("handshake with no client parameters: %v; want errTransportParametersRequired", err)
   410  	}
   411  	srv.conn.SetTransportParameters(nil)
   412  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err == nil {
   413  		t.Fatalf("handshake with GetEncryptedClientHelloKeys errors: nil, want error")
   414  	}
   415  	if srv.gotError == nil {
   416  		t.Fatalf("after GetEncryptedClientHelloKeys error, server did not see QUICErrorEvent")
   417  	}
   418  	if _, ok := errors.AsType[AlertError](srv.gotError); !ok {
   419  		t.Errorf("connection handshake terminated with error %T, want AlertError", srv.gotError)
   420  	}
   421  	if !errors.Is(srv.gotError, getECHKeysError) {
   422  		t.Errorf("connection handshake terminated with error %v, want error returned by GetEncryptedClientHelloKeys", srv.gotError)
   423  	}
   424  }
   425  
   426  // Test that QUICConn.ConnectionState can be used during the handshake,
   427  // and that it reports the application protocol as soon as it has been
   428  // negotiated.
   429  func TestQUICConnectionState(t *testing.T) {
   430  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   431  	config.TLSConfig.MinVersion = VersionTLS13
   432  	config.TLSConfig.NextProtos = []string{"h3"}
   433  	cli := newTestQUICClient(t, config)
   434  	cli.conn.SetTransportParameters(nil)
   435  	srv := newTestQUICServer(t, config)
   436  	srv.conn.SetTransportParameters(nil)
   437  	onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
   438  		cliCS := cli.conn.ConnectionState()
   439  		if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; ok {
   440  			if want, got := cliCS.NegotiatedProtocol, "h3"; want != got {
   441  				t.Errorf("cli.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
   442  			}
   443  		}
   444  		srvCS := srv.conn.ConnectionState()
   445  		if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; ok {
   446  			if want, got := srvCS.NegotiatedProtocol, "h3"; want != got {
   447  				t.Errorf("srv.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
   448  			}
   449  		}
   450  		return false
   451  	}
   452  	if err := runTestQUICConnection(context.Background(), cli, srv, onEvent); err != nil {
   453  		t.Fatalf("error during connection handshake: %v", err)
   454  	}
   455  }
   456  
   457  func TestQUICStartContextPropagation(t *testing.T) {
   458  	const key = "key"
   459  	const value = "value"
   460  	ctx := context.WithValue(context.Background(), key, value)
   461  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   462  	config.TLSConfig.MinVersion = VersionTLS13
   463  	calls := 0
   464  	config.TLSConfig.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) {
   465  		calls++
   466  		got, _ := info.Context().Value(key).(string)
   467  		if got != value {
   468  			t.Errorf("GetConfigForClient context key %q has value %q, want %q", key, got, value)
   469  		}
   470  		return nil, nil
   471  	}
   472  	cli := newTestQUICClient(t, config)
   473  	cli.conn.SetTransportParameters(nil)
   474  	srv := newTestQUICServer(t, config)
   475  	srv.conn.SetTransportParameters(nil)
   476  	if err := runTestQUICConnection(ctx, cli, srv, nil); err != nil {
   477  		t.Fatalf("error during connection handshake: %v", err)
   478  	}
   479  	if calls != 1 {
   480  		t.Errorf("GetConfigForClient called %v times, want 1", calls)
   481  	}
   482  }
   483  
   484  func TestQUICContextCancelation(t *testing.T) {
   485  	ctx, cancel := context.WithCancel(context.Background())
   486  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   487  	config.TLSConfig.MinVersion = VersionTLS13
   488  	cli := newTestQUICClient(t, config)
   489  	cli.conn.SetTransportParameters(nil)
   490  	srv := newTestQUICServer(t, config)
   491  	srv.conn.SetTransportParameters(nil)
   492  	// Verify that canceling the connection context concurrently does not cause any races.
   493  	// See https://go.dev/issue/77274.
   494  	var wg sync.WaitGroup
   495  	wg.Go(func() {
   496  		_ = runTestQUICConnection(ctx, cli, srv, nil)
   497  	})
   498  	wg.Go(cancel)
   499  	wg.Wait()
   500  }
   501  
   502  func TestQUICDelayedTransportParameters(t *testing.T) {
   503  	clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   504  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   505  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   506  	clientConfig.TLSConfig.ServerName = "example.go.dev"
   507  
   508  	serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   509  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   510  
   511  	cliParams := "client params"
   512  	srvParams := "server params"
   513  
   514  	cli := newTestQUICClient(t, clientConfig)
   515  	srv := newTestQUICServer(t, serverConfig)
   516  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
   517  		t.Fatalf("handshake with no client parameters: %v; want errTransportParametersRequired", err)
   518  	}
   519  	cli.conn.SetTransportParameters([]byte(cliParams))
   520  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
   521  		t.Fatalf("handshake with no server parameters: %v; want errTransportParametersRequired", err)
   522  	}
   523  	srv.conn.SetTransportParameters([]byte(srvParams))
   524  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   525  		t.Fatalf("error during connection handshake: %v", err)
   526  	}
   527  
   528  	if got, want := string(cli.gotParams), srvParams; got != want {
   529  		t.Errorf("client got transport params: %q, want %q", got, want)
   530  	}
   531  	if got, want := string(srv.gotParams), cliParams; got != want {
   532  		t.Errorf("server got transport params: %q, want %q", got, want)
   533  	}
   534  }
   535  
   536  func TestQUICEmptyTransportParameters(t *testing.T) {
   537  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   538  	config.TLSConfig.MinVersion = VersionTLS13
   539  
   540  	cli := newTestQUICClient(t, config)
   541  	cli.conn.SetTransportParameters(nil)
   542  	srv := newTestQUICServer(t, config)
   543  	srv.conn.SetTransportParameters(nil)
   544  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   545  		t.Fatalf("error during connection handshake: %v", err)
   546  	}
   547  
   548  	if cli.gotParams == nil {
   549  		t.Errorf("client did not get transport params")
   550  	}
   551  	if srv.gotParams == nil {
   552  		t.Errorf("server did not get transport params")
   553  	}
   554  	if len(cli.gotParams) != 0 {
   555  		t.Errorf("client got transport params: %v, want empty", cli.gotParams)
   556  	}
   557  	if len(srv.gotParams) != 0 {
   558  		t.Errorf("server got transport params: %v, want empty", srv.gotParams)
   559  	}
   560  }
   561  
   562  func TestQUICCanceledWaitingForData(t *testing.T) {
   563  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   564  	config.TLSConfig.MinVersion = VersionTLS13
   565  	cli := newTestQUICClient(t, config)
   566  	cli.conn.SetTransportParameters(nil)
   567  	cli.conn.Start(context.Background())
   568  	for cli.conn.NextEvent().Kind != QUICNoEvent {
   569  	}
   570  	err := cli.conn.Close()
   571  	if !errors.Is(err, alertCloseNotify) {
   572  		t.Errorf("conn.Close() = %v, want alertCloseNotify", err)
   573  	}
   574  }
   575  
   576  func TestQUICCanceledWaitingForTransportParams(t *testing.T) {
   577  	config := &QUICConfig{TLSConfig: testConfig.Clone()}
   578  	config.TLSConfig.MinVersion = VersionTLS13
   579  	cli := newTestQUICClient(t, config)
   580  	cli.conn.Start(context.Background())
   581  	for cli.conn.NextEvent().Kind != QUICTransportParametersRequired {
   582  	}
   583  	err := cli.conn.Close()
   584  	if !errors.Is(err, alertCloseNotify) {
   585  		t.Errorf("conn.Close() = %v, want alertCloseNotify", err)
   586  	}
   587  }
   588  
   589  func TestQUICEarlyData(t *testing.T) {
   590  	clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   591  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   592  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   593  	clientConfig.TLSConfig.ServerName = "example.go.dev"
   594  	clientConfig.TLSConfig.NextProtos = []string{"h3"}
   595  
   596  	serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   597  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   598  	serverConfig.TLSConfig.NextProtos = []string{"h3"}
   599  
   600  	cli := newTestQUICClient(t, clientConfig)
   601  	cli.conn.SetTransportParameters(nil)
   602  	srv := newTestQUICServer(t, serverConfig)
   603  	srv.conn.SetTransportParameters(nil)
   604  	srv.ticketOpts.EarlyData = true
   605  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   606  		t.Fatalf("error during first connection handshake: %v", err)
   607  	}
   608  	if cli.conn.ConnectionState().DidResume {
   609  		t.Errorf("first connection unexpectedly used session resumption")
   610  	}
   611  
   612  	cli2 := newTestQUICClient(t, clientConfig)
   613  	cli2.conn.SetTransportParameters(nil)
   614  	srv2 := newTestQUICServer(t, serverConfig)
   615  	srv2.conn.SetTransportParameters(nil)
   616  	onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
   617  		switch e.Kind {
   618  		case QUICStoreSession, QUICResumeSession:
   619  			t.Errorf("with EnableSessionEvents=false, got unexpected event %v", e.Kind)
   620  		}
   621  		return false
   622  	}
   623  	if err := runTestQUICConnection(context.Background(), cli2, srv2, onEvent); err != nil {
   624  		t.Fatalf("error during second connection handshake: %v", err)
   625  	}
   626  	if !cli2.conn.ConnectionState().DidResume {
   627  		t.Errorf("second connection did not use session resumption")
   628  	}
   629  	cliSecret := cli2.writeSecret[QUICEncryptionLevelEarly]
   630  	if cliSecret.secret == nil {
   631  		t.Errorf("client did not receive early data write secret")
   632  	}
   633  	srvSecret := srv2.readSecret[QUICEncryptionLevelEarly]
   634  	if srvSecret.secret == nil {
   635  		t.Errorf("server did not receive early data read secret")
   636  	}
   637  	if cliSecret.suite != srvSecret.suite || !bytes.Equal(cliSecret.secret, srvSecret.secret) {
   638  		t.Errorf("client early data secret does not match server")
   639  	}
   640  }
   641  
   642  func TestQUICEarlyDataDeclined(t *testing.T) {
   643  	t.Run("server", func(t *testing.T) {
   644  		testQUICEarlyDataDeclined(t, true)
   645  	})
   646  	t.Run("client", func(t *testing.T) {
   647  		testQUICEarlyDataDeclined(t, false)
   648  	})
   649  }
   650  
   651  func testQUICEarlyDataDeclined(t *testing.T, server bool) {
   652  	clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   653  	clientConfig.EnableSessionEvents = true
   654  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   655  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   656  	clientConfig.TLSConfig.ServerName = "example.go.dev"
   657  	clientConfig.TLSConfig.NextProtos = []string{"h3"}
   658  
   659  	serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()}
   660  	serverConfig.EnableSessionEvents = true
   661  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   662  	serverConfig.TLSConfig.NextProtos = []string{"h3"}
   663  
   664  	cli := newTestQUICClient(t, clientConfig)
   665  	cli.conn.SetTransportParameters(nil)
   666  	srv := newTestQUICServer(t, serverConfig)
   667  	srv.conn.SetTransportParameters(nil)
   668  	srv.ticketOpts.EarlyData = true
   669  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   670  		t.Fatalf("error during first connection handshake: %v", err)
   671  	}
   672  	if cli.conn.ConnectionState().DidResume {
   673  		t.Errorf("first connection unexpectedly used session resumption")
   674  	}
   675  
   676  	cli2 := newTestQUICClient(t, clientConfig)
   677  	cli2.conn.SetTransportParameters(nil)
   678  	srv2 := newTestQUICServer(t, serverConfig)
   679  	srv2.conn.SetTransportParameters(nil)
   680  	declineEarlyData := func(state *SessionState) {
   681  		state.EarlyData = false
   682  	}
   683  	if server {
   684  		srv2.onResumeSession = declineEarlyData
   685  	} else {
   686  		cli2.onResumeSession = declineEarlyData
   687  	}
   688  	if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil {
   689  		t.Fatalf("error during second connection handshake: %v", err)
   690  	}
   691  	if !cli2.conn.ConnectionState().DidResume {
   692  		t.Errorf("second connection did not use session resumption")
   693  	}
   694  	_, cliEarlyData := cli2.writeSecret[QUICEncryptionLevelEarly]
   695  	if server {
   696  		if !cliEarlyData {
   697  			t.Errorf("client did not receive early data write secret")
   698  		}
   699  		if !cli2.earlyDataRejected {
   700  			t.Errorf("client did not receive QUICEarlyDataRejected")
   701  		}
   702  	}
   703  	if _, srvEarlyData := srv2.readSecret[QUICEncryptionLevelEarly]; srvEarlyData {
   704  		t.Errorf("server received early data read secret")
   705  	}
   706  }
   707  

View as plain text