diff --git a/src/crypto/aes/aes_gcm.go b/src/crypto/aes/aes_gcm.go
index c1cacdb7524d13..13ae2fcb82032b 100644
--- a/src/crypto/aes/aes_gcm.go
+++ b/src/crypto/aes/aes_gcm.go
@@ -8,6 +8,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	subtleoverlap "crypto/internal/subtle"
 	"crypto/subtle"
 	"errors"
 )
@@ -99,10 +100,10 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) {
 // details.
 func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
-		panic("cipher: message too large for GCM")
+		panic("crypto/cipher: message too large for GCM")
 	}
 
 	var counter, tagMask [gcmBlockSize]byte
@@ -123,6 +124,9 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
 	gcmAesData(&g.productTable, data, &tagOut)
 
 	ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+	if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	if len(plaintext) > 0 {
 		gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, g.ks)
 	}
@@ -136,12 +140,12 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
 // for details.
 func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	// Sanity check to prevent the authentication from always succeeding if an implementation
 	// leaves tagSize uninitialized, for example.
 	if g.tagSize < gcmMinimumTagSize {
-		panic("cipher: incorrect GCM tag size")
+		panic("crypto/cipher: incorrect GCM tag size")
 	}
 
 	if len(ciphertext) < g.tagSize {
@@ -173,6 +177,9 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	gcmAesData(&g.productTable, data, &expectedTag)
 
 	ret, out := sliceForAppend(dst, len(ciphertext))
+	if subtleoverlap.InexactOverlap(out, ciphertext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	if len(ciphertext) > 0 {
 		gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, g.ks)
 	}
diff --git a/src/crypto/aes/cbc_s390x.go b/src/crypto/aes/cbc_s390x.go
index 739e1febc310f2..28a6b1d5461570 100644
--- a/src/crypto/aes/cbc_s390x.go
+++ b/src/crypto/aes/cbc_s390x.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 )
 
 // Assert that aesCipherAsm implements the cbcEncAble and cbcDecAble interfaces.
@@ -48,6 +49,9 @@ func (x *cbc) CryptBlocks(dst, src []byte) {
 	if len(dst) < len(src) {
 		panic("crypto/cipher: output smaller than input")
 	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	if len(src) > 0 {
 		cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src))
 	}
diff --git a/src/crypto/aes/cipher.go b/src/crypto/aes/cipher.go
index c5a8e91d009b79..bb93fbb36e289a 100644
--- a/src/crypto/aes/cipher.go
+++ b/src/crypto/aes/cipher.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 	"strconv"
 )
 
@@ -57,6 +58,9 @@ func (c *aesCipher) Encrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	encryptBlockGo(c.enc, dst, src)
 }
 
@@ -67,5 +71,8 @@ func (c *aesCipher) Decrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	decryptBlockGo(c.dec, dst, src)
 }
diff --git a/src/crypto/aes/cipher_amd64.go b/src/crypto/aes/cipher_amd64.go
index 4b3b877cd72b41..b12d9b46a2b760 100644
--- a/src/crypto/aes/cipher_amd64.go
+++ b/src/crypto/aes/cipher_amd64.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 	"internal/cpu"
 )
 
@@ -52,6 +53,9 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0])
 }
 
@@ -62,6 +66,9 @@ func (c *aesCipherAsm) Decrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0])
 }
 
diff --git a/src/crypto/aes/cipher_arm64.go b/src/crypto/aes/cipher_arm64.go
index c8027eec8b4291..a03547841f2682 100644
--- a/src/crypto/aes/cipher_arm64.go
+++ b/src/crypto/aes/cipher_arm64.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 	"internal/cpu"
 	"math/bits"
 )
@@ -40,6 +41,9 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0])
 }
 
@@ -50,6 +54,9 @@ func (c *aesCipherAsm) Decrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0])
 }
 
