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

View as plain text