Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * CTR: Counter mode
0004  *
0005  * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
0006  */
0007 
0008 #ifndef _CRYPTO_CTR_H
0009 #define _CRYPTO_CTR_H
0010 
0011 #include <crypto/algapi.h>
0012 #include <crypto/internal/skcipher.h>
0013 #include <linux/string.h>
0014 #include <linux/types.h>
0015 
0016 #define CTR_RFC3686_NONCE_SIZE 4
0017 #define CTR_RFC3686_IV_SIZE 8
0018 #define CTR_RFC3686_BLOCK_SIZE 16
0019 
0020 static inline int crypto_ctr_encrypt_walk(struct skcipher_request *req,
0021                       void (*fn)(struct crypto_skcipher *,
0022                              const u8 *, u8 *))
0023 {
0024     struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0025     int blocksize = crypto_skcipher_chunksize(tfm);
0026     u8 buf[MAX_CIPHER_BLOCKSIZE];
0027     struct skcipher_walk walk;
0028     int err;
0029 
0030     /* avoid integer division due to variable blocksize parameter */
0031     if (WARN_ON_ONCE(!is_power_of_2(blocksize)))
0032         return -EINVAL;
0033 
0034     err = skcipher_walk_virt(&walk, req, false);
0035 
0036     while (walk.nbytes > 0) {
0037         u8 *dst = walk.dst.virt.addr;
0038         u8 *src = walk.src.virt.addr;
0039         int nbytes = walk.nbytes;
0040         int tail = 0;
0041 
0042         if (nbytes < walk.total) {
0043             tail = walk.nbytes & (blocksize - 1);
0044             nbytes -= tail;
0045         }
0046 
0047         do {
0048             int bsize = min(nbytes, blocksize);
0049 
0050             fn(tfm, walk.iv, buf);
0051 
0052             crypto_xor_cpy(dst, src, buf, bsize);
0053             crypto_inc(walk.iv, blocksize);
0054 
0055             dst += bsize;
0056             src += bsize;
0057             nbytes -= bsize;
0058         } while (nbytes > 0);
0059 
0060         err = skcipher_walk_done(&walk, tail);
0061     }
0062     return err;
0063 }
0064 
0065 #endif  /* _CRYPTO_CTR_H */