github.com/MerlinKodo/quic-go@v0.39.2/internal/handshake/aead.go (about)

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