diff --git a/src/crypto/aes/cipher_ppc64le.go b/src/crypto/aes/cipher_ppc64le.go
index 110f61f57c0d10..b788ea7d475fa9 100644
--- a/src/crypto/aes/cipher_ppc64le.go
+++ b/src/crypto/aes/cipher_ppc64le.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 )
 
 // defined in asm_ppc64le.s
@@ -54,6 +55,9 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	encryptBlockAsm(&dst[0], &src[0], &c.enc[0])
 }
 
@@ -64,6 +68,9 @@ func (c *aesCipherAsm) Decrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	decryptBlockAsm(&dst[0], &src[0], &c.dec[0])
 }
 
diff --git a/src/crypto/aes/cipher_s390x.go b/src/crypto/aes/cipher_s390x.go
index 82f6f8f335c42a..65b6b2fc1b593c 100644
--- a/src/crypto/aes/cipher_s390x.go
+++ b/src/crypto/aes/cipher_s390x.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 	"internal/cpu"
 )
 
@@ -67,6 +68,9 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize)
 }
 
@@ -77,6 +81,9 @@ func (c *aesCipherAsm) Decrypt(dst, src []byte) {
 	if len(dst) < BlockSize {
 		panic("crypto/aes: output not full block")
 	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/aes: invalid buffer overlap")
+	}
 	// The decrypt function code is equal to the function code + 128.
 	cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize)
 }
diff --git a/src/crypto/aes/ctr_s390x.go b/src/crypto/aes/ctr_s390x.go
index 8078aa68026c37..8fa85a3ae8fe79 100644
--- a/src/crypto/aes/ctr_s390x.go
+++ b/src/crypto/aes/ctr_s390x.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 	"unsafe"
 )
 
