diff options
Diffstat (limited to 'crypto/xts.c')
-rw-r--r-- | crypto/xts.c | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/crypto/xts.c b/crypto/xts.c index 851705446c82..ca1608f44cb5 100644 --- a/crypto/xts.c +++ b/crypto/xts.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | 23 | ||
24 | #include <crypto/xts.h> | ||
24 | #include <crypto/b128ops.h> | 25 | #include <crypto/b128ops.h> |
25 | #include <crypto/gf128mul.h> | 26 | #include <crypto/gf128mul.h> |
26 | 27 | ||
@@ -96,7 +97,7 @@ static int crypt(struct blkcipher_desc *d, | |||
96 | { | 97 | { |
97 | int err; | 98 | int err; |
98 | unsigned int avail; | 99 | unsigned int avail; |
99 | const int bs = crypto_cipher_blocksize(ctx->child); | 100 | const int bs = XTS_BLOCK_SIZE; |
100 | struct sinfo s = { | 101 | struct sinfo s = { |
101 | .tfm = crypto_cipher_tfm(ctx->child), | 102 | .tfm = crypto_cipher_tfm(ctx->child), |
102 | .fn = fn | 103 | .fn = fn |
@@ -165,6 +166,78 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | |||
165 | crypto_cipher_alg(ctx->child)->cia_decrypt); | 166 | crypto_cipher_alg(ctx->child)->cia_decrypt); |
166 | } | 167 | } |
167 | 168 | ||
169 | int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst, | ||
170 | struct scatterlist *ssrc, unsigned int nbytes, | ||
171 | struct xts_crypt_req *req) | ||
172 | { | ||
173 | const unsigned int bsize = XTS_BLOCK_SIZE; | ||
174 | const unsigned int max_blks = req->tbuflen / bsize; | ||
175 | struct blkcipher_walk walk; | ||
176 | unsigned int nblocks; | ||
177 | be128 *src, *dst, *t; | ||
178 | be128 *t_buf = req->tbuf; | ||
179 | int err, i; | ||
180 | |||
181 | BUG_ON(max_blks < 1); | ||
182 | |||
183 | blkcipher_walk_init(&walk, sdst, ssrc, nbytes); | ||
184 | |||
185 | err = blkcipher_walk_virt(desc, &walk); | ||
186 | nbytes = walk.nbytes; | ||
187 | if (!nbytes) | ||
188 | return err; | ||
189 | |||
190 | nblocks = min(nbytes / bsize, max_blks); | ||
191 | src = (be128 *)walk.src.virt.addr; | ||
192 | dst = (be128 *)walk.dst.virt.addr; | ||
193 | |||
194 | /* calculate first value of T */ | ||
195 | req->tweak_fn(req->tweak_ctx, (u8 *)&t_buf[0], walk.iv); | ||
196 | |||
197 | i = 0; | ||
198 | goto first; | ||
199 | |||
200 | for (;;) { | ||
201 | do { | ||
202 | for (i = 0; i < nblocks; i++) { | ||
203 | gf128mul_x_ble(&t_buf[i], t); | ||
204 | first: | ||
205 | t = &t_buf[i]; | ||
206 | |||
207 | /* PP <- T xor P */ | ||
208 | be128_xor(dst + i, t, src + i); | ||
209 | } | ||
210 | |||
211 | /* CC <- E(Key2,PP) */ | ||
212 | req->crypt_fn(req->crypt_ctx, (u8 *)dst, | ||
213 | nblocks * bsize); | ||
214 | |||
215 | /* C <- T xor CC */ | ||
216 | for (i = 0; i < nblocks; i++) | ||
217 | be128_xor(dst + i, dst + i, &t_buf[i]); | ||
218 | |||
219 | src += nblocks; | ||
220 | dst += nblocks; | ||
221 | nbytes -= nblocks * bsize; | ||
222 | nblocks = min(nbytes / bsize, max_blks); | ||
223 | } while (nblocks > 0); | ||
224 | |||
225 | *(be128 *)walk.iv = *t; | ||
226 | |||
227 | err = blkcipher_walk_done(desc, &walk, nbytes); | ||
228 | nbytes = walk.nbytes; | ||
229 | if (!nbytes) | ||
230 | break; | ||
231 | |||
232 | nblocks = min(nbytes / bsize, max_blks); | ||
233 | src = (be128 *)walk.src.virt.addr; | ||
234 | dst = (be128 *)walk.dst.virt.addr; | ||
235 | } | ||
236 | |||
237 | return err; | ||
238 | } | ||
239 | EXPORT_SYMBOL_GPL(xts_crypt); | ||
240 | |||
168 | static int init_tfm(struct crypto_tfm *tfm) | 241 | static int init_tfm(struct crypto_tfm *tfm) |
169 | { | 242 | { |
170 | struct crypto_cipher *cipher; | 243 | struct crypto_cipher *cipher; |
@@ -177,7 +250,7 @@ static int init_tfm(struct crypto_tfm *tfm) | |||
177 | if (IS_ERR(cipher)) | 250 | if (IS_ERR(cipher)) |
178 | return PTR_ERR(cipher); | 251 | return PTR_ERR(cipher); |
179 | 252 | ||
180 | if (crypto_cipher_blocksize(cipher) != 16) { | 253 | if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) { |
181 | *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; | 254 | *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; |
182 | crypto_free_cipher(cipher); | 255 | crypto_free_cipher(cipher); |
183 | return -EINVAL; | 256 | return -EINVAL; |
@@ -192,7 +265,7 @@ static int init_tfm(struct crypto_tfm *tfm) | |||
192 | } | 265 | } |
193 | 266 | ||
194 | /* this check isn't really needed, leave it here just in case */ | 267 | /* this check isn't really needed, leave it here just in case */ |
195 | if (crypto_cipher_blocksize(cipher) != 16) { | 268 | if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) { |
196 | crypto_free_cipher(cipher); | 269 | crypto_free_cipher(cipher); |
197 | crypto_free_cipher(ctx->child); | 270 | crypto_free_cipher(ctx->child); |
198 | *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; | 271 | *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; |