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"
     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  

View as plain text