| // Copyright 2024 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 aes |
| |
| import ( |
| "crypto/internal/fips140" |
| "crypto/internal/fips140/alias" |
| "crypto/internal/fips140/subtle" |
| ) |
| |
| type CBCEncrypter struct { |
| b Block |
| iv [BlockSize]byte |
| } |
| |
| // NewCBCEncrypter returns a [cipher.BlockMode] which encrypts in cipher block |
| // chaining mode, using the given Block. |
| func NewCBCEncrypter(b *Block, iv [BlockSize]byte) *CBCEncrypter { |
| return &CBCEncrypter{b: *b, iv: iv} |
| } |
| |
| func (c *CBCEncrypter) BlockSize() int { return BlockSize } |
| |
| func (c *CBCEncrypter) CryptBlocks(dst, src []byte) { |
| if len(src)%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") |
| } |
| fips140.RecordApproved() |
| if len(src) == 0 { |
| return |
| } |
| cryptBlocksEnc(&c.b, &c.iv, dst, src) |
| } |
| |
| func (x *CBCEncrypter) SetIV(iv []byte) { |
| if len(iv) != len(x.iv) { |
| panic("cipher: incorrect length IV") |
| } |
| copy(x.iv[:], iv) |
| } |
| |
| func cryptBlocksEncGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { |
| iv := civ[:] |
| for len(src) > 0 { |
| // Write the xor to dst, then encrypt in place. |
| subtle.XORBytes(dst[:BlockSize], src[:BlockSize], iv) |
| encryptBlock(b, dst[:BlockSize], dst[:BlockSize]) |
| |
| // Move to the next block with this block as the next iv. |
| iv = dst[:BlockSize] |
| src = src[BlockSize:] |
| dst = dst[BlockSize:] |
| } |
| |
| // Save the iv for the next CryptBlocks call. |
| copy(civ[:], iv) |
| } |
| |
| type CBCDecrypter struct { |
| b Block |
| iv [BlockSize]byte |
| } |
| |
| // NewCBCDecrypter returns a [cipher.BlockMode] which decrypts in cipher block |
| // chaining mode, using the given Block. |
| func NewCBCDecrypter(b *Block, iv [BlockSize]byte) *CBCDecrypter { |
| return &CBCDecrypter{b: *b, iv: iv} |
| } |
| |
| func (c *CBCDecrypter) BlockSize() int { return BlockSize } |
| |
| func (c *CBCDecrypter) CryptBlocks(dst, src []byte) { |
| if len(src)%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") |
| } |
| fips140.RecordApproved() |
| if len(src) == 0 { |
| return |
| } |
| cryptBlocksDec(&c.b, &c.iv, dst, src) |
| } |
| |
| func (x *CBCDecrypter) SetIV(iv []byte) { |
| if len(iv) != len(x.iv) { |
| panic("cipher: incorrect length IV") |
| } |
| copy(x.iv[:], iv) |
| } |
| |
| func cryptBlocksDecGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { |
| // For each block, we need to xor the decrypted data with the previous |
| // block's ciphertext (the iv). To avoid making a copy each time, we loop |
| // over the blocks backwards. |
| end := len(src) |
| start := end - BlockSize |
| prev := start - BlockSize |
| |
| // Copy the last block of ciphertext as the IV of the next call. |
| iv := *civ |
| copy(civ[:], src[start:end]) |
| |
| for start >= 0 { |
| decryptBlock(b, dst[start:end], src[start:end]) |
| |
| if start > 0 { |
| subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start]) |
| } else { |
| // The first block is special because it uses the saved iv. |
| subtle.XORBytes(dst[start:end], dst[start:end], iv[:]) |
| } |
| |
| end -= BlockSize |
| start -= BlockSize |
| prev -= BlockSize |
| } |
| } |