forked from quic-go/quic-go
115 lines
3.9 KiB
Go
115 lines
3.9 KiB
Go
package handshake
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/quic-go/quic-go/internal/protocol"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func getSealerAndOpener(t *testing.T, cs *cipherSuite, v protocol.Version) (LongHeaderSealer, LongHeaderOpener) {
|
|
t.Helper()
|
|
key := make([]byte, 16)
|
|
hpKey := make([]byte, 16)
|
|
rand.Read(key)
|
|
rand.Read(hpKey)
|
|
block, err := aes.NewCipher(key)
|
|
require.NoError(t, err)
|
|
aead, err := cipher.NewGCM(block)
|
|
require.NoError(t, err)
|
|
|
|
return newLongHeaderSealer(&xorNonceAEAD{aead: aead}, newHeaderProtector(cs, hpKey, true, v)),
|
|
newLongHeaderOpener(&xorNonceAEAD{aead: aead}, newHeaderProtector(cs, hpKey, true, v))
|
|
}
|
|
|
|
func TestEncryptAndDecryptMessage(t *testing.T) {
|
|
for _, v := range []protocol.Version{protocol.Version1, protocol.Version2} {
|
|
for _, cs := range cipherSuites {
|
|
t.Run(fmt.Sprintf("QUIC %s/%s", v, tls.CipherSuiteName(cs.ID)), func(t *testing.T) {
|
|
sealer, opener := getSealerAndOpener(t, cs, v)
|
|
msg := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
|
|
ad := []byte("Donec in velit neque.")
|
|
|
|
encrypted := sealer.Seal(nil, msg, 0x1337, ad)
|
|
|
|
opened, err := opener.Open(nil, encrypted, 0x1337, ad)
|
|
require.NoError(t, err)
|
|
require.Equal(t, msg, opened)
|
|
|
|
// incorrect associated data
|
|
_, err = opener.Open(nil, encrypted, 0x1337, []byte("wrong ad"))
|
|
require.Equal(t, ErrDecryptionFailed, err)
|
|
|
|
// incorrect packet number
|
|
_, err = opener.Open(nil, encrypted, 0x42, ad)
|
|
require.Equal(t, ErrDecryptionFailed, err)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDecodePacketNumber(t *testing.T) {
|
|
msg := []byte("Lorem ipsum dolor sit amet")
|
|
ad := []byte("Donec in velit neque.")
|
|
|
|
sealer, opener := getSealerAndOpener(t, getCipherSuite(tls.TLS_AES_128_GCM_SHA256), protocol.Version1)
|
|
encrypted := sealer.Seal(nil, msg, 0x1337, ad)
|
|
|
|
// can't decode the packet number if encryption failed
|
|
_, err := opener.Open(nil, encrypted[:len(encrypted)-1], 0x1337, ad)
|
|
require.Error(t, err)
|
|
require.Equal(t, protocol.PacketNumber(0x38), opener.DecodePacketNumber(0x38, protocol.PacketNumberLen1))
|
|
|
|
_, err = opener.Open(nil, encrypted, 0x1337, ad)
|
|
require.NoError(t, err)
|
|
require.Equal(t, protocol.PacketNumber(0x1338), opener.DecodePacketNumber(0x38, protocol.PacketNumberLen1))
|
|
}
|
|
|
|
func TestEncryptAndDecryptHeader(t *testing.T) {
|
|
for _, v := range []protocol.Version{protocol.Version1, protocol.Version2} {
|
|
t.Run("QUIC "+v.String(), func(t *testing.T) {
|
|
for _, cs := range cipherSuites {
|
|
t.Run(tls.CipherSuiteName(cs.ID), func(t *testing.T) {
|
|
testEncryptAndDecryptHeader(t, cs, v)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func testEncryptAndDecryptHeader(t *testing.T, cs *cipherSuite, v protocol.Version) {
|
|
sealer, opener := getSealerAndOpener(t, cs, v)
|
|
var lastFourBitsDifferent int
|
|
|
|
for i := 0; i < 100; i++ {
|
|
sample := make([]byte, 16)
|
|
rand.Read(sample)
|
|
header := []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}
|
|
sealer.EncryptHeader(sample, &header[0], header[9:13])
|
|
if header[0]&0xf != 0xb5&0xf {
|
|
lastFourBitsDifferent++
|
|
}
|
|
require.Equal(t, byte(0xb5&0xf0), header[0]&0xf0)
|
|
require.Equal(t, []byte{1, 2, 3, 4, 5, 6, 7, 8}, header[1:9])
|
|
require.NotEqual(t, []byte{0xde, 0xad, 0xbe, 0xef}, header[9:13])
|
|
opener.DecryptHeader(sample, &header[0], header[9:13])
|
|
require.Equal(t, []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}, header)
|
|
}
|
|
require.Greater(t, lastFourBitsDifferent, 75)
|
|
|
|
// decryption failure with different sample
|
|
header := []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}
|
|
sample := make([]byte, 16)
|
|
rand.Read(sample)
|
|
sealer.EncryptHeader(sample, &header[0], header[9:13])
|
|
rand.Read(sample) // use a different sample
|
|
opener.DecryptHeader(sample, &header[0], header[9:13])
|
|
require.NotEqual(t, []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}, header)
|
|
}
|