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 }