aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Mueller <smueller@chronox.de>2017-04-24 05:15:23 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-20 08:28:37 -0400
commitbcc70358396abb905f448a5c43f54dda457a0959 (patch)
tree7b4de5ed5450bfc774fbb80925f4e82ed1ec6789
parent9b2fb8ad5ba1b528e2f2927898403b0df40fd09b (diff)
crypto: algif_aead - Require setkey before accept(2)
commit 2a2a251f110576b1d89efbd0662677d7e7db21a8 upstream. 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") Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 fde8d885f7b6..6c11537ca404 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;
@@ -732,24 +737,146 @@ static struct proto_ops algif_aead_ops = {
732 .poll = aead_poll, 737 .poll = aead_poll,
733}; 738};
734 739
740static int aead_check_key(struct socket *sock)
741{
742 int err = 0;
743 struct sock *psk;
744 struct alg_sock *pask;
745 struct aead_tfm *tfm;
746 struct sock *sk = sock->sk;
747 struct alg_sock *ask = alg_sk(sk);
748
749 lock_sock(sk);
750 if (ask->refcnt)
751 goto unlock_child;
752
753 psk = ask->parent;
754 pask = alg_sk(ask->parent);
755 tfm = pask->private;
756
757 err = -ENOKEY;
758 lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
759 if (!tfm->has_key)
760 goto unlock;
761
762 if (!pask->refcnt++)
763 sock_hold(psk);
764
765 ask->refcnt = 1;
766 sock_put(psk);
767
768 err = 0;
769
770unlock:
771 release_sock(psk);
772unlock_child:
773 release_sock(sk);
774
775 return err;
776}
777
778static int aead_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
779 size_t size)
780{
781 int err;
782
783 err = aead_check_key(sock);
784 if (err)
785 return err;
786
787 return aead_sendmsg(sock, msg, size);
788}
789
790static ssize_t aead_sendpage_nokey(struct socket *sock, struct page *page,
791 int offset, size_t size, int flags)
792{
793 int err;
794
795 err = aead_check_key(sock);
796 if (err)
797 return err;
798
799 return aead_sendpage(sock, page, offset, size, flags);
800}
801
802static int aead_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
803 size_t ignored, int flags)
804{
805 int err;
806
807 err = aead_check_key(sock);
808 if (err)
809 return err;
810
811 return aead_recvmsg(sock, msg, ignored, flags);
812}
813
814static struct proto_ops algif_aead_ops_nokey = {
815 .family = PF_ALG,
816
817 .connect = sock_no_connect,
818 .socketpair = sock_no_socketpair,
819 .getname = sock_no_getname,
820 .ioctl = sock_no_ioctl,
821 .listen = sock_no_listen,
822 .shutdown = sock_no_shutdown,
823 .getsockopt = sock_no_getsockopt,
824 .mmap = sock_no_mmap,
825 .bind = sock_no_bind,
826 .accept = sock_no_accept,
827 .setsockopt = sock_no_setsockopt,
828
829 .release = af_alg_release,
830 .sendmsg = aead_sendmsg_nokey,
831 .sendpage = aead_sendpage_nokey,
832 .recvmsg = aead_recvmsg_nokey,
833 .poll = aead_poll,
834};
835
735static void *aead_bind(const char *name, u32 type, u32 mask) 836static void *aead_bind(const char *name, u32 type, u32 mask)
736{ 837{
737 return crypto_alloc_aead(name, type, mask); 838 struct aead_tfm *tfm;
839 struct crypto_aead *aead;
840
841 tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
842 if (!tfm)
843 return ERR_PTR(-ENOMEM);
844
845 aead = crypto_alloc_aead(name, type, mask);
846 if (IS_ERR(aead)) {
847 kfree(tfm);
848 return ERR_CAST(aead);
849 }
850
851 tfm->aead = aead;
852
853 return tfm;
738} 854}
739 855
740static void aead_release(void *private) 856static void aead_release(void *private)
741{ 857{
742 crypto_free_aead(private); 858 struct aead_tfm *tfm = private;
859
860 crypto_free_aead(tfm->aead);
861 kfree(tfm);
743} 862}
744 863
745static int aead_setauthsize(void *private, unsigned int authsize) 864static int aead_setauthsize(void *private, unsigned int authsize)
746{ 865{
747 return crypto_aead_setauthsize(private, authsize); 866 struct aead_tfm *tfm = private;
867
868 return crypto_aead_setauthsize(tfm->aead, authsize);
748} 869}
749 870
750static int aead_setkey(void *private, const u8 *key, unsigned int keylen) 871static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
751{ 872{
752 return crypto_aead_setkey(private, key, keylen); 873 struct aead_tfm *tfm = private;
874 int err;
875
876 err = crypto_aead_setkey(tfm->aead, key, keylen);
877 tfm->has_key = !err;
878
879 return err;
753} 880}
754 881
755static void aead_sock_destruct(struct sock *sk) 882static void aead_sock_destruct(struct sock *sk)
@@ -766,12 +893,14 @@ static void aead_sock_destruct(struct sock *sk)
766 af_alg_release_parent(sk); 893 af_alg_release_parent(sk);
767} 894}
768 895
769static int aead_accept_parent(void *private, struct sock *sk) 896static int aead_accept_parent_nokey(void *private, struct sock *sk)
770{ 897{
771 struct aead_ctx *ctx; 898 struct aead_ctx *ctx;
772 struct alg_sock *ask = alg_sk(sk); 899 struct alg_sock *ask = alg_sk(sk);
773 unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private); 900 struct aead_tfm *tfm = private;
774 unsigned int ivlen = crypto_aead_ivsize(private); 901 struct crypto_aead *aead = tfm->aead;
902 unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(aead);
903 unsigned int ivlen = crypto_aead_ivsize(aead);
775 904
776 ctx = sock_kmalloc(sk, len, GFP_KERNEL); 905 ctx = sock_kmalloc(sk, len, GFP_KERNEL);
777 if (!ctx) 906 if (!ctx)
@@ -798,7 +927,7 @@ static int aead_accept_parent(void *private, struct sock *sk)
798 927
799 ask->private = ctx; 928 ask->private = ctx;
800 929
801 aead_request_set_tfm(&ctx->aead_req, private); 930 aead_request_set_tfm(&ctx->aead_req, aead);
802 aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, 931 aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
803 af_alg_complete, &ctx->completion); 932 af_alg_complete, &ctx->completion);
804 933
@@ -807,13 +936,25 @@ static int aead_accept_parent(void *private, struct sock *sk)
807 return 0; 936 return 0;
808} 937}
809 938
939static int aead_accept_parent(void *private, struct sock *sk)
940{
941 struct aead_tfm *tfm = private;
942
943 if (!tfm->has_key)
944 return -ENOKEY;
945
946 return aead_accept_parent_nokey(private, sk);
947}
948
810static const struct af_alg_type algif_type_aead = { 949static const struct af_alg_type algif_type_aead = {
811 .bind = aead_bind, 950 .bind = aead_bind,
812 .release = aead_release, 951 .release = aead_release,
813 .setkey = aead_setkey, 952 .setkey = aead_setkey,
814 .setauthsize = aead_setauthsize, 953 .setauthsize = aead_setauthsize,
815 .accept = aead_accept_parent, 954 .accept = aead_accept_parent,
955 .accept_nokey = aead_accept_parent_nokey,
816 .ops = &algif_aead_ops, 956 .ops = &algif_aead_ops,
957 .ops_nokey = &algif_aead_ops_nokey,
817 .name = "aead", 958 .name = "aead",
818 .owner = THIS_MODULE 959 .owner = THIS_MODULE
819}; 960};