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

     1  package handshake
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"crypto/rand"
     8  	"crypto/tls"
     9  	"fmt"
    10  
    11  	"github.com/MerlinKodo/quic-go/internal/protocol"
    12  
    13  	. "github.com/onsi/ginkgo/v2"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("Long Header AEAD", func() {
    18  	for _, ver := range []protocol.VersionNumber{protocol.Version1, protocol.Version2} {
    19  		v := ver
    20  
    21  		Context(fmt.Sprintf("using version %s", v), func() {
    22  			for i := range cipherSuites {
    23  				cs := cipherSuites[i]
    24  
    25  				Context(fmt.Sprintf("using %s", tls.CipherSuiteName(cs.ID)), func() {
    26  					getSealerAndOpener := func() (LongHeaderSealer, LongHeaderOpener) {
    27  						key := make([]byte, 16)
    28  						hpKey := make([]byte, 16)
    29  						rand.Read(key)
    30  						rand.Read(hpKey)
    31  						block, err := aes.NewCipher(key)
    32  						Expect(err).ToNot(HaveOccurred())
    33  						aead, err := cipher.NewGCM(block)
    34  						Expect(err).ToNot(HaveOccurred())
    35  
    36  						return newLongHeaderSealer(aead, newHeaderProtector(cs, hpKey, true, v)),
    37  							newLongHeaderOpener(aead, newHeaderProtector(cs, hpKey, true, v))
    38  					}
    39  
    40  					Context("message encryption", func() {
    41  						msg := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
    42  						ad := []byte("Donec in velit neque.")
    43  
    44  						It("encrypts and decrypts a message", func() {
    45  							sealer, opener := getSealerAndOpener()
    46  							encrypted := sealer.Seal(nil, msg, 0x1337, ad)
    47  							opened, err := opener.Open(nil, encrypted, 0x1337, ad)
    48  							Expect(err).ToNot(HaveOccurred())
    49  							Expect(opened).To(Equal(msg))
    50  						})
    51  
    52  						It("fails to open a message if the associated data is not the same", func() {
    53  							sealer, opener := getSealerAndOpener()
    54  							encrypted := sealer.Seal(nil, msg, 0x1337, ad)
    55  							_, err := opener.Open(nil, encrypted, 0x1337, []byte("wrong ad"))
    56  							Expect(err).To(MatchError(ErrDecryptionFailed))
    57  						})
    58  
    59  						It("fails to open a message if the packet number is not the same", func() {
    60  							sealer, opener := getSealerAndOpener()
    61  							encrypted := sealer.Seal(nil, msg, 0x1337, ad)
    62  							_, err := opener.Open(nil, encrypted, 0x42, ad)
    63  							Expect(err).To(MatchError(ErrDecryptionFailed))
    64  						})
    65  
    66  						It("decodes the packet number", func() {
    67  							sealer, opener := getSealerAndOpener()
    68  							encrypted := sealer.Seal(nil, msg, 0x1337, ad)
    69  							_, err := opener.Open(nil, encrypted, 0x1337, ad)
    70  							Expect(err).ToNot(HaveOccurred())
    71  							Expect(opener.DecodePacketNumber(0x38, protocol.PacketNumberLen1)).To(BeEquivalentTo(0x1338))
    72  						})
    73  
    74  						It("ignores packets it can't decrypt for packet number derivation", func() {
    75  							sealer, opener := getSealerAndOpener()
    76  							encrypted := sealer.Seal(nil, msg, 0x1337, ad)
    77  							_, err := opener.Open(nil, encrypted[:len(encrypted)-1], 0x1337, ad)
    78  							Expect(err).To(HaveOccurred())
    79  							Expect(opener.DecodePacketNumber(0x38, protocol.PacketNumberLen1)).To(BeEquivalentTo(0x38))
    80  						})
    81  					})
    82  
    83  					Context("header encryption", func() {
    84  						It("encrypts and encrypts the header", func() {
    85  							sealer, opener := getSealerAndOpener()
    86  							var lastFourBitsDifferent int
    87  							for i := 0; i < 100; i++ {
    88  								sample := make([]byte, 16)
    89  								rand.Read(sample)
    90  								header := []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}
    91  								sealer.EncryptHeader(sample, &header[0], header[9:13])
    92  								if header[0]&0xf != 0xb5&0xf {
    93  									lastFourBitsDifferent++
    94  								}
    95  								Expect(header[0] & 0xf0).To(Equal(byte(0xb5 & 0xf0)))
    96  								Expect(header[1:9]).To(Equal([]byte{1, 2, 3, 4, 5, 6, 7, 8}))
    97  								Expect(header[9:13]).ToNot(Equal([]byte{0xde, 0xad, 0xbe, 0xef}))
    98  								opener.DecryptHeader(sample, &header[0], header[9:13])
    99  								Expect(header).To(Equal([]byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}))
   100  							}
   101  							Expect(lastFourBitsDifferent).To(BeNumerically(">", 75))
   102  						})
   103  
   104  						It("encrypts and encrypts the header, for a 0xfff..fff sample", func() {
   105  							sealer, opener := getSealerAndOpener()
   106  							var lastFourBitsDifferent int
   107  							for i := 0; i < 100; i++ {
   108  								sample := bytes.Repeat([]byte{0xff}, 16)
   109  								header := []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}
   110  								sealer.EncryptHeader(sample, &header[0], header[9:13])
   111  								if header[0]&0xf != 0xb5&0xf {
   112  									lastFourBitsDifferent++
   113  								}
   114  								Expect(header[0] & 0xf0).To(Equal(byte(0xb5 & 0xf0)))
   115  								Expect(header[1:9]).To(Equal([]byte{1, 2, 3, 4, 5, 6, 7, 8}))
   116  								Expect(header[9:13]).ToNot(Equal([]byte{0xde, 0xad, 0xbe, 0xef}))
   117  								opener.DecryptHeader(sample, &header[0], header[9:13])
   118  								Expect(header).To(Equal([]byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}))
   119  							}
   120  						})
   121  
   122  						It("fails to decrypt the header when using a different sample", func() {
   123  							sealer, opener := getSealerAndOpener()
   124  							header := []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}
   125  							sample := make([]byte, 16)
   126  							rand.Read(sample)
   127  							sealer.EncryptHeader(sample, &header[0], header[9:13])
   128  							rand.Read(sample) // use a different sample
   129  							opener.DecryptHeader(sample, &header[0], header[9:13])
   130  							Expect(header).ToNot(Equal([]byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}))
   131  						})
   132  					})
   133  				})
   134  			}
   135  		})
   136  	}
   137  })