Source file src/crypto/tls/quic_test.go

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

View as plain text