stupidgcm: allow zero-length input data
We used to panic in this case because it is useless. But Go stdlib supports it, so we should as well.
This commit is contained in:
parent
738d5a2b3a
commit
3a80db953d
@ -19,6 +19,8 @@ func testCiphers(t *testing.T, our cipher.AEAD, ref cipher.AEAD) {
|
|||||||
t.Run("testCorruption_c1", func(t *testing.T) { testCorruption(t, our) })
|
t.Run("testCorruption_c1", func(t *testing.T) { testCorruption(t, our) })
|
||||||
t.Run("testCorruption_c2", func(t *testing.T) { testCorruption(t, ref) })
|
t.Run("testCorruption_c2", func(t *testing.T) { testCorruption(t, ref) })
|
||||||
t.Run("testConcurrency", func(t *testing.T) { testConcurrency(t, our, ref) })
|
t.Run("testConcurrency", func(t *testing.T) { testConcurrency(t, our, ref) })
|
||||||
|
t.Run("testOpenAllZero_our", func(t *testing.T) { testOpenAllZero(t, our) })
|
||||||
|
t.Run("testOpenAllZero_ref", func(t *testing.T) { testOpenAllZero(t, ref) })
|
||||||
t.Run("testWipe", func(t *testing.T) { testWipe(t, our) })
|
t.Run("testWipe", func(t *testing.T) { testWipe(t, our) })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +39,13 @@ func testEncryptDecrypt(t *testing.T, c1 cipher.AEAD, c2 cipher.AEAD) {
|
|||||||
|
|
||||||
dst := make([]byte, 71) // 71 = arbitrary length
|
dst := make([]byte, 71) // 71 = arbitrary length
|
||||||
|
|
||||||
// Check all block sizes from 1 to 5000
|
// Check all block sizes from nil to 0 to 5000
|
||||||
for i := 1; i < 5000; i++ {
|
for i := -1; i < 5000; i++ {
|
||||||
in := make([]byte, i)
|
// stays nil at i == -1
|
||||||
|
var in []byte
|
||||||
|
if i >= 0 {
|
||||||
|
in = make([]byte, i)
|
||||||
|
}
|
||||||
|
|
||||||
c1out := c1.Seal(dst, iv, in, authData)
|
c1out := c1.Seal(dst, iv, in, authData)
|
||||||
c2out := c2.Seal(dst, iv, in, authData)
|
c2out := c2.Seal(dst, iv, in, authData)
|
||||||
@ -79,8 +85,8 @@ func testConcurrency(t *testing.T, c1 cipher.AEAD, c2 cipher.AEAD) {
|
|||||||
for i := 0; i < goroutineCount; i++ {
|
for i := 0; i < goroutineCount; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
testEncryptDecrypt(t, c1, c2)
|
testEncryptDecrypt(t, c1, c2)
|
||||||
wg.Done()
|
|
||||||
}()
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
@ -96,8 +102,9 @@ func testInplaceSeal(t *testing.T, c1 cipher.AEAD, c2 cipher.AEAD) {
|
|||||||
iv := randBytes(c1.NonceSize())
|
iv := randBytes(c1.NonceSize())
|
||||||
|
|
||||||
max := 5016
|
max := 5016
|
||||||
// Check all block sizes from 1 to 5000
|
|
||||||
for i := 1; i < max-16; i++ {
|
// Check all block sizes from 0 to 5000
|
||||||
|
for i := 0; i < max-16; i++ {
|
||||||
in := make([]byte, i)
|
in := make([]byte, i)
|
||||||
dst := make([]byte, max-i)
|
dst := make([]byte, max-i)
|
||||||
dst = dst[:16]
|
dst = dst[:16]
|
||||||
@ -185,6 +192,27 @@ func testCorruption(t *testing.T, c cipher.AEAD) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testOpenAllZero tests that we do not crash for nil or any block size of zeros
|
||||||
|
func testOpenAllZero(t *testing.T, c cipher.AEAD) {
|
||||||
|
authData := make([]byte, 24)
|
||||||
|
iv := make([]byte, c.NonceSize())
|
||||||
|
|
||||||
|
for i := -1; i < 5000; i++ {
|
||||||
|
// stays nil at i == -1
|
||||||
|
var cipher []byte
|
||||||
|
if i >= 0 {
|
||||||
|
cipher = make([]byte, i)
|
||||||
|
}
|
||||||
|
plain, err := c.Open(nil, iv, cipher, authData)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("should have gotten error, but did not")
|
||||||
|
}
|
||||||
|
if len(plain) > 0 {
|
||||||
|
t.Errorf("should not have received data, but got %d bytes", len(plain))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testWipe(t *testing.T, c cipher.AEAD) {
|
func testWipe(t *testing.T, c cipher.AEAD) {
|
||||||
switch c2 := c.(type) {
|
switch c2 := c.(type) {
|
||||||
case *StupidGCM:
|
case *StupidGCM:
|
||||||
|
@ -20,9 +20,6 @@ func openSSLSeal(a *stupidAEADCommon, dst, iv, in, authData []byte) []byte {
|
|||||||
if len(iv) != a.NonceSize() {
|
if len(iv) != a.NonceSize() {
|
||||||
log.Panicf("Only %d-byte IVs are supported, you passed %d bytes", a.NonceSize(), len(iv))
|
log.Panicf("Only %d-byte IVs are supported, you passed %d bytes", a.NonceSize(), len(iv))
|
||||||
}
|
}
|
||||||
if len(in) == 0 {
|
|
||||||
log.Panic("Zero-length input data is not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the "dst" slice is large enough we can use it as our output buffer
|
// If the "dst" slice is large enough we can use it as our output buffer
|
||||||
outLen := len(in) + tagLen
|
outLen := len(in) + tagLen
|
||||||
@ -36,7 +33,7 @@ func openSSLSeal(a *stupidAEADCommon, dst, iv, in, authData []byte) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := int(C.openssl_aead_seal(a.openSSLEVPCipher,
|
res := int(C.openssl_aead_seal(a.openSSLEVPCipher,
|
||||||
(*C.uchar)(&in[0]),
|
slicePointerOrNull(in),
|
||||||
C.int(len(in)),
|
C.int(len(in)),
|
||||||
(*C.uchar)(&authData[0]),
|
(*C.uchar)(&authData[0]),
|
||||||
C.int(len(authData)),
|
C.int(len(authData)),
|
||||||
@ -64,7 +61,7 @@ func openSSLOpen(a *stupidAEADCommon, dst, iv, in, authData []byte) ([]byte, err
|
|||||||
if len(iv) != a.NonceSize() {
|
if len(iv) != a.NonceSize() {
|
||||||
log.Panicf("Only %d-byte IVs are supported, you passed %d bytes", a.NonceSize(), len(iv))
|
log.Panicf("Only %d-byte IVs are supported, you passed %d bytes", a.NonceSize(), len(iv))
|
||||||
}
|
}
|
||||||
if len(in) <= tagLen {
|
if len(in) < tagLen {
|
||||||
return nil, fmt.Errorf("stupidChacha20poly1305: input data too short (%d bytes)", len(in))
|
return nil, fmt.Errorf("stupidChacha20poly1305: input data too short (%d bytes)", len(in))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +80,7 @@ func openSSLOpen(a *stupidAEADCommon, dst, iv, in, authData []byte) ([]byte, err
|
|||||||
tag := in[len(in)-tagLen:]
|
tag := in[len(in)-tagLen:]
|
||||||
|
|
||||||
res := int(C.openssl_aead_open(a.openSSLEVPCipher,
|
res := int(C.openssl_aead_open(a.openSSLEVPCipher,
|
||||||
(*C.uchar)(&ciphertext[0]),
|
slicePointerOrNull(ciphertext),
|
||||||
C.int(len(ciphertext)),
|
C.int(len(ciphertext)),
|
||||||
(*C.uchar)(&authData[0]),
|
(*C.uchar)(&authData[0]),
|
||||||
C.int(len(authData)),
|
C.int(len(authData)),
|
||||||
@ -93,7 +90,7 @@ func openSSLOpen(a *stupidAEADCommon, dst, iv, in, authData []byte) ([]byte, err
|
|||||||
C.int(len(a.key)),
|
C.int(len(a.key)),
|
||||||
(*C.uchar)(&iv[0]),
|
(*C.uchar)(&iv[0]),
|
||||||
C.int(len(iv)),
|
C.int(len(iv)),
|
||||||
(*C.uchar)(&buf[0]),
|
slicePointerOrNull(buf),
|
||||||
C.int(len(buf))))
|
C.int(len(buf))))
|
||||||
|
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
@ -109,6 +106,16 @@ func openSSLOpen(a *stupidAEADCommon, dst, iv, in, authData []byte) ([]byte, err
|
|||||||
return append(dst, buf...), nil
|
return append(dst, buf...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// slicePointerOrNull returns a C pointer to the beginning of the byte slice,
|
||||||
|
// or NULL if the byte slice is empty. This is useful for slices that can be
|
||||||
|
// empty, otherwise you can directly use "(*C.uchar)(&s[0])".
|
||||||
|
func slicePointerOrNull(s []byte) (ptr *C.uchar) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return (*C.uchar)(&s[0])
|
||||||
|
}
|
||||||
|
|
||||||
// This functions exists to benchmark the C call overhead from Go.
|
// This functions exists to benchmark the C call overhead from Go.
|
||||||
// See BenchmarkCCall for resuts.
|
// See BenchmarkCCall for resuts.
|
||||||
func noopCFunction() {
|
func noopCFunction() {
|
||||||
|
Loading…
Reference in New Issue
Block a user