mirror of
https://github.com/golang/go
synced 2024-11-12 09:50:21 -07:00
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: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
c6e455bb11
commit
75d15a2082
@ -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)
|
||||
|
34
src/crypto/internal/subtle/aliasing.go
Normal file
34
src/crypto/internal/subtle/aliasing.go
Normal file
@ -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)
|
||||
}
|
37
src/crypto/internal/subtle/aliasing_appengine.go
Normal file
37
src/crypto/internal/subtle/aliasing_appengine.go
Normal file
@ -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)
|
||||
}
|
50
src/crypto/internal/subtle/aliasing_test.go
Normal file
50
src/crypto/internal/subtle/aliasing_test.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
@ -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"},
|
||||
|
Loading…
Reference in New Issue
Block a user