crypto: Return error when same slice is used

This commit is contained in:
Alexander Neumann 2015-04-19 14:06:55 +02:00
parent 8e867817a5
commit 61d1f6ad18
2 changed files with 33 additions and 1 deletions

View file

@ -204,13 +204,23 @@ func (k *EncryptionKey) UnmarshalJSON(data []byte) error {
return nil
}
// ErrInvalidCiphertext is returned when trying to encrypt into the slice that
// holds the plaintext.
var ErrInvalidCiphertext = errors.New("invalid ciphertext, same slice used for plaintext")
// Encrypt encrypts and signs data. Stored in ciphertext is IV || Ciphertext ||
// MAC. Encrypt returns the new ciphertext slice, which is extended when
// necessary. ciphertext and plaintext may not point to (exactly) the same
// slice or non-intersecting slices.
func Encrypt(ks *Key, ciphertext, plaintext []byte) ([]byte, error) {
// extend ciphertext slice if necessary
ciphertext = ciphertext[:cap(ciphertext)]
// test for same slice, if possible
if len(plaintext) > 0 && len(ciphertext) > 0 && &plaintext[0] == &ciphertext[0] {
return nil, ErrInvalidCiphertext
}
// extend ciphertext slice if necessary
if len(ciphertext) < len(plaintext)+Extension {
ext := len(plaintext) + Extension - cap(ciphertext)
ciphertext = append(ciphertext, make([]byte, ext)...)

View file

@ -95,6 +95,28 @@ func TestSameBuffer(t *testing.T) {
"wrong plaintext returned")
}
func TestCornerCases(t *testing.T) {
k := crypto.NewKey()
// nil plaintext should encrypt to the empty string
// nil ciphertext should allocate a new slice for the ciphertext
c, err := crypto.Encrypt(k, nil, nil)
OK(t, err)
Assert(t, len(c) == crypto.Extension,
"wrong length returned for ciphertext, expected 0, got %d",
len(c))
// this should decrypt to an empty slice
p, err := crypto.Decrypt(k, nil, c)
OK(t, err)
Equals(t, []byte{}, p)
// test encryption for same slice, this should return an error
_, err = crypto.Encrypt(k, c, c)
Equals(t, crypto.ErrInvalidCiphertext, err)
}
func TestLargeEncrypt(t *testing.T) {
if !*testLargeCrypto {
t.SkipNow()