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  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   176  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   177  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   178  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   179  
   180  	cli := newTestQUICClient(t, clientConfig)
   181  	cli.conn.SetTransportParameters(nil)
   182  
   183  	srv := newTestQUICServer(t, serverConfig)
   184  	srv.conn.SetTransportParameters(nil)
   185  
   186  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   187  		t.Fatalf("error during connection handshake: %v", err)
   188  	}
   189  
   190  	if _, ok := cli.readSecret[QUICEncryptionLevelHandshake]; !ok {
   191  		t.Errorf("client has no Handshake secret")
   192  	}
   193  	if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; !ok {
   194  		t.Errorf("client has no Application secret")
   195  	}
   196  	if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; !ok {
   197  		t.Errorf("server has no Handshake secret")
   198  	}
   199  	if _, ok := srv.readSecret[QUICEncryptionLevelApplication]; !ok {
   200  		t.Errorf("server has no Application secret")
   201  	}
   202  	for _, level := range []QUICEncryptionLevel{QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication} {
   203  		if _, ok := cli.readSecret[level]; !ok {
   204  			t.Errorf("client has no %v read secret", level)
   205  		}
   206  		if _, ok := srv.readSecret[level]; !ok {
   207  			t.Errorf("server has no %v read secret", level)
   208  		}
   209  		if !reflect.DeepEqual(cli.readSecret[level], srv.writeSecret[level]) {
   210  			t.Errorf("client read secret does not match server write secret for level %v", level)
   211  		}
   212  		if !reflect.DeepEqual(cli.writeSecret[level], srv.readSecret[level]) {
   213  			t.Errorf("client write secret does not match server read secret for level %v", level)
   214  		}
   215  	}
   216  }
   217  
   218  func TestQUICVersions(t *testing.T) {
   219  	for _, tc := range []struct {
   220  		name      string
   221  		clientMin uint16
   222  		clientMax uint16
   223  		serverMin uint16
   224  		serverMax uint16
   225  		wantErr   bool
   226  	}{
   227  		{
   228  			name: "defaults",
   229  		},
   230  		{
   231  			name:      "MinVersion TLS 1.2",
   232  			clientMin: VersionTLS12,
   233  			serverMin: VersionTLS12,
   234  		},
   235  		{
   236  			name:      "MinVersion TLS 1.3",
   237  			clientMin: VersionTLS13,
   238  			serverMin: VersionTLS13,
   239  		},
   240  		{
   241  			name:      "client MaxVersion TLS 1.2",
   242  			clientMax: VersionTLS12,
   243  			wantErr:   true,
   244  		},
   245  		{
   246  			name:      "server MaxVersion TLS 1.2",
   247  			serverMax: VersionTLS12,
   248  			wantErr:   true,
   249  		},
   250  	} {
   251  		t.Run(tc.name, func(t *testing.T) {
   252  			client := testConfigClient.Clone()
   253  			client.MinVersion = tc.clientMin
   254  			client.MaxVersion = tc.clientMax
   255  			server := testConfigServer.Clone()
   256  			server.MinVersion = tc.serverMin
   257  			server.MaxVersion = tc.serverMax
   258  
   259  			cli := newTestQUICClient(t, &QUICConfig{TLSConfig: client})
   260  			cli.conn.SetTransportParameters(nil)
   261  			srv := newTestQUICServer(t, &QUICConfig{TLSConfig: server})
   262  			srv.conn.SetTransportParameters(nil)
   263  			err := runTestQUICConnection(context.Background(), cli, srv, nil)
   264  			if tc.wantErr == (err == nil) {
   265  				t.Errorf("got err=%v, wantErr=%v", err, tc.wantErr)
   266  			}
   267  		})
   268  	}
   269  }
   270  
   271  func TestQUICSessionResumption(t *testing.T) {
   272  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   273  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   274  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   275  
   276  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   277  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   278  
   279  	cli := newTestQUICClient(t, clientConfig)
   280  	cli.conn.SetTransportParameters(nil)
   281  	srv := newTestQUICServer(t, serverConfig)
   282  	srv.conn.SetTransportParameters(nil)
   283  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   284  		t.Fatalf("error during first connection handshake: %v", err)
   285  	}
   286  	if cli.conn.ConnectionState().DidResume {
   287  		t.Errorf("first connection unexpectedly used session resumption")
   288  	}
   289  
   290  	cli2 := newTestQUICClient(t, clientConfig)
   291  	cli2.conn.SetTransportParameters(nil)
   292  	srv2 := newTestQUICServer(t, serverConfig)
   293  	srv2.conn.SetTransportParameters(nil)
   294  	if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil {
   295  		t.Fatalf("error during second connection handshake: %v", err)
   296  	}
   297  	if !cli2.conn.ConnectionState().DidResume {
   298  		t.Errorf("second connection did not use session resumption")
   299  	}
   300  
   301  	clientConfig.TLSConfig.SessionTicketsDisabled = true
   302  	cli3 := newTestQUICClient(t, clientConfig)
   303  	cli3.conn.SetTransportParameters(nil)
   304  	srv3 := newTestQUICServer(t, serverConfig)
   305  	srv3.conn.SetTransportParameters(nil)
   306  	if err := runTestQUICConnection(context.Background(), cli3, srv3, nil); err != nil {
   307  		t.Fatalf("error during third connection handshake: %v", err)
   308  	}
   309  	if cli3.conn.ConnectionState().DidResume {
   310  		t.Errorf("third connection unexpectedly used session resumption")
   311  	}
   312  }
   313  
   314  func TestQUICFragmentaryData(t *testing.T) {
   315  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   316  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   317  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   318  
   319  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   320  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   321  
   322  	cli := newTestQUICClient(t, clientConfig)
   323  	cli.conn.SetTransportParameters(nil)
   324  	srv := newTestQUICServer(t, serverConfig)
   325  	srv.conn.SetTransportParameters(nil)
   326  	onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
   327  		if e.Kind == QUICWriteData {
   328  			// Provide the data one byte at a time.
   329  			for i := range e.Data {
   330  				if err := dst.conn.HandleData(e.Level, e.Data[i:i+1]); err != nil {
   331  					t.Errorf("HandleData: %v", err)
   332  					break
   333  				}
   334  			}
   335  			return true
   336  		}
   337  		return false
   338  	}
   339  	if err := runTestQUICConnection(context.Background(), cli, srv, onEvent); err != nil {
   340  		t.Fatalf("error during first connection handshake: %v", err)
   341  	}
   342  }
   343  
   344  func TestQUICPostHandshakeClientAuthentication(t *testing.T) {
   345  	// RFC 9001, Section 4.4.
   346  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   347  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   348  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   349  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   350  	cli := newTestQUICClient(t, clientConfig)
   351  	cli.conn.SetTransportParameters(nil)
   352  	srv := newTestQUICServer(t, serverConfig)
   353  	srv.conn.SetTransportParameters(nil)
   354  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   355  		t.Fatalf("error during connection handshake: %v", err)
   356  	}
   357  
   358  	certReq := new(certificateRequestMsgTLS13)
   359  	certReq.ocspStapling = true
   360  	certReq.scts = true
   361  	certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms(VersionTLS13, VersionTLS13)
   362  	certReqBytes, err := certReq.marshal()
   363  	if err != nil {
   364  		t.Fatal(err)
   365  	}
   366  	if err := cli.conn.HandleData(QUICEncryptionLevelApplication, append([]byte{
   367  		byte(typeCertificateRequest),
   368  		byte(0), byte(0), byte(len(certReqBytes)),
   369  	}, certReqBytes...)); err == nil {
   370  		t.Fatalf("post-handshake authentication request: got no error, want one")
   371  	}
   372  }
   373  
   374  func TestQUICPostHandshakeKeyUpdate(t *testing.T) {
   375  	// RFC 9001, Section 6.
   376  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   377  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   378  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   379  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   380  	cli := newTestQUICClient(t, clientConfig)
   381  	cli.conn.SetTransportParameters(nil)
   382  	srv := newTestQUICServer(t, serverConfig)
   383  	srv.conn.SetTransportParameters(nil)
   384  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   385  		t.Fatalf("error during connection handshake: %v", err)
   386  	}
   387  
   388  	keyUpdate := new(keyUpdateMsg)
   389  	keyUpdateBytes, err := keyUpdate.marshal()
   390  	if err != nil {
   391  		t.Fatal(err)
   392  	}
   393  	expectedErr := "unexpected key update message"
   394  	if err = cli.conn.HandleData(QUICEncryptionLevelApplication, keyUpdateBytes); err == nil {
   395  		t.Fatalf("key update request: expected error from post-handshake key update, got nil")
   396  	} else if !strings.Contains(err.Error(), expectedErr) {
   397  		t.Fatalf("key update request: got error %v, expected substring %q", err, expectedErr)
   398  	}
   399  }
   400  
   401  func TestQUICPostHandshakeMessageTooLarge(t *testing.T) {
   402  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   403  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   404  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   405  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   406  	cli := newTestQUICClient(t, clientConfig)
   407  	cli.conn.SetTransportParameters(nil)
   408  	srv := newTestQUICServer(t, serverConfig)
   409  	srv.conn.SetTransportParameters(nil)
   410  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   411  		t.Fatalf("error during connection handshake: %v", err)
   412  	}
   413  
   414  	size := maxHandshake + 1
   415  	if err := cli.conn.HandleData(QUICEncryptionLevelApplication, []byte{
   416  		byte(typeNewSessionTicket),
   417  		byte(size >> 16),
   418  		byte(size >> 8),
   419  		byte(size),
   420  	}); err == nil {
   421  		t.Fatalf("%v-byte post-handshake message: got no error, want one", size)
   422  	}
   423  }
   424  
   425  func TestQUICHandshakeError(t *testing.T) {
   426  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   427  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   428  	clientConfig.TLSConfig.InsecureSkipVerify = false
   429  	clientConfig.TLSConfig.ServerName = "name"
   430  
   431  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   432  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   433  
   434  	cli := newTestQUICClient(t, clientConfig)
   435  	cli.conn.SetTransportParameters(nil)
   436  	srv := newTestQUICServer(t, serverConfig)
   437  	srv.conn.SetTransportParameters(nil)
   438  	err := runTestQUICConnection(context.Background(), cli, srv, nil)
   439  	if !errors.Is(err, AlertError(alertBadCertificate)) {
   440  		t.Errorf("connection handshake terminated with error %q, want alertBadCertificate", err)
   441  	}
   442  	if _, ok := errors.AsType[*CertificateVerificationError](err); !ok {
   443  		t.Errorf("connection handshake terminated with error %q, want CertificateVerificationError", err)
   444  	}
   445  
   446  	ev := cli.conn.NextEvent()
   447  	if ev.Kind != QUICErrorEvent {
   448  		t.Errorf("client.NextEvent: no QUICErrorEvent, want one")
   449  	}
   450  	if ev.Err != err {
   451  		t.Errorf("client.NextEvent: want same error returned by Start, got %v", ev.Err)
   452  	}
   453  }
   454  
   455  // Test that we can report an error produced by the GetEncryptedClientHelloKeys function.
   456  func TestQUICECHKeyError(t *testing.T) {
   457  	getECHKeysError := errors.New("error returned by GetEncryptedClientHelloKeys")
   458  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   459  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   460  	clientConfig.TLSConfig.NextProtos = []string{"h3"}
   461  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   462  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   463  	serverConfig.TLSConfig.NextProtos = []string{"h3"}
   464  	serverConfig.TLSConfig.GetEncryptedClientHelloKeys = func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error) {
   465  		return nil, getECHKeysError
   466  	}
   467  	cli := newTestQUICClient(t, clientConfig)
   468  	cli.conn.SetTransportParameters(nil)
   469  	srv := newTestQUICServer(t, serverConfig)
   470  
   471  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
   472  		t.Fatalf("handshake with no client parameters: %v; want errTransportParametersRequired", err)
   473  	}
   474  	srv.conn.SetTransportParameters(nil)
   475  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err == nil {
   476  		t.Fatalf("handshake with GetEncryptedClientHelloKeys errors: nil, want error")
   477  	}
   478  	if srv.gotError == nil {
   479  		t.Fatalf("after GetEncryptedClientHelloKeys error, server did not see QUICErrorEvent")
   480  	}
   481  	if _, ok := errors.AsType[AlertError](srv.gotError); !ok {
   482  		t.Errorf("connection handshake terminated with error %T, want AlertError", srv.gotError)
   483  	}
   484  	if !errors.Is(srv.gotError, getECHKeysError) {
   485  		t.Errorf("connection handshake terminated with error %v, want error returned by GetEncryptedClientHelloKeys", srv.gotError)
   486  	}
   487  }
   488  
   489  // Test that QUICConn.ConnectionState can be used during the handshake,
   490  // and that it reports the application protocol as soon as it has been
   491  // negotiated.
   492  func TestQUICConnectionState(t *testing.T) {
   493  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   494  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   495  	clientConfig.TLSConfig.NextProtos = []string{"h3"}
   496  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   497  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   498  	serverConfig.TLSConfig.NextProtos = []string{"h3"}
   499  	cli := newTestQUICClient(t, clientConfig)
   500  	cli.conn.SetTransportParameters(nil)
   501  	srv := newTestQUICServer(t, serverConfig)
   502  	srv.conn.SetTransportParameters(nil)
   503  	onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
   504  		cliCS := cli.conn.ConnectionState()
   505  		if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; ok {
   506  			if want, got := cliCS.NegotiatedProtocol, "h3"; want != got {
   507  				t.Errorf("cli.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
   508  			}
   509  		}
   510  		srvCS := srv.conn.ConnectionState()
   511  		if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; ok {
   512  			if want, got := srvCS.NegotiatedProtocol, "h3"; want != got {
   513  				t.Errorf("srv.ConnectionState().NegotiatedProtocol = %q, want %q", want, got)
   514  			}
   515  		}
   516  		return false
   517  	}
   518  	if err := runTestQUICConnection(context.Background(), cli, srv, onEvent); err != nil {
   519  		t.Fatalf("error during connection handshake: %v", err)
   520  	}
   521  }
   522  
   523  func TestQUICStartContextPropagation(t *testing.T) {
   524  	const key = "key"
   525  	const value = "value"
   526  	ctx := context.WithValue(context.Background(), key, value)
   527  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   528  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   529  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   530  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   531  	calls := 0
   532  	serverConfig.TLSConfig.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) {
   533  		calls++
   534  		got, _ := info.Context().Value(key).(string)
   535  		if got != value {
   536  			t.Errorf("GetConfigForClient context key %q has value %q, want %q", key, got, value)
   537  		}
   538  		return nil, nil
   539  	}
   540  	cli := newTestQUICClient(t, clientConfig)
   541  	cli.conn.SetTransportParameters(nil)
   542  	srv := newTestQUICServer(t, serverConfig)
   543  	srv.conn.SetTransportParameters(nil)
   544  	if err := runTestQUICConnection(ctx, cli, srv, nil); err != nil {
   545  		t.Fatalf("error during connection handshake: %v", err)
   546  	}
   547  	if calls != 1 {
   548  		t.Errorf("GetConfigForClient called %v times, want 1", calls)
   549  	}
   550  }
   551  
   552  func TestQUICClientHelloInfoConn(t *testing.T) {
   553  	clientHelloInfoConn, peerConn := net.Pipe()
   554  	t.Cleanup(func() {
   555  		clientHelloInfoConn.Close()
   556  		peerConn.Close()
   557  	})
   558  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   559  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   560  	serverConfig := &QUICConfig{
   561  		TLSConfig:           testConfigServer.Clone(),
   562  		ClientHelloInfoConn: clientHelloInfoConn,
   563  	}
   564  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   565  	var called bool
   566  	serverConfig.TLSConfig.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) {
   567  		called = true
   568  		if info.Conn != clientHelloInfoConn {
   569  			t.Errorf("ClientHelloInfo.Conn = %v, want %v", info.Conn, clientHelloInfoConn)
   570  		}
   571  		return nil, nil
   572  	}
   573  	cli := newTestQUICClient(t, clientConfig)
   574  	cli.conn.SetTransportParameters(nil)
   575  	srv := newTestQUICServer(t, serverConfig)
   576  	srv.conn.SetTransportParameters(nil)
   577  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   578  		t.Fatalf("error during connection handshake: %v", err)
   579  	}
   580  	if !called {
   581  		t.Fatal("GetConfigForClient was not called")
   582  	}
   583  }
   584  
   585  func TestQUICContextCancelation(t *testing.T) {
   586  	ctx, cancel := context.WithCancel(context.Background())
   587  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   588  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   589  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   590  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   591  	cli := newTestQUICClient(t, clientConfig)
   592  	cli.conn.SetTransportParameters(nil)
   593  	srv := newTestQUICServer(t, serverConfig)
   594  	srv.conn.SetTransportParameters(nil)
   595  	// Verify that canceling the connection context concurrently does not cause any races.
   596  	// See https://go.dev/issue/77274.
   597  	var wg sync.WaitGroup
   598  	wg.Go(func() {
   599  		_ = runTestQUICConnection(ctx, cli, srv, nil)
   600  	})
   601  	wg.Go(cancel)
   602  	wg.Wait()
   603  }
   604  
   605  func TestQUICDelayedTransportParameters(t *testing.T) {
   606  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   607  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   608  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   609  
   610  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   611  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   612  
   613  	cliParams := "client params"
   614  	srvParams := "server params"
   615  
   616  	cli := newTestQUICClient(t, clientConfig)
   617  	srv := newTestQUICServer(t, serverConfig)
   618  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
   619  		t.Fatalf("handshake with no client parameters: %v; want errTransportParametersRequired", err)
   620  	}
   621  	cli.conn.SetTransportParameters([]byte(cliParams))
   622  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired {
   623  		t.Fatalf("handshake with no server parameters: %v; want errTransportParametersRequired", err)
   624  	}
   625  	srv.conn.SetTransportParameters([]byte(srvParams))
   626  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   627  		t.Fatalf("error during connection handshake: %v", err)
   628  	}
   629  
   630  	if got, want := string(cli.gotParams), srvParams; got != want {
   631  		t.Errorf("client got transport params: %q, want %q", got, want)
   632  	}
   633  	if got, want := string(srv.gotParams), cliParams; got != want {
   634  		t.Errorf("server got transport params: %q, want %q", got, want)
   635  	}
   636  }
   637  
   638  func TestQUICEmptyTransportParameters(t *testing.T) {
   639  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   640  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   641  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   642  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   643  
   644  	cli := newTestQUICClient(t, clientConfig)
   645  	cli.conn.SetTransportParameters(nil)
   646  	srv := newTestQUICServer(t, serverConfig)
   647  	srv.conn.SetTransportParameters(nil)
   648  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   649  		t.Fatalf("error during connection handshake: %v", err)
   650  	}
   651  
   652  	if cli.gotParams == nil {
   653  		t.Errorf("client did not get transport params")
   654  	}
   655  	if srv.gotParams == nil {
   656  		t.Errorf("server did not get transport params")
   657  	}
   658  	if len(cli.gotParams) != 0 {
   659  		t.Errorf("client got transport params: %v, want empty", cli.gotParams)
   660  	}
   661  	if len(srv.gotParams) != 0 {
   662  		t.Errorf("server got transport params: %v, want empty", srv.gotParams)
   663  	}
   664  }
   665  
   666  func TestQUICCanceledWaitingForData(t *testing.T) {
   667  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   668  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   669  	cli := newTestQUICClient(t, clientConfig)
   670  	cli.conn.SetTransportParameters(nil)
   671  	cli.conn.Start(context.Background())
   672  	for cli.conn.NextEvent().Kind != QUICNoEvent {
   673  	}
   674  	err := cli.conn.Close()
   675  	if !errors.Is(err, alertCloseNotify) {
   676  		t.Errorf("conn.Close() = %v, want alertCloseNotify", err)
   677  	}
   678  }
   679  
   680  func TestQUICCanceledWaitingForTransportParams(t *testing.T) {
   681  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   682  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   683  	cli := newTestQUICClient(t, clientConfig)
   684  	cli.conn.Start(context.Background())
   685  	for cli.conn.NextEvent().Kind != QUICTransportParametersRequired {
   686  	}
   687  	err := cli.conn.Close()
   688  	if !errors.Is(err, alertCloseNotify) {
   689  		t.Errorf("conn.Close() = %v, want alertCloseNotify", err)
   690  	}
   691  }
   692  
   693  func TestQUICEarlyData(t *testing.T) {
   694  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   695  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   696  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   697  	clientConfig.TLSConfig.NextProtos = []string{"h3"}
   698  
   699  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   700  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   701  	serverConfig.TLSConfig.NextProtos = []string{"h3"}
   702  
   703  	cli := newTestQUICClient(t, clientConfig)
   704  	cli.conn.SetTransportParameters(nil)
   705  	srv := newTestQUICServer(t, serverConfig)
   706  	srv.conn.SetTransportParameters(nil)
   707  	srv.ticketOpts.EarlyData = true
   708  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   709  		t.Fatalf("error during first connection handshake: %v", err)
   710  	}
   711  	if cli.conn.ConnectionState().DidResume {
   712  		t.Errorf("first connection unexpectedly used session resumption")
   713  	}
   714  
   715  	cli2 := newTestQUICClient(t, clientConfig)
   716  	cli2.conn.SetTransportParameters(nil)
   717  	srv2 := newTestQUICServer(t, serverConfig)
   718  	srv2.conn.SetTransportParameters(nil)
   719  	onEvent := func(e QUICEvent, src, dst *testQUICConn) bool {
   720  		switch e.Kind {
   721  		case QUICStoreSession, QUICResumeSession:
   722  			t.Errorf("with EnableSessionEvents=false, got unexpected event %v", e.Kind)
   723  		}
   724  		return false
   725  	}
   726  	if err := runTestQUICConnection(context.Background(), cli2, srv2, onEvent); err != nil {
   727  		t.Fatalf("error during second connection handshake: %v", err)
   728  	}
   729  	if !cli2.conn.ConnectionState().DidResume {
   730  		t.Errorf("second connection did not use session resumption")
   731  	}
   732  	cliSecret := cli2.writeSecret[QUICEncryptionLevelEarly]
   733  	if cliSecret.secret == nil {
   734  		t.Errorf("client did not receive early data write secret")
   735  	}
   736  	srvSecret := srv2.readSecret[QUICEncryptionLevelEarly]
   737  	if srvSecret.secret == nil {
   738  		t.Errorf("server did not receive early data read secret")
   739  	}
   740  	if cliSecret.suite != srvSecret.suite || !bytes.Equal(cliSecret.secret, srvSecret.secret) {
   741  		t.Errorf("client early data secret does not match server")
   742  	}
   743  }
   744  
   745  func TestQUICEarlyDataDeclined(t *testing.T) {
   746  	t.Run("server", func(t *testing.T) {
   747  		testQUICEarlyDataDeclined(t, true)
   748  	})
   749  	t.Run("client", func(t *testing.T) {
   750  		testQUICEarlyDataDeclined(t, false)
   751  	})
   752  }
   753  
   754  func testQUICEarlyDataDeclined(t *testing.T, server bool) {
   755  	clientConfig := &QUICConfig{TLSConfig: testConfigClient.Clone()}
   756  	clientConfig.EnableSessionEvents = true
   757  	clientConfig.TLSConfig.MinVersion = VersionTLS13
   758  	clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1)
   759  	clientConfig.TLSConfig.NextProtos = []string{"h3"}
   760  
   761  	serverConfig := &QUICConfig{TLSConfig: testConfigServer.Clone()}
   762  	serverConfig.EnableSessionEvents = true
   763  	serverConfig.TLSConfig.MinVersion = VersionTLS13
   764  	serverConfig.TLSConfig.NextProtos = []string{"h3"}
   765  
   766  	cli := newTestQUICClient(t, clientConfig)
   767  	cli.conn.SetTransportParameters(nil)
   768  	srv := newTestQUICServer(t, serverConfig)
   769  	srv.conn.SetTransportParameters(nil)
   770  	srv.ticketOpts.EarlyData = true
   771  	if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil {
   772  		t.Fatalf("error during first connection handshake: %v", err)
   773  	}
   774  	if cli.conn.ConnectionState().DidResume {
   775  		t.Errorf("first connection unexpectedly used session resumption")
   776  	}
   777  
   778  	cli2 := newTestQUICClient(t, clientConfig)
   779  	cli2.conn.SetTransportParameters(nil)
   780  	srv2 := newTestQUICServer(t, serverConfig)
   781  	srv2.conn.SetTransportParameters(nil)
   782  	declineEarlyData := func(state *SessionState) {
   783  		state.EarlyData = false
   784  	}
   785  	if server {
   786  		srv2.onResumeSession = declineEarlyData
   787  	} else {
   788  		cli2.onResumeSession = declineEarlyData
   789  	}
   790  	if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil {
   791  		t.Fatalf("error during second connection handshake: %v", err)
   792  	}
   793  	if !cli2.conn.ConnectionState().DidResume {
   794  		t.Errorf("second connection did not use session resumption")
   795  	}
   796  	_, cliEarlyData := cli2.writeSecret[QUICEncryptionLevelEarly]
   797  	if server {
   798  		if !cliEarlyData {
   799  			t.Errorf("client did not receive early data write secret")
   800  		}
   801  		if !cli2.earlyDataRejected {
   802  			t.Errorf("client did not receive QUICEarlyDataRejected")
   803  		}
   804  	}
   805  	if _, srvEarlyData := srv2.readSecret[QUICEncryptionLevelEarly]; srvEarlyData {
   806  		t.Errorf("server received early data read secret")
   807  	}
   808  }
   809  

View as plain text