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

View as plain text