aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2012-12-28 05:04:58 -0500
committerSteffen Klassert <steffen.klassert@secunet.com>2013-01-08 01:03:04 -0500
commit69d3150cfc2075d1693d17dc711de61bf4e4a6c4 (patch)
treed7adbb68df3daa6d6f8fc39b1b27c0255083f9db /crypto
parent71331da500cc13dc3c7e5db397d553c80b2e9994 (diff)
crypto: ctr - make rfc3686 asynchronous block cipher
Some hardware crypto drivers register asynchronous ctr(aes), which is left unused in IPSEC because rfc3686 template only supports synchronous block ciphers. Some other drivers register rfc3686(ctr(aes)) to workaround this limitation but not all. This patch changes rfc3686 to use asynchronous block ciphers, to allow async ctr(aes) algorithms to be utilized automatically by IPSEC. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/ctr.c173
-rw-r--r--crypto/tcrypt.c4
-rw-r--r--crypto/tcrypt.h1
3 files changed, 115 insertions, 63 deletions
diff --git a/crypto/ctr.c b/crypto/ctr.c
index 4ca7222cfeb6..1f2997cbfdd4 100644
--- a/crypto/ctr.c
+++ b/crypto/ctr.c
@@ -12,6 +12,7 @@
12 12
13#include <crypto/algapi.h> 13#include <crypto/algapi.h>
14#include <crypto/ctr.h> 14#include <crypto/ctr.h>
15#include <crypto/internal/skcipher.h>
15#include <linux/err.h> 16#include <linux/err.h>
16#include <linux/init.h> 17#include <linux/init.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
@@ -25,10 +26,15 @@ struct crypto_ctr_ctx {
25}; 26};
26 27
27struct crypto_rfc3686_ctx { 28struct crypto_rfc3686_ctx {
28 struct crypto_blkcipher *child; 29 struct crypto_ablkcipher *child;
29 u8 nonce[CTR_RFC3686_NONCE_SIZE]; 30 u8 nonce[CTR_RFC3686_NONCE_SIZE];
30}; 31};
31 32
33struct crypto_rfc3686_req_ctx {
34 u8 iv[CTR_RFC3686_BLOCK_SIZE];
35 struct ablkcipher_request subreq CRYPTO_MINALIGN_ATTR;
36};
37
32static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key, 38static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
33 unsigned int keylen) 39 unsigned int keylen)
34{ 40{
@@ -243,11 +249,11 @@ static struct crypto_template crypto_ctr_tmpl = {
243 .module = THIS_MODULE, 249 .module = THIS_MODULE,
244}; 250};
245 251
246static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key, 252static int crypto_rfc3686_setkey(struct crypto_ablkcipher *parent,
247 unsigned int keylen) 253 const u8 *key, unsigned int keylen)
248{ 254{
249 struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent); 255 struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(parent);
250 struct crypto_blkcipher *child = ctx->child; 256 struct crypto_ablkcipher *child = ctx->child;
251 int err; 257 int err;
252 258
253 /* the nonce is stored in bytes at end of key */ 259 /* the nonce is stored in bytes at end of key */
@@ -259,59 +265,64 @@ static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
259 265
260 keylen -= CTR_RFC3686_NONCE_SIZE; 266 keylen -= CTR_RFC3686_NONCE_SIZE;
261 267
262 crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 268 crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
263 crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) & 269 crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(parent) &
264 CRYPTO_TFM_REQ_MASK); 270 CRYPTO_TFM_REQ_MASK);
265 err = crypto_blkcipher_setkey(child, key, keylen); 271 err = crypto_ablkcipher_setkey(child, key, keylen);
266 crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) & 272 crypto_ablkcipher_set_flags(parent, crypto_ablkcipher_get_flags(child) &
267 CRYPTO_TFM_RES_MASK); 273 CRYPTO_TFM_RES_MASK);
268 274
269 return err; 275 return err;
270} 276}
271 277
272static int crypto_rfc3686_crypt(struct blkcipher_desc *desc, 278static int crypto_rfc3686_crypt(struct ablkcipher_request *req)
273 struct scatterlist *dst,
274 struct scatterlist *src, unsigned int nbytes)
275{ 279{
276 struct crypto_blkcipher *tfm = desc->tfm; 280 struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
277 struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm); 281 struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(tfm);
278 struct crypto_blkcipher *child = ctx->child; 282 struct crypto_ablkcipher *child = ctx->child;
279 unsigned long alignmask = crypto_blkcipher_alignmask(tfm); 283 unsigned long align = crypto_ablkcipher_alignmask(tfm);
280 u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask]; 284 struct crypto_rfc3686_req_ctx *rctx =
281 u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1); 285 (void *)PTR_ALIGN((u8 *)ablkcipher_request_ctx(req), align + 1);
282 u8 *info = desc->info; 286 struct ablkcipher_request *subreq = &rctx->subreq;
283 int err; 287 u8 *iv = rctx->iv;
284 288
285 /* set up counter block */ 289 /* set up counter block */
286 memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE); 290 memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
287 memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE); 291 memcpy(iv + CTR_RFC3686_NONCE_SIZE, req->info, CTR_RFC3686_IV_SIZE);
288 292
289 /* initialize counter portion of counter block */ 293 /* initialize counter portion of counter block */
290 *(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) = 294 *(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
291 cpu_to_be32(1); 295 cpu_to_be32(1);
292 296
293 desc->tfm = child; 297 ablkcipher_request_set_tfm(subreq, child);
294 desc->info = iv; 298 ablkcipher_request_set_callback(subreq, req->base.flags,
295 err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes); 299 req->base.complete, req->base.data);
296 desc->tfm = tfm; 300 ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
297 desc->info = info; 301 iv);
298 302
299 return err; 303 return crypto_ablkcipher_encrypt(subreq);
300} 304}
301 305
302static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm) 306static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
303{ 307{
304 struct crypto_instance *inst = (void *)tfm->__crt_alg; 308 struct crypto_instance *inst = (void *)tfm->__crt_alg;
305 struct crypto_spawn *spawn = crypto_instance_ctx(inst); 309 struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst);
306 struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm); 310 struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
307 struct crypto_blkcipher *cipher; 311 struct crypto_ablkcipher *cipher;
312 unsigned long align;
308 313
309 cipher = crypto_spawn_blkcipher(spawn); 314 cipher = crypto_spawn_skcipher(spawn);
310 if (IS_ERR(cipher)) 315 if (IS_ERR(cipher))
311 return PTR_ERR(cipher); 316 return PTR_ERR(cipher);
312 317
313 ctx->child = cipher; 318 ctx->child = cipher;
314 319
320 align = crypto_tfm_alg_alignmask(tfm);
321 align &= ~(crypto_tfm_ctx_alignment() - 1);
322 tfm->crt_ablkcipher.reqsize = align +
323 sizeof(struct crypto_rfc3686_req_ctx) +
324 crypto_ablkcipher_reqsize(cipher);
325
315 return 0; 326 return 0;
316} 327}
317 328
@@ -319,74 +330,110 @@ static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
319{ 330{
320 struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm); 331 struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
321 332
322 crypto_free_blkcipher(ctx->child); 333 crypto_free_ablkcipher(ctx->child);
323} 334}
324 335
325static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb) 336static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
326{ 337{
338 struct crypto_attr_type *algt;
327 struct crypto_instance *inst; 339 struct crypto_instance *inst;
328 struct crypto_alg *alg; 340 struct crypto_alg *alg;
341 struct crypto_skcipher_spawn *spawn;
342 const char *cipher_name;
329 int err; 343 int err;
330 344
331 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); 345 algt = crypto_get_attr_type(tb);
332 if (err) 346 err = PTR_ERR(algt);
347 if (IS_ERR(algt))
333 return ERR_PTR(err); 348 return ERR_PTR(err);
334 349
335 alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER, 350 if ((algt->type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & algt->mask)
336 CRYPTO_ALG_TYPE_MASK); 351 return ERR_PTR(-EINVAL);
337 err = PTR_ERR(alg); 352
338 if (IS_ERR(alg)) 353 cipher_name = crypto_attr_alg_name(tb[1]);
354 err = PTR_ERR(cipher_name);
355 if (IS_ERR(cipher_name))
339 return ERR_PTR(err); 356 return ERR_PTR(err);
340 357
358 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
359 if (!inst)
360 return ERR_PTR(-ENOMEM);
361
362 spawn = crypto_instance_ctx(inst);
363
364 crypto_set_skcipher_spawn(spawn, inst);
365 err = crypto_grab_skcipher(spawn, cipher_name, 0,
366 crypto_requires_sync(algt->type,
367 algt->mask));
368 if (err)
369 goto err_free_inst;
370
371 alg = crypto_skcipher_spawn_alg(spawn);
372
341 /* We only support 16-byte blocks. */ 373 /* We only support 16-byte blocks. */
342 err = -EINVAL; 374 err = -EINVAL;
343 if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE) 375 if (alg->cra_ablkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
344 goto out_put_alg; 376 goto err_drop_spawn;
345 377
346 /* Not a stream cipher? */ 378 /* Not a stream cipher? */
347 if (alg->cra_blocksize != 1) 379 if (alg->cra_blocksize != 1)
348 goto out_put_alg; 380 goto err_drop_spawn;
349 381
350 inst = crypto_alloc_instance("rfc3686", alg); 382 err = -ENAMETOOLONG;
351 if (IS_ERR(inst)) 383 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "rfc3686(%s)",
352 goto out; 384 alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
385 goto err_drop_spawn;
386 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
387 "rfc3686(%s)", alg->cra_driver_name) >=
388 CRYPTO_MAX_ALG_NAME)
389 goto err_drop_spawn;
353 390
354 inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
355 inst->alg.cra_priority = alg->cra_priority; 391 inst->alg.cra_priority = alg->cra_priority;
356 inst->alg.cra_blocksize = 1; 392 inst->alg.cra_blocksize = 1;
357 inst->alg.cra_alignmask = alg->cra_alignmask; 393 inst->alg.cra_alignmask = alg->cra_alignmask;
358 inst->alg.cra_type = &crypto_blkcipher_type;
359 394
360 inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE; 395 inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
361 inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize 396 (alg->cra_flags & CRYPTO_ALG_ASYNC);
362 + CTR_RFC3686_NONCE_SIZE; 397 inst->alg.cra_type = &crypto_ablkcipher_type;
363 inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize 398
364 + CTR_RFC3686_NONCE_SIZE; 399 inst->alg.cra_ablkcipher.ivsize = CTR_RFC3686_IV_SIZE;
400 inst->alg.cra_ablkcipher.min_keysize =
401 alg->cra_ablkcipher.min_keysize + CTR_RFC3686_NONCE_SIZE;
402 inst->alg.cra_ablkcipher.max_keysize =
403 alg->cra_ablkcipher.max_keysize + CTR_RFC3686_NONCE_SIZE;
365 404
366 inst->alg.cra_blkcipher.geniv = "seqiv"; 405 inst->alg.cra_ablkcipher.geniv = "seqiv";
406
407 inst->alg.cra_ablkcipher.setkey = crypto_rfc3686_setkey;
408 inst->alg.cra_ablkcipher.encrypt = crypto_rfc3686_crypt;
409 inst->alg.cra_ablkcipher.decrypt = crypto_rfc3686_crypt;
367 410
368 inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx); 411 inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);
369 412
370 inst->alg.cra_init = crypto_rfc3686_init_tfm; 413 inst->alg.cra_init = crypto_rfc3686_init_tfm;
371 inst->alg.cra_exit = crypto_rfc3686_exit_tfm; 414 inst->alg.cra_exit = crypto_rfc3686_exit_tfm;
372 415
373 inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
374 inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
375 inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;
376
377out:
378 crypto_mod_put(alg);
379 return inst; 416 return inst;
380 417
381out_put_alg: 418err_drop_spawn:
382 inst = ERR_PTR(err); 419 crypto_drop_skcipher(spawn);
383 goto out; 420err_free_inst:
421 kfree(inst);
422 return ERR_PTR(err);
423}
424
425static void crypto_rfc3686_free(struct crypto_instance *inst)
426{
427 struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst);
428
429 crypto_drop_skcipher(spawn);
430 kfree(inst);
384} 431}
385 432
386static struct crypto_template crypto_rfc3686_tmpl = { 433static struct crypto_template crypto_rfc3686_tmpl = {
387 .name = "rfc3686", 434 .name = "rfc3686",
388 .alloc = crypto_rfc3686_alloc, 435 .alloc = crypto_rfc3686_alloc,
389 .free = crypto_ctr_free, 436 .free = crypto_rfc3686_free,
390 .module = THIS_MODULE, 437 .module = THIS_MODULE,
391}; 438};
392 439
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 7ae2130e1b00..87ef7d66bc20 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1591,6 +1591,10 @@ static int do_test(int m)
1591 speed_template_16_24_32); 1591 speed_template_16_24_32);
1592 test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0, 1592 test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0,
1593 speed_template_16_24_32); 1593 speed_template_16_24_32);
1594 test_acipher_speed("rfc3686(ctr(aes))", ENCRYPT, sec, NULL, 0,
1595 speed_template_20_28_36);
1596 test_acipher_speed("rfc3686(ctr(aes))", DECRYPT, sec, NULL, 0,
1597 speed_template_20_28_36);
1594 break; 1598 break;
1595 1599
1596 case 501: 1600 case 501:
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index cd2068524f3f..ecdeeb1a7b05 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -51,6 +51,7 @@ static u8 speed_template_8_16[] = {8, 16, 0};
51static u8 speed_template_8_32[] = {8, 32, 0}; 51static u8 speed_template_8_32[] = {8, 32, 0};
52static u8 speed_template_16_32[] = {16, 32, 0}; 52static u8 speed_template_16_32[] = {16, 32, 0};
53static u8 speed_template_16_24_32[] = {16, 24, 32, 0}; 53static u8 speed_template_16_24_32[] = {16, 24, 32, 0};
54static u8 speed_template_20_28_36[] = {20, 28, 36, 0};
54static u8 speed_template_32_40_48[] = {32, 40, 48, 0}; 55static u8 speed_template_32_40_48[] = {32, 40, 48, 0};
55static u8 speed_template_32_48[] = {32, 48, 0}; 56static u8 speed_template_32_48[] = {32, 48, 0};
56static u8 speed_template_32_48_64[] = {32, 48, 64, 0}; 57static u8 speed_template_32_48_64[] = {32, 48, 64, 0};