github.com/emmansun/gmsm@v0.29.1/cipher/ofbnlf.go (about)

     1  // Output feedback with a nonlinear function operation mode (OFBNLF mode) in Chinese national standard GB/T 17964-2021.
     2  // See GB/T 17964-2021 Chapter 13.
     3  
     4  package cipher
     5  
     6  import (
     7  	_cipher "crypto/cipher"
     8  	"errors"
     9  )
    10  
    11  type ofbnlf struct {
    12  	cipherFunc CipherCreator
    13  	b          _cipher.Block
    14  	blockSize  int
    15  	iv         []byte
    16  }
    17  
    18  func newOFBNLF(cipherFunc CipherCreator, key, iv []byte) (*ofbnlf, error) {
    19  	c := &ofbnlf{
    20  		cipherFunc: cipherFunc,
    21  	}
    22  	var err error
    23  	c.b, err = cipherFunc(key)
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	c.blockSize = c.b.BlockSize()
    28  	if len(iv) != c.blockSize {
    29  		return nil, errors.New("cipher: IV length must equal block size")
    30  	}
    31  	c.iv = make([]byte, c.blockSize)
    32  	copy(c.iv, iv)
    33  	return c, nil
    34  }
    35  
    36  type ofbnlfEncrypter ofbnlf
    37  
    38  // NewOFBNLFEncrypter returns a BlockMode which encrypts in Output feedback
    39  // with a nonlinear function operation mode, using the given Block.
    40  // The length of iv must be the same as the Block's block size.
    41  func NewOFBNLFEncrypter(cipherFunc CipherCreator, key, iv []byte) (_cipher.BlockMode, error) {
    42  	c, err := newOFBNLF(cipherFunc, key, iv)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	return (*ofbnlfEncrypter)(c), nil
    47  }
    48  
    49  func (x *ofbnlfEncrypter) BlockSize() int { return x.blockSize }
    50  
    51  func (x *ofbnlfEncrypter) CryptBlocks(dst, src []byte) {
    52  	validate(x.blockSize, dst, src)
    53  
    54  	iv := x.iv
    55  	k := make([]byte, x.blockSize)
    56  
    57  	for len(src) > 0 {
    58  		x.b.Encrypt(k, iv)
    59  		c, err := x.cipherFunc(k)
    60  		if err != nil {
    61  			panic(err)
    62  		}
    63  		c.Encrypt(dst, src)
    64  		src = src[x.blockSize:]
    65  		dst = dst[x.blockSize:]
    66  		copy(iv, k)
    67  	}
    68  
    69  	// Save the iv for the next CryptBlocks call.
    70  	copy(x.iv, iv)
    71  }
    72  
    73  func (x *ofbnlfEncrypter) SetIV(iv []byte) {
    74  	if len(iv) != len(x.iv) {
    75  		panic("cipher: incorrect length IV")
    76  	}
    77  	copy(x.iv, iv)
    78  }
    79  
    80  type ofbnlfDecrypter ofbnlf
    81  
    82  // NewOFBNLFDecrypter returns a BlockMode which decrypts in Output feedback
    83  // with a nonlinear function operation mode, using the given Block.
    84  // The length of iv must be the same as the Block's block size and must match
    85  // the iv used to encrypt the data.
    86  func NewOFBNLFDecrypter(cipherFunc CipherCreator, key, iv []byte) (_cipher.BlockMode, error) {
    87  	c, err := newOFBNLF(cipherFunc, key, iv)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	return (*ofbnlfDecrypter)(c), nil
    92  }
    93  
    94  func (x *ofbnlfDecrypter) BlockSize() int { return x.blockSize }
    95  
    96  func (x *ofbnlfDecrypter) CryptBlocks(dst, src []byte) {
    97  	validate(x.blockSize, dst, src)
    98  
    99  	if len(src) == 0 {
   100  		return
   101  	}
   102  
   103  	iv := x.iv
   104  	k := make([]byte, x.blockSize)
   105  
   106  	for len(src) > 0 {
   107  		x.b.Encrypt(k, iv)
   108  		c, err := x.cipherFunc(k)
   109  		if err != nil {
   110  			panic(err)
   111  		}
   112  		c.Decrypt(dst, src)
   113  		src = src[x.blockSize:]
   114  		dst = dst[x.blockSize:]
   115  		copy(iv, k)
   116  	}
   117  
   118  	// Save the iv for the next CryptBlocks call.
   119  	copy(x.iv, iv)
   120  }
   121  
   122  func (x *ofbnlfDecrypter) SetIV(iv []byte) {
   123  	if len(iv) != len(x.iv) {
   124  		panic("cipher: incorrect length IV")
   125  	}
   126  	copy(x.iv, iv)
   127  }