From a815dfbd5d796224455718143db708535dfe27fc Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Tue, 9 Jan 2024 12:00:23 -0600 Subject: [PATCH] Fix TLS 1.3 additionalData length check --- aes_test.go | 28 ++++++++++++++++++++-------- cipher.go | 15 ++++++++++++--- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/aes_test.go b/aes_test.go index 142ac878..71162e87 100644 --- a/aes_test.go +++ b/aes_test.go @@ -155,12 +155,12 @@ func TestSealAndOpenTLS(t *testing.T) { key := []byte("D249BF6DEC97B1EBD69BC4D6B3A3C49D") tests := []struct { name string - new func(c cipher.Block) (cipher.AEAD, error) + tls string mask func(n *[12]byte) }{ - {"1.2", openssl.NewGCMTLS, nil}, - {"1.3", openssl.NewGCMTLS13, nil}, - {"1.3_masked", openssl.NewGCMTLS13, func(n *[12]byte) { + {"1.2", "1.2", nil}, + {"1.3", "1.3", nil}, + {"1.3_masked", "1.3", func(n *[12]byte) { // Arbitrary mask in the high bits. n[9] ^= 0x42 // Mask the very first bit. This makes sure that if Seal doesn't @@ -175,7 +175,13 @@ func TestSealAndOpenTLS(t *testing.T) { if err != nil { t.Fatal(err) } - gcm, err := tt.new(ci) + var gcm cipher.AEAD + switch tt.tls { + case "1.2": + gcm, err = openssl.NewGCMTLS(ci) + case "1.3": + gcm, err = openssl.NewGCMTLS13(ci) + } if err != nil { t.Fatal(err) } @@ -190,9 +196,15 @@ func TestSealAndOpenTLS(t *testing.T) { } } plainText := []byte{0x01, 0x02, 0x03} - additionalData := make([]byte, 13) - additionalData[11] = byte(len(plainText) >> 8) - additionalData[12] = byte(len(plainText)) + var additionalData []byte + switch tt.tls { + case "1.2": + additionalData = make([]byte, 13) + case "1.3": + additionalData = []byte{23, 3, 3, 0, 0} + } + additionalData[len(additionalData)-2] = byte(len(plainText) >> 8) + additionalData[len(additionalData)-1] = byte(len(plainText)) sealed := gcm.Seal(nil, nonce[:], plainText, additionalData) assertPanic(t, func() { gcm.Seal(nil, nonce[:], plainText, additionalData) diff --git a/cipher.go b/cipher.go index 1113d067..ddaadfa8 100644 --- a/cipher.go +++ b/cipher.go @@ -337,7 +337,14 @@ type cipherGCM struct { const ( gcmTagSize = 16 gcmStandardNonceSize = 12 - gcmTlsAddSize = 13 + // TLS 1.2 additional data is constructed as: + // + // additional_data = seq_num(8) + TLSCompressed.type(1) + TLSCompressed.version(2) + TLSCompressed.length(2); + gcmTls12AddSize = 13 + // TLS 1.3 additional data is constructed as: + // + // additional_data = TLSCiphertext.opaque_type(1) || TLSCiphertext.legacy_record_version(2) || TLSCiphertext.length(2) + gcmTls13AddSize = 5 gcmTlsFixedNonceSize = 4 ) @@ -404,8 +411,10 @@ func (g *cipherGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte { panic("cipher: message too large for buffer") } if g.tls != cipherGCMTLSNone { - if len(additionalData) != gcmTlsAddSize { - panic("cipher: incorrect additional data length given to GCM TLS") + if g.tls == cipherGCMTLS12 && len(additionalData) != gcmTls12AddSize { + panic("cipher: incorrect additional data length given to GCM TLS 1.2") + } else if g.tls == cipherGCMTLS13 && len(additionalData) != gcmTls13AddSize { + panic("cipher: incorrect additional data length given to GCM TLS 1.3") } counter := binary.BigEndian.Uint64(nonce[gcmTlsFixedNonceSize:]) if g.tls == cipherGCMTLS13 {