Skip to content

Commit 89ba9e3

Browse files
committed
[dev.boringcrypto] crypto/aes: panic on invalid dst, src overlap
I've now debugged multiple mysterious "inability to communicate" bugs that manifest as a silent unexplained authentication failure but are really crypto.AEAD.Open being invoked with badly aligned buffers. In #21624 I suggested using a panic as the consequence of bad alignment, so that this kind of failure is loud and clearly different from, say, a corrupted or invalid message signature. Adding the panic here made my failure very easy to track down, once I realized that was the problem. I don't want to debug another one of these. Also using this CL as an experiment to get data about the impact of maybe applying this change more broadly in the master branch. Change-Id: Id2e2d8e980439f8acacac985fc2674f7c96c5032 Reviewed-on: https://go-review.googlesource.com/63915 Reviewed-by: Adam Langley <[email protected]>
1 parent a929f3a commit 89ba9e3

File tree

1 file changed

+35
-0
lines changed
  • src/crypto/internal/boring

1 file changed

+35
-0
lines changed

src/crypto/internal/boring/aes.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ func NewAESCipher(key []byte) (cipher.Block, error) {
5959
func (c *aesCipher) BlockSize() int { return aesBlockSize }
6060

6161
func (c *aesCipher) Encrypt(dst, src []byte) {
62+
if inexactOverlap(dst, src) {
63+
panic("crypto/cipher: invalid buffer overlap")
64+
}
6265
if len(src) < aesBlockSize {
6366
panic("crypto/aes: input not full block")
6467
}
@@ -72,6 +75,9 @@ func (c *aesCipher) Encrypt(dst, src []byte) {
7275
}
7376

7477
func (c *aesCipher) Decrypt(dst, src []byte) {
78+
if inexactOverlap(dst, src) {
79+
panic("crypto/cipher: invalid buffer overlap")
80+
}
7581
if len(src) < aesBlockSize {
7682
panic("crypto/aes: input not full block")
7783
}
@@ -93,6 +99,9 @@ type aesCBC struct {
9399
func (x *aesCBC) BlockSize() int { return aesBlockSize }
94100

95101
func (x *aesCBC) CryptBlocks(dst, src []byte) {
102+
if inexactOverlap(dst, src) {
103+
panic("crypto/cipher: invalid buffer overlap")
104+
}
96105
if len(src)%aesBlockSize != 0 {
97106
panic("crypto/cipher: input not full blocks")
98107
}
@@ -135,6 +144,9 @@ type aesCTR struct {
135144
}
136145

137146
func (x *aesCTR) XORKeyStream(dst, src []byte) {
147+
if inexactOverlap(dst, src) {
148+
panic("crypto/cipher: invalid buffer overlap")
149+
}
138150
if len(dst) < len(src) {
139151
panic("crypto/cipher: output smaller than input")
140152
}
@@ -262,6 +274,11 @@ func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
262274
}
263275
dst = dst[:n+len(plaintext)+gcmTagSize]
264276

277+
// Check delayed until now to make sure len(dst) is accurate.
278+
if inexactOverlap(dst[n:], plaintext) {
279+
panic("cipher: invalid buffer overlap")
280+
}
281+
265282
var outLen C.size_t
266283
ok := C._goboringcrypto_EVP_AEAD_CTX_seal(
267284
&g.ctx,
@@ -298,6 +315,11 @@ func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, er
298315
}
299316
dst = dst[:n+len(ciphertext)-gcmTagSize]
300317

318+
// Check delayed until now to make sure len(dst) is accurate.
319+
if inexactOverlap(dst[n:], ciphertext) {
320+
panic("cipher: invalid buffer overlap")
321+
}
322+
301323
var outLen C.size_t
302324
ok := C._goboringcrypto_EVP_AEAD_CTX_open(
303325
&g.ctx,
@@ -313,3 +335,16 @@ func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, er
313335
}
314336
return dst[:n+int(outLen)], nil
315337
}
338+
339+
func anyOverlap(x, y []byte) bool {
340+
return len(x) > 0 && len(y) > 0 &&
341+
uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
342+
uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
343+
}
344+
345+
func inexactOverlap(x, y []byte) bool {
346+
if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
347+
return false
348+
}
349+
return anyOverlap(x, y)
350+
}

0 commit comments

Comments
 (0)