| | |
| | |
| | |
| |
|
| | |
| |
|
| | |
| | |
| |
|
| | |
| |
|
| | package cipher |
| |
|
| | import ( |
| | "bytes" |
| | "crypto/internal/fips140/aes" |
| | "crypto/internal/fips140/alias" |
| | "crypto/internal/fips140only" |
| | "crypto/subtle" |
| | ) |
| |
|
| | type cbc struct { |
| | b Block |
| | blockSize int |
| | iv []byte |
| | tmp []byte |
| | } |
| |
|
| | func newCBC(b Block, iv []byte) *cbc { |
| | return &cbc{ |
| | b: b, |
| | blockSize: b.BlockSize(), |
| | iv: bytes.Clone(iv), |
| | tmp: make([]byte, b.BlockSize()), |
| | } |
| | } |
| |
|
| | type cbcEncrypter cbc |
| |
|
| | |
| | |
| | |
| | type cbcEncAble interface { |
| | NewCBCEncrypter(iv []byte) BlockMode |
| | } |
| |
|
| | |
| | |
| | |
| | func NewCBCEncrypter(b Block, iv []byte) BlockMode { |
| | if len(iv) != b.BlockSize() { |
| | panic("cipher.NewCBCEncrypter: IV length must equal block size") |
| | } |
| | if b, ok := b.(*aes.Block); ok { |
| | return aes.NewCBCEncrypter(b, [16]byte(iv)) |
| | } |
| | if fips140only.Enforced() { |
| | panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") |
| | } |
| | if cbc, ok := b.(cbcEncAble); ok { |
| | return cbc.NewCBCEncrypter(iv) |
| | } |
| | return (*cbcEncrypter)(newCBC(b, iv)) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | func newCBCGenericEncrypter(b Block, iv []byte) BlockMode { |
| | if len(iv) != b.BlockSize() { |
| | panic("cipher.NewCBCEncrypter: IV length must equal block size") |
| | } |
| | return (*cbcEncrypter)(newCBC(b, iv)) |
| | } |
| |
|
| | func (x *cbcEncrypter) BlockSize() int { return x.blockSize } |
| |
|
| | func (x *cbcEncrypter) CryptBlocks(dst, src []byte) { |
| | if len(src)%x.blockSize != 0 { |
| | panic("crypto/cipher: input not full blocks") |
| | } |
| | if len(dst) < len(src) { |
| | panic("crypto/cipher: output smaller than input") |
| | } |
| | if alias.InexactOverlap(dst[:len(src)], src) { |
| | panic("crypto/cipher: invalid buffer overlap") |
| | } |
| | if _, ok := x.b.(*aes.Block); ok { |
| | panic("crypto/cipher: internal error: generic CBC used with AES") |
| | } |
| |
|
| | iv := x.iv |
| |
|
| | for len(src) > 0 { |
| | |
| | subtle.XORBytes(dst[:x.blockSize], src[:x.blockSize], iv) |
| | x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize]) |
| |
|
| | |
| | iv = dst[:x.blockSize] |
| | src = src[x.blockSize:] |
| | dst = dst[x.blockSize:] |
| | } |
| |
|
| | |
| | copy(x.iv, iv) |
| | } |
| |
|
| | func (x *cbcEncrypter) SetIV(iv []byte) { |
| | if len(iv) != len(x.iv) { |
| | panic("cipher: incorrect length IV") |
| | } |
| | copy(x.iv, iv) |
| | } |
| |
|
| | type cbcDecrypter cbc |
| |
|
| | |
| | |
| | |
| | type cbcDecAble interface { |
| | NewCBCDecrypter(iv []byte) BlockMode |
| | } |
| |
|
| | |
| | |
| | |
| | func NewCBCDecrypter(b Block, iv []byte) BlockMode { |
| | if len(iv) != b.BlockSize() { |
| | panic("cipher.NewCBCDecrypter: IV length must equal block size") |
| | } |
| | if b, ok := b.(*aes.Block); ok { |
| | return aes.NewCBCDecrypter(b, [16]byte(iv)) |
| | } |
| | if fips140only.Enforced() { |
| | panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") |
| | } |
| | if cbc, ok := b.(cbcDecAble); ok { |
| | return cbc.NewCBCDecrypter(iv) |
| | } |
| | return (*cbcDecrypter)(newCBC(b, iv)) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | func newCBCGenericDecrypter(b Block, iv []byte) BlockMode { |
| | if len(iv) != b.BlockSize() { |
| | panic("cipher.NewCBCDecrypter: IV length must equal block size") |
| | } |
| | return (*cbcDecrypter)(newCBC(b, iv)) |
| | } |
| |
|
| | func (x *cbcDecrypter) BlockSize() int { return x.blockSize } |
| |
|
| | func (x *cbcDecrypter) CryptBlocks(dst, src []byte) { |
| | if len(src)%x.blockSize != 0 { |
| | panic("crypto/cipher: input not full blocks") |
| | } |
| | if len(dst) < len(src) { |
| | panic("crypto/cipher: output smaller than input") |
| | } |
| | if alias.InexactOverlap(dst[:len(src)], src) { |
| | panic("crypto/cipher: invalid buffer overlap") |
| | } |
| | if _, ok := x.b.(*aes.Block); ok { |
| | panic("crypto/cipher: internal error: generic CBC used with AES") |
| | } |
| | if len(src) == 0 { |
| | return |
| | } |
| |
|
| | |
| | |
| | end := len(src) |
| | start := end - x.blockSize |
| | prev := start - x.blockSize |
| |
|
| | |
| | copy(x.tmp, src[start:end]) |
| |
|
| | |
| | for start > 0 { |
| | x.b.Decrypt(dst[start:end], src[start:end]) |
| | subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start]) |
| |
|
| | end = start |
| | start = prev |
| | prev -= x.blockSize |
| | } |
| |
|
| | |
| | x.b.Decrypt(dst[start:end], src[start:end]) |
| | subtle.XORBytes(dst[start:end], dst[start:end], x.iv) |
| |
|
| | |
| | x.iv, x.tmp = x.tmp, x.iv |
| | } |
| |
|
| | func (x *cbcDecrypter) SetIV(iv []byte) { |
| | if len(iv) != len(x.iv) { |
| | panic("cipher: incorrect length IV") |
| | } |
| | copy(x.iv, iv) |
| | } |
| |
|