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

View as plain text