Blame view

crypto/pcbc.c 4.65 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
2
3
4
5
6
7
8
9
  /*
   * PCBC: Propagating Cipher Block Chaining mode
   *
   * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * Derived from cbc.c
   * - Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
10
   */
6650c4de6   Salvatore Mesoraca   crypto: remove se...
11
  #include <crypto/algapi.h>
043a44001   Herbert Xu   crypto: pcbc - Co...
12
  #include <crypto/internal/skcipher.h>
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
13
14
15
16
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
17

043a44001   Herbert Xu   crypto: pcbc - Co...
18
19
  static int crypto_pcbc_encrypt_segment(struct skcipher_request *req,
  				       struct skcipher_walk *walk,
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
20
  				       struct crypto_cipher *tfm)
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
21
  {
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
22
23
24
25
  	int bsize = crypto_cipher_blocksize(tfm);
  	unsigned int nbytes = walk->nbytes;
  	u8 *src = walk->src.virt.addr;
  	u8 *dst = walk->dst.virt.addr;
251b7aea3   Eric Biggers   crypto: pcbc - re...
26
  	u8 * const iv = walk->iv;
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
27
28
  
  	do {
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
29
  		crypto_xor(iv, src, bsize);
043a44001   Herbert Xu   crypto: pcbc - Co...
30
  		crypto_cipher_encrypt_one(tfm, dst, iv);
45fe93dff   Ard Biesheuvel   crypto: algapi - ...
31
  		crypto_xor_cpy(iv, dst, src, bsize);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
32
33
34
35
36
37
38
  
  		src += bsize;
  		dst += bsize;
  	} while ((nbytes -= bsize) >= bsize);
  
  	return nbytes;
  }
043a44001   Herbert Xu   crypto: pcbc - Co...
39
40
  static int crypto_pcbc_encrypt_inplace(struct skcipher_request *req,
  				       struct skcipher_walk *walk,
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
41
  				       struct crypto_cipher *tfm)
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
42
  {
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
43
44
45
  	int bsize = crypto_cipher_blocksize(tfm);
  	unsigned int nbytes = walk->nbytes;
  	u8 *src = walk->src.virt.addr;
251b7aea3   Eric Biggers   crypto: pcbc - re...
46
  	u8 * const iv = walk->iv;
6650c4de6   Salvatore Mesoraca   crypto: remove se...
47
  	u8 tmpbuf[MAX_CIPHER_BLOCKSIZE];
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
48
49
50
  
  	do {
  		memcpy(tmpbuf, src, bsize);
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
51
  		crypto_xor(iv, src, bsize);
043a44001   Herbert Xu   crypto: pcbc - Co...
52
  		crypto_cipher_encrypt_one(tfm, src, iv);
45fe93dff   Ard Biesheuvel   crypto: algapi - ...
53
  		crypto_xor_cpy(iv, tmpbuf, src, bsize);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
54
55
56
  
  		src += bsize;
  	} while ((nbytes -= bsize) >= bsize);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
57
58
  	return nbytes;
  }
043a44001   Herbert Xu   crypto: pcbc - Co...
59
  static int crypto_pcbc_encrypt(struct skcipher_request *req)
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
60
  {
043a44001   Herbert Xu   crypto: pcbc - Co...
61
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0be487ba2   Eric Biggers   crypto: pcbc - co...
62
  	struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
043a44001   Herbert Xu   crypto: pcbc - Co...
63
64
  	struct skcipher_walk walk;
  	unsigned int nbytes;
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
65
  	int err;
043a44001   Herbert Xu   crypto: pcbc - Co...
66
  	err = skcipher_walk_virt(&walk, req, false);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
67
68
69
  
  	while ((nbytes = walk.nbytes)) {
  		if (walk.src.virt.addr == walk.dst.virt.addr)
043a44001   Herbert Xu   crypto: pcbc - Co...
70
  			nbytes = crypto_pcbc_encrypt_inplace(req, &walk,
0be487ba2   Eric Biggers   crypto: pcbc - co...
71
  							     cipher);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
72
  		else
043a44001   Herbert Xu   crypto: pcbc - Co...
73
  			nbytes = crypto_pcbc_encrypt_segment(req, &walk,
0be487ba2   Eric Biggers   crypto: pcbc - co...
74
  							     cipher);
043a44001   Herbert Xu   crypto: pcbc - Co...
75
  		err = skcipher_walk_done(&walk, nbytes);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
76
77
78
79
  	}
  
  	return err;
  }
043a44001   Herbert Xu   crypto: pcbc - Co...
80
81
  static int crypto_pcbc_decrypt_segment(struct skcipher_request *req,
  				       struct skcipher_walk *walk,
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
82
  				       struct crypto_cipher *tfm)
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
83
  {
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
84
85
86
87
  	int bsize = crypto_cipher_blocksize(tfm);
  	unsigned int nbytes = walk->nbytes;
  	u8 *src = walk->src.virt.addr;
  	u8 *dst = walk->dst.virt.addr;
251b7aea3   Eric Biggers   crypto: pcbc - re...
88
  	u8 * const iv = walk->iv;
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
89
90
  
  	do {
043a44001   Herbert Xu   crypto: pcbc - Co...
91
  		crypto_cipher_decrypt_one(tfm, dst, src);
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
92
  		crypto_xor(dst, iv, bsize);
45fe93dff   Ard Biesheuvel   crypto: algapi - ...
93
  		crypto_xor_cpy(iv, dst, src, bsize);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
94
95
96
97
  
  		src += bsize;
  		dst += bsize;
  	} while ((nbytes -= bsize) >= bsize);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
98
99
  	return nbytes;
  }
