github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/internal/handshake/aead.go (about)

     1  package handshake
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	"github.com/apernet/quic-go/internal/protocol"
     7  )
     8  
     9  func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.Version) *xorNonceAEAD {
    10  	keyLabel := hkdfLabelKeyV1
    11  	ivLabel := hkdfLabelIVV1
    12  	if v == protocol.Version2 {
    13  		keyLabel = hkdfLabelKeyV2
    14  		ivLabel = hkdfLabelIVV2
    15  	}
    16  	key := hkdfExpandLabel(suite.Hash, trafficSecret, []byte{}, keyLabel, suite.KeyLen)
    17  	iv := hkdfExpandLabel(suite.Hash, trafficSecret, []byte{}, ivLabel, suite.IVLen())
    18  	return suite.AEAD(key, iv)
    19  }
    20  
    21  type longHeaderSealer struct {
    22  	aead            *xorNonceAEAD
    23  	headerProtector headerProtector
    24  	nonceBuf        [8]byte
    25  }
    26  
    27  var _ LongHeaderSealer = &longHeaderSealer{}
    28  
    29  func newLongHeaderSealer(aead *xorNonceAEAD, headerProtector headerProtector) LongHeaderSealer {
    30  	if aead.NonceSize() != 8 {
    31  		panic("unexpected nonce size")
    32  	}
    33  	return &longHeaderSealer{
    34  		aead:            aead,
    35  		headerProtector: headerProtector,
    36  	}
    37  }
    38  
    39  func (s *longHeaderSealer) Seal(dst, src []byte, pn protocol.PacketNumber, ad []byte) []byte {
    40  	binary.BigEndian.PutUint64(s.nonceBuf[:], uint64(pn))
    41  	return s.aead.Seal(dst, s.nonceBuf[:], src, ad)
    42  }
    43  
    44  func (s *longHeaderSealer) EncryptHeader(sample []byte, firstByte *byte, pnBytes []byte) {
    45  	s.headerProtector.EncryptHeader(sample, firstByte, pnBytes)
    46  }
    47  
    48  func (s *longHeaderSealer) Overhead() int {
    49  	return s.aead.Overhead()
    50  }
    51  
    52  type longHeaderOpener struct {
    53  	aead            *xorNonceAEAD
    54  	headerProtector headerProtector
    55  	highestRcvdPN   protocol.PacketNumber // highest packet number received (which could be successfully unprotected)
    56  
    57  	// use a single array to avoid allocations
    58  	nonceBuf [8]byte
    59  }
    60  
    61  var _ LongHeaderOpener = &longHeaderOpener{}
    62  
    63  func newLongHeaderOpener(aead *xorNonceAEAD, headerProtector headerProtector) LongHeaderOpener {
    64  	if aead.NonceSize() != 8 {
    65  		panic("unexpected nonce size")
    66  	}
    67  	return &longHeaderOpener{
    68  		aead:            aead,
    69  		headerProtector: headerProtector,
    70  	}
    71  }
    72  
    73  func (o *longHeaderOpener) DecodePacketNumber(wirePN protocol.PacketNumber, wirePNLen protocol.PacketNumberLen) protocol.PacketNumber {
    74  	return protocol.DecodePacketNumber(wirePNLen, o.highestRcvdPN, wirePN)
    75  }
    76  
    77  func (o *longHeaderOpener) Open(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error) {
    78  	binary.BigEndian.PutUint64(o.nonceBuf[:], uint64(pn))
    79  	dec, err := o.aead.Open(dst, o.nonceBuf[:], src, ad)
    80  	if err == nil {
    81  		o.highestRcvdPN = max(o.highestRcvdPN, pn)
    82  	} else {
    83  		err = ErrDecryptionFailed
    84  	}
    85  	return dec, err
    86  }
    87  
    88  func (o *longHeaderOpener) DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte) {
    89  	o.headerProtector.DecryptHeader(sample, firstByte, pnBytes)
    90  }