cbc.mx raw

   1  // Copyright 2024 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  package aes
   6  
   7  import (
   8  	"crypto/internal/fips140"
   9  	"crypto/internal/fips140/alias"
  10  	"crypto/internal/fips140/subtle"
  11  )
  12  
  13  type CBCEncrypter struct {
  14  	b  Block
  15  	iv [BlockSize]byte
  16  }
  17  
  18  // NewCBCEncrypter returns a [cipher.BlockMode] which encrypts in cipher block
  19  // chaining mode, using the given Block.
  20  func NewCBCEncrypter(b *Block, iv [BlockSize]byte) *CBCEncrypter {
  21  	return &CBCEncrypter{b: *b, iv: iv}
  22  }
  23  
  24  func (c *CBCEncrypter) BlockSize() int { return BlockSize }
  25  
  26  func (c *CBCEncrypter) CryptBlocks(dst, src []byte) {
  27  	if len(src)%BlockSize != 0 {
  28  		panic("crypto/cipher: input not full blocks")
  29  	}
  30  	if len(dst) < len(src) {
  31  		panic("crypto/cipher: output smaller than input")
  32  	}
  33  	if alias.InexactOverlap(dst[:len(src)], src) {
  34  		panic("crypto/cipher: invalid buffer overlap")
  35  	}
  36  	fips140.RecordApproved()
  37  	if len(src) == 0 {
  38  		return
  39  	}
  40  	cryptBlocksEnc(&c.b, &c.iv, dst, src)
  41  }
  42  
  43  func (x *CBCEncrypter) SetIV(iv []byte) {
  44  	if len(iv) != len(x.iv) {
  45  		panic("cipher: incorrect length IV")
  46  	}
  47  	copy(x.iv[:], iv)
  48  }
  49  
  50  func cryptBlocksEncGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) {
  51  	iv := civ[:]
  52  	for len(src) > 0 {
  53  		// Write the xor to dst, then encrypt in place.
  54  		subtle.XORBytes(dst[:BlockSize], src[:BlockSize], iv)
  55  		encryptBlock(b, dst[:BlockSize], dst[:BlockSize])
  56  
  57  		// Move to the next block with this block as the next iv.
  58  		iv = dst[:BlockSize]
  59  		src = src[BlockSize:]
  60  		dst = dst[BlockSize:]
  61  	}
  62  
  63  	// Save the iv for the next CryptBlocks call.
  64  	copy(civ[:], iv)
  65  }
  66  
  67  type CBCDecrypter struct {
  68  	b  Block
  69  	iv [BlockSize]byte
  70  }
  71  
  72  // NewCBCDecrypter returns a [cipher.BlockMode] which decrypts in cipher block
  73  // chaining mode, using the given Block.
  74  func NewCBCDecrypter(b *Block, iv [BlockSize]byte) *CBCDecrypter {
  75  	return &CBCDecrypter{b: *b, iv: iv}
  76  }
  77  
  78  func (c *CBCDecrypter) BlockSize() int { return BlockSize }
  79  
  80  func (c *CBCDecrypter) CryptBlocks(dst, src []byte) {
  81  	if len(src)%BlockSize != 0 {
  82  		panic("crypto/cipher: input not full blocks")
  83  	}
  84  	if len(dst) < len(src) {
  85  		panic("crypto/cipher: output smaller than input")
  86  	}
  87  	if alias.InexactOverlap(dst[:len(src)], src) {
  88  		panic("crypto/cipher: invalid buffer overlap")
  89  	}
  90  	fips140.RecordApproved()
  91  	if len(src) == 0 {
  92  		return
  93  	}
  94  	cryptBlocksDec(&c.b, &c.iv, dst, src)
  95  }
  96  
  97  func (x *CBCDecrypter) SetIV(iv []byte) {
  98  	if len(iv) != len(x.iv) {
  99  		panic("cipher: incorrect length IV")
 100  	}
 101  	copy(x.iv[:], iv)
 102  }
 103  
 104  func cryptBlocksDecGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) {
 105  	// For each block, we need to xor the decrypted data with the previous
 106  	// block's ciphertext (the iv). To avoid making a copy each time, we loop
 107  	// over the blocks backwards.
 108  	end := len(src)
 109  	start := end - BlockSize
 110  	prev := start - BlockSize
 111  
 112  	// Copy the last block of ciphertext as the IV of the next call.
 113  	iv := *civ
 114  	copy(civ[:], src[start:end])
 115  
 116  	for start >= 0 {
 117  		decryptBlock(b, dst[start:end], src[start:end])
 118  
 119  		if start > 0 {
 120  			subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start])
 121  		} else {
 122  			// The first block is special because it uses the saved iv.
 123  			subtle.XORBytes(dst[start:end], dst[start:end], iv[:])
 124  		}
 125  
 126  		end -= BlockSize
 127  		start -= BlockSize
 128  		prev -= BlockSize
 129  	}
 130  }
 131