aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/gcm.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/crypto/gcm.c b/crypto/gcm.c
index d539f5e56879..e70afd0c73dd 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <crypto/gf128mul.h> 11#include <crypto/gf128mul.h>
12#include <crypto/internal/aead.h>
12#include <crypto/internal/skcipher.h> 13#include <crypto/internal/skcipher.h>
13#include <crypto/scatterwalk.h> 14#include <crypto/scatterwalk.h>
14#include <linux/completion.h> 15#include <linux/completion.h>
@@ -27,6 +28,11 @@ struct crypto_gcm_ctx {
27 struct gf128mul_4k *gf128; 28 struct gf128mul_4k *gf128;
28}; 29};
29 30
31struct crypto_rfc4106_ctx {
32 struct crypto_aead *child;
33 u8 nonce[4];
34};
35
30struct crypto_gcm_ghash_ctx { 36struct crypto_gcm_ghash_ctx {
31 u32 bytes; 37 u32 bytes;
32 u32 flags; 38 u32 flags;
@@ -240,6 +246,25 @@ out:
240 return err; 246 return err;
241} 247}
242 248
249static int crypto_gcm_setauthsize(struct crypto_aead *tfm,
250 unsigned int authsize)
251{
252 switch (authsize) {
253 case 4:
254 case 8:
255 case 12:
256 case 13:
257 case 14:
258 case 15:
259 case 16:
260 break;
261 default:
262 return -EINVAL;
263 }
264
265 return 0;
266}
267
243static void crypto_gcm_init_crypt(struct ablkcipher_request *ablk_req, 268static void crypto_gcm_init_crypt(struct ablkcipher_request *ablk_req,
244 struct aead_request *req, 269 struct aead_request *req,
245 unsigned int cryptlen) 270 unsigned int cryptlen)
@@ -472,6 +497,7 @@ static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb,
472 inst->alg.cra_init = crypto_gcm_init_tfm; 497 inst->alg.cra_init = crypto_gcm_init_tfm;
473 inst->alg.cra_exit = crypto_gcm_exit_tfm; 498 inst->alg.cra_exit = crypto_gcm_exit_tfm;
474 inst->alg.cra_aead.setkey = crypto_gcm_setkey; 499 inst->alg.cra_aead.setkey = crypto_gcm_setkey;
500 inst->alg.cra_aead.setauthsize = crypto_gcm_setauthsize;
475 inst->alg.cra_aead.encrypt = crypto_gcm_encrypt; 501 inst->alg.cra_aead.encrypt = crypto_gcm_encrypt;
476 inst->alg.cra_aead.decrypt = crypto_gcm_decrypt; 502 inst->alg.cra_aead.decrypt = crypto_gcm_decrypt;
477 503
@@ -549,6 +575,211 @@ static struct crypto_template crypto_gcm_base_tmpl = {
549 .module = THIS_MODULE, 575 .module = THIS_MODULE,
550}; 576};
551 577
578static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key,
579 unsigned int keylen)
580{
581 struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
582 struct crypto_aead *child = ctx->child;
583 int err;
584
585 if (keylen < 4)
586 return -EINVAL;
587
588 keylen -= 4;
589 memcpy(ctx->nonce, key + keylen, 4);
590
591 crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
592 crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
593 CRYPTO_TFM_REQ_MASK);
594 err = crypto_aead_setkey(child, key, keylen);
595 crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
596 CRYPTO_TFM_RES_MASK);
597
598 return err;
599}
600
601static int crypto_rfc4106_setauthsize(struct crypto_aead *parent,
602 unsigned int authsize)
603{
604 struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
605
606 switch (authsize) {
607 case 8:
608 case 12:
609 case 16:
610 break;
611 default:
612 return -EINVAL;
613 }
614
615 return crypto_aead_setauthsize(ctx->child, authsize);
616}
617
618static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
619{
620 struct aead_request *subreq = aead_request_ctx(req);
621 struct crypto_aead *aead = crypto_aead_reqtfm(req);
622 struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
623 struct crypto_aead *child = ctx->child;
624 u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
625 crypto_aead_alignmask(child) + 1);
626
627 memcpy(iv, ctx->nonce, 4);
628 memcpy(iv + 4, req->iv, 8);
629
630 aead_request_set_tfm(subreq, child);
631 aead_request_set_callback(subreq, req->base.flags, req->base.complete,
632 req->base.data);
633 aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
634 aead_request_set_assoc(subreq, req->assoc, req->assoclen);
635
636 return subreq;
637}
638
639static int crypto_rfc4106_encrypt(struct aead_request *req)
640{
641 req = crypto_rfc4106_crypt(req);
642
643 return crypto_aead_encrypt(req);
644}
645
646static int crypto_rfc4106_decrypt(struct aead_request *req)
647{
648 req = crypto_rfc4106_crypt(req);
649
650 return crypto_aead_decrypt(req);
651}
652
653static int crypto_rfc4106_init_tfm(struct crypto_tfm *tfm)
654{
655 struct crypto_instance *inst = (void *)tfm->__crt_alg;
656 struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
657 struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
658 struct crypto_aead *aead;
659 unsigned long align;
660
661 aead = crypto_spawn_aead(spawn);
662 if (IS_ERR(aead))
663 return PTR_ERR(aead);
664
665 ctx->child = aead;
666
667 align = crypto_aead_alignmask(aead);
668 align &= ~(crypto_tfm_ctx_alignment() - 1);
669 tfm->crt_aead.reqsize = sizeof(struct aead_request) +
670 ALIGN(crypto_aead_reqsize(aead),
671 crypto_tfm_ctx_alignment()) +
672 align + 16;
673
674 return 0;
675}
676
677static void crypto_rfc4106_exit_tfm(struct crypto_tfm *tfm)
678{
679 struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
680
681 crypto_free_aead(ctx->child);
682}
683
684static struct crypto_instance *crypto_rfc4106_alloc(struct rtattr **tb)
685{
686 struct crypto_attr_type *algt;
687 struct crypto_instance *inst;
688 struct crypto_aead_spawn *spawn;
689 struct crypto_alg *alg;
690 const char *ccm_name;
691 int err;
692
693 algt = crypto_get_attr_type(tb);
694 err = PTR_ERR(algt);
695 if (IS_ERR(algt))
696 return ERR_PTR(err);
697
698 if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
699 return ERR_PTR(-EINVAL);
700
701 ccm_name = crypto_attr_alg_name(tb[1]);
702 err = PTR_ERR(ccm_name);
703 if (IS_ERR(ccm_name))
704 return ERR_PTR(err);
705
706 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
707 if (!inst)
708 return ERR_PTR(-ENOMEM);
709
710 spawn = crypto_instance_ctx(inst);
711 crypto_set_aead_spawn(spawn, inst);
712 err = crypto_grab_aead(spawn, ccm_name, 0,
713 crypto_requires_sync(algt->type, algt->mask));
714 if (err)
715 goto out_free_inst;
716
717 alg = crypto_aead_spawn_alg(spawn);
718
719 err = -EINVAL;
720
721 /* We only support 16-byte blocks. */
722 if (alg->cra_aead.ivsize != 16)
723 goto out_drop_alg;
724
725 /* Not a stream cipher? */
726 if (alg->cra_blocksize != 1)
727 goto out_drop_alg;
728
729 err = -ENAMETOOLONG;
730 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
731 "rfc4106(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
732 snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
733 "rfc4106(%s)", alg->cra_driver_name) >=
734 CRYPTO_MAX_ALG_NAME)
735 goto out_drop_alg;
736
737 inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
738 inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
739 inst->alg.cra_priority = alg->cra_priority;
740 inst->alg.cra_blocksize = 1;
741 inst->alg.cra_alignmask = alg->cra_alignmask;
742 inst->alg.cra_type = &crypto_nivaead_type;
743
744 inst->alg.cra_aead.ivsize = 8;
745 inst->alg.cra_aead.maxauthsize = 16;
746
747 inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx);
748
749 inst->alg.cra_init = crypto_rfc4106_init_tfm;
750 inst->alg.cra_exit = crypto_rfc4106_exit_tfm;
751
752 inst->alg.cra_aead.setkey = crypto_rfc4106_setkey;
753 inst->alg.cra_aead.setauthsize = crypto_rfc4106_setauthsize;
754 inst->alg.cra_aead.encrypt = crypto_rfc4106_encrypt;
755 inst->alg.cra_aead.decrypt = crypto_rfc4106_decrypt;
756
757 inst->alg.cra_aead.geniv = "seqiv";
758
759out:
760 return inst;
761
762out_drop_alg:
763 crypto_drop_aead(spawn);
764out_free_inst:
765 kfree(inst);
766 inst = ERR_PTR(err);
767 goto out;
768}
769
770static void crypto_rfc4106_free(struct crypto_instance *inst)
771{
772 crypto_drop_spawn(crypto_instance_ctx(inst));
773 kfree(inst);
774}
775
776static struct crypto_template crypto_rfc4106_tmpl = {
777 .name = "rfc4106",
778 .alloc = crypto_rfc4106_alloc,
779 .free = crypto_rfc4106_free,
780 .module = THIS_MODULE,
781};
782
552static int __init crypto_gcm_module_init(void) 783static int __init crypto_gcm_module_init(void)
553{ 784{
554 int err; 785 int err;
@@ -561,9 +792,15 @@ static int __init crypto_gcm_module_init(void)
561 if (err) 792 if (err)
562 goto out_undo_base; 793 goto out_undo_base;
563 794
795 err = crypto_register_template(&crypto_rfc4106_tmpl);
796 if (err)
797 goto out_undo_gcm;
798
564out: 799out:
565 return err; 800 return err;
566 801
802out_undo_gcm:
803 crypto_unregister_template(&crypto_gcm_tmpl);
567out_undo_base: 804out_undo_base:
568 crypto_unregister_template(&crypto_gcm_base_tmpl); 805 crypto_unregister_template(&crypto_gcm_base_tmpl);
569 goto out; 806 goto out;
@@ -571,6 +808,7 @@ out_undo_base:
571 808
572static void __exit crypto_gcm_module_exit(void) 809static void __exit crypto_gcm_module_exit(void)
573{ 810{
811 crypto_unregister_template(&crypto_rfc4106_tmpl);
574 crypto_unregister_template(&crypto_gcm_tmpl); 812 crypto_unregister_template(&crypto_gcm_tmpl);
575 crypto_unregister_template(&crypto_gcm_base_tmpl); 813 crypto_unregister_template(&crypto_gcm_base_tmpl);
576} 814}
@@ -582,3 +820,4 @@ MODULE_LICENSE("GPL");
582MODULE_DESCRIPTION("Galois/Counter Mode"); 820MODULE_DESCRIPTION("Galois/Counter Mode");
583MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>"); 821MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>");
584MODULE_ALIAS("gcm_base"); 822MODULE_ALIAS("gcm_base");
823MODULE_ALIAS("rfc4106");