diff options
| author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2011-11-08 22:56:06 -0500 |
|---|---|---|
| committer | Herbert Xu <herbert@gondor.apana.org.au> | 2011-11-08 22:56:06 -0500 |
| commit | ce0045561e1edb92e4a509eb433ff52d3afaa258 (patch) | |
| tree | 78c8a6fcd82d966aca6a48d17c9063de34e224e9 | |
| parent | f9d2691fc9a00f39b587f965c33cca012a5597bc (diff) | |
crypto: xts: add interface for parallelized cipher implementations
Add xts_crypt() function that can be used by cipher implementations that can
benefit from parallelized cipher operations.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
| -rw-r--r-- | crypto/xts.c | 75 | ||||
| -rw-r--r-- | include/crypto/xts.h | 27 |
2 files changed, 100 insertions, 2 deletions
diff --git a/crypto/xts.c b/crypto/xts.c index 96f3f88d576e..ca1608f44cb5 100644 --- a/crypto/xts.c +++ b/crypto/xts.c | |||
| @@ -21,11 +21,10 @@ | |||
| 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 | ||
| 27 | #define XTS_BLOCK_SIZE 16 | ||
| 28 | |||
| 29 | struct priv { | 28 | struct priv { |
| 30 | struct crypto_cipher *child; | 29 | struct crypto_cipher *child; |
| 31 | struct crypto_cipher *tweak; | 30 | struct crypto_cipher *tweak; |
| @@ -167,6 +166,78 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, | |||
| 167 | crypto_cipher_alg(ctx->child)->cia_decrypt); | 166 | crypto_cipher_alg(ctx->child)->cia_decrypt); |
| 168 | } | 167 | } |
| 169 | 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 | |||
| 170 | static int init_tfm(struct crypto_tfm *tfm) | 241 | static int init_tfm(struct crypto_tfm *tfm) |
| 171 | { | 242 | { |
| 172 | struct crypto_cipher *cipher; | 243 | struct crypto_cipher *cipher; |
diff --git a/include/crypto/xts.h b/include/crypto/xts.h new file mode 100644 index 000000000000..72c09eb56437 --- /dev/null +++ b/include/crypto/xts.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef _CRYPTO_XTS_H | ||
| 2 | #define _CRYPTO_XTS_H | ||
| 3 | |||
| 4 | #include <crypto/b128ops.h> | ||
| 5 | |||
| 6 | struct scatterlist; | ||
| 7 | struct blkcipher_desc; | ||
| 8 | |||
| 9 | #define XTS_BLOCK_SIZE 16 | ||
| 10 | |||
| 11 | struct xts_crypt_req { | ||
| 12 | be128 *tbuf; | ||
| 13 | unsigned int tbuflen; | ||
| 14 | |||
| 15 | void *tweak_ctx; | ||
| 16 | void (*tweak_fn)(void *ctx, u8* dst, const u8* src); | ||
| 17 | void *crypt_ctx; | ||
| 18 | void (*crypt_fn)(void *ctx, u8 *blks, unsigned int nbytes); | ||
| 19 | }; | ||
| 20 | |||
| 21 | #define XTS_TWEAK_CAST(x) ((void (*)(void *, u8*, const u8*))(x)) | ||
| 22 | |||
| 23 | int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *dst, | ||
| 24 | struct scatterlist *src, unsigned int nbytes, | ||
| 25 | struct xts_crypt_req *req); | ||
| 26 | |||
| 27 | #endif /* _CRYPTO_XTS_H */ | ||
