Loading crypto/algif_skcipher.c +144 −5 Original line number Diff line number Diff line Loading @@ -753,6 +753,99 @@ static struct proto_ops algif_skcipher_ops = { .poll = skcipher_poll, }; static int skcipher_check_key(struct socket *sock) { int err; struct sock *psk; struct alg_sock *pask; struct skcipher_tfm *tfm; struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); if (ask->refcnt) return 0; psk = ask->parent; pask = alg_sk(ask->parent); tfm = pask->private; err = -ENOKEY; lock_sock(psk); if (!tfm->has_key) goto unlock; if (!pask->refcnt++) sock_hold(psk); ask->refcnt = 1; sock_put(psk); err = 0; unlock: release_sock(psk); return err; } static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg, size_t size) { int err; err = skcipher_check_key(sock); if (err) return err; return skcipher_sendmsg(sock, msg, size); } static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page, int offset, size_t size, int flags) { int err; err = skcipher_check_key(sock); if (err) return err; return skcipher_sendpage(sock, page, offset, size, flags); } static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { int err; err = skcipher_check_key(sock); if (err) return err; return skcipher_recvmsg(sock, msg, ignored, flags); } static struct proto_ops algif_skcipher_ops_nokey = { .family = PF_ALG, .connect = sock_no_connect, .socketpair = sock_no_socketpair, .getname = sock_no_getname, .ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, .getsockopt = sock_no_getsockopt, .mmap = sock_no_mmap, .bind = sock_no_bind, .accept = sock_no_accept, .setsockopt = sock_no_setsockopt, .release = af_alg_release, .sendmsg = skcipher_sendmsg_nokey, .sendpage = skcipher_sendpage_nokey, .recvmsg = skcipher_recvmsg_nokey, .poll = skcipher_poll, }; static void *skcipher_bind(const char *name, u32 type, u32 mask) { struct skcipher_tfm *tfm; Loading Loading @@ -802,7 +895,7 @@ static void skcipher_wait(struct sock *sk) msleep(100); } static void skcipher_sock_destruct(struct sock *sk) static void skcipher_sock_destruct_common(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); struct skcipher_ctx *ctx = ask->private; Loading @@ -814,10 +907,33 @@ static void skcipher_sock_destruct(struct sock *sk) skcipher_free_sgl(sk); sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm)); sock_kfree_s(sk, ctx, ctx->len); } static void skcipher_sock_destruct(struct sock *sk) { skcipher_sock_destruct_common(sk); af_alg_release_parent(sk); } static int skcipher_accept_parent(void *private, struct sock *sk) static void skcipher_release_parent_nokey(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); if (!ask->refcnt) { sock_put(ask->parent); return; } af_alg_release_parent(sk); } static void skcipher_sock_destruct_nokey(struct sock *sk) { skcipher_sock_destruct_common(sk); skcipher_release_parent_nokey(sk); } static int skcipher_accept_parent_common(void *private, struct sock *sk) { struct skcipher_ctx *ctx; struct alg_sock *ask = alg_sk(sk); Loading @@ -825,9 +941,6 @@ static int skcipher_accept_parent(void *private, struct sock *sk) struct crypto_skcipher *skcipher = tfm->skcipher; unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher); if (!tfm->has_key) return -ENOKEY; ctx = sock_kmalloc(sk, len, GFP_KERNEL); if (!ctx) return -ENOMEM; Loading Loading @@ -861,12 +974,38 @@ static int skcipher_accept_parent(void *private, struct sock *sk) return 0; } static int skcipher_accept_parent(void *private, struct sock *sk) { struct skcipher_tfm *tfm = private; if (!tfm->has_key) return -ENOKEY; return skcipher_accept_parent_common(private, sk); } static int skcipher_accept_parent_nokey(void *private, struct sock *sk) { int err; err = skcipher_accept_parent_common(private, sk); if (err) goto out; sk->sk_destruct = skcipher_sock_destruct_nokey; out: return err; } static const struct af_alg_type algif_type_skcipher = { .bind = skcipher_bind, .release = skcipher_release, .setkey = skcipher_setkey, .accept = skcipher_accept_parent, .accept_nokey = skcipher_accept_parent_nokey, .ops = &algif_skcipher_ops, .ops_nokey = &algif_skcipher_ops_nokey, .name = "skcipher", .owner = THIS_MODULE }; Loading Loading
crypto/algif_skcipher.c +144 −5 Original line number Diff line number Diff line Loading @@ -753,6 +753,99 @@ static struct proto_ops algif_skcipher_ops = { .poll = skcipher_poll, }; static int skcipher_check_key(struct socket *sock) { int err; struct sock *psk; struct alg_sock *pask; struct skcipher_tfm *tfm; struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); if (ask->refcnt) return 0; psk = ask->parent; pask = alg_sk(ask->parent); tfm = pask->private; err = -ENOKEY; lock_sock(psk); if (!tfm->has_key) goto unlock; if (!pask->refcnt++) sock_hold(psk); ask->refcnt = 1; sock_put(psk); err = 0; unlock: release_sock(psk); return err; } static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg, size_t size) { int err; err = skcipher_check_key(sock); if (err) return err; return skcipher_sendmsg(sock, msg, size); } static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page, int offset, size_t size, int flags) { int err; err = skcipher_check_key(sock); if (err) return err; return skcipher_sendpage(sock, page, offset, size, flags); } static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { int err; err = skcipher_check_key(sock); if (err) return err; return skcipher_recvmsg(sock, msg, ignored, flags); } static struct proto_ops algif_skcipher_ops_nokey = { .family = PF_ALG, .connect = sock_no_connect, .socketpair = sock_no_socketpair, .getname = sock_no_getname, .ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, .getsockopt = sock_no_getsockopt, .mmap = sock_no_mmap, .bind = sock_no_bind, .accept = sock_no_accept, .setsockopt = sock_no_setsockopt, .release = af_alg_release, .sendmsg = skcipher_sendmsg_nokey, .sendpage = skcipher_sendpage_nokey, .recvmsg = skcipher_recvmsg_nokey, .poll = skcipher_poll, }; static void *skcipher_bind(const char *name, u32 type, u32 mask) { struct skcipher_tfm *tfm; Loading Loading @@ -802,7 +895,7 @@ static void skcipher_wait(struct sock *sk) msleep(100); } static void skcipher_sock_destruct(struct sock *sk) static void skcipher_sock_destruct_common(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); struct skcipher_ctx *ctx = ask->private; Loading @@ -814,10 +907,33 @@ static void skcipher_sock_destruct(struct sock *sk) skcipher_free_sgl(sk); sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm)); sock_kfree_s(sk, ctx, ctx->len); } static void skcipher_sock_destruct(struct sock *sk) { skcipher_sock_destruct_common(sk); af_alg_release_parent(sk); } static int skcipher_accept_parent(void *private, struct sock *sk) static void skcipher_release_parent_nokey(struct sock *sk) { struct alg_sock *ask = alg_sk(sk); if (!ask->refcnt) { sock_put(ask->parent); return; } af_alg_release_parent(sk); } static void skcipher_sock_destruct_nokey(struct sock *sk) { skcipher_sock_destruct_common(sk); skcipher_release_parent_nokey(sk); } static int skcipher_accept_parent_common(void *private, struct sock *sk) { struct skcipher_ctx *ctx; struct alg_sock *ask = alg_sk(sk); Loading @@ -825,9 +941,6 @@ static int skcipher_accept_parent(void *private, struct sock *sk) struct crypto_skcipher *skcipher = tfm->skcipher; unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher); if (!tfm->has_key) return -ENOKEY; ctx = sock_kmalloc(sk, len, GFP_KERNEL); if (!ctx) return -ENOMEM; Loading Loading @@ -861,12 +974,38 @@ static int skcipher_accept_parent(void *private, struct sock *sk) return 0; } static int skcipher_accept_parent(void *private, struct sock *sk) { struct skcipher_tfm *tfm = private; if (!tfm->has_key) return -ENOKEY; return skcipher_accept_parent_common(private, sk); } static int skcipher_accept_parent_nokey(void *private, struct sock *sk) { int err; err = skcipher_accept_parent_common(private, sk); if (err) goto out; sk->sk_destruct = skcipher_sock_destruct_nokey; out: return err; } static const struct af_alg_type algif_type_skcipher = { .bind = skcipher_bind, .release = skcipher_release, .setkey = skcipher_setkey, .accept = skcipher_accept_parent, .accept_nokey = skcipher_accept_parent_nokey, .ops = &algif_skcipher_ops, .ops_nokey = &algif_skcipher_ops_nokey, .name = "skcipher", .owner = THIS_MODULE }; Loading