golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/packet_parser.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  // parseLongHeaderPacket parses a QUIC long header packet.
    10  //
    11  // It does not parse Version Negotiation packets.
    12  //
    13  // On input, pkt contains a long header packet (possibly followed by more packets),
    14  // k the decryption keys for the packet, and pnumMax the largest packet number seen
    15  // in the number space of this packet.
    16  //
    17  // parseLongHeaderPacket returns the parsed packet with protection removed
    18  // and its length in bytes.
    19  //
    20  // It returns an empty packet and -1 if the packet could not be parsed.
    21  func parseLongHeaderPacket(pkt []byte, k fixedKeys, pnumMax packetNumber) (p longPacket, n int) {
    22  	if len(pkt) < 5 || !isLongHeader(pkt[0]) {
    23  		return longPacket{}, -1
    24  	}
    25  
    26  	// Header Form (1) = 1,
    27  	// Fixed Bit (1) = 1,
    28  	// Long Packet Type (2),
    29  	// Type-Specific Bits (4),
    30  	b := pkt
    31  	p.ptype = getPacketType(b)
    32  	if p.ptype == packetTypeInvalid {
    33  		return longPacket{}, -1
    34  	}
    35  	b = b[1:]
    36  	// Version (32),
    37  	p.version, n = consumeUint32(b)
    38  	if n < 0 {
    39  		return longPacket{}, -1
    40  	}
    41  	b = b[n:]
    42  	if p.version == 0 {
    43  		// Version Negotiation packet; not handled here.
    44  		return longPacket{}, -1
    45  	}
    46  
    47  	// Destination Connection ID Length (8),
    48  	// Destination Connection ID (0..160),
    49  	p.dstConnID, n = consumeUint8Bytes(b)
    50  	if n < 0 || len(p.dstConnID) > maxConnIDLen {
    51  		return longPacket{}, -1
    52  	}
    53  	b = b[n:]
    54  
    55  	// Source Connection ID Length (8),
    56  	// Source Connection ID (0..160),
    57  	p.srcConnID, n = consumeUint8Bytes(b)
    58  	if n < 0 || len(p.dstConnID) > maxConnIDLen {
    59  		return longPacket{}, -1
    60  	}
    61  	b = b[n:]
    62  
    63  	switch p.ptype {
    64  	case packetTypeInitial:
    65  		// Token Length (i),
    66  		// Token (..),
    67  		p.extra, n = consumeVarintBytes(b)
    68  		if n < 0 {
    69  			return longPacket{}, -1
    70  		}
    71  		b = b[n:]
    72  	case packetTypeRetry:
    73  		// Retry Token (..),
    74  		// Retry Integrity Tag (128),
    75  		p.extra = b
    76  		return p, len(pkt)
    77  	}
    78  
    79  	// Length (i),
    80  	payLen, n := consumeVarint(b)
    81  	if n < 0 {
    82  		return longPacket{}, -1
    83  	}
    84  	b = b[n:]
    85  	if uint64(len(b)) < payLen {
    86  		return longPacket{}, -1
    87  	}
    88  
    89  	// Packet Number (8..32),
    90  	// Packet Payload (..),
    91  	pnumOff := len(pkt) - len(b)
    92  	pkt = pkt[:pnumOff+int(payLen)]
    93  
    94  	if k.isSet() {
    95  		var err error
    96  		p.payload, p.num, err = k.unprotect(pkt, pnumOff, pnumMax)
    97  		if err != nil {
    98  			return longPacket{}, -1
    99  		}
   100  	}
   101  	return p, len(pkt)
   102  }
   103  
   104  // skipLongHeaderPacket returns the length of the long header packet at the start of pkt,
   105  // or -1 if the buffer does not contain a valid packet.
   106  func skipLongHeaderPacket(pkt []byte) int {
   107  	// Header byte, 4 bytes of version.
   108  	n := 5
   109  	if len(pkt) <= n {
   110  		return -1
   111  	}
   112  	// Destination connection ID length, destination connection ID.
   113  	n += 1 + int(pkt[n])
   114  	if len(pkt) <= n {
   115  		return -1
   116  	}
   117  	// Source connection ID length, source connection ID.
   118  	n += 1 + int(pkt[n])
   119  	if len(pkt) <= n {
   120  		return -1
   121  	}
   122  	if getPacketType(pkt) == packetTypeInitial {
   123  		// Token length, token.
   124  		_, nn := consumeVarintBytes(pkt[n:])
   125  		if nn < 0 {
   126  			return -1
   127  		}
   128  		n += nn
   129  	}
   130  	// Length, packet number, payload.
   131  	_, nn := consumeVarintBytes(pkt[n:])
   132  	if nn < 0 {
   133  		return -1
   134  	}
   135  	n += nn
   136  	if len(pkt) < n {
   137  		return -1
   138  	}
   139  	return n
   140  }
   141  
   142  // parse1RTTPacket parses a QUIC 1-RTT (short header) packet.
   143  //
   144  // On input, pkt contains a short header packet, k the decryption keys for the packet,
   145  // and pnumMax the largest packet number seen in the number space of this packet.
   146  func parse1RTTPacket(pkt []byte, k *updatingKeyPair, dstConnIDLen int, pnumMax packetNumber) (p shortPacket, err error) {
   147  	pay, pnum, err := k.unprotect(pkt, 1+dstConnIDLen, pnumMax)
   148  	if err != nil {
   149  		return shortPacket{}, err
   150  	}
   151  	p.num = pnum
   152  	p.payload = pay
   153  	return p, nil
   154  }
   155  
   156  // Consume functions return n=-1 on conditions which result in FRAME_ENCODING_ERROR,
   157  // which includes both general parse failures and specific violations of frame
   158  // constraints.
   159  
   160  func consumeAckFrame(frame []byte, f func(rangeIndex int, start, end packetNumber)) (largest packetNumber, ackDelay unscaledAckDelay, n int) {
   161  	b := frame[1:] // type
   162  
   163  	largestAck, n := consumeVarint(b)
   164  	if n < 0 {
   165  		return 0, 0, -1
   166  	}
   167  	b = b[n:]
   168  
   169  	v, n := consumeVarintInt64(b)
   170  	if n < 0 {
   171  		return 0, 0, -1
   172  	}
   173  	b = b[n:]
   174  	ackDelay = unscaledAckDelay(v)
   175  
   176  	ackRangeCount, n := consumeVarint(b)
   177  	if n < 0 {
   178  		return 0, 0, -1
   179  	}
   180  	b = b[n:]
   181  
   182  	rangeMax := packetNumber(largestAck)
   183  	for i := uint64(0); ; i++ {
   184  		rangeLen, n := consumeVarint(b)
   185  		if n < 0 {
   186  			return 0, 0, -1
   187  		}
   188  		b = b[n:]
   189  		rangeMin := rangeMax - packetNumber(rangeLen)
   190  		if rangeMin < 0 || rangeMin > rangeMax {
   191  			return 0, 0, -1
   192  		}
   193  		f(int(i), rangeMin, rangeMax+1)
   194  
   195  		if i == ackRangeCount {
   196  			break
   197  		}
   198  
   199  		gap, n := consumeVarint(b)
   200  		if n < 0 {
   201  			return 0, 0, -1
   202  		}
   203  		b = b[n:]
   204  
   205  		rangeMax = rangeMin - packetNumber(gap) - 2
   206  	}
   207  
   208  	if frame[0] != frameTypeAckECN {
   209  		return packetNumber(largestAck), ackDelay, len(frame) - len(b)
   210  	}
   211  
   212  	ect0Count, n := consumeVarint(b)
   213  	if n < 0 {
   214  		return 0, 0, -1
   215  	}
   216  	b = b[n:]
   217  	ect1Count, n := consumeVarint(b)
   218  	if n < 0 {
   219  		return 0, 0, -1
   220  	}
   221  	b = b[n:]
   222  	ecnCECount, n := consumeVarint(b)
   223  	if n < 0 {
   224  		return 0, 0, -1
   225  	}
   226  	b = b[n:]
   227  
   228  	// TODO: Make use of ECN feedback.
   229  	// https://www.rfc-editor.org/rfc/rfc9000.html#section-19.3.2
   230  	_ = ect0Count
   231  	_ = ect1Count
   232  	_ = ecnCECount
   233  
   234  	return packetNumber(largestAck), ackDelay, len(frame) - len(b)
   235  }
   236  
   237  func consumeResetStreamFrame(b []byte) (id streamID, code uint64, finalSize int64, n int) {
   238  	n = 1
   239  	idInt, nn := consumeVarint(b[n:])
   240  	if nn < 0 {
   241  		return 0, 0, 0, -1
   242  	}
   243  	n += nn
   244  	code, nn = consumeVarint(b[n:])
   245  	if nn < 0 {
   246  		return 0, 0, 0, -1
   247  	}
   248  	n += nn
   249  	v, nn := consumeVarint(b[n:])
   250  	if nn < 0 {
   251  		return 0, 0, 0, -1
   252  	}
   253  	n += nn
   254  	finalSize = int64(v)
   255  	return streamID(idInt), code, finalSize, n
   256  }
   257  
   258  func consumeStopSendingFrame(b []byte) (id streamID, code uint64, n int) {
   259  	n = 1
   260  	idInt, nn := consumeVarint(b[n:])
   261  	if nn < 0 {
   262  		return 0, 0, -1
   263  	}
   264  	n += nn
   265  	code, nn = consumeVarint(b[n:])
   266  	if nn < 0 {
   267  		return 0, 0, -1
   268  	}
   269  	n += nn
   270  	return streamID(idInt), code, n
   271  }
   272  
   273  func consumeCryptoFrame(b []byte) (off int64, data []byte, n int) {
   274  	n = 1
   275  	v, nn := consumeVarint(b[n:])
   276  	if nn < 0 {
   277  		return 0, nil, -1
   278  	}
   279  	off = int64(v)
   280  	n += nn
   281  	data, nn = consumeVarintBytes(b[n:])
   282  	if nn < 0 {
   283  		return 0, nil, -1
   284  	}
   285  	n += nn
   286  	return off, data, n
   287  }
   288  
   289  func consumeNewTokenFrame(b []byte) (token []byte, n int) {
   290  	n = 1
   291  	data, nn := consumeVarintBytes(b[n:])
   292  	if nn < 0 {
   293  		return nil, -1
   294  	}
   295  	if len(data) == 0 {
   296  		return nil, -1
   297  	}
   298  	n += nn
   299  	return data, n
   300  }
   301  
   302  func consumeStreamFrame(b []byte) (id streamID, off int64, fin bool, data []byte, n int) {
   303  	fin = (b[0] & 0x01) != 0
   304  	n = 1
   305  	idInt, nn := consumeVarint(b[n:])
   306  	if nn < 0 {
   307  		return 0, 0, false, nil, -1
   308  	}
   309  	n += nn
   310  	if b[0]&0x04 != 0 {
   311  		v, nn := consumeVarint(b[n:])
   312  		if nn < 0 {
   313  			return 0, 0, false, nil, -1
   314  		}
   315  		n += nn
   316  		off = int64(v)
   317  	}
   318  	if b[0]&0x02 != 0 {
   319  		data, nn = consumeVarintBytes(b[n:])
   320  		if nn < 0 {
   321  			return 0, 0, false, nil, -1
   322  		}
   323  		n += nn
   324  	} else {
   325  		data = b[n:]
   326  		n += len(data)
   327  	}
   328  	if off+int64(len(data)) >= 1<<62 {
   329  		return 0, 0, false, nil, -1
   330  	}
   331  	return streamID(idInt), off, fin, data, n
   332  }
   333  
   334  func consumeMaxDataFrame(b []byte) (max int64, n int) {
   335  	n = 1
   336  	v, nn := consumeVarint(b[n:])
   337  	if nn < 0 {
   338  		return 0, -1
   339  	}
   340  	n += nn
   341  	return int64(v), n
   342  }
   343  
   344  func consumeMaxStreamDataFrame(b []byte) (id streamID, max int64, n int) {
   345  	n = 1
   346  	v, nn := consumeVarint(b[n:])
   347  	if nn < 0 {
   348  		return 0, 0, -1
   349  	}
   350  	n += nn
   351  	id = streamID(v)
   352  	v, nn = consumeVarint(b[n:])
   353  	if nn < 0 {
   354  		return 0, 0, -1
   355  	}
   356  	n += nn
   357  	max = int64(v)
   358  	return id, max, n
   359  }
   360  
   361  func consumeMaxStreamsFrame(b []byte) (typ streamType, max int64, n int) {
   362  	switch b[0] {
   363  	case frameTypeMaxStreamsBidi:
   364  		typ = bidiStream
   365  	case frameTypeMaxStreamsUni:
   366  		typ = uniStream
   367  	default:
   368  		return 0, 0, -1
   369  	}
   370  	n = 1
   371  	v, nn := consumeVarint(b[n:])
   372  	if nn < 0 {
   373  		return 0, 0, -1
   374  	}
   375  	n += nn
   376  	if v > maxStreamsLimit {
   377  		return 0, 0, -1
   378  	}
   379  	return typ, int64(v), n
   380  }
   381  
   382  func consumeStreamDataBlockedFrame(b []byte) (id streamID, max int64, n int) {
   383  	n = 1
   384  	v, nn := consumeVarint(b[n:])
   385  	if nn < 0 {
   386  		return 0, 0, -1
   387  	}
   388  	n += nn
   389  	id = streamID(v)
   390  	max, nn = consumeVarintInt64(b[n:])
   391  	if nn < 0 {
   392  		return 0, 0, -1
   393  	}
   394  	n += nn
   395  	return id, max, n
   396  }
   397  
   398  func consumeDataBlockedFrame(b []byte) (max int64, n int) {
   399  	n = 1
   400  	max, nn := consumeVarintInt64(b[n:])
   401  	if nn < 0 {
   402  		return 0, -1
   403  	}
   404  	n += nn
   405  	return max, n
   406  }
   407  
   408  func consumeStreamsBlockedFrame(b []byte) (typ streamType, max int64, n int) {
   409  	if b[0] == frameTypeStreamsBlockedBidi {
   410  		typ = bidiStream
   411  	} else {
   412  		typ = uniStream
   413  	}
   414  	n = 1
   415  	max, nn := consumeVarintInt64(b[n:])
   416  	if nn < 0 {
   417  		return 0, 0, -1
   418  	}
   419  	n += nn
   420  	return typ, max, n
   421  }
   422  
   423  func consumeNewConnectionIDFrame(b []byte) (seq, retire int64, connID []byte, resetToken statelessResetToken, n int) {
   424  	n = 1
   425  	var nn int
   426  	seq, nn = consumeVarintInt64(b[n:])
   427  	if nn < 0 {
   428  		return 0, 0, nil, statelessResetToken{}, -1
   429  	}
   430  	n += nn
   431  	retire, nn = consumeVarintInt64(b[n:])
   432  	if nn < 0 {
   433  		return 0, 0, nil, statelessResetToken{}, -1
   434  	}
   435  	n += nn
   436  	if seq < retire {
   437  		return 0, 0, nil, statelessResetToken{}, -1
   438  	}
   439  	connID, nn = consumeVarintBytes(b[n:])
   440  	if nn < 0 {
   441  		return 0, 0, nil, statelessResetToken{}, -1
   442  	}
   443  	if len(connID) < 1 || len(connID) > 20 {
   444  		return 0, 0, nil, statelessResetToken{}, -1
   445  	}
   446  	n += nn
   447  	if len(b[n:]) < len(resetToken) {
   448  		return 0, 0, nil, statelessResetToken{}, -1
   449  	}
   450  	copy(resetToken[:], b[n:])
   451  	n += len(resetToken)
   452  	return seq, retire, connID, resetToken, n
   453  }
   454  
   455  func consumeRetireConnectionIDFrame(b []byte) (seq int64, n int) {
   456  	n = 1
   457  	var nn int
   458  	seq, nn = consumeVarintInt64(b[n:])
   459  	if nn < 0 {
   460  		return 0, -1
   461  	}
   462  	n += nn
   463  	return seq, n
   464  }
   465  
   466  func consumePathChallengeFrame(b []byte) (data pathChallengeData, n int) {
   467  	n = 1
   468  	nn := copy(data[:], b[n:])
   469  	if nn != len(data) {
   470  		return data, -1
   471  	}
   472  	n += nn
   473  	return data, n
   474  }
   475  
   476  func consumePathResponseFrame(b []byte) (data pathChallengeData, n int) {
   477  	return consumePathChallengeFrame(b) // identical frame format
   478  }
   479  
   480  func consumeConnectionCloseTransportFrame(b []byte) (code transportError, frameType uint64, reason string, n int) {
   481  	n = 1
   482  	var nn int
   483  	var codeInt uint64
   484  	codeInt, nn = consumeVarint(b[n:])
   485  	if nn < 0 {
   486  		return 0, 0, "", -1
   487  	}
   488  	code = transportError(codeInt)
   489  	n += nn
   490  	frameType, nn = consumeVarint(b[n:])
   491  	if nn < 0 {
   492  		return 0, 0, "", -1
   493  	}
   494  	n += nn
   495  	reasonb, nn := consumeVarintBytes(b[n:])
   496  	if nn < 0 {
   497  		return 0, 0, "", -1
   498  	}
   499  	n += nn
   500  	reason = string(reasonb)
   501  	return code, frameType, reason, n
   502  }
   503  
   504  func consumeConnectionCloseApplicationFrame(b []byte) (code uint64, reason string, n int) {
   505  	n = 1
   506  	var nn int
   507  	code, nn = consumeVarint(b[n:])
   508  	if nn < 0 {
   509  		return 0, "", -1
   510  	}
   511  	n += nn
   512  	reasonb, nn := consumeVarintBytes(b[n:])
   513  	if nn < 0 {
   514  		return 0, "", -1
   515  	}
   516  	n += nn
   517  	reason = string(reasonb)
   518  	return code, reason, n
   519  }