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

View as plain text