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  }