Commit | Line | Data |
---|---|---|
2874c5fd | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
5311f248 HX |
2 | /* |
3 | * CTR: Counter mode | |
4 | * | |
5 | * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> | |
5311f248 HX |
6 | */ |
7 | ||
8 | #ifndef _CRYPTO_CTR_H | |
9 | #define _CRYPTO_CTR_H | |
10 | ||
d9ec772d AB |
11 | #include <crypto/algapi.h> |
12 | #include <crypto/internal/skcipher.h> | |
13 | #include <linux/string.h> | |
14 | #include <linux/types.h> | |
15 | ||
5311f248 HX |
16 | #define CTR_RFC3686_NONCE_SIZE 4 |
17 | #define CTR_RFC3686_IV_SIZE 8 | |
18 | #define CTR_RFC3686_BLOCK_SIZE 16 | |
19 | ||
d9ec772d AB |
20 | static inline int crypto_ctr_encrypt_walk(struct skcipher_request *req, |
21 | void (*fn)(struct crypto_skcipher *, | |
22 | const u8 *, u8 *)) | |
23 | { | |
24 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); | |
25 | int blocksize = crypto_skcipher_chunksize(tfm); | |
26 | u8 buf[MAX_CIPHER_BLOCKSIZE]; | |
27 | struct skcipher_walk walk; | |
28 | int err; | |
29 | ||
30 | /* avoid integer division due to variable blocksize parameter */ | |
31 | if (WARN_ON_ONCE(!is_power_of_2(blocksize))) | |
32 | return -EINVAL; | |
33 | ||
34 | err = skcipher_walk_virt(&walk, req, false); | |
35 | ||
36 | while (walk.nbytes > 0) { | |
37 | u8 *dst = walk.dst.virt.addr; | |
38 | u8 *src = walk.src.virt.addr; | |
39 | int nbytes = walk.nbytes; | |
40 | int tail = 0; | |
41 | ||
42 | if (nbytes < walk.total) { | |
43 | tail = walk.nbytes & (blocksize - 1); | |
44 | nbytes -= tail; | |
45 | } | |
46 | ||
47 | do { | |
48 | int bsize = min(nbytes, blocksize); | |
49 | ||
50 | fn(tfm, walk.iv, buf); | |
51 | ||
52 | crypto_xor_cpy(dst, src, buf, bsize); | |
53 | crypto_inc(walk.iv, blocksize); | |
54 | ||
55 | dst += bsize; | |
56 | src += bsize; | |
57 | nbytes -= bsize; | |
58 | } while (nbytes > 0); | |
59 | ||
60 | err = skcipher_walk_done(&walk, tail); | |
61 | } | |
62 | return err; | |
63 | } | |
64 | ||
5311f248 | 65 | #endif /* _CRYPTO_CTR_H */ |