aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/gcm.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-12-17 02:33:17 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:56 -0500
commitdadbc53d0bbde0e84c40b9f6bc5c50eb9eb7352a (patch)
treef3fe8df7e75041c3ce9a5de3e0dc3f5123f729d8 /crypto/gcm.c
parent189ed66e95fb23666a62963b718dcbe62adbadde (diff)
[CRYPTO] gcm: Introduce rfc4106
This patch introduces the rfc4106 wrapper for GCM just as we have an rfc4309 wrapper for CCM. The purpose of the wrapper is to include part of the IV in the key so that it can be negotiated by IPsec. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/gcm.c')
-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");