@@ -64,9 +65,11 @@ func (c *aesctr) refill() {
 }
 
 func (c *aesctr) XORKeyStream(dst, src []byte) {
-	if len(src) > 0 {
-		// Assert len(dst) >= len(src)
-		_ = dst[len(src)-1]
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
 	}
 	for len(src) > 0 {
 		if len(c.buffer) == 0 {
diff --git a/src/crypto/aes/gcm_s390x.go b/src/crypto/aes/gcm_s390x.go
index ca06ae52ac0bd0..d154ddbaa0834a 100644
--- a/src/crypto/aes/gcm_s390x.go
+++ b/src/crypto/aes/gcm_s390x.go
@@ -6,6 +6,7 @@ package aes
 
 import (
 	"crypto/cipher"
+	subtleoverlap "crypto/internal/subtle"
 	"crypto/subtle"
 	"errors"
 	"internal/cpu"
@@ -220,13 +221,16 @@ func (g *gcmAsm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSi
 // details.
 func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
-		panic("cipher: message too large for GCM")
+		panic("crypto/cipher: message too large for GCM")
 	}
 
 	ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+	if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 
 	counter := g.deriveCounter(nonce)
 
@@ -246,12 +250,12 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
 // for details.
 func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	// Sanity check to prevent the authentication from always succeeding if an implementation
 	// leaves tagSize uninitialized, for example.
 	if g.tagSize < gcmMinimumTagSize {
-		panic("cipher: incorrect GCM tag size")
+		panic("crypto/cipher: incorrect GCM tag size")
 	}
 	if len(ciphertext) < g.tagSize {
 		return nil, errOpen
@@ -273,6 +277,9 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	g.auth(expectedTag[:], ciphertext, data, &tagMask)
 
 	ret, out := sliceForAppend(dst, len(ciphertext))
+	if subtleoverlap.InexactOverlap(out, ciphertext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 
 	if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
 		// The AESNI code decrypts and authenticates concurrently, and
@@ -314,13 +321,16 @@ func kmaGCM(fn code, key, dst, src, aad []byte, tag *[16]byte, cnt *gcmCount)
 // details.
 func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
-		panic("cipher: message too large for GCM")
+		panic("crypto/cipher: message too large for GCM")
 	}
 
 	ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+	if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 
 	counter := g.deriveCounter(nonce)
 	fc := g.block.function | kmaLAAD | kmaLPC
@@ -336,7 +346,7 @@ func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte {
 // for details.
 func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	if len(ciphertext) < g.tagSize {
 		return nil, errOpen
@@ -348,9 +358,12 @@ func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	tag := ciphertext[len(ciphertext)-g.tagSize:]
 	ciphertext = ciphertext[:len(ciphertext)-g.tagSize]
 	ret, out := sliceForAppend(dst, len(ciphertext))
+	if subtleoverlap.InexactOverlap(out, ciphertext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 
 	if g.tagSize < gcmMinimumTagSize {
-		panic("cipher: incorrect GCM tag size")
+		panic("crypto/cipher: incorrect GCM tag size")
 	}
 
 	counter := g.deriveCounter(nonce)
diff --git a/src/crypto/cipher/cbc.go b/src/crypto/cipher/cbc.go
index 0367d5971a6b80..0d07192e291aa1 100644
--- a/src/crypto/cipher/cbc.go
+++ b/src/crypto/cipher/cbc.go
@@ -11,6 +11,8 @@
 
 package cipher
 
+import "crypto/internal/subtle"
+
 type cbc struct {
 	b         Block
 	blockSize int
@@ -59,6 +61,9 @@ func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
 	if len(dst) < len(src) {
 		panic("crypto/cipher: output smaller than input")
 	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 
 	iv := x.iv
 
@@ -116,6 +121,9 @@ func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
 	if len(dst) < len(src) {
 		panic("crypto/cipher: output smaller than input")
 	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	if len(src) == 0 {
 		return
 	}
diff --git a/src/crypto/cipher/cfb.go b/src/crypto/cipher/cfb.go
index 9b4eebf5b45416..80c9bc24ea01f7 100644
--- a/src/crypto/cipher/cfb.go
+++ b/src/crypto/cipher/cfb.go
@@ -6,6 +6,8 @@
 
 package cipher
 
+import "crypto/internal/subtle"
+
 type cfb struct {
 	b       Block
 	next    []byte
@@ -16,6 +18,12 @@ type cfb struct {
 }
 
 func (x *cfb) XORKeyStream(dst, src []byte) {
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	for len(src) > 0 {
 		if x.outUsed == len(x.out) {
 			x.b.Encrypt(x.out, x.next)
diff --git a/src/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go
index 75f46cfe512a97..cba028d2a4453c 100644
--- a/src/crypto/cipher/ctr.go
+++ b/src/crypto/cipher/ctr.go
@@ -12,6 +12,8 @@
 
 package cipher
 
+import "crypto/internal/subtle"
+
 type ctr struct {
 	b       Block
 	ctr     []byte
@@ -71,6 +73,12 @@ func (x *ctr) refill() {
 }
 
 func (x *ctr) XORKeyStream(dst, src []byte) {
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	for len(src) > 0 {
 		if x.outUsed >= len(x.out)-x.b.BlockSize() {
 			x.refill()
diff --git a/src/crypto/cipher/gcm.go b/src/crypto/cipher/gcm.go
index 28f8b2093e74e5..6321e9e82d3d6a 100644
--- a/src/crypto/cipher/gcm.go
+++ b/src/crypto/cipher/gcm.go
@@ -5,6 +5,7 @@
 package cipher
 
 import (
+	subtleoverlap "crypto/internal/subtle"
 	"crypto/subtle"
 	"errors"
 )
@@ -26,8 +27,8 @@ type AEAD interface {
 	// slice. The nonce must be NonceSize() bytes long and unique for all
 	// time, for a given key.
 	//
-	// The plaintext and dst must overlap exactly or not at all. To reuse
-	// plaintext's storage for the encrypted output, use plaintext[:0] as dst.
+	// To reuse plaintext's storage for the encrypted output, use plaintext[:0]
+	// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
 	Seal(dst, nonce, plaintext, additionalData []byte) []byte
 
 	// Open decrypts and authenticates ciphertext, authenticates the
@@ -36,8 +37,8 @@ type AEAD interface {
 	// bytes long and both it and the additional data must match the
 	// value passed to Seal.
 	//
-	// The ciphertext and dst must overlap exactly or not at all. To reuse
-	// ciphertext's storage for the decrypted output, use ciphertext[:0] as dst.
+	// To reuse ciphertext's storage for the decrypted output, use ciphertext[:0]
+	// as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
 	//
 	// Even if the function fails, the contents of dst, up to its capacity,
 	// may be overwritten.
@@ -159,13 +160,16 @@ func (g *gcm) Overhead() int {
 
 func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) {
-		panic("cipher: message too large for GCM")
+		panic("crypto/cipher: message too large for GCM")
 	}
 
 	ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+	if subtleoverlap.InexactOverlap(out, plaintext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 
 	var counter, tagMask [gcmBlockSize]byte
 	g.deriveCounter(&counter, nonce)
@@ -186,12 +190,12 @@ var errOpen = errors.New("cipher: message authentication failed")
 
 func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	if len(nonce) != g.nonceSize {
-		panic("cipher: incorrect nonce length given to GCM")
+		panic("crypto/cipher: incorrect nonce length given to GCM")
 	}
 	// Sanity check to prevent the authentication from always succeeding if an implementation
 	// leaves tagSize uninitialized, for example.
 	if g.tagSize < gcmMinimumTagSize {
-		panic("cipher: incorrect GCM tag size")
+		panic("crypto/cipher: incorrect GCM tag size")
 	}
 
 	if len(ciphertext) < g.tagSize {
@@ -214,6 +218,9 @@ func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	g.auth(expectedTag[:], ciphertext, data, &tagMask)
 
 	ret, out := sliceForAppend(dst, len(ciphertext))
+	if subtleoverlap.InexactOverlap(out, ciphertext) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 
 	if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
 		// The AESNI code decrypts and authenticates concurrently, and
diff --git a/src/crypto/cipher/ofb.go b/src/crypto/cipher/ofb.go
index 7b35f8995c8e71..fc477248658c8d 100644
--- a/src/crypto/cipher/ofb.go
+++ b/src/crypto/cipher/ofb.go
@@ -6,6 +6,8 @@
 
 package cipher
 
+import "crypto/internal/subtle"
+
 type ofb struct {
 	b       Block
 	cipher  []byte
@@ -54,6 +56,12 @@ func (x *ofb) refill() {
 }
 
 func (x *ofb) XORKeyStream(dst, src []byte) {
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	for len(src) > 0 {
 		if x.outUsed >= len(x.out)-x.b.BlockSize() {
 			x.refill()
diff --git a/src/crypto/des/cipher.go b/src/crypto/des/cipher.go
index 46af5b0f022c88..9e6779c216b5f8 100644
--- a/src/crypto/des/cipher.go
+++ b/src/crypto/des/cipher.go
@@ -6,6 +6,7 @@ package des
 
 import (
 	"crypto/cipher"
+	"crypto/internal/subtle"
 	"encoding/binary"
 	"strconv"
 )
@@ -37,9 +38,31 @@ func NewCipher(key []byte) (cipher.Block, error) {
 
 func (c *desCipher) BlockSize() int { return BlockSize }
 
-func (c *desCipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
+func (c *desCipher) Encrypt(dst, src []byte) {
+	if len(src) < BlockSize {
+		panic("crypto/des: input not full block")
+	}
+	if len(dst) < BlockSize {
+		panic("crypto/des: output not full block")
+	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/des: invalid buffer overlap")
+	}
+	encryptBlock(c.subkeys[:], dst, src)
+}
 
-func (c *desCipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
+func (c *desCipher) Decrypt(dst, src []byte) {
+	if len(src) < BlockSize {
+		panic("crypto/des: input not full block")
+	}
+	if len(dst) < BlockSize {
+		panic("crypto/des: output not full block")
+	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/des: invalid buffer overlap")
+	}
+	decryptBlock(c.subkeys[:], dst, src)
+}
 
 // A tripleDESCipher is an instance of TripleDES encryption.
 type tripleDESCipher struct {
@@ -62,6 +85,16 @@ func NewTripleDESCipher(key []byte) (cipher.Block, error) {
 func (c *tripleDESCipher) BlockSize() int { return BlockSize }
 
 func (c *tripleDESCipher) Encrypt(dst, src []byte) {
+	if len(src) < BlockSize {
+		panic("crypto/des: input not full block")
+	}
+	if len(dst) < BlockSize {
+		panic("crypto/des: output not full block")
+	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/des: invalid buffer overlap")
+	}
+
 	b := binary.BigEndian.Uint64(src)
 	b = permuteInitialBlock(b)
 	left, right := uint32(b>>32), uint32(b)
@@ -87,6 +120,16 @@ func (c *tripleDESCipher) Encrypt(dst, src []byte) {
 }
 
 func (c *tripleDESCipher) Decrypt(dst, src []byte) {
+	if len(src) < BlockSize {
+		panic("crypto/des: input not full block")
+	}
+	if len(dst) < BlockSize {
+		panic("crypto/des: output not full block")
+	}
+	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+		panic("crypto/des: invalid buffer overlap")
+	}
+
 	b := binary.BigEndian.Uint64(src)
 	b = permuteInitialBlock(b)
 	left, right := uint32(b>>32), uint32(b)
diff --git a/src/crypto/internal/subtle/aliasing.go b/src/crypto/internal/subtle/aliasing.go
new file mode 100644
index 00000000000000..812ce3c65522bd
--- /dev/null
+++ b/src/crypto/internal/subtle/aliasing.go
@@ -0,0 +1,34 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+// Package subtle implements functions that are often useful in cryptographic
+// code but require careful thought to use correctly.
+//
+// This is a mirror of golang.org/x/crypto/internal/subtle.
+package subtle // import "crypto/internal/subtle"
+
+import "unsafe"
+
+// AnyOverlap reports whether x and y share memory at any (not necessarily
+// corresponding) index. The memory beyond the slice length is ignored.
+func AnyOverlap(x, y []byte) bool {
+	return len(x) > 0 && len(y) > 0 &&
+		uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
+		uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
+}
+
+// InexactOverlap reports whether x and y share memory at any non-corresponding
+// index. The memory beyond the slice length is ignored. Note that x and y can
+// have different lengths and still not have any inexact overlap.
+//
+// InexactOverlap can be used to implement the requirements of the crypto/cipher
+// AEAD, Block, BlockMode and Stream interfaces.
+func InexactOverlap(x, y []byte) bool {
+	if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
+		return false
+	}
+	return AnyOverlap(x, y)
+}
diff --git a/src/crypto/internal/subtle/aliasing_appengine.go b/src/crypto/internal/subtle/aliasing_appengine.go
new file mode 100644
index 00000000000000..844f901d18e631
--- /dev/null
+++ b/src/crypto/internal/subtle/aliasing_appengine.go
@@ -0,0 +1,37 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+// Package subtle implements functions that are often useful in cryptographic
+// code but require careful thought to use correctly.
+//
+// This is a mirror of golang.org/x/crypto/internal/subtle.
+package subtle // import "crypto/internal/subtle"
+
+// This is the Google App Engine standard variant based on reflect
+// because the unsafe package and cgo are disallowed.
+
+import "reflect"
+
+// AnyOverlap reports whether x and y share memory at any (not necessarily
+// corresponding) index. The memory beyond the slice length is ignored.
+func AnyOverlap(x, y []byte) bool {
+	return len(x) > 0 && len(y) > 0 &&
+		reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() &&
+		reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer()
+}
+
+// InexactOverlap reports whether x and y share memory at any non-corresponding
+// index. The memory beyond the slice length is ignored. Note that x and y can
+// have different lengths and still not have any inexact overlap.
+//
+// InexactOverlap can be used to implement the requirements of the crypto/cipher
+// AEAD, Block, BlockMode and Stream interfaces.
+func InexactOverlap(x, y []byte) bool {
+	if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
+		return false
+	}
+	return AnyOverlap(x, y)
+}
diff --git a/src/crypto/internal/subtle/aliasing_test.go b/src/crypto/internal/subtle/aliasing_test.go
new file mode 100644
index 00000000000000..f1e723848124fd
--- /dev/null
+++ b/src/crypto/internal/subtle/aliasing_test.go
@@ -0,0 +1,50 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package subtle_test
+
+import (
+	"testing"
+
+	"crypto/internal/subtle"
+)
+
+var a, b [100]byte
+
+var aliasingTests = []struct {
+	x, y                       []byte
+	anyOverlap, inexactOverlap bool
+}{
+	{a[:], b[:], false, false},
+	{a[:], b[:0], false, false},
+	{a[:], b[:50], false, false},
+	{a[40:50], a[50:60], false, false},
+	{a[40:50], a[60:70], false, false},
+	{a[:51], a[50:], true, true},
+	{a[:], a[:], true, false},
+	{a[:50], a[:60], true, false},
+	{a[:], nil, false, false},
+	{nil, nil, false, false},
+	{a[:], a[:0], false, false},
+	{a[:10], a[:10:20], true, false},
+	{a[:10], a[5:10:20], true, true},
+}
+
+func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) {
+	any := subtle.AnyOverlap(x, y)
+	if any != anyOverlap {
+		t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any)
+	}
+	inexact := subtle.InexactOverlap(x, y)
+	if inexact != inexactOverlap {
+		t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any)
+	}
+}
+
+func TestAliasing(t *testing.T) {
+	for i, tt := range aliasingTests {
+		testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap)
+		testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap)
+	}
+}
diff --git a/src/crypto/rc4/rc4.go b/src/crypto/rc4/rc4.go
index cf08ba7f8c42ec..c445bb078f290d 100644
--- a/src/crypto/rc4/rc4.go
+++ b/src/crypto/rc4/rc4.go
@@ -9,7 +9,10 @@
 // applications.
 package rc4
 
-import "strconv"
+import (
+	"crypto/internal/subtle"
+	"strconv"
+)
 
 // A Cipher is an instance of RC4 using a particular key.
 type Cipher struct {
@@ -60,6 +63,9 @@ func (c *Cipher) xorKeyStreamGeneric(dst, src []byte) {
 	if len(src) == 0 {
 		return
 	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/rc4: invalid buffer overlap")
+	}
 	i, j := c.i, c.j
 	_ = dst[len(src)-1]
 	dst = dst[:len(src)] // eliminate bounds check from loop
diff --git a/src/crypto/rc4/rc4_asm.go b/src/crypto/rc4/rc4_asm.go
index 7e5f8b2fa40296..fc79e7ffc78346 100644
--- a/src/crypto/rc4/rc4_asm.go
+++ b/src/crypto/rc4/rc4_asm.go
@@ -6,6 +6,8 @@
 
 package rc4
 
+import "crypto/internal/subtle"
+
 func xorKeyStream(dst, src *byte, n int, state *[256]uint32, i, j *uint8)
 
 // XORKeyStream sets dst to the result of XORing src with the key stream.
@@ -14,7 +16,11 @@ func (c *Cipher) XORKeyStream(dst, src []byte) {
 	if len(src) == 0 {
 		return
 	}
-	// Assert len(dst) >= len(src)
-	_ = dst[len(src)-1]
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	if subtle.InexactOverlap(dst[:len(src)], src) {
+		panic("crypto/cipher: invalid buffer overlap")
+	}
 	xorKeyStream(&dst[0], &src[0], len(src), &c.s, &c.i, &c.j)
 }
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 663d5246f89c38..508ed8ac301e08 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -99,27 +99,29 @@ var pkgDeps = map[string][]string{
 	// L3 adds reflection and some basic utility packages
 	// and interface definitions, but nothing that makes
 	// system calls.
-	"crypto":              {"L2", "hash"}, // interfaces
-	"crypto/cipher":       {"L2", "crypto/subtle"},
-	"crypto/subtle":       {},
-	"encoding/base32":     {"L2"},
-	"encoding/base64":     {"L2", "encoding/binary"},
-	"encoding/binary":     {"L2", "reflect"},
-	"hash":                {"L2"}, // interfaces
-	"hash/adler32":        {"L2", "hash"},
-	"hash/crc32":          {"L2", "hash"},
-	"hash/crc64":          {"L2", "hash"},
-	"hash/fnv":            {"L2", "hash"},
-	"image":               {"L2", "image/color"}, // interfaces
-	"image/color":         {"L2"},                // interfaces
-	"image/color/palette": {"L2", "image/color"},
-	"reflect":             {"L2"},
-	"sort":                {"reflect"},
+	"crypto":                 {"L2", "hash"}, // interfaces
+	"crypto/cipher":          {"L2", "crypto/subtle", "crypto/internal/subtle"},
+	"crypto/internal/subtle": {"unsafe", "reflect"}, // reflect behind a appengine tag
+	"crypto/subtle":          {},
+	"encoding/base32":        {"L2"},
+	"encoding/base64":        {"L2", "encoding/binary"},
+	"encoding/binary":        {"L2", "reflect"},
+	"hash":                   {"L2"}, // interfaces
+	"hash/adler32":           {"L2", "hash"},
+	"hash/crc32":             {"L2", "hash"},
+	"hash/crc64":             {"L2", "hash"},
+	"hash/fnv":               {"L2", "hash"},
+	"image":                  {"L2", "image/color"}, // interfaces
+	"image/color":            {"L2"},                // interfaces
+	"image/color/palette":    {"L2", "image/color"},
+	"reflect":                {"L2"},
+	"sort":                   {"reflect"},
 
 	"L3": {
 		"L2",
 		"crypto",
 		"crypto/cipher",
+		"crypto/internal/subtle",
 		"crypto/subtle",
 		"encoding/base32",
 		"encoding/base64",
@@ -229,49 +231,49 @@ var pkgDeps = map[string][]string{
 	"go/types":                  {"L4", "GOPARSER", "container/heap", "go/constant"},
 
 	// One of a kind.
-	"archive/tar":                    {"L4", "OS", "syscall", "os/user"},
-	"archive/zip":                    {"L4", "OS", "compress/flate"},
-	"container/heap":                 {"sort"},
-	"compress/bzip2":                 {"L4"},
-	"compress/flate":                 {"L4"},
-	"compress/gzip":                  {"L4", "compress/flate"},
-	"compress/lzw":                   {"L4"},
-	"compress/zlib":                  {"L4", "compress/flate"},
-	"context":                        {"errors", "fmt", "reflect", "sync", "time"},
-	"database/sql":                   {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
-	"database/sql/driver":            {"L4", "context", "time", "database/sql/internal"},
-	"debug/dwarf":                    {"L4"},
-	"debug/elf":                      {"L4", "OS", "debug/dwarf", "compress/zlib"},
-	"debug/gosym":                    {"L4"},
-	"debug/macho":                    {"L4", "OS", "debug/dwarf"},
-	"debug/pe":                       {"L4", "OS", "debug/dwarf"},
-	"debug/plan9obj":                 {"L4", "OS"},
-	"encoding":                       {"L4"},
-	"encoding/ascii85":               {"L4"},
-	"encoding/asn1":                  {"L4", "math/big"},
-	"encoding/csv":                   {"L4"},
-	"encoding/gob":                   {"L4", "OS", "encoding"},
-	"encoding/hex":                   {"L4"},
-	"encoding/json":                  {"L4", "encoding"},
-	"encoding/pem":                   {"L4"},
-	"encoding/xml":                   {"L4", "encoding"},
-	"flag":                           {"L4", "OS"},
-	"go/build":                       {"L4", "OS", "GOPARSER"},
-	"html":                           {"L4"},
-	"image/draw":                     {"L4", "image/internal/imageutil"},
-	"image/gif":                      {"L4", "compress/lzw", "image/color/palette", "image/draw"},
-	"image/internal/imageutil":       {"L4"},
-	"image/jpeg":                     {"L4", "image/internal/imageutil"},
-	"image/png":                      {"L4", "compress/zlib"},
-	"index/suffixarray":              {"L4", "regexp"},
-	"internal/singleflight":          {"sync"},
-	"internal/trace":                 {"L4", "OS"},
-	"math/big":                       {"L4"},
-	"mime":                           {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
-	"mime/quotedprintable":           {"L4"},
-	"net/internal/socktest":          {"L4", "OS", "syscall", "internal/syscall/windows"},
-	"net/url":                        {"L4"},
-	"plugin":                         {"L0", "OS", "CGO"},
+	"archive/tar":              {"L4", "OS", "syscall", "os/user"},
+	"archive/zip":              {"L4", "OS", "compress/flate"},
+	"container/heap":           {"sort"},
+	"compress/bzip2":           {"L4"},
+	"compress/flate":           {"L4"},
+	"compress/gzip":            {"L4", "compress/flate"},
+	"compress/lzw":             {"L4"},
+	"compress/zlib":            {"L4", "compress/flate"},
+	"context":                  {"errors", "fmt", "reflect", "sync", "time"},
+	"database/sql":             {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
+	"database/sql/driver":      {"L4", "context", "time", "database/sql/internal"},
+	"debug/dwarf":              {"L4"},
+	"debug/elf":                {"L4", "OS", "debug/dwarf", "compress/zlib"},
+	"debug/gosym":              {"L4"},
+	"debug/macho":              {"L4", "OS", "debug/dwarf"},
+	"debug/pe":                 {"L4", "OS", "debug/dwarf"},
+	"debug/plan9obj":           {"L4", "OS"},
+	"encoding":                 {"L4"},
+	"encoding/ascii85":         {"L4"},
+	"encoding/asn1":            {"L4", "math/big"},
+	"encoding/csv":             {"L4"},
+	"encoding/gob":             {"L4", "OS", "encoding"},
+	"encoding/hex":             {"L4"},
+	"encoding/json":            {"L4", "encoding"},
+	"encoding/pem":             {"L4"},
+	"encoding/xml":             {"L4", "encoding"},
+	"flag":                     {"L4", "OS"},
+	"go/build":                 {"L4", "OS", "GOPARSER"},
+	"html":                     {"L4"},
+	"image/draw":               {"L4", "image/internal/imageutil"},
+	"image/gif":                {"L4", "compress/lzw", "image/color/palette", "image/draw"},
+	"image/internal/imageutil": {"L4"},
+	"image/jpeg":               {"L4", "image/internal/imageutil"},
+	"image/png":                {"L4", "compress/zlib"},
+	"index/suffixarray":        {"L4", "regexp"},
+	"internal/singleflight":    {"sync"},
+	"internal/trace":           {"L4", "OS"},
+	"math/big":                 {"L4"},
+	"mime":                     {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
+	"mime/quotedprintable":     {"L4"},
+	"net/internal/socktest":    {"L4", "OS", "syscall", "internal/syscall/windows"},
+	"net/url":                  {"L4"},
+	"plugin":                   {"L0", "OS", "CGO"},
 	"runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},
 	"testing/internal/testdeps":      {"L4", "internal/testlog", "runtime/pprof", "regexp"},
 	"text/scanner":                   {"L4", "OS"},