summaryrefslogtreecommitdiffstats
path: root/crypto/algif_aead.c
diff options
context:
space:
mode:
authorStephan Mueller <smueller@chronox.de>2017-04-24 05:15:23 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2017-04-24 06:11:08 -0400
commit2a2a251f110576b1d89efbd0662677d7e7db21a8 (patch)
tree4d4237387e1a5a3160858286da5e2665d06cf955 /crypto/algif_aead.c
parenta368f43d6e3a001e684e9191a27df384fbff12f5 (diff)
crypto: algif_aead - Require setkey before accept(2)
Some cipher implementations will crash if you try to use them without calling setkey first. This patch adds a check so that the accept(2) call will fail with -ENOKEY if setkey hasn't been done on the socket yet. Fixes: 400c40cf78da ("crypto: algif - add AEAD support") Cc: <stable@vger.kernel.org> Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/algif_aead.c')
-rw-r--r--crypto/algif_aead.c157
1 files changed, 149 insertions, 8 deletions
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 5a8053758657..e0d55ea2f0eb 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -44,6 +44,11 @@ struct aead_async_req {
44 char iv[]; 44 char iv[];
45}; 45};
46 46
47struct aead_tfm {
48 struct crypto_aead *aead;
49 bool has_key;
50};
51
47struct aead_ctx { 52struct aead_ctx {
48 struct aead_sg_list tsgl; 53 struct aead_sg_list tsgl;
49 struct aead_async_rsgl first_rsgl; 54 struct aead_async_rsgl first_rsgl;
@@ -723,24 +728,146 @@ static struct proto_ops algif_aead_ops = {
723 .poll = aead_poll, 728 .poll = aead_poll,
724}; 729};
725 730
731static int aead_check_key(struct socket *sock)
732{
733 int err = 0;
734 struct sock *psk;
735 struct alg_sock *pask;
736 struct aead_tfm *tfm;
737 struct sock *sk = sock->sk;
738 struct alg_sock *ask = alg_sk(sk);
739
740 lock_sock(sk);
741 if (ask->refcnt)
742 goto unlock_child;
743
744 psk = ask->parent;
745 pask = alg_sk(ask->parent);
746 tfm = pask->private;
747
748 err = -ENOKEY;
749 lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
750 if (!tfm->has_key)
751 goto unlock;
752
753 if (!pask->refcnt++)
754 sock_hold(psk);
755
756 ask->refcnt = 1;
757 sock_put(psk);
758
759 err = 0;
760
761unlock:
762 release_sock(psk);
763unlock_child:
764 release_sock(sk);
765
766 return err;
767}
768
769static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
770 size_t size)
771{
772 int err;
773
774 err = aead_check_key(sock);
775 if (err)
776 return err;
777
778 return aead_sendmsg(sock, msg, size);
779}
780
781static ssize_t aead_sendpage_nokey(struct socket *sock, struct page *page,
782 int offset, size_t size, int flags)
783{
784 int err;
785
786 err = aead_check_key(sock);
787 if (err)
788 return err;
789
790 return aead_sendpage(sock, page, offset, size, flags);
791}
792
793static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
794 size_t ignored, int flags)
795{
796 int err;
797
798 err = aead_check_key(sock);
799 if (err)
800 return err;
801
802 return aead_recvmsg(sock, msg, ignored, flags);
803}
804
805static struct proto_ops algif_aead_ops_nokey = {
806 .family = PF_ALG,
807
808 .connect = sock_no_connect,
809 .socketpair = sock_no_socketpair,
810 .getname = sock_no_getname,
811 .ioctl = sock_no_ioctl,
812 .listen = sock_no_listen,
813 .shutdown = sock_no_shutdown,
814 .getsockopt = sock_no_getsockopt,
815 .mmap = sock_no_mmap,
816 .bind = sock_no_bind,
817 .accept = sock_no_accept,
818 .setsockopt = sock_no_setsockopt,
819
820 .release = af_alg_release,
821 .sendmsg = aead_sendmsg_nokey,
822 .sendpage = aead_sendpage_nokey,
823 .recvmsg = aead_recvmsg_nokey,
824 .poll = aead_poll,
825};
826
726static void *aead_bind(const char *name, u32 type, u32 mask) 827static void *aead_bind(const char *name, u32 type, u32 mask)
727{ 828{
728 return crypto_alloc_aead(name, type, mask); 829 struct aead_tfm *tfm;
830 struct crypto_aead *aead;
831
832 tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
833 if (!tfm)
834 return ERR_PTR(-ENOMEM);
835
836 aead = crypto_alloc_aead(name, type, mask);
837 if (IS_ERR(aead)) {
838 kfree(tfm);
839 return ERR_CAST(aead);
840 }
841
842 tfm->aead = aead;
843
844 return tfm;
729} 845}
730 846
731static void aead_release(void *private) 847static void aead_release(void *private)
732{ 848{
733 crypto_free_aead(private); 849 struct aead_tfm *tfm = private;
850
851 crypto_free_aead(tfm->aead);
852 kfree(tfm);
734} 853}
735 854
736static int aead_setauthsize(void *private, unsigned int authsize) 855static int aead_setauthsize(void *private, unsigned int authsize)
737{ 856{
738 return crypto_aead_setauthsize(private, authsize); 857 struct aead_tfm *tfm = private;
858
859 return crypto_aead_setauthsize(tfm->aead, authsize);
739} 860}
740 861
741static int aead_setkey(void *private, const u8 *key, unsigned int keylen) 862static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
742{ 863{
743 return crypto_aead_setkey(private, key, keylen); 864 struct aead_tfm *tfm = private;
865 int err;
866
867 err = crypto_aead_setkey(tfm->aead, key, keylen);
868 tfm->has_key = !err;
869
870 return err;
744} 871}
745 872
746static void aead_sock_destruct(struct sock *sk) 873static void aead_sock_destruct(struct sock *sk)
@@ -757,12 +884,14 @@ static void aead_sock_destruct(struct sock *sk)
757 af_alg_release_parent(sk); 884 af_alg_release_parent(sk);
758} 885}
759 886
760static int aead_accept_parent(void *private, struct sock *sk) 887static int aead_accept_parent_nokey(void *private, struct sock *sk)
761{ 888{
762 struct aead_ctx *ctx; 889 struct aead_ctx *ctx;
763 struct alg_sock *ask = alg_sk(sk); 890 struct alg_sock *ask = alg_sk(sk);
764 unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private); 891 struct aead_tfm *tfm = private;
765 unsigned int ivlen = crypto_aead_ivsize(private); 892 struct crypto_aead *aead = tfm->aead;
893 unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(aead);
894 unsigned int ivlen = crypto_aead_ivsize(aead);
766 895
767 ctx = sock_kmalloc(sk, len, GFP_KERNEL); 896 ctx = sock_kmalloc(sk, len, GFP_KERNEL);
768 if (!ctx) 897 if (!ctx)
@@ -789,7 +918,7 @@ static int aead_accept_parent(void *private, struct sock *sk)
789 918
790 ask->private = ctx; 919 ask->private = ctx;
791 920
792 aead_request_set_tfm(&ctx->aead_req, private); 921 aead_request_set_tfm(&ctx->aead_req, aead);
793 aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, 922 aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
794 af_alg_complete, &ctx->completion); 923 af_alg_complete, &ctx->completion);
795 924
@@ -798,13 +927,25 @@ static int aead_accept_parent(void *private, struct sock *sk)
798 return 0; 927 return 0;
799} 928}
800 929
930static int aead_accept_parent(void *private, struct sock *sk)
931{
932 struct aead_tfm *tfm = private;
933
934 if (!tfm->has_key)
935 return -ENOKEY;
936
937 return aead_accept_parent_nokey(private, sk);
938}
939
801static const struct af_alg_type algif_type_aead = { 940static const struct af_alg_type algif_type_aead = {
802 .bind = aead_bind, 941 .bind = aead_bind,
803 .release = aead_release, 942 .release = aead_release,
804 .setkey = aead_setkey, 943 .setkey = aead_setkey,
805 .setauthsize = aead_setauthsize, 944 .setauthsize = aead_setauthsize,
806 .accept = aead_accept_parent, 945 .accept = aead_accept_parent,
946 .accept_nokey = aead_accept_parent_nokey,
807 .ops = &algif_aead_ops, 947 .ops = &algif_aead_ops,
948 .ops_nokey = &algif_aead_ops_nokey,
808 .name = "aead", 949 .name = "aead",
809 .owner = THIS_MODULE 950 .owner = THIS_MODULE
810}; 951};