// 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 (
	
	
)

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 ( *Block,  [BlockSize]byte) *CBCEncrypter {
	return &CBCEncrypter{b: *, iv: }
}

func ( *CBCEncrypter) () int { return BlockSize }

func ( *CBCEncrypter) (,  []byte) {
	if len()%BlockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len() < len() {
		panic("crypto/cipher: output smaller than input")
	}
	if alias.InexactOverlap([:len()], ) {
		panic("crypto/cipher: invalid buffer overlap")
	}
	if len() == 0 {
		return
	}
	cryptBlocksEnc(&.b, &.iv, , )
}

func ( *CBCEncrypter) ( []byte) {
	if len() != len(.iv) {
		panic("cipher: incorrect length IV")
	}
	copy(.iv[:], )
}

func cryptBlocksEncGeneric( *Block,  *[BlockSize]byte, ,  []byte) {
	 := [:]
	for len() > 0 {
		// Write the xor to dst, then encrypt in place.
		subtle.XORBytes([:BlockSize], [:BlockSize], )
		.Encrypt([:BlockSize], [:BlockSize])

		// Move to the next block with this block as the next iv.
		 = [:BlockSize]
		 = [BlockSize:]
		 = [BlockSize:]
	}

	// Save the iv for the next CryptBlocks call.
	copy([:], )
}

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 ( *Block,  [BlockSize]byte) *CBCDecrypter {
	return &CBCDecrypter{b: *, iv: }
}

func ( *CBCDecrypter) () int { return BlockSize }

func ( *CBCDecrypter) (,  []byte) {
	if len()%BlockSize != 0 {
		panic("crypto/cipher: input not full blocks")
	}
	if len() < len() {
		panic("crypto/cipher: output smaller than input")
	}
	if alias.InexactOverlap([:len()], ) {
		panic("crypto/cipher: invalid buffer overlap")
	}
	if len() == 0 {
		return
	}
	cryptBlocksDec(&.b, &.iv, , )
}

func ( *CBCDecrypter) ( []byte) {
	if len() != len(.iv) {
		panic("cipher: incorrect length IV")
	}
	copy(.iv[:], )
}

func cryptBlocksDecGeneric( *Block,  *[BlockSize]byte, ,  []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.
	 := len()
	 :=  - BlockSize
	 :=  - BlockSize

	// Copy the last block of ciphertext as the IV of the next call.
	 := *
	copy([:], [:])

	for  >= 0 {
		.Decrypt([:], [:])

		if  > 0 {
			subtle.XORBytes([:], [:], [:])
		} else {
			// The first block is special because it uses the saved iv.
			subtle.XORBytes([:], [:], [:])
		}

		 -= BlockSize
		 -= BlockSize
		 -= BlockSize
	}
}