diff options
-rw-r--r-- | crypto/blkcipher.c | 70 | ||||
-rw-r--r-- | include/linux/crypto.h | 199 |
2 files changed, 260 insertions, 9 deletions
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index bf459179efe3..8edf40c835a7 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c | |||
@@ -349,13 +349,48 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key, | |||
349 | return cipher->setkey(tfm, key, keylen); | 349 | return cipher->setkey(tfm, key, keylen); |
350 | } | 350 | } |
351 | 351 | ||
352 | static int async_setkey(struct crypto_ablkcipher *tfm, const u8 *key, | ||
353 | unsigned int keylen) | ||
354 | { | ||
355 | return setkey(crypto_ablkcipher_tfm(tfm), key, keylen); | ||
356 | } | ||
357 | |||
358 | static int async_encrypt(struct ablkcipher_request *req) | ||
359 | { | ||
360 | struct crypto_tfm *tfm = req->base.tfm; | ||
361 | struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; | ||
362 | struct blkcipher_desc desc = { | ||
363 | .tfm = __crypto_blkcipher_cast(tfm), | ||
364 | .info = req->info, | ||
365 | .flags = req->base.flags, | ||
366 | }; | ||
367 | |||
368 | |||
369 | return alg->encrypt(&desc, req->dst, req->src, req->nbytes); | ||
370 | } | ||
371 | |||
372 | static int async_decrypt(struct ablkcipher_request *req) | ||
373 | { | ||
374 | struct crypto_tfm *tfm = req->base.tfm; | ||
375 | struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; | ||
376 | struct blkcipher_desc desc = { | ||
377 | .tfm = __crypto_blkcipher_cast(tfm), | ||
378 | .info = req->info, | ||
379 | .flags = req->base.flags, | ||
380 | }; | ||
381 | |||
382 | return alg->decrypt(&desc, req->dst, req->src, req->nbytes); | ||
383 | } | ||
384 | |||
352 | static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type, | 385 | static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type, |
353 | u32 mask) | 386 | u32 mask) |
354 | { | 387 | { |
355 | struct blkcipher_alg *cipher = &alg->cra_blkcipher; | 388 | struct blkcipher_alg *cipher = &alg->cra_blkcipher; |
356 | unsigned int len = alg->cra_ctxsize; | 389 | unsigned int len = alg->cra_ctxsize; |
357 | 390 | ||
358 | if (cipher->ivsize) { | 391 | type ^= CRYPTO_ALG_ASYNC; |
392 | mask &= CRYPTO_ALG_ASYNC; | ||
393 | if ((type & mask) && cipher->ivsize) { | ||
359 | len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1); | 394 | len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1); |
360 | len += cipher->ivsize; | 395 | len += cipher->ivsize; |
361 | } | 396 | } |
@@ -363,16 +398,26 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type, | |||
363 | return len; | 398 | return len; |
364 | } | 399 | } |
365 | 400 | ||
366 | static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | 401 | static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm) |
402 | { | ||
403 | struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher; | ||
404 | struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; | ||
405 | |||
406 | crt->setkey = async_setkey; | ||
407 | crt->encrypt = async_encrypt; | ||
408 | crt->decrypt = async_decrypt; | ||
409 | crt->ivsize = alg->ivsize; | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static int crypto_init_blkcipher_ops_sync(struct crypto_tfm *tfm) | ||
367 | { | 415 | { |
368 | struct blkcipher_tfm *crt = &tfm->crt_blkcipher; | 416 | struct blkcipher_tfm *crt = &tfm->crt_blkcipher; |
369 | struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; | 417 | struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; |
370 | unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1; | 418 | unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1; |
371 | unsigned long addr; | 419 | unsigned long addr; |
372 | 420 | ||
373 | if (alg->ivsize > PAGE_SIZE / 8) | ||
374 | return -EINVAL; | ||
375 | |||
376 | crt->setkey = setkey; | 421 | crt->setkey = setkey; |
377 | crt->encrypt = alg->encrypt; | 422 | crt->encrypt = alg->encrypt; |
378 | crt->decrypt = alg->decrypt; | 423 | crt->decrypt = alg->decrypt; |
@@ -385,6 +430,21 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | |||
385 | return 0; | 430 | return 0; |
386 | } | 431 | } |
387 | 432 | ||
433 | static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | ||
434 | { | ||
435 | struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; | ||
436 | |||
437 | if (alg->ivsize > PAGE_SIZE / 8) | ||
438 | return -EINVAL; | ||
439 | |||
440 | type ^= CRYPTO_ALG_ASYNC; | ||
441 | mask &= CRYPTO_ALG_ASYNC; | ||
442 | if (type & mask) | ||
443 | return crypto_init_blkcipher_ops_sync(tfm); | ||
444 | else | ||
445 | return crypto_init_blkcipher_ops_async(tfm); | ||
446 | } | ||
447 | |||
388 | static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) | 448 | static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) |
389 | __attribute__ ((unused)); | 449 | __attribute__ ((unused)); |
390 | static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) | 450 | static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) |
diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 779aa78ee643..d4d05313280c 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h | |||
@@ -56,6 +56,7 @@ | |||
56 | 56 | ||
57 | #define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 | 57 | #define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 |
58 | #define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200 | 58 | #define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200 |
59 | #define CRYPTO_TFM_REQ_MAY_BACKLOG 0x00000400 | ||
59 | #define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 | 60 | #define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 |
60 | #define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 | 61 | #define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 |
61 | #define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 | 62 | #define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 |
@@ -88,11 +89,37 @@ | |||
88 | #endif | 89 | #endif |
89 | 90 | ||
90 | struct scatterlist; | 91 | struct scatterlist; |
92 | struct crypto_ablkcipher; | ||
93 | struct crypto_async_request; | ||
91 | struct crypto_blkcipher; | 94 | struct crypto_blkcipher; |
92 | struct crypto_hash; | 95 | struct crypto_hash; |
93 | struct crypto_tfm; | 96 | struct crypto_tfm; |
94 | struct crypto_type; | 97 | struct crypto_type; |
95 | 98 | ||
99 | typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err); | ||
100 | |||
101 | struct crypto_async_request { | ||
102 | struct list_head list; | ||
103 | crypto_completion_t complete; | ||
104 | void *data; | ||
105 | struct crypto_tfm *tfm; | ||
106 | |||
107 | u32 flags; | ||
108 | }; | ||
109 | |||
110 | struct ablkcipher_request { | ||
111 | struct crypto_async_request base; | ||
112 | |||
113 | unsigned int nbytes; | ||
114 | |||
115 | void *info; | ||
116 | |||
117 | struct scatterlist *src; | ||
118 | struct scatterlist *dst; | ||
119 | |||
120 | void *__ctx[] CRYPTO_MINALIGN_ATTR; | ||
121 | }; | ||
122 | |||
96 | struct blkcipher_desc { | 123 | struct blkcipher_desc { |
97 | struct crypto_blkcipher *tfm; | 124 | struct crypto_blkcipher *tfm; |
98 | void *info; | 125 | void *info; |
@@ -232,6 +259,15 @@ static inline int crypto_has_alg(const char *name, u32 type, u32 mask) | |||
232 | * crypto_free_*(), as well as the various helpers below. | 259 | * crypto_free_*(), as well as the various helpers below. |
233 | */ | 260 | */ |
234 | 261 | ||
262 | struct ablkcipher_tfm { | ||
263 | int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key, | ||
264 | unsigned int keylen); | ||
265 | int (*encrypt)(struct ablkcipher_request *req); | ||
266 | int (*decrypt)(struct ablkcipher_request *req); | ||
267 | unsigned int ivsize; | ||
268 | unsigned int reqsize; | ||
269 | }; | ||
270 | |||
235 | struct blkcipher_tfm { | 271 | struct blkcipher_tfm { |
236 | void *iv; | 272 | void *iv; |
237 | int (*setkey)(struct crypto_tfm *tfm, const u8 *key, | 273 | int (*setkey)(struct crypto_tfm *tfm, const u8 *key, |
@@ -290,6 +326,7 @@ struct compress_tfm { | |||
290 | u8 *dst, unsigned int *dlen); | 326 | u8 *dst, unsigned int *dlen); |
291 | }; | 327 | }; |
292 | 328 | ||
329 | #define crt_ablkcipher crt_u.ablkcipher | ||
293 | #define crt_blkcipher crt_u.blkcipher | 330 | #define crt_blkcipher crt_u.blkcipher |
294 | #define crt_cipher crt_u.cipher | 331 | #define crt_cipher crt_u.cipher |
295 | #define crt_hash crt_u.hash | 332 | #define crt_hash crt_u.hash |
@@ -300,6 +337,7 @@ struct crypto_tfm { | |||
300 | u32 crt_flags; | 337 | u32 crt_flags; |
301 | 338 | ||
302 | union { | 339 | union { |
340 | struct ablkcipher_tfm ablkcipher; | ||
303 | struct blkcipher_tfm blkcipher; | 341 | struct blkcipher_tfm blkcipher; |
304 | struct cipher_tfm cipher; | 342 | struct cipher_tfm cipher; |
305 | struct hash_tfm hash; | 343 | struct hash_tfm hash; |
@@ -311,6 +349,10 @@ struct crypto_tfm { | |||
311 | void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; | 349 | void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; |
312 | }; | 350 | }; |
313 | 351 | ||
352 | struct crypto_ablkcipher { | ||
353 | struct crypto_tfm base; | ||
354 | }; | ||
355 | |||
314 | struct crypto_blkcipher { | 356 | struct crypto_blkcipher { |
315 | struct crypto_tfm base; | 357 | struct crypto_tfm base; |
316 | }; | 358 | }; |
@@ -411,6 +453,155 @@ static inline unsigned int crypto_tfm_ctx_alignment(void) | |||
411 | /* | 453 | /* |
412 | * API wrappers. | 454 | * API wrappers. |
413 | */ | 455 | */ |
456 | static inline struct crypto_ablkcipher *__crypto_ablkcipher_cast( | ||
457 | struct crypto_tfm *tfm) | ||
458 | { | ||
459 | return (struct crypto_ablkcipher *)tfm; | ||
460 | } | ||
461 | |||
462 | static inline struct crypto_ablkcipher *crypto_alloc_ablkcipher( | ||
463 | const char *alg_name, u32 type, u32 mask) | ||
464 | { | ||
465 | type &= ~CRYPTO_ALG_TYPE_MASK; | ||
466 | type |= CRYPTO_ALG_TYPE_BLKCIPHER; | ||
467 | mask |= CRYPTO_ALG_TYPE_MASK; | ||
468 | |||
469 | return __crypto_ablkcipher_cast( | ||
470 | crypto_alloc_base(alg_name, type, mask)); | ||
471 | } | ||
472 | |||
473 | static inline struct crypto_tfm *crypto_ablkcipher_tfm( | ||
474 | struct crypto_ablkcipher *tfm) | ||
475 | { | ||
476 | return &tfm->base; | ||
477 | } | ||
478 | |||
479 | static inline void crypto_free_ablkcipher(struct crypto_ablkcipher *tfm) | ||
480 | { | ||
481 | crypto_free_tfm(crypto_ablkcipher_tfm(tfm)); | ||
482 | } | ||
483 | |||
484 | static inline int crypto_has_ablkcipher(const char *alg_name, u32 type, | ||
485 | u32 mask) | ||
486 | { | ||
487 | type &= ~CRYPTO_ALG_TYPE_MASK; | ||
488 | type |= CRYPTO_ALG_TYPE_BLKCIPHER; | ||
489 | mask |= CRYPTO_ALG_TYPE_MASK; | ||
490 | |||
491 | return crypto_has_alg(alg_name, type, mask); | ||
492 | } | ||
493 | |||
494 | static inline struct ablkcipher_tfm *crypto_ablkcipher_crt( | ||
495 | struct crypto_ablkcipher *tfm) | ||
496 | { | ||
497 | return &crypto_ablkcipher_tfm(tfm)->crt_ablkcipher; | ||
498 | } | ||
499 | |||
500 | static inline unsigned int crypto_ablkcipher_ivsize( | ||
501 | struct crypto_ablkcipher *tfm) | ||
502 | { | ||
503 | return crypto_ablkcipher_crt(tfm)->ivsize; | ||
504 | } | ||
505 | |||
506 | static inline unsigned int crypto_ablkcipher_blocksize( | ||
507 | struct crypto_ablkcipher *tfm) | ||
508 | { | ||
509 | return crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(tfm)); | ||
510 | } | ||
511 | |||
512 | static inline unsigned int crypto_ablkcipher_alignmask( | ||
513 | struct crypto_ablkcipher *tfm) | ||
514 | { | ||
515 | return crypto_tfm_alg_alignmask(crypto_ablkcipher_tfm(tfm)); | ||
516 | } | ||
517 | |||
518 | static inline u32 crypto_ablkcipher_get_flags(struct crypto_ablkcipher *tfm) | ||
519 | { | ||
520 | return crypto_tfm_get_flags(crypto_ablkcipher_tfm(tfm)); | ||
521 | } | ||
522 | |||
523 | static inline void crypto_ablkcipher_set_flags(struct crypto_ablkcipher *tfm, | ||
524 | u32 flags) | ||
525 | { | ||
526 | crypto_tfm_set_flags(crypto_ablkcipher_tfm(tfm), flags); | ||
527 | } | ||
528 | |||
529 | static inline void crypto_ablkcipher_clear_flags(struct crypto_ablkcipher *tfm, | ||
530 | u32 flags) | ||
531 | { | ||
532 | crypto_tfm_clear_flags(crypto_ablkcipher_tfm(tfm), flags); | ||
533 | } | ||
534 | |||
535 | static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm, | ||
536 | const u8 *key, unsigned int keylen) | ||
537 | { | ||
538 | return crypto_ablkcipher_crt(tfm)->setkey(tfm, key, keylen); | ||
539 | } | ||
540 | |||
541 | static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm( | ||
542 | struct ablkcipher_request *req) | ||
543 | { | ||
544 | return __crypto_ablkcipher_cast(req->base.tfm); | ||
545 | } | ||
546 | |||
547 | static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req) | ||
548 | { | ||
549 | struct ablkcipher_tfm *crt = | ||
550 | crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req)); | ||
551 | return crt->encrypt(req); | ||
552 | } | ||
553 | |||
554 | static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req) | ||
555 | { | ||
556 | struct ablkcipher_tfm *crt = | ||
557 | crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req)); | ||
558 | return crt->decrypt(req); | ||
559 | } | ||
560 | |||
561 | static inline int crypto_ablkcipher_reqsize(struct crypto_ablkcipher *tfm) | ||
562 | { | ||
563 | return crypto_ablkcipher_crt(tfm)->reqsize; | ||
564 | } | ||
565 | |||
566 | static inline struct ablkcipher_request *ablkcipher_request_alloc( | ||
567 | struct crypto_ablkcipher *tfm, gfp_t gfp) | ||
568 | { | ||
569 | struct ablkcipher_request *req; | ||
570 | |||
571 | req = kmalloc(sizeof(struct ablkcipher_request) + | ||
572 | crypto_ablkcipher_reqsize(tfm), gfp); | ||
573 | |||
574 | if (likely(req)) | ||
575 | req->base.tfm = crypto_ablkcipher_tfm(tfm); | ||
576 | |||
577 | return req; | ||
578 | } | ||
579 | |||
580 | static inline void ablkcipher_request_free(struct ablkcipher_request *req) | ||
581 | { | ||
582 | kfree(req); | ||
583 | } | ||
584 | |||
585 | static inline void ablkcipher_request_set_callback( | ||
586 | struct ablkcipher_request *req, | ||
587 | u32 flags, crypto_completion_t complete, void *data) | ||
588 | { | ||
589 | req->base.complete = complete; | ||
590 | req->base.data = data; | ||
591 | req->base.flags = flags; | ||
592 | } | ||
593 | |||
594 | static inline void ablkcipher_request_set_crypt( | ||
595 | struct ablkcipher_request *req, | ||
596 | struct scatterlist *src, struct scatterlist *dst, | ||
597 | unsigned int nbytes, void *iv) | ||
598 | { | ||
599 | req->src = src; | ||
600 | req->dst = dst; | ||
601 | req->nbytes = nbytes; | ||
602 | req->info = iv; | ||
603 | } | ||
604 | |||
414 | static inline struct crypto_blkcipher *__crypto_blkcipher_cast( | 605 | static inline struct crypto_blkcipher *__crypto_blkcipher_cast( |
415 | struct crypto_tfm *tfm) | 606 | struct crypto_tfm *tfm) |
416 | { | 607 | { |
@@ -427,9 +618,9 @@ static inline struct crypto_blkcipher *crypto_blkcipher_cast( | |||
427 | static inline struct crypto_blkcipher *crypto_alloc_blkcipher( | 618 | static inline struct crypto_blkcipher *crypto_alloc_blkcipher( |
428 | const char *alg_name, u32 type, u32 mask) | 619 | const char *alg_name, u32 type, u32 mask) |
429 | { | 620 | { |
430 | type &= ~CRYPTO_ALG_TYPE_MASK; | 621 | type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); |
431 | type |= CRYPTO_ALG_TYPE_BLKCIPHER; | 622 | type |= CRYPTO_ALG_TYPE_BLKCIPHER; |
432 | mask |= CRYPTO_ALG_TYPE_MASK; | 623 | mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC; |
433 | 624 | ||
434 | return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask)); | 625 | return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask)); |
435 | } | 626 | } |
@@ -447,9 +638,9 @@ static inline void crypto_free_blkcipher(struct crypto_blkcipher *tfm) | |||
447 | 638 | ||
448 | static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask) | 639 | static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask) |
449 | { | 640 | { |
450 | type &= ~CRYPTO_ALG_TYPE_MASK; | 641 | type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); |
451 | type |= CRYPTO_ALG_TYPE_BLKCIPHER; | 642 | type |= CRYPTO_ALG_TYPE_BLKCIPHER; |
452 | mask |= CRYPTO_ALG_TYPE_MASK; | 643 | mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC; |
453 | 644 | ||
454 | return crypto_has_alg(alg_name, type, mask); | 645 | return crypto_has_alg(alg_name, type, mask); |
455 | } | 646 | } |