golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/tls_test.go (about)

     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  //go:build go1.21
     6  
     7  package quic
     8  
     9  import (
    10  	"crypto/tls"
    11  	"crypto/x509"
    12  	"errors"
    13  	"testing"
    14  	"time"
    15  )
    16  
    17  // handshake executes the handshake.
    18  func (tc *testConn) handshake() {
    19  	tc.t.Helper()
    20  	if *testVV {
    21  		*testVV = false
    22  		defer func() {
    23  			tc.t.Helper()
    24  			*testVV = true
    25  			tc.t.Logf("performed connection handshake")
    26  		}()
    27  	}
    28  	defer func(saved map[byte]bool) {
    29  		tc.ignoreFrames = saved
    30  	}(tc.ignoreFrames)
    31  	tc.ignoreFrames = nil
    32  	t := tc.t
    33  	dgrams := handshakeDatagrams(tc)
    34  	i := 0
    35  	for {
    36  		if i == len(dgrams)-1 {
    37  			if tc.conn.side == clientSide {
    38  				want := tc.endpoint.now.Add(maxAckDelay - timerGranularity)
    39  				if !tc.timer.Equal(want) {
    40  					t.Fatalf("want timer = %v (max_ack_delay), got %v", want, tc.timer)
    41  				}
    42  				if got := tc.readDatagram(); got != nil {
    43  					t.Fatalf("client unexpectedly sent: %v", got)
    44  				}
    45  			}
    46  			tc.advance(maxAckDelay)
    47  		}
    48  
    49  		// Check that we're sending exactly the data we expect.
    50  		// Any variation from the norm here should be intentional.
    51  		got := tc.readDatagram()
    52  		var want *testDatagram
    53  		if !(tc.conn.side == serverSide && i == 0) && i < len(dgrams) {
    54  			want = dgrams[i]
    55  			fillCryptoFrames(want, tc.cryptoDataOut)
    56  			i++
    57  		}
    58  		if !datagramEqual(got, want) {
    59  			t.Fatalf("dgram %v:\ngot %v\n\nwant %v", i, got, want)
    60  		}
    61  		if i >= len(dgrams) {
    62  			break
    63  		}
    64  
    65  		fillCryptoFrames(dgrams[i], tc.cryptoDataIn)
    66  		tc.write(dgrams[i])
    67  		i++
    68  	}
    69  }
    70  
    71  func handshakeDatagrams(tc *testConn) (dgrams []*testDatagram) {
    72  	var (
    73  		clientConnIDs    [][]byte
    74  		serverConnIDs    [][]byte
    75  		clientResetToken statelessResetToken
    76  		serverResetToken statelessResetToken
    77  		transientConnID  []byte
    78  	)
    79  	localConnIDs := [][]byte{
    80  		testLocalConnID(0),
    81  		testLocalConnID(1),
    82  	}
    83  	peerConnIDs := [][]byte{
    84  		testPeerConnID(0),
    85  		testPeerConnID(1),
    86  	}
    87  	localResetToken := tc.endpoint.e.resetGen.tokenForConnID(localConnIDs[1])
    88  	peerResetToken := testPeerStatelessResetToken(1)
    89  	if tc.conn.side == clientSide {
    90  		clientConnIDs = localConnIDs
    91  		serverConnIDs = peerConnIDs
    92  		clientResetToken = localResetToken
    93  		serverResetToken = peerResetToken
    94  		transientConnID = testLocalConnID(-1)
    95  	} else {
    96  		clientConnIDs = peerConnIDs
    97  		serverConnIDs = localConnIDs
    98  		clientResetToken = peerResetToken
    99  		serverResetToken = localResetToken
   100  		transientConnID = testPeerConnID(-1)
   101  	}
   102  	return []*testDatagram{{
   103  		// Client Initial
   104  		packets: []*testPacket{{
   105  			ptype:     packetTypeInitial,
   106  			num:       0,
   107  			version:   quicVersion1,
   108  			srcConnID: clientConnIDs[0],
   109  			dstConnID: transientConnID,
   110  			frames: []debugFrame{
   111  				debugFrameCrypto{},
   112  			},
   113  		}},
   114  		paddedSize: 1200,
   115  	}, {
   116  		// Server Initial + Handshake + 1-RTT
   117  		packets: []*testPacket{{
   118  			ptype:     packetTypeInitial,
   119  			num:       0,
   120  			version:   quicVersion1,
   121  			srcConnID: serverConnIDs[0],
   122  			dstConnID: clientConnIDs[0],
   123  			frames: []debugFrame{
   124  				debugFrameAck{
   125  					ranges: []i64range[packetNumber]{{0, 1}},
   126  				},
   127  				debugFrameCrypto{},
   128  			},
   129  		}, {
   130  			ptype:     packetTypeHandshake,
   131  			num:       0,
   132  			version:   quicVersion1,
   133  			srcConnID: serverConnIDs[0],
   134  			dstConnID: clientConnIDs[0],
   135  			frames: []debugFrame{
   136  				debugFrameCrypto{},
   137  			},
   138  		}, {
   139  			ptype:     packetType1RTT,
   140  			num:       0,
   141  			dstConnID: clientConnIDs[0],
   142  			frames: []debugFrame{
   143  				debugFrameNewConnectionID{
   144  					seq:    1,
   145  					connID: serverConnIDs[1],
   146  					token:  serverResetToken,
   147  				},
   148  			},
   149  		}},
   150  		paddedSize: 1200,
   151  	}, {
   152  		// Client Initial + Handshake + 1-RTT
   153  		packets: []*testPacket{{
   154  			ptype:     packetTypeInitial,
   155  			num:       1,
   156  			version:   quicVersion1,
   157  			srcConnID: clientConnIDs[0],
   158  			dstConnID: serverConnIDs[0],
   159  			frames: []debugFrame{
   160  				debugFrameAck{
   161  					ranges: []i64range[packetNumber]{{0, 1}},
   162  				},
   163  			},
   164  		}, {
   165  			ptype:     packetTypeHandshake,
   166  			num:       0,
   167  			version:   quicVersion1,
   168  			srcConnID: clientConnIDs[0],
   169  			dstConnID: serverConnIDs[0],
   170  			frames: []debugFrame{
   171  				debugFrameAck{
   172  					ranges: []i64range[packetNumber]{{0, 1}},
   173  				},
   174  				debugFrameCrypto{},
   175  			},
   176  		}, {
   177  			ptype:     packetType1RTT,
   178  			num:       0,
   179  			dstConnID: serverConnIDs[0],
   180  			frames: []debugFrame{
   181  				debugFrameAck{
   182  					ranges: []i64range[packetNumber]{{0, 1}},
   183  				},
   184  				debugFrameNewConnectionID{
   185  					seq:    1,
   186  					connID: clientConnIDs[1],
   187  					token:  clientResetToken,
   188  				},
   189  			},
   190  		}},
   191  		paddedSize: 1200,
   192  	}, {
   193  		// Server HANDSHAKE_DONE
   194  		packets: []*testPacket{{
   195  			ptype:     packetType1RTT,
   196  			num:       1,
   197  			dstConnID: clientConnIDs[0],
   198  			frames: []debugFrame{
   199  				debugFrameAck{
   200  					ranges: []i64range[packetNumber]{{0, 1}},
   201  				},
   202  				debugFrameHandshakeDone{},
   203  			},
   204  		}},
   205  	}, {
   206  		// Client ack (after max_ack_delay)
   207  		packets: []*testPacket{{
   208  			ptype:     packetType1RTT,
   209  			num:       1,
   210  			dstConnID: serverConnIDs[0],
   211  			frames: []debugFrame{
   212  				debugFrameAck{
   213  					ackDelay: unscaledAckDelayFromDuration(
   214  						maxAckDelay, ackDelayExponent),
   215  					ranges: []i64range[packetNumber]{{0, 2}},
   216  				},
   217  			},
   218  		}},
   219  	}}
   220  }
   221  
   222  func fillCryptoFrames(d *testDatagram, data map[tls.QUICEncryptionLevel][]byte) {
   223  	for _, p := range d.packets {
   224  		var level tls.QUICEncryptionLevel
   225  		switch p.ptype {
   226  		case packetTypeInitial:
   227  			level = tls.QUICEncryptionLevelInitial
   228  		case packetTypeHandshake:
   229  			level = tls.QUICEncryptionLevelHandshake
   230  		case packetType1RTT:
   231  			level = tls.QUICEncryptionLevelApplication
   232  		default:
   233  			continue
   234  		}
   235  		for i := range p.frames {
   236  			c, ok := p.frames[i].(debugFrameCrypto)
   237  			if !ok {
   238  				continue
   239  			}
   240  			c.data = data[level]
   241  			data[level] = nil
   242  			p.frames[i] = c
   243  		}
   244  	}
   245  }
   246  
   247  // uncheckedHandshake executes the handshake.
   248  //
   249  // Unlike testConn.handshake, it sends nothing unnecessary
   250  // (in particular, no NEW_CONNECTION_ID frames),
   251  // and does not validate the conn's responses.
   252  //
   253  // Useful for testing scenarios where configuration has
   254  // changed the handshake responses in some way.
   255  func (tc *testConn) uncheckedHandshake() {
   256  	tc.t.Helper()
   257  	defer func(saved map[byte]bool) {
   258  		tc.ignoreFrames = saved
   259  	}(tc.ignoreFrames)
   260  	tc.ignoreFrames = map[byte]bool{
   261  		frameTypeAck:             true,
   262  		frameTypeCrypto:          true,
   263  		frameTypeNewConnectionID: true,
   264  	}
   265  	if tc.conn.side == serverSide {
   266  		tc.writeFrames(packetTypeInitial,
   267  			debugFrameCrypto{
   268  				data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   269  			})
   270  		tc.writeFrames(packetTypeHandshake,
   271  			debugFrameCrypto{
   272  				data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake],
   273  			})
   274  		tc.wantFrame("send HANDSHAKE_DONE after handshake completes",
   275  			packetType1RTT, debugFrameHandshakeDone{})
   276  		tc.writeFrames(packetType1RTT,
   277  			debugFrameAck{
   278  				ackDelay: unscaledAckDelayFromDuration(
   279  					maxAckDelay, ackDelayExponent),
   280  				ranges: []i64range[packetNumber]{{0, tc.lastPacket.num + 1}},
   281  			})
   282  	} else {
   283  		tc.wantIdle("initial frames are ignored")
   284  		tc.writeFrames(packetTypeInitial,
   285  			debugFrameCrypto{
   286  				data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   287  			})
   288  		tc.writeFrames(packetTypeHandshake,
   289  			debugFrameCrypto{
   290  				data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake],
   291  			})
   292  		tc.wantIdle("don't expect any frames we aren't ignoring")
   293  		// Send the next two frames in separate packets, so the client sends an
   294  		// ack immediately without delay. We want to consume that ack here, rather
   295  		// than returning with a delayed ack waiting to be sent.
   296  		tc.ignoreFrames = nil
   297  		tc.writeFrames(packetType1RTT,
   298  			debugFrameHandshakeDone{})
   299  		tc.writeFrames(packetType1RTT,
   300  			debugFrameCrypto{
   301  				data: tc.cryptoDataIn[tls.QUICEncryptionLevelApplication],
   302  			})
   303  		tc.wantFrame("client ACKs server's first 1-RTT packet",
   304  			packetType1RTT, debugFrameAck{
   305  				ranges: []i64range[packetNumber]{{0, 2}},
   306  			})
   307  
   308  	}
   309  	tc.wantIdle("handshake is done")
   310  }
   311  
   312  func TestConnClientHandshake(t *testing.T) {
   313  	tc := newTestConn(t, clientSide)
   314  	tc.handshake()
   315  	tc.advance(1 * time.Second)
   316  	tc.wantIdle("no packets should be sent by an idle conn after the handshake")
   317  }
   318  
   319  func TestConnServerHandshake(t *testing.T) {
   320  	tc := newTestConn(t, serverSide)
   321  	tc.handshake()
   322  	tc.advance(1 * time.Second)
   323  	tc.wantIdle("no packets should be sent by an idle conn after the handshake")
   324  }
   325  
   326  func TestConnKeysDiscardedClient(t *testing.T) {
   327  	tc := newTestConn(t, clientSide)
   328  	tc.ignoreFrame(frameTypeAck)
   329  
   330  	tc.wantFrame("client sends Initial CRYPTO frame",
   331  		packetTypeInitial, debugFrameCrypto{
   332  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelInitial],
   333  		})
   334  	tc.writeFrames(packetTypeInitial,
   335  		debugFrameCrypto{
   336  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   337  		})
   338  	tc.writeFrames(packetTypeHandshake,
   339  		debugFrameCrypto{
   340  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake],
   341  		})
   342  	tc.wantFrame("client sends Handshake CRYPTO frame",
   343  		packetTypeHandshake, debugFrameCrypto{
   344  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelHandshake],
   345  		})
   346  	tc.wantFrame("client provides an additional connection ID",
   347  		packetType1RTT, debugFrameNewConnectionID{
   348  			seq:    1,
   349  			connID: testLocalConnID(1),
   350  			token:  testLocalStatelessResetToken(1),
   351  		})
   352  
   353  	// The client discards Initial keys after sending a Handshake packet.
   354  	tc.writeFrames(packetTypeInitial,
   355  		debugFrameConnectionCloseTransport{code: errInternal})
   356  	tc.wantIdle("client has discarded Initial keys, cannot read CONNECTION_CLOSE")
   357  
   358  	// The client discards Handshake keys after receiving a HANDSHAKE_DONE frame.
   359  	tc.writeFrames(packetType1RTT,
   360  		debugFrameHandshakeDone{})
   361  	tc.writeFrames(packetTypeHandshake,
   362  		debugFrameConnectionCloseTransport{code: errInternal})
   363  	tc.wantIdle("client has discarded Handshake keys, cannot read CONNECTION_CLOSE")
   364  
   365  	tc.writeFrames(packetType1RTT,
   366  		debugFrameConnectionCloseTransport{code: errInternal})
   367  	tc.conn.Abort(nil)
   368  	tc.wantFrame("client closes connection after 1-RTT CONNECTION_CLOSE",
   369  		packetType1RTT, debugFrameConnectionCloseTransport{
   370  			code: errNo,
   371  		})
   372  }
   373  
   374  func TestConnKeysDiscardedServer(t *testing.T) {
   375  	tc := newTestConn(t, serverSide)
   376  	tc.ignoreFrame(frameTypeAck)
   377  
   378  	tc.writeFrames(packetTypeInitial,
   379  		debugFrameCrypto{
   380  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   381  		})
   382  	tc.wantFrame("server sends Initial CRYPTO frame",
   383  		packetTypeInitial, debugFrameCrypto{
   384  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelInitial],
   385  		})
   386  	tc.wantFrame("server sends Handshake CRYPTO frame",
   387  		packetTypeHandshake, debugFrameCrypto{
   388  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelHandshake],
   389  		})
   390  
   391  	// The server discards Initial keys after receiving a Handshake packet.
   392  	// The Handshake packet contains only the start of the client's CRYPTO flight here,
   393  	// to avoids completing the handshake yet.
   394  	tc.writeFrames(packetTypeHandshake,
   395  		debugFrameCrypto{
   396  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake][:1],
   397  		})
   398  	tc.writeFrames(packetTypeInitial,
   399  		debugFrameConnectionCloseTransport{code: errInternal})
   400  	tc.wantFrame("server provides an additional connection ID",
   401  		packetType1RTT, debugFrameNewConnectionID{
   402  			seq:    1,
   403  			connID: testLocalConnID(1),
   404  			token:  testLocalStatelessResetToken(1),
   405  		})
   406  	tc.wantIdle("server has discarded Initial keys, cannot read CONNECTION_CLOSE")
   407  
   408  	// The server discards Handshake keys after sending a HANDSHAKE_DONE frame.
   409  	tc.writeFrames(packetTypeHandshake,
   410  		debugFrameCrypto{
   411  			off:  1,
   412  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake][1:],
   413  		})
   414  	tc.wantFrame("server sends HANDSHAKE_DONE after handshake completes",
   415  		packetType1RTT, debugFrameHandshakeDone{})
   416  	tc.writeFrames(packetTypeHandshake,
   417  		debugFrameConnectionCloseTransport{code: errInternal})
   418  	tc.wantIdle("server has discarded Handshake keys, cannot read CONNECTION_CLOSE")
   419  
   420  	tc.writeFrames(packetType1RTT,
   421  		debugFrameConnectionCloseTransport{code: errInternal})
   422  	tc.conn.Abort(nil)
   423  	tc.wantFrame("server closes connection after 1-RTT CONNECTION_CLOSE",
   424  		packetType1RTT, debugFrameConnectionCloseTransport{
   425  			code: errNo,
   426  		})
   427  }
   428  
   429  func TestConnInvalidCryptoData(t *testing.T) {
   430  	tc := newTestConn(t, clientSide)
   431  	tc.ignoreFrame(frameTypeAck)
   432  
   433  	tc.wantFrame("client sends Initial CRYPTO frame",
   434  		packetTypeInitial, debugFrameCrypto{
   435  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelInitial],
   436  		})
   437  	tc.writeFrames(packetTypeInitial,
   438  		debugFrameCrypto{
   439  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   440  		})
   441  
   442  	// Render the server's response invalid.
   443  	//
   444  	// The client closes the connection with CRYPTO_ERROR.
   445  	//
   446  	// Changing the first byte will change the TLS message type,
   447  	// so we can reasonably assume that this is an unexpected_message alert (10).
   448  	tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake][0] ^= 0x1
   449  	tc.writeFrames(packetTypeHandshake,
   450  		debugFrameCrypto{
   451  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake],
   452  		})
   453  	tc.wantFrame("client closes connection due to TLS handshake error",
   454  		packetTypeInitial, debugFrameConnectionCloseTransport{
   455  			code: errTLSBase + 10,
   456  		})
   457  }
   458  
   459  func TestConnInvalidPeerCertificate(t *testing.T) {
   460  	tc := newTestConn(t, clientSide, func(c *tls.Config) {
   461  		c.VerifyPeerCertificate = func([][]byte, [][]*x509.Certificate) error {
   462  			return errors.New("I will not buy this certificate. It is scratched.")
   463  		}
   464  	})
   465  	tc.ignoreFrame(frameTypeAck)
   466  
   467  	tc.wantFrame("client sends Initial CRYPTO frame",
   468  		packetTypeInitial, debugFrameCrypto{
   469  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelInitial],
   470  		})
   471  	tc.writeFrames(packetTypeInitial,
   472  		debugFrameCrypto{
   473  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   474  		})
   475  	tc.writeFrames(packetTypeHandshake,
   476  		debugFrameCrypto{
   477  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake],
   478  		})
   479  	tc.wantFrame("client closes connection due to rejecting server certificate",
   480  		packetTypeInitial, debugFrameConnectionCloseTransport{
   481  			code: errTLSBase + 42, // 42: bad_certificate
   482  		})
   483  }
   484  
   485  func TestConnHandshakeDoneSentToServer(t *testing.T) {
   486  	tc := newTestConn(t, serverSide)
   487  	tc.handshake()
   488  
   489  	tc.writeFrames(packetType1RTT,
   490  		debugFrameHandshakeDone{})
   491  	tc.wantFrame("server closes connection when client sends a HANDSHAKE_DONE frame",
   492  		packetType1RTT, debugFrameConnectionCloseTransport{
   493  			code: errProtocolViolation,
   494  		})
   495  }
   496  
   497  func TestConnCryptoDataOutOfOrder(t *testing.T) {
   498  	tc := newTestConn(t, clientSide)
   499  	tc.ignoreFrame(frameTypeAck)
   500  
   501  	tc.wantFrame("client sends Initial CRYPTO frame",
   502  		packetTypeInitial, debugFrameCrypto{
   503  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelInitial],
   504  		})
   505  	tc.writeFrames(packetTypeInitial,
   506  		debugFrameCrypto{
   507  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   508  		})
   509  	tc.wantIdle("client is idle, server Handshake flight has not arrived")
   510  
   511  	tc.writeFrames(packetTypeHandshake,
   512  		debugFrameCrypto{
   513  			off:  15,
   514  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake][15:],
   515  		})
   516  	tc.wantIdle("client is idle, server Handshake flight is not complete")
   517  
   518  	tc.writeFrames(packetTypeHandshake,
   519  		debugFrameCrypto{
   520  			off:  1,
   521  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake][1:20],
   522  		})
   523  	tc.wantIdle("client is idle, server Handshake flight is still not complete")
   524  
   525  	tc.writeFrames(packetTypeHandshake,
   526  		debugFrameCrypto{
   527  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake][0:1],
   528  		})
   529  	tc.wantFrame("client sends Handshake CRYPTO frame",
   530  		packetTypeHandshake, debugFrameCrypto{
   531  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelHandshake],
   532  		})
   533  }
   534  
   535  func TestConnCryptoBufferSizeExceeded(t *testing.T) {
   536  	tc := newTestConn(t, clientSide)
   537  	tc.ignoreFrame(frameTypeAck)
   538  
   539  	tc.wantFrame("client sends Initial CRYPTO frame",
   540  		packetTypeInitial, debugFrameCrypto{
   541  			data: tc.cryptoDataOut[tls.QUICEncryptionLevelInitial],
   542  		})
   543  	tc.writeFrames(packetTypeInitial,
   544  		debugFrameCrypto{
   545  			off:  cryptoBufferSize,
   546  			data: []byte{0},
   547  		})
   548  	tc.wantFrame("client closes connection after server exceeds CRYPTO buffer",
   549  		packetTypeInitial, debugFrameConnectionCloseTransport{
   550  			code: errCryptoBufferExceeded,
   551  		})
   552  }
   553  
   554  func TestConnAEADLimitReached(t *testing.T) {
   555  	// "[...] endpoints MUST count the number of received packets that
   556  	// fail authentication during the lifetime of a connection.
   557  	// If the total number of received packets that fail authentication [...]
   558  	// exceeds the integrity limit for the selected AEAD,
   559  	// the endpoint MUST immediately close the connection [...]"
   560  	// https://www.rfc-editor.org/rfc/rfc9001#section-6.6-6
   561  	tc := newTestConn(t, clientSide, func(c *Config) {
   562  		clear(c.StatelessResetKey[:])
   563  	})
   564  	tc.handshake()
   565  
   566  	var limit int64
   567  	switch suite := tc.conn.keysAppData.r.suite; suite {
   568  	case tls.TLS_AES_128_GCM_SHA256, tls.TLS_AES_256_GCM_SHA384:
   569  		limit = 1 << 52
   570  	case tls.TLS_CHACHA20_POLY1305_SHA256:
   571  		limit = 1 << 36
   572  	default:
   573  		t.Fatalf("conn.keysAppData.r.suite = %v, unknown suite", suite)
   574  	}
   575  
   576  	dstConnID := tc.conn.connIDState.local[0].cid
   577  	if tc.conn.connIDState.local[0].seq == -1 {
   578  		// Only use the transient connection ID in Initial packets.
   579  		dstConnID = tc.conn.connIDState.local[1].cid
   580  	}
   581  	invalid := encodeTestPacket(t, tc, &testPacket{
   582  		ptype:     packetType1RTT,
   583  		num:       1000,
   584  		frames:    []debugFrame{debugFramePing{}},
   585  		version:   quicVersion1,
   586  		dstConnID: dstConnID,
   587  		srcConnID: tc.peerConnID,
   588  	}, 0)
   589  	invalid[len(invalid)-1] ^= 1
   590  	sendInvalid := func() {
   591  		t.Logf("<- conn under test receives invalid datagram")
   592  		tc.conn.sendMsg(&datagram{
   593  			b: invalid,
   594  		})
   595  		tc.wait()
   596  	}
   597  
   598  	// Set the conn's auth failure count to just before the AEAD integrity limit.
   599  	tc.conn.keysAppData.authFailures = limit - 1
   600  
   601  	tc.writeFrames(packetType1RTT, debugFramePing{})
   602  	tc.advanceToTimer()
   603  	tc.wantFrameType("auth failures less than limit: conn ACKs packet",
   604  		packetType1RTT, debugFrameAck{})
   605  
   606  	sendInvalid()
   607  	tc.writeFrames(packetType1RTT, debugFramePing{})
   608  	tc.advanceToTimer()
   609  	tc.wantFrameType("auth failures at limit: conn closes",
   610  		packetType1RTT, debugFrameConnectionCloseTransport{
   611  			code: errAEADLimitReached,
   612  		})
   613  
   614  	tc.writeFrames(packetType1RTT, debugFramePing{})
   615  	tc.advance(1 * time.Second)
   616  	tc.wantIdle("auth failures at limit: conn does not process additional packets")
   617  }