Source file src/crypto/internal/fips140/aes/cbc.go

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

View as plain text