Skip to content

Commit 7607bd8

Browse files
herbertxDavid S. Miller
authored andcommitted
[CRYPTO] blkcipher: Added blkcipher_walk_virt_block
This patch adds the helper blkcipher_walk_virt_block which is similar to blkcipher_walk_virt but uses a supplied block size instead of the block size of the block cipher. This is useful for CTR where the block size is 1 but we still want to walk by the block size of the underlying cipher. Signed-off-by: Herbert Xu <[email protected]>
1 parent 2614de1 commit 7607bd8

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

crypto/blkcipher.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm,
8484
static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk,
8585
unsigned int n)
8686
{
87-
n = walk->nbytes - n;
88-
8987
if (walk->flags & BLKCIPHER_WALK_COPY) {
9088
blkcipher_map_dst(walk);
9189
memcpy(walk->dst.virt.addr, walk->page, n);
@@ -109,13 +107,15 @@ int blkcipher_walk_done(struct blkcipher_desc *desc,
109107
unsigned int nbytes = 0;
110108

111109
if (likely(err >= 0)) {
112-
unsigned int bsize = crypto_blkcipher_blocksize(tfm);
113-
unsigned int n;
110+
unsigned int n = walk->nbytes - err;
114111

115112
if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW)))
116-
n = blkcipher_done_fast(walk, err);
117-
else
118-
n = blkcipher_done_slow(tfm, walk, bsize);
113+
n = blkcipher_done_fast(walk, n);
114+
else if (WARN_ON(err)) {
115+
err = -EINVAL;
116+
goto err;
117+
} else
118+
n = blkcipher_done_slow(tfm, walk, n);
119119

120120
nbytes = walk->total - n;
121121
err = 0;
@@ -132,6 +132,7 @@ int blkcipher_walk_done(struct blkcipher_desc *desc,
132132
return blkcipher_walk_next(desc, walk);
133133
}
134134

135+
err:
135136
if (walk->iv != desc->info)
136137
memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm));
137138
if (walk->buffer != walk->page)
@@ -225,12 +226,12 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc,
225226
{
226227
struct crypto_blkcipher *tfm = desc->tfm;
227228
unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
228-
unsigned int bsize = crypto_blkcipher_blocksize(tfm);
229+
unsigned int bsize;
229230
unsigned int n;
230231
int err;
231232

232233
n = walk->total;
233-
if (unlikely(n < bsize)) {
234+
if (unlikely(n < crypto_blkcipher_blocksize(tfm))) {
234235
desc->flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
235236
return blkcipher_walk_done(desc, walk, -EINVAL);
236237
}
@@ -247,6 +248,7 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc,
247248
}
248249
}
249250

251+
bsize = min(walk->blocksize, n);
250252
n = scatterwalk_clamp(&walk->in, n);
251253
n = scatterwalk_clamp(&walk->out, n);
252254

@@ -277,7 +279,7 @@ static inline int blkcipher_copy_iv(struct blkcipher_walk *walk,
277279
struct crypto_blkcipher *tfm,
278280
unsigned int alignmask)
279281
{
280-
unsigned bs = crypto_blkcipher_blocksize(tfm);
282+
unsigned bs = walk->blocksize;
281283
unsigned int ivsize = crypto_blkcipher_ivsize(tfm);
282284
unsigned aligned_bs = ALIGN(bs, alignmask + 1);
283285
unsigned int size = aligned_bs * 2 + ivsize + max(aligned_bs, ivsize) -
@@ -302,6 +304,7 @@ int blkcipher_walk_virt(struct blkcipher_desc *desc,
302304
struct blkcipher_walk *walk)
303305
{
304306
walk->flags &= ~BLKCIPHER_WALK_PHYS;
307+
walk->blocksize = crypto_blkcipher_blocksize(desc->tfm);
305308
return blkcipher_walk_first(desc, walk);
306309
}
307310
EXPORT_SYMBOL_GPL(blkcipher_walk_virt);
@@ -310,6 +313,7 @@ int blkcipher_walk_phys(struct blkcipher_desc *desc,
310313
struct blkcipher_walk *walk)
311314
{
312315
walk->flags |= BLKCIPHER_WALK_PHYS;
316+
walk->blocksize = crypto_blkcipher_blocksize(desc->tfm);
313317
return blkcipher_walk_first(desc, walk);
314318
}
315319
EXPORT_SYMBOL_GPL(blkcipher_walk_phys);
@@ -342,6 +346,16 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
342346
return blkcipher_walk_next(desc, walk);
343347
}
344348

349+
int blkcipher_walk_virt_block(struct blkcipher_desc *desc,
350+
struct blkcipher_walk *walk,
351+
unsigned int blocksize)
352+
{
353+
walk->flags &= ~BLKCIPHER_WALK_PHYS;
354+
walk->blocksize = blocksize;
355+
return blkcipher_walk_first(desc, walk);
356+
}
357+
EXPORT_SYMBOL_GPL(blkcipher_walk_virt_block);
358+
345359
static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
346360
unsigned int keylen)
347361
{

include/crypto/algapi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ struct blkcipher_walk {
9191
u8 *iv;
9292

9393
int flags;
94+
unsigned int blocksize;
9495
};
9596

9697
extern const struct crypto_type crypto_ablkcipher_type;
@@ -129,6 +130,9 @@ int blkcipher_walk_virt(struct blkcipher_desc *desc,
129130
struct blkcipher_walk *walk);
130131
int blkcipher_walk_phys(struct blkcipher_desc *desc,
131132
struct blkcipher_walk *walk);
133+
int blkcipher_walk_virt_block(struct blkcipher_desc *desc,
134+
struct blkcipher_walk *walk,
135+
unsigned int blocksize);
132136

133137
static inline void *crypto_tfm_ctx_aligned(struct crypto_tfm *tfm)
134138
{

0 commit comments

Comments
 (0)