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 }