From 5f92ea446c66e8fbc20b4180f841610902d22811 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Fri, 13 Oct 2023 10:46:34 +0200 Subject: [PATCH 1/2] panic if rc4 xor'ed buffer doesn't fit into output buffer --- rc4.go | 3 +++ rc4_test.go | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/rc4.go b/rc4.go index db28b61f..94a96b20 100644 --- a/rc4.go +++ b/rc4.go @@ -52,6 +52,9 @@ func (c *RC4Cipher) XORKeyStream(dst, src []byte) { if inexactOverlap(dst[:len(src)], src) { panic("crypto/rc4: invalid buffer overlap") } + // panic if len(dst) < len(src) with a runtime out of bound error, + // which is what crypto/rc4 does. + _ = dst[len(src)-1] var outLen C.int if C.go_openssl_EVP_EncryptUpdate(c.ctx, base(dst), &outLen, base(src), C.int(len(src))) != 1 { panic("crypto/cipher: EncryptUpdate failed") diff --git a/rc4_test.go b/rc4_test.go index e9f8dca9..6c9e471c 100644 --- a/rc4_test.go +++ b/rc4_test.go @@ -138,6 +138,29 @@ func TestRC4Block(t *testing.T) { } } +func TestRC4OutOfBoundsWrite(t *testing.T) { + // This cipherText is encrypted "0123456789" + cipherText := []byte{238, 41, 187, 114, 151, 2, 107, 13, 178, 63} + cipher, err := openssl.NewRC4Cipher([]byte{0}) + if err != nil { + panic(err) + } + want := "abcdefghij" + plainText := []byte(want) + shorterLen := len(cipherText) / 2 + defer func() { + err := recover() + if err == nil { + t.Error("XORKeyStream expected to panic on len(dst) < len(src), but didn't") + } + const plain = "0123456789" + if plainText[shorterLen] == plain[shorterLen] { + t.Errorf("XORKeyStream did out of bounds write, want %v, got %v", want, string(plainText)) + } + }() + cipher.XORKeyStream(plainText[:shorterLen], cipherText) +} + func benchmarkRC4(b *testing.B, size int64) { if !openssl.SupportsRC4() { b.Skip("RC4 is not supported") From 688e6bee01d61d30d0153de598fbd2ab37400a3c Mon Sep 17 00:00:00 2001 From: qmuntal Date: Fri, 13 Oct 2023 10:49:36 +0200 Subject: [PATCH 2/2] fix rc4 test --- rc4_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rc4_test.go b/rc4_test.go index 6c9e471c..8182947b 100644 --- a/rc4_test.go +++ b/rc4_test.go @@ -139,6 +139,9 @@ func TestRC4Block(t *testing.T) { } func TestRC4OutOfBoundsWrite(t *testing.T) { + if !openssl.SupportsRC4() { + t.Skip("RC4 is not supported") + } // This cipherText is encrypted "0123456789" cipherText := []byte{238, 41, 187, 114, 151, 2, 107, 13, 178, 63} cipher, err := openssl.NewRC4Cipher([]byte{0})