Blame view
crypto/cbc.c
5.18 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
db131ef90 [CRYPTO] cipher: ... |
2 3 4 |
/* * CBC: Cipher Block Chaining mode * |
cc868d82a crypto: cbc - Exp... |
5 |
* Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au> |
db131ef90 [CRYPTO] cipher: ... |
6 |
*/ |
e6c2e65c7 crypto: cbc - Pro... |
7 |
#include <crypto/algapi.h> |
0eb76ba29 crypto: remove ci... |
8 |
#include <crypto/internal/cipher.h> |
79c65d179 crypto: cbc - Con... |
9 |
#include <crypto/internal/skcipher.h> |
db131ef90 [CRYPTO] cipher: ... |
10 11 12 |
#include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> |
50b6544e1 [CRYPTO] cbc: Req... |
13 |
#include <linux/log2.h> |
db131ef90 [CRYPTO] cipher: ... |
14 |
#include <linux/module.h> |
db131ef90 [CRYPTO] cipher: ... |
15 |
|
5f254dd44 crypto: cbc - Rem... |
16 17 |
static int crypto_cbc_encrypt_segment(struct skcipher_walk *walk, struct crypto_skcipher *skcipher) |
79c65d179 crypto: cbc - Con... |
18 |
{ |
5f254dd44 crypto: cbc - Rem... |
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
unsigned int bsize = crypto_skcipher_blocksize(skcipher); void (*fn)(struct crypto_tfm *, u8 *, const u8 *); unsigned int nbytes = walk->nbytes; u8 *src = walk->src.virt.addr; u8 *dst = walk->dst.virt.addr; struct crypto_cipher *cipher; struct crypto_tfm *tfm; u8 *iv = walk->iv; cipher = skcipher_cipher_simple(skcipher); tfm = crypto_cipher_tfm(cipher); fn = crypto_cipher_alg(cipher)->cia_encrypt; do { crypto_xor(iv, src, bsize); fn(tfm, dst, iv); memcpy(iv, dst, bsize); src += bsize; dst += bsize; } while ((nbytes -= bsize) >= bsize); return nbytes; } static int crypto_cbc_encrypt_inplace(struct skcipher_walk *walk, struct crypto_skcipher *skcipher) { unsigned int bsize = crypto_skcipher_blocksize(skcipher); void (*fn)(struct crypto_tfm *, u8 *, const u8 *); unsigned int nbytes = walk->nbytes; u8 *src = walk->src.virt.addr; struct crypto_cipher *cipher; struct crypto_tfm *tfm; u8 *iv = walk->iv; cipher = skcipher_cipher_simple(skcipher); tfm = crypto_cipher_tfm(cipher); fn = crypto_cipher_alg(cipher)->cia_encrypt; do { crypto_xor(src, iv, bsize); fn(tfm, src, src); iv = src; src += bsize; } while ((nbytes -= bsize) >= bsize); memcpy(walk->iv, iv, bsize); return nbytes; |
79c65d179 crypto: cbc - Con... |
70 71 72 |
} static int crypto_cbc_encrypt(struct skcipher_request *req) |
db131ef90 [CRYPTO] cipher: ... |
73 |
{ |
5f254dd44 crypto: cbc - Rem... |
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); struct skcipher_walk walk; int err; err = skcipher_walk_virt(&walk, req, false); while (walk.nbytes) { if (walk.src.virt.addr == walk.dst.virt.addr) err = crypto_cbc_encrypt_inplace(&walk, skcipher); else err = crypto_cbc_encrypt_segment(&walk, skcipher); err = skcipher_walk_done(&walk, err); } return err; } static int crypto_cbc_decrypt_segment(struct skcipher_walk *walk, struct crypto_skcipher *skcipher) { unsigned int bsize = crypto_skcipher_blocksize(skcipher); void (*fn)(struct crypto_tfm *, u8 *, const u8 *); unsigned int nbytes = walk->nbytes; u8 *src = walk->src.virt.addr; u8 *dst = walk->dst.virt.addr; struct crypto_cipher *cipher; struct crypto_tfm *tfm; u8 *iv = walk->iv; cipher = skcipher_cipher_simple(skcipher); tfm = crypto_cipher_tfm(cipher); fn = crypto_cipher_alg(cipher)->cia_decrypt; do { fn(tfm, dst, src); crypto_xor(dst, iv, bsize); iv = src; src += bsize; dst += bsize; } while ((nbytes -= bsize) >= bsize); memcpy(walk->iv, iv, bsize); return nbytes; |
79c65d179 crypto: cbc - Con... |
119 |
} |
5f254dd44 crypto: cbc - Rem... |
120 121 |
static int crypto_cbc_decrypt_inplace(struct skcipher_walk *walk, struct crypto_skcipher *skcipher) |
79c65d179 crypto: cbc - Con... |
122 |
{ |
5f254dd44 crypto: cbc - Rem... |
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
unsigned int bsize = crypto_skcipher_blocksize(skcipher); void (*fn)(struct crypto_tfm *, u8 *, const u8 *); unsigned int nbytes = walk->nbytes; u8 *src = walk->src.virt.addr; u8 last_iv[MAX_CIPHER_BLOCKSIZE]; struct crypto_cipher *cipher; struct crypto_tfm *tfm; cipher = skcipher_cipher_simple(skcipher); tfm = crypto_cipher_tfm(cipher); fn = crypto_cipher_alg(cipher)->cia_decrypt; /* Start of the last block. */ src += nbytes - (nbytes & (bsize - 1)) - bsize; memcpy(last_iv, src, bsize); for (;;) { fn(tfm, src, src); if ((nbytes -= bsize) < bsize) break; crypto_xor(src, src - bsize, bsize); src -= bsize; } crypto_xor(src, walk->iv, bsize); memcpy(walk->iv, last_iv, bsize); return nbytes; |
79c65d179 crypto: cbc - Con... |
151 152 153 154 |
} static int crypto_cbc_decrypt(struct skcipher_request *req) { |
5f254dd44 crypto: cbc - Rem... |
155 |
struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); |
79c65d179 crypto: cbc - Con... |
156 |
struct skcipher_walk walk; |
db131ef90 [CRYPTO] cipher: ... |
157 |
int err; |
79c65d179 crypto: cbc - Con... |
158 |
err = skcipher_walk_virt(&walk, req, false); |
db131ef90 [CRYPTO] cipher: ... |
159 |
|
79c65d179 crypto: cbc - Con... |
160 |
while (walk.nbytes) { |
5f254dd44 crypto: cbc - Rem... |
161 162 163 164 |
if (walk.src.virt.addr == walk.dst.virt.addr) err = crypto_cbc_decrypt_inplace(&walk, skcipher); else err = crypto_cbc_decrypt_segment(&walk, skcipher); |
79c65d179 crypto: cbc - Con... |
165 |
err = skcipher_walk_done(&walk, err); |
db131ef90 [CRYPTO] cipher: ... |
166 167 168 169 |
} return err; } |
79c65d179 crypto: cbc - Con... |
170 171 172 |
static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) { struct skcipher_instance *inst; |
db131ef90 [CRYPTO] cipher: ... |
173 |
struct crypto_alg *alg; |
ebc610e5b [CRYPTO] template... |
174 |
int err; |
b3c16bfc6 crypto: skcipher ... |
175 |
inst = skcipher_alloc_instance_simple(tmpl, tb); |
a5a84a9db crypto: cbc - con... |
176 177 |
if (IS_ERR(inst)) return PTR_ERR(inst); |
50b6544e1 [CRYPTO] cbc: Req... |
178 |
|
b3c16bfc6 crypto: skcipher ... |
179 |
alg = skcipher_ialg_simple(inst); |
79c65d179 crypto: cbc - Con... |
180 181 |
err = -EINVAL; if (!is_power_of_2(alg->cra_blocksize)) |
a5a84a9db crypto: cbc - con... |
182 |
goto out_free_inst; |
db131ef90 [CRYPTO] cipher: ... |
183 |
|
79c65d179 crypto: cbc - Con... |
184 185 |
inst->alg.encrypt = crypto_cbc_encrypt; inst->alg.decrypt = crypto_cbc_decrypt; |
db131ef90 [CRYPTO] cipher: ... |
186 |
|
79c65d179 crypto: cbc - Con... |
187 |
err = skcipher_register_instance(tmpl, inst); |
b3c16bfc6 crypto: skcipher ... |
188 |
if (err) { |
a5a84a9db crypto: cbc - con... |
189 |
out_free_inst: |
b3c16bfc6 crypto: skcipher ... |
190 191 |
inst->free(inst); } |
a5a84a9db crypto: cbc - con... |
192 |
return err; |
db131ef90 [CRYPTO] cipher: ... |
193 194 195 196 |
} static struct crypto_template crypto_cbc_tmpl = { .name = "cbc", |
79c65d179 crypto: cbc - Con... |
197 |
.create = crypto_cbc_create, |
db131ef90 [CRYPTO] cipher: ... |
198 199 200 201 202 203 204 205 206 207 208 209 |
.module = THIS_MODULE, }; static int __init crypto_cbc_module_init(void) { return crypto_register_template(&crypto_cbc_tmpl); } static void __exit crypto_cbc_module_exit(void) { crypto_unregister_template(&crypto_cbc_tmpl); } |
c4741b230 crypto: run initc... |
210 |
subsys_initcall(crypto_cbc_module_init); |
db131ef90 [CRYPTO] cipher: ... |
211 212 213 |
module_exit(crypto_cbc_module_exit); MODULE_LICENSE("GPL"); |
a5a84a9db crypto: cbc - con... |
214 |
MODULE_DESCRIPTION("CBC block cipher mode of operation"); |
4943ba16b crypto: include c... |
215 |
MODULE_ALIAS_CRYPTO("cbc"); |