Commit 75d15a20 authored by Filippo Valsorda's avatar Filippo Valsorda

crypto: panic on illegal input and output overlap

Normalized all panic checks and added inexact aliasing panics across
Stream, Block, BlockMode and AEAD implementations.

Also, tweaked the aliasing docs of cipher.AEAD, as they did not account
for the append nature of the API.

Fixes #21624

Change-Id: I075c4415f59b3c06e3099bd9f76de6d12af086bf
Reviewed-on: https://go-review.googlesource.com/109697
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent c6e455bb
......@@ -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)
}
......
......@@ -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))
}
......
......@@ -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)
}
......@@ -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])
}
......
......@@ -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])
}
......
......@@ -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])
}
......
......@@ -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)
}
......
......@@ -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 {
......
......@@ -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)
......
......@@ -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
}
......
......@@ -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)
......
......@@ -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()
......
......@@ -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
......
......@@ -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()
......
......@@ -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)
......
// 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)
}
// 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)
}
// 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)
}
}
......@@ -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
......
......@@ -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)
}
......@@ -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"},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment