aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2016-01-03 23:36:12 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2016-01-18 05:16:11 -0500
commita0fa2d037129a9849918a92d91b79ed6c7bd2818 (patch)
treef47b94a584d539028ef941f261c1ea2ce15a7d68 /crypto
parent37766586c965d63758ad542325a96d5384f4a8c9 (diff)
crypto: algif_skcipher - Add nokey compatibility path
This patch adds a compatibility path to support old applications that do acept(2) before setkey. Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/algif_skcipher.c149
1 files changed, 144 insertions, 5 deletions
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index f4431bc1ce43..110bab499e43 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -753,6 +753,99 @@ static struct proto_ops algif_skcipher_ops = {
753 .poll = skcipher_poll, 753 .poll = skcipher_poll,
754}; 754};
755 755
756static int skcipher_check_key(struct socket *sock)
757{
758 int err;
759 struct sock *psk;
760 struct alg_sock *pask;
761 struct skcipher_tfm *tfm;
762 struct sock *sk = sock->sk;
763 struct alg_sock *ask = alg_sk(sk);
764
765 if (ask->refcnt)
766 return 0;
767
768 psk = ask->parent;
769 pask = alg_sk(ask->parent);
770 tfm = pask->private;
771
772 err = -ENOKEY;
773 lock_sock(psk);
774 if (!tfm->has_key)
775 goto unlock;
776
777 if (!pask->refcnt++)
778 sock_hold(psk);
779
780 ask->refcnt = 1;
781 sock_put(psk);
782
783 err = 0;
784
785unlock:
786 release_sock(psk);
787
788 return err;
789}
790
791static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
792 size_t size)
793{
794 int err;
795
796 err = skcipher_check_key(sock);
797 if (err)
798 return err;
799
800 return skcipher_sendmsg(sock, msg, size);
801}
802
803static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
804 int offset, size_t size, int flags)
805{
806 int err;
807
808 err = skcipher_check_key(sock);
809 if (err)
810 return err;
811
812 return skcipher_sendpage(sock, page, offset, size, flags);
813}
814
815static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
816 size_t ignored, int flags)
817{
818 int err;
819
820 err = skcipher_check_key(sock);
821 if (err)
822 return err;
823
824 return skcipher_recvmsg(sock, msg, ignored, flags);
825}
826
827static struct proto_ops algif_skcipher_ops_nokey = {
828 .family = PF_ALG,
829
830 .connect = sock_no_connect,
831 .socketpair = sock_no_socketpair,
832 .getname = sock_no_getname,
833 .ioctl = sock_no_ioctl,
834 .listen = sock_no_listen,
835 .shutdown = sock_no_shutdown,
836 .getsockopt = sock_no_getsockopt,
837 .mmap = sock_no_mmap,
838 .bind = sock_no_bind,
839 .accept = sock_no_accept,
840 .setsockopt = sock_no_setsockopt,
841
842 .release = af_alg_release,
843 .sendmsg = skcipher_sendmsg_nokey,
844 .sendpage = skcipher_sendpage_nokey,
845 .recvmsg = skcipher_recvmsg_nokey,
846 .poll = skcipher_poll,
847};
848
756static void *skcipher_bind(const char *name, u32 type, u32 mask) 849static void *skcipher_bind(const char *name, u32 type, u32 mask)
757{ 850{
758 struct skcipher_tfm *tfm; 851 struct skcipher_tfm *tfm;
@@ -802,7 +895,7 @@ static void skcipher_wait(struct sock *sk)
802 msleep(100); 895 msleep(100);
803} 896}
804 897
805static void skcipher_sock_destruct(struct sock *sk) 898static void skcipher_sock_destruct_common(struct sock *sk)
806{ 899{
807 struct alg_sock *ask = alg_sk(sk); 900 struct alg_sock *ask = alg_sk(sk);
808 struct skcipher_ctx *ctx = ask->private; 901 struct skcipher_ctx *ctx = ask->private;
@@ -814,10 +907,33 @@ static void skcipher_sock_destruct(struct sock *sk)
814 skcipher_free_sgl(sk); 907 skcipher_free_sgl(sk);
815 sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm)); 908 sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
816 sock_kfree_s(sk, ctx, ctx->len); 909 sock_kfree_s(sk, ctx, ctx->len);
910}
911
912static void skcipher_sock_destruct(struct sock *sk)
913{
914 skcipher_sock_destruct_common(sk);
817 af_alg_release_parent(sk); 915 af_alg_release_parent(sk);
818} 916}
819 917
820static int skcipher_accept_parent(void *private, struct sock *sk) 918static void skcipher_release_parent_nokey(struct sock *sk)
919{
920 struct alg_sock *ask = alg_sk(sk);
921
922 if (!ask->refcnt) {
923 sock_put(ask->parent);
924 return;
925 }
926
927 af_alg_release_parent(sk);
928}
929
930static void skcipher_sock_destruct_nokey(struct sock *sk)
931{
932 skcipher_sock_destruct_common(sk);
933 skcipher_release_parent_nokey(sk);
934}
935
936static int skcipher_accept_parent_common(void *private, struct sock *sk)
821{ 937{
822 struct skcipher_ctx *ctx; 938 struct skcipher_ctx *ctx;
823 struct alg_sock *ask = alg_sk(sk); 939 struct alg_sock *ask = alg_sk(sk);
@@ -825,9 +941,6 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
825 struct crypto_skcipher *skcipher = tfm->skcipher; 941 struct crypto_skcipher *skcipher = tfm->skcipher;
826 unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher); 942 unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
827 943
828 if (!tfm->has_key)
829 return -ENOKEY;
830
831 ctx = sock_kmalloc(sk, len, GFP_KERNEL); 944 ctx = sock_kmalloc(sk, len, GFP_KERNEL);
832 if (!ctx) 945 if (!ctx)
833 return -ENOMEM; 946 return -ENOMEM;
@@ -861,12 +974,38 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
861 return 0; 974 return 0;
862} 975}
863 976
977static int skcipher_accept_parent(void *private, struct sock *sk)
978{
979 struct skcipher_tfm *tfm = private;
980
981 if (!tfm->has_key)
982 return -ENOKEY;
983
984 return skcipher_accept_parent_common(private, sk);
985}
986
987static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
988{
989 int err;
990
991 err = skcipher_accept_parent_common(private, sk);
992 if (err)
993 goto out;
994
995 sk->sk_destruct = skcipher_sock_destruct_nokey;
996
997out:
998 return err;
999}
1000
864static const struct af_alg_type algif_type_skcipher = { 1001static const struct af_alg_type algif_type_skcipher = {
865 .bind = skcipher_bind, 1002 .bind = skcipher_bind,
866 .release = skcipher_release, 1003 .release = skcipher_release,
867 .setkey = skcipher_setkey, 1004 .setkey = skcipher_setkey,
868 .accept = skcipher_accept_parent, 1005 .accept = skcipher_accept_parent,
1006 .accept_nokey = skcipher_accept_parent_nokey,
869 .ops = &algif_skcipher_ops, 1007 .ops = &algif_skcipher_ops,
1008 .ops_nokey = &algif_skcipher_ops_nokey,
870 .name = "skcipher", 1009 .name = "skcipher",
871 .owner = THIS_MODULE 1010 .owner = THIS_MODULE
872}; 1011};