043a44001   Herbert Xu   crypto: pcbc - Co...
100
101
  static int crypto_pcbc_decrypt_inplace(struct skcipher_request *req,
  				       struct skcipher_walk *walk,
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
102
  				       struct crypto_cipher *tfm)
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
103
  {
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
104
105
106
  	int bsize = crypto_cipher_blocksize(tfm);
  	unsigned int nbytes = walk->nbytes;
  	u8 *src = walk->src.virt.addr;
251b7aea3   Eric Biggers   crypto: pcbc - re...
107
  	u8 * const iv = walk->iv;
6650c4de6   Salvatore Mesoraca   crypto: remove se...
108
  	u8 tmpbuf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(u32));
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
109
110
111
  
  	do {
  		memcpy(tmpbuf, src, bsize);
043a44001   Herbert Xu   crypto: pcbc - Co...
112
  		crypto_cipher_decrypt_one(tfm, src, src);
d0b9007a2   Herbert Xu   [CRYPTO] pcbc: Us...
113
  		crypto_xor(src, iv, bsize);
45fe93dff   Ard Biesheuvel   crypto: algapi - ...
114
  		crypto_xor_cpy(iv, src, tmpbuf, bsize);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
115
116
117
  
  		src += bsize;
  	} while ((nbytes -= bsize) >= bsize);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
118
119
  	return nbytes;
  }
043a44001   Herbert Xu   crypto: pcbc - Co...
120
  static int crypto_pcbc_decrypt(struct skcipher_request *req)
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
121
  {
043a44001   Herbert Xu   crypto: pcbc - Co...
122
  	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0be487ba2   Eric Biggers   crypto: pcbc - co...
123
  	struct crypto_cipher *cipher = skcipher_cipher_simple(tfm);
043a44001   Herbert Xu   crypto: pcbc - Co...
124
125
  	struct skcipher_walk walk;
  	unsigned int nbytes;
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
126
  	int err;
043a44001   Herbert Xu   crypto: pcbc - Co...
127
  	err = skcipher_walk_virt(&walk, req, false);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
128
129
130
  
  	while ((nbytes = walk.nbytes)) {
  		if (walk.src.virt.addr == walk.dst.virt.addr)
043a44001   Herbert Xu   crypto: pcbc - Co...
131
  			nbytes = crypto_pcbc_decrypt_inplace(req, &walk,
0be487ba2   Eric Biggers   crypto: pcbc - co...
132
  							     cipher);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
133
  		else
043a44001   Herbert Xu   crypto: pcbc - Co...
134
  			nbytes = crypto_pcbc_decrypt_segment(req, &walk,
0be487ba2   Eric Biggers   crypto: pcbc - co...
135
  							     cipher);
043a44001   Herbert Xu   crypto: pcbc - Co...
136
  		err = skcipher_walk_done(&walk, nbytes);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
137
138
139
140
  	}
  
  	return err;
  }
043a44001   Herbert Xu   crypto: pcbc - Co...
141
  static int crypto_pcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
142
  {
043a44001   Herbert Xu   crypto: pcbc - Co...
143
  	struct skcipher_instance *inst;
ebc610e5b   Herbert Xu   [CRYPTO] template...
144
  	int err;
b3c16bfc6   Herbert Xu   crypto: skcipher ...
145
  	inst = skcipher_alloc_instance_simple(tmpl, tb);
0be487ba2   Eric Biggers   crypto: pcbc - co...
146
147
  	if (IS_ERR(inst))
  		return PTR_ERR(inst);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
148

043a44001   Herbert Xu   crypto: pcbc - Co...
149
150
  	inst->alg.encrypt = crypto_pcbc_encrypt;
  	inst->alg.decrypt = crypto_pcbc_decrypt;
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
151

043a44001   Herbert Xu   crypto: pcbc - Co...
152
153
  	err = skcipher_register_instance(tmpl, inst);
  	if (err)
0be487ba2   Eric Biggers   crypto: pcbc - co...
154
  		inst->free(inst);
b3c16bfc6   Herbert Xu   crypto: skcipher ...
155

043a44001   Herbert Xu   crypto: pcbc - Co...
156
  	return err;
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
157
158
159
160
  }
  
  static struct crypto_template crypto_pcbc_tmpl = {
  	.name = "pcbc",
043a44001   Herbert Xu   crypto: pcbc - Co...
161
  	.create = crypto_pcbc_create,
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
162
163
164
165
166
167
168
169
170
171
172
173
  	.module = THIS_MODULE,
  };
  
  static int __init crypto_pcbc_module_init(void)
  {
  	return crypto_register_template(&crypto_pcbc_tmpl);
  }
  
  static void __exit crypto_pcbc_module_exit(void)
  {
  	crypto_unregister_template(&crypto_pcbc_tmpl);
  }
c4741b230   Eric Biggers   crypto: run initc...
174
  subsys_initcall(crypto_pcbc_module_init);
91652be5d   David Howells   [CRYPTO] pcbc: Ad...
175
176
177
  module_exit(crypto_pcbc_module_exit);
  
  MODULE_LICENSE("GPL");
0be487ba2   Eric Biggers   crypto: pcbc - co...
178
  MODULE_DESCRIPTION("PCBC block cipher mode of operation");
4943ba16b   Kees Cook   crypto: include c...
179
  MODULE_ALIAS_CRYPTO("pcbc");