Blame view
crypto/cbc.c
5.15 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> |
79c65d179 crypto: cbc - Con... |
8 |
#include <crypto/internal/skcipher.h> |
db131ef90 [CRYPTO] cipher: ... |
9 10 11 |
#include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> |
50b6544e1 [CRYPTO] cbc: Req... |
12 |
#include <linux/log2.h> |
db131ef90 [CRYPTO] cipher: ... |
13 |
#include <linux/module.h> |
db131ef90 [CRYPTO] cipher: ... |
14 |
|
5f254dd44 crypto: cbc - Rem... |
15 16 |
static int crypto_cbc_encrypt_segment(struct skcipher_walk *walk, struct crypto_skcipher *skcipher) |
79c65d179 crypto: cbc - Con... |
17 |
{ |
5f254dd44 crypto: cbc - Rem... |
18 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 |
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... |
69 70 71 |
} static int crypto_cbc_encrypt(struct skcipher_request *req) |
db131ef90 [CRYPTO] cipher: ... |
72 |
{ |
5f254dd44 crypto: cbc - Rem... |
73 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 |
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... |
118 |
} |
5f254dd44 crypto: cbc - Rem... |
119 120 |
static int crypto_cbc_decrypt_inplace(struct skcipher_walk *walk, struct crypto_skcipher *skcipher) |
79c65d179 crypto: cbc - Con... |
121 |
{ |
5f254dd44 crypto: cbc - Rem... |
122 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 |
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... |
150 151 152 153 |
} static int crypto_cbc_decrypt(struct skcipher_request *req) { |
5f254dd44 crypto: cbc - Rem... |
154 |
struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); |
79c65d179 crypto: cbc - Con... |
155 |
struct skcipher_walk walk; |
db131ef90 [CRYPTO] cipher: ... |
156 |
int err; |
79c65d179 crypto: cbc - Con... |
157 |
err = skcipher_walk_virt(&walk, req, false); |
db131ef90 [CRYPTO] cipher: ... |
158 |
|
79c65d179 crypto: cbc - Con... |
159 |
while (walk.nbytes) { |
5f254dd44 crypto: cbc - Rem... |
160 161 162 163 |
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... |
164 |
err = skcipher_walk_done(&walk, err); |
db131ef90 [CRYPTO] cipher: ... |
165 166 167 168 |
} return err; } |
79c65d179 crypto: cbc - Con... |
169 170 171 |
static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) { struct skcipher_instance *inst; |
db131ef90 [CRYPTO] cipher: ... |
172 |
struct crypto_alg *alg; |
ebc610e5b [CRYPTO] template... |
173 |
int err; |
b3c16bfc6 crypto: skcipher ... |
174 |
inst = skcipher_alloc_instance_simple(tmpl, tb); |
a5a84a9db crypto: cbc - con... |
175 176 |
if (IS_ERR(inst)) return PTR_ERR(inst); |
50b6544e1 [CRYPTO] cbc: Req... |
177 |
|
b3c16bfc6 crypto: skcipher ... |
178 |
alg = skcipher_ialg_simple(inst); |
79c65d179 crypto: cbc - Con... |
179 180 |
err = -EINVAL; if (!is_power_of_2(alg->cra_blocksize)) |
a5a84a9db crypto: cbc - con... |
181 |
goto out_free_inst; |
db131ef90 [CRYPTO] cipher: ... |
182 |
|
79c65d179 crypto: cbc - Con... |
183 184 |
inst->alg.encrypt = crypto_cbc_encrypt; inst->alg.decrypt = crypto_cbc_decrypt; |
db131ef90 [CRYPTO] cipher: ... |
185 |
|
79c65d179 crypto: cbc - Con... |
186 |
err = skcipher_register_instance(tmpl, inst); |
b3c16bfc6 crypto: skcipher ... |
187 |
if (err) { |
a5a84a9db crypto: cbc - con... |
188 |
out_free_inst: |
b3c16bfc6 crypto: skcipher ... |
189 190 |
inst->free(inst); } |
a5a84a9db crypto: cbc - con... |
191 |
return err; |
db131ef90 [CRYPTO] cipher: ... |
192 193 194 195 |
} static struct crypto_template crypto_cbc_tmpl = { .name = "cbc", |
79c65d179 crypto: cbc - Con... |
196 |
.create = crypto_cbc_create, |
db131ef90 [CRYPTO] cipher: ... |
197 198 199 200 201 202 203 204 205 206 207 208 |
.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... |
209 |
subsys_initcall(crypto_cbc_module_init); |
db131ef90 [CRYPTO] cipher: ... |
210 211 212 |
module_exit(crypto_cbc_module_exit); MODULE_LICENSE("GPL"); |
a5a84a9db crypto: cbc - con... |
213 |
MODULE_DESCRIPTION("CBC block cipher mode of operation"); |
4943ba16b crypto: include c... |
214 |
MODULE_ALIAS_CRYPTO("cbc"); |