golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/packet_protection.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" 11 "crypto/aes" 12 "crypto/cipher" 13 "crypto/sha256" 14 "crypto/tls" 15 "errors" 16 "hash" 17 18 "golang.org/x/crypto/chacha20" 19 "golang.org/x/crypto/chacha20poly1305" 20 "golang.org/x/crypto/cryptobyte" 21 "golang.org/x/crypto/hkdf" 22 ) 23 24 var errInvalidPacket = errors.New("quic: invalid packet") 25 26 // headerProtectionSampleSize is the size of the ciphertext sample used for header protection. 27 // https://www.rfc-editor.org/rfc/rfc9001#section-5.4.2 28 const headerProtectionSampleSize = 16 29 30 // aeadOverhead is the difference in size between the AEAD output and input. 31 // All cipher suites defined for use with QUIC have 16 bytes of overhead. 32 const aeadOverhead = 16 33 34 // A headerKey applies or removes header protection. 35 // https://www.rfc-editor.org/rfc/rfc9001#section-5.4 36 type headerKey struct { 37 hp headerProtection 38 } 39 40 func (k headerKey) isSet() bool { 41 return k.hp != nil 42 } 43 44 func (k *headerKey) init(suite uint16, secret []byte) { 45 h, keySize := hashForSuite(suite) 46 hpKey := hkdfExpandLabel(h.New, secret, "quic hp", nil, keySize) 47 switch suite { 48 case tls.TLS_AES_128_GCM_SHA256, tls.TLS_AES_256_GCM_SHA384: 49 c, err := aes.NewCipher(hpKey) 50 if err != nil { 51 panic(err) 52 } 53 k.hp = &aesHeaderProtection{cipher: c} 54 case tls.TLS_CHACHA20_POLY1305_SHA256: 55 k.hp = chaCha20HeaderProtection{hpKey} 56 default: 57 panic("BUG: unknown cipher suite") 58 } 59 } 60 61 // protect applies header protection. 62 // pnumOff is the offset of the packet number in the packet. 63 func (k headerKey) protect(hdr []byte, pnumOff int) { 64 // Apply header protection. 65 pnumSize := int(hdr[0]&0x03) + 1 66 sample := hdr[pnumOff+4:][:headerProtectionSampleSize] 67 mask := k.hp.headerProtection(sample) 68 if isLongHeader(hdr[0]) { 69 hdr[0] ^= mask[0] & 0x0f 70 } else { 71 hdr[0] ^= mask[0] & 0x1f 72 } 73 for i := 0; i < pnumSize; i++ { 74 hdr[pnumOff+i] ^= mask[1+i] 75 } 76 } 77 78 // unprotect removes header protection. 79 // pnumOff is the offset of the packet number in the packet. 80 // pnumMax is the largest packet number seen in the number space of this packet. 81 func (k headerKey) unprotect(pkt []byte, pnumOff int, pnumMax packetNumber) (hdr, pay []byte, pnum packetNumber, _ error) { 82 if len(pkt) < pnumOff+4+headerProtectionSampleSize { 83 return nil, nil, 0, errInvalidPacket 84 } 85 numpay := pkt[pnumOff:] 86 sample := numpay[4:][:headerProtectionSampleSize] 87 mask := k.hp.headerProtection(sample) 88 if isLongHeader(pkt[0]) { 89 pkt[0] ^= mask[0] & 0x0f 90 } else { 91 pkt[0] ^= mask[0] & 0x1f 92 } 93 pnumLen := int(pkt[0]&0x03) + 1 94 pnum = packetNumber(0) 95 for i := 0; i < pnumLen; i++ { 96 numpay[i] ^= mask[1+i] 97 pnum = (pnum << 8) | packetNumber(numpay[i]) 98 } 99 pnum = decodePacketNumber(pnumMax, pnum, pnumLen) 100 hdr = pkt[:pnumOff+pnumLen] 101 pay = numpay[pnumLen:] 102 return hdr, pay, pnum, nil 103 } 104 105 // headerProtection is the header_protection function as defined in: 106 // https://www.rfc-editor.org/rfc/rfc9001#section-5.4.1 107 // 108 // This function takes a sample of the packet ciphertext 109 // and returns a 5-byte mask which will be applied to the 110 // protected portions of the packet header. 111 type headerProtection interface { 112 headerProtection(sample []byte) (mask [5]byte) 113 } 114 115 // AES-based header protection. 116 // https://www.rfc-editor.org/rfc/rfc9001#section-5.4.3 117 type aesHeaderProtection struct { 118 cipher cipher.Block 119 scratch [aes.BlockSize]byte 120 } 121 122 func (hp *aesHeaderProtection) headerProtection(sample []byte) (mask [5]byte) { 123 hp.cipher.Encrypt(hp.scratch[:], sample) 124 copy(mask[:], hp.scratch[:]) 125 return mask 126 } 127 128 // ChaCha20-based header protection. 129 // https://www.rfc-editor.org/rfc/rfc9001#section-5.4.4 130 type chaCha20HeaderProtection struct { 131 key []byte 132 } 133 134 func (hp chaCha20HeaderProtection) headerProtection(sample []byte) (mask [5]byte) { 135 counter := uint32(sample[3])<<24 | uint32(sample[2])<<16 | uint32(sample[1])<<8 | uint32(sample[0]) 136 nonce := sample[4:16] 137 c, err := chacha20.NewUnauthenticatedCipher(hp.key, nonce) 138 if err != nil { 139 panic(err) 140 } 141 c.SetCounter(counter) 142 c.XORKeyStream(mask[:], mask[:]) 143 return mask 144 } 145 146 // A packetKey applies or removes packet protection. 147 // https://www.rfc-editor.org/rfc/rfc9001#section-5.1 148 type packetKey struct { 149 aead cipher.AEAD // AEAD function used for packet protection. 150 iv []byte // IV used to construct the AEAD nonce. 151 } 152 153 func (k *packetKey) init(suite uint16, secret []byte) { 154 // https://www.rfc-editor.org/rfc/rfc9001#section-5.1 155 h, keySize := hashForSuite(suite) 156 key := hkdfExpandLabel(h.New, secret, "quic key", nil, keySize) 157 switch suite { 158 case tls.TLS_AES_128_GCM_SHA256, tls.TLS_AES_256_GCM_SHA384: 159 k.aead = newAESAEAD(key) 160 case tls.TLS_CHACHA20_POLY1305_SHA256: 161 k.aead = newChaCha20AEAD(key) 162 default: 163 panic("BUG: unknown cipher suite") 164 } 165 k.iv = hkdfExpandLabel(h.New, secret, "quic iv", nil, k.aead.NonceSize()) 166 } 167 168 func newAESAEAD(key []byte) cipher.AEAD { 169 c, err := aes.NewCipher(key) 170 if err != nil { 171 panic(err) 172 } 173 aead, err := cipher.NewGCM(c) 174 if err != nil { 175 panic(err) 176 } 177 return aead 178 } 179 180 func newChaCha20AEAD(key []byte) cipher.AEAD { 181 var err error 182 aead, err := chacha20poly1305.New(key) 183 if err != nil { 184 panic(err) 185 } 186 return aead 187 } 188 189 func (k packetKey) protect(hdr, pay []byte, pnum packetNumber) []byte { 190 k.xorIV(pnum) 191 defer k.xorIV(pnum) 192 return k.aead.Seal(hdr, k.iv, pay, hdr) 193 } 194 195 func (k packetKey) unprotect(hdr, pay []byte, pnum packetNumber) (dec []byte, err error) { 196 k.xorIV(pnum) 197 defer k.xorIV(pnum) 198 return k.aead.Open(pay[:0], k.iv, pay, hdr) 199 } 200 201 // xorIV xors the packet protection IV with the packet number. 202 func (k packetKey) xorIV(pnum packetNumber) { 203 k.iv[len(k.iv)-8] ^= uint8(pnum >> 56) 204 k.iv[len(k.iv)-7] ^= uint8(pnum >> 48) 205 k.iv[len(k.iv)-6] ^= uint8(pnum >> 40) 206 k.iv[len(k.iv)-5] ^= uint8(pnum >> 32) 207 k.iv[len(k.iv)-4] ^= uint8(pnum >> 24) 208 k.iv[len(k.iv)-3] ^= uint8(pnum >> 16) 209 k.iv[len(k.iv)-2] ^= uint8(pnum >> 8) 210 k.iv[len(k.iv)-1] ^= uint8(pnum) 211 } 212 213 // A fixedKeys is a header protection key and fixed packet protection key. 214 // The packet protection key is fixed (it does not update). 215 // 216 // Fixed keys are used for Initial and Handshake keys, which do not update. 217 type fixedKeys struct { 218 hdr headerKey 219 pkt packetKey 220 } 221 222 func (k *fixedKeys) init(suite uint16, secret []byte) { 223 k.hdr.init(suite, secret) 224 k.pkt.init(suite, secret) 225 } 226 227 func (k fixedKeys) isSet() bool { 228 return k.hdr.hp != nil 229 } 230 231 // protect applies packet protection to a packet. 232 // 233 // On input, hdr contains the packet header, pay the unencrypted payload, 234 // pnumOff the offset of the packet number in the header, and pnum the untruncated 235 // packet number. 236 // 237 // protect returns the result of appending the encrypted payload to hdr and 238 // applying header protection. 239 func (k fixedKeys) protect(hdr, pay []byte, pnumOff int, pnum packetNumber) []byte { 240 pkt := k.pkt.protect(hdr, pay, pnum) 241 k.hdr.protect(pkt, pnumOff) 242 return pkt 243 } 244 245 // unprotect removes packet protection from a packet. 246 // 247 // On input, pkt contains the full protected packet, pnumOff the offset of 248 // the packet number in the header, and pnumMax the largest packet number 249 // seen in the number space of this packet. 250 // 251 // unprotect removes header protection from the header in pkt, and returns 252 // the unprotected payload and packet number. 253 func (k fixedKeys) unprotect(pkt []byte, pnumOff int, pnumMax packetNumber) (pay []byte, num packetNumber, err error) { 254 hdr, pay, pnum, err := k.hdr.unprotect(pkt, pnumOff, pnumMax) 255 if err != nil { 256 return nil, 0, err 257 } 258 pay, err = k.pkt.unprotect(hdr, pay, pnum) 259 if err != nil { 260 return nil, 0, err 261 } 262 return pay, pnum, nil 263 } 264 265 // A fixedKeyPair is a read/write pair of fixed keys. 266 type fixedKeyPair struct { 267 r, w fixedKeys 268 } 269 270 func (k *fixedKeyPair) discard() { 271 *k = fixedKeyPair{} 272 } 273 274 func (k *fixedKeyPair) canRead() bool { 275 return k.r.isSet() 276 } 277 278 func (k *fixedKeyPair) canWrite() bool { 279 return k.w.isSet() 280 } 281 282 // An updatingKeys is a header protection key and updatable packet protection key. 283 // updatingKeys are used for 1-RTT keys, where the packet protection key changes 284 // over the lifetime of a connection. 285 // https://www.rfc-editor.org/rfc/rfc9001#section-6 286 type updatingKeys struct { 287 suite uint16 288 hdr headerKey 289 pkt [2]packetKey // current, next 290 nextSecret []byte // secret used to generate pkt[1] 291 } 292 293 func (k *updatingKeys) init(suite uint16, secret []byte) { 294 k.suite = suite 295 k.hdr.init(suite, secret) 296 // Initialize pkt[1] with secret_0, and then call update to generate secret_1. 297 k.pkt[1].init(suite, secret) 298 k.nextSecret = secret 299 k.update() 300 } 301 302 // update performs a key update. 303 // The current key in pkt[0] is discarded. 304 // The next key in pkt[1] becomes the current key. 305 // A new next key is generated in pkt[1]. 306 func (k *updatingKeys) update() { 307 k.nextSecret = updateSecret(k.suite, k.nextSecret) 308 k.pkt[0] = k.pkt[1] 309 k.pkt[1].init(k.suite, k.nextSecret) 310 } 311 312 func updateSecret(suite uint16, secret []byte) (nextSecret []byte) { 313 h, _ := hashForSuite(suite) 314 return hkdfExpandLabel(h.New, secret, "quic ku", nil, len(secret)) 315 } 316 317 // An updatingKeyPair is a read/write pair of updating keys. 318 // 319 // We keep two keys (current and next) in both read and write directions. 320 // When an incoming packet's phase matches the current phase bit, 321 // we unprotect it using the current keys; otherwise we use the next keys. 322 // 323 // When updating=false, outgoing packets are protected using the current phase. 324 // 325 // An update is initiated and updating is set to true when: 326 // - we decide to initiate a key update; or 327 // - we successfully unprotect a packet using the next keys, 328 // indicating the peer has initiated a key update. 329 // 330 // When updating=true, outgoing packets are protected using the next phase. 331 // We do not change the current phase bit or generate new keys yet. 332 // 333 // The update concludes when we receive an ACK frame for a packet sent 334 // with the next keys. At this time, we set updating to false, flip the 335 // phase bit, and update the keys. This permits us to handle up to 1-RTT 336 // of reordered packets before discarding the previous phase's keys after 337 // an update. 338 type updatingKeyPair struct { 339 phase uint8 // current key phase (r.pkt[0], w.pkt[0]) 340 updating bool 341 authFailures int64 // total packet unprotect failures 342 minSent packetNumber // min packet number sent since entering the updating state 343 minReceived packetNumber // min packet number received in the next phase 344 updateAfter packetNumber // packet number after which to initiate key update 345 r, w updatingKeys 346 } 347 348 func (k *updatingKeyPair) init() { 349 // 1-RTT packets until the first key update. 350 // 351 // We perform the first key update early in the connection so a peer 352 // which does not support key updates will fail rapidly, 353 // rather than after the connection has been long established. 354 // 355 // The QUIC interop runner "keyupdate" test requires that the client 356 // initiate a key rotation early in the connection. Increasing this 357 // value may cause interop test failures; if we do want to increase it, 358 // we should either skip the keyupdate test or provide a way to override 359 // the setting in interop tests. 360 k.updateAfter = 100 361 } 362 363 func (k *updatingKeyPair) canRead() bool { 364 return k.r.hdr.hp != nil 365 } 366 367 func (k *updatingKeyPair) canWrite() bool { 368 return k.w.hdr.hp != nil 369 } 370 371 // handleAckFor finishes a key update after receiving an ACK for a packet in the next phase. 372 func (k *updatingKeyPair) handleAckFor(pnum packetNumber) { 373 if k.updating && pnum >= k.minSent { 374 k.updating = false 375 k.phase ^= keyPhaseBit 376 k.r.update() 377 k.w.update() 378 } 379 } 380 381 // needAckEliciting reports whether we should send an ack-eliciting packet in the next phase. 382 // The first packet sent in a phase is ack-eliciting, since the peer must acknowledge a 383 // packet in the new phase for us to finish the update. 384 func (k *updatingKeyPair) needAckEliciting() bool { 385 return k.updating && k.minSent == maxPacketNumber 386 } 387 388 // protect applies packet protection to a packet. 389 // Parameters and returns are as for fixedKeyPair.protect. 390 func (k *updatingKeyPair) protect(hdr, pay []byte, pnumOff int, pnum packetNumber) []byte { 391 var pkt []byte 392 if k.updating { 393 hdr[0] |= k.phase ^ keyPhaseBit 394 pkt = k.w.pkt[1].protect(hdr, pay, pnum) 395 k.minSent = min(pnum, k.minSent) 396 } else { 397 hdr[0] |= k.phase 398 pkt = k.w.pkt[0].protect(hdr, pay, pnum) 399 if pnum >= k.updateAfter { 400 // Initiate a key update, starting with the next packet we send. 401 // 402 // We do this after protecting the current packet 403 // to allow Conn.appendFrames to ensure that the first packet sent 404 // in the new phase is ack-eliciting. 405 k.updating = true 406 k.minSent = maxPacketNumber 407 k.minReceived = maxPacketNumber 408 // The lowest confidentiality limit for a supported AEAD is 2^23 packets. 409 // https://www.rfc-editor.org/rfc/rfc9001#section-6.6-5 410 // 411 // Schedule our next update for half that. 412 k.updateAfter += (1 << 22) 413 } 414 } 415 k.w.hdr.protect(pkt, pnumOff) 416 return pkt 417 } 418 419 // unprotect removes packet protection from a packet. 420 // Parameters and returns are as for fixedKeyPair.unprotect. 421 func (k *updatingKeyPair) unprotect(pkt []byte, pnumOff int, pnumMax packetNumber) (pay []byte, pnum packetNumber, err error) { 422 hdr, pay, pnum, err := k.r.hdr.unprotect(pkt, pnumOff, pnumMax) 423 if err != nil { 424 return nil, 0, err 425 } 426 // To avoid timing signals that might indicate the key phase bit is invalid, 427 // we always attempt to unprotect the packet with one key. 428 // 429 // If the key phase bit matches and the packet number doesn't come after 430 // the start of an in-progress update, use the current phase. 431 // Otherwise, use the next phase. 432 if hdr[0]&keyPhaseBit == k.phase && (!k.updating || pnum < k.minReceived) { 433 pay, err = k.r.pkt[0].unprotect(hdr, pay, pnum) 434 } else { 435 pay, err = k.r.pkt[1].unprotect(hdr, pay, pnum) 436 if err == nil { 437 if !k.updating { 438 // The peer has initiated a key update. 439 k.updating = true 440 k.minSent = maxPacketNumber 441 k.minReceived = pnum 442 } else { 443 k.minReceived = min(pnum, k.minReceived) 444 } 445 } 446 } 447 if err != nil { 448 k.authFailures++ 449 if k.authFailures >= aeadIntegrityLimit(k.r.suite) { 450 return nil, 0, localTransportError{code: errAEADLimitReached} 451 } 452 return nil, 0, err 453 } 454 return pay, pnum, nil 455 } 456 457 // aeadIntegrityLimit returns the integrity limit for an AEAD: 458 // The maximum number of received packets that may fail authentication 459 // before closing the connection. 460 // 461 // https://www.rfc-editor.org/rfc/rfc9001#section-6.6-4 462 func aeadIntegrityLimit(suite uint16) int64 { 463 switch suite { 464 case tls.TLS_AES_128_GCM_SHA256, tls.TLS_AES_256_GCM_SHA384: 465 return 1 << 52 466 case tls.TLS_CHACHA20_POLY1305_SHA256: 467 return 1 << 36 468 default: 469 panic("BUG: unknown cipher suite") 470 } 471 } 472 473 // https://www.rfc-editor.org/rfc/rfc9001#section-5.2-2 474 var initialSalt = []byte{0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a} 475 476 // initialKeys returns the keys used to protect Initial packets. 477 // 478 // The Initial packet keys are derived from the Destination Connection ID 479 // field in the client's first Initial packet. 480 // 481 // https://www.rfc-editor.org/rfc/rfc9001#section-5.2 482 func initialKeys(cid []byte, side connSide) fixedKeyPair { 483 initialSecret := hkdf.Extract(sha256.New, cid, initialSalt) 484 var clientKeys fixedKeys 485 clientSecret := hkdfExpandLabel(sha256.New, initialSecret, "client in", nil, sha256.Size) 486 clientKeys.init(tls.TLS_AES_128_GCM_SHA256, clientSecret) 487 var serverKeys fixedKeys 488 serverSecret := hkdfExpandLabel(sha256.New, initialSecret, "server in", nil, sha256.Size) 489 serverKeys.init(tls.TLS_AES_128_GCM_SHA256, serverSecret) 490 if side == clientSide { 491 return fixedKeyPair{r: serverKeys, w: clientKeys} 492 } else { 493 return fixedKeyPair{w: serverKeys, r: clientKeys} 494 } 495 } 496 497 // checkCipherSuite returns an error if suite is not a supported cipher suite. 498 func checkCipherSuite(suite uint16) error { 499 switch suite { 500 case tls.TLS_AES_128_GCM_SHA256: 501 case tls.TLS_AES_256_GCM_SHA384: 502 case tls.TLS_CHACHA20_POLY1305_SHA256: 503 default: 504 return errors.New("invalid cipher suite") 505 } 506 return nil 507 } 508 509 func hashForSuite(suite uint16) (h crypto.Hash, keySize int) { 510 switch suite { 511 case tls.TLS_AES_128_GCM_SHA256: 512 return crypto.SHA256, 128 / 8 513 case tls.TLS_AES_256_GCM_SHA384: 514 return crypto.SHA384, 256 / 8 515 case tls.TLS_CHACHA20_POLY1305_SHA256: 516 return crypto.SHA256, chacha20.KeySize 517 default: 518 panic("BUG: unknown cipher suite") 519 } 520 } 521 522 // hdkfExpandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. 523 // 524 // Copied from crypto/tls/key_schedule.go. 525 func hkdfExpandLabel(hash func() hash.Hash, secret []byte, label string, context []byte, length int) []byte { 526 var hkdfLabel cryptobyte.Builder 527 hkdfLabel.AddUint16(uint16(length)) 528 hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { 529 b.AddBytes([]byte("tls13 ")) 530 b.AddBytes([]byte(label)) 531 }) 532 hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { 533 b.AddBytes(context) 534 }) 535 out := make([]byte, length) 536 n, err := hkdf.Expand(hash, secret, hkdfLabel.BytesOrPanic()).Read(out) 537 if err != nil || n != length { 538 panic("quic: HKDF-Expand-Label invocation failed unexpectedly") 539 } 540 return out 541 }