Created
January 15, 2016 18:21
-
-
Save dvyukov/7d4eca91f086d7042379 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/crypto/af_alg.c b/crypto/af_alg.c | |
index a8e7aa3..f5e18c2 100644 | |
--- a/crypto/af_alg.c | |
+++ b/crypto/af_alg.c | |
@@ -76,6 +76,8 @@ int af_alg_register_type(const struct af_alg_type *type) | |
goto unlock; | |
type->ops->owner = THIS_MODULE; | |
+ if (type->ops_nokey) | |
+ type->ops_nokey->owner = THIS_MODULE; | |
node->type = type; | |
list_add(&node->list, &alg_types); | |
err = 0; | |
@@ -125,6 +127,26 @@ int af_alg_release(struct socket *sock) | |
} | |
EXPORT_SYMBOL_GPL(af_alg_release); | |
+void af_alg_release_parent(struct sock *sk) | |
+{ | |
+ struct alg_sock *ask = alg_sk(sk); | |
+ unsigned int nokey = ask->nokey_refcnt; | |
+ bool last = nokey && !ask->refcnt; | |
+ | |
+ sk = ask->parent; | |
+ ask = alg_sk(sk); | |
+ | |
+ lock_sock(sk); | |
+ ask->nokey_refcnt -= nokey; | |
+ if (!last) | |
+ last = !--ask->refcnt; | |
+ release_sock(sk); | |
+ | |
+ if (last) | |
+ sock_put(sk); | |
+} | |
+EXPORT_SYMBOL_GPL(af_alg_release_parent); | |
+ | |
static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |
{ | |
const u32 forbidden = CRYPTO_ALG_INTERNAL; | |
@@ -133,6 +155,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |
struct sockaddr_alg *sa = (void *)uaddr; | |
const struct af_alg_type *type; | |
void *private; | |
+ int err; | |
if (sock->state == SS_CONNECTED) | |
return -EINVAL; | |
@@ -160,16 +183,22 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |
return PTR_ERR(private); | |
} | |
+ err = -EBUSY; | |
lock_sock(sk); | |
+ if (ask->refcnt | ask->nokey_refcnt) | |
+ goto unlock; | |
swap(ask->type, type); | |
swap(ask->private, private); | |
+ err = 0; | |
+ | |
+unlock: | |
release_sock(sk); | |
alg_do_release(type, private); | |
- return 0; | |
+ return err; | |
} | |
static int alg_setkey(struct sock *sk, char __user *ukey, | |
@@ -202,11 +231,15 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, | |
struct sock *sk = sock->sk; | |
struct alg_sock *ask = alg_sk(sk); | |
const struct af_alg_type *type; | |
- int err = -ENOPROTOOPT; | |
+ int err = -EBUSY; | |
lock_sock(sk); | |
+ if (ask->refcnt) | |
+ goto unlock; | |
+ | |
type = ask->type; | |
+ err = -ENOPROTOOPT; | |
if (level != SOL_ALG || !type) | |
goto unlock; | |
@@ -238,6 +271,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock) | |
struct alg_sock *ask = alg_sk(sk); | |
const struct af_alg_type *type; | |
struct sock *sk2; | |
+ unsigned int nokey; | |
int err; | |
lock_sock(sk); | |
@@ -257,20 +291,29 @@ int af_alg_accept(struct sock *sk, struct socket *newsock) | |
security_sk_clone(sk, sk2); | |
err = type->accept(ask->private, sk2); | |
- if (err) { | |
- sk_free(sk2); | |
+ | |
+ nokey = err == -ENOKEY; | |
+ if (nokey && type->accept_nokey) | |
+ err = type->accept_nokey(ask->private, sk2); | |
+ | |
+ if (err) | |
goto unlock; | |
- } | |
sk2->sk_family = PF_ALG; | |
- sock_hold(sk); | |
+ if (nokey || !ask->refcnt++) | |
+ sock_hold(sk); | |
+ ask->nokey_refcnt += nokey; | |
alg_sk(sk2)->parent = sk; | |
alg_sk(sk2)->type = type; | |
+ alg_sk(sk2)->nokey_refcnt = nokey; | |
newsock->ops = type->ops; | |
newsock->state = SS_CONNECTED; | |
+ if (nokey) | |
+ newsock->ops = type->ops_nokey; | |
+ | |
err = 0; | |
unlock: | |
diff --git a/crypto/ahash.c b/crypto/ahash.c | |
index 9c1dc8d..d19b523 100644 | |
--- a/crypto/ahash.c | |
+++ b/crypto/ahash.c | |
@@ -451,6 +451,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) | |
struct ahash_alg *alg = crypto_ahash_alg(hash); | |
hash->setkey = ahash_nosetkey; | |
+ hash->has_setkey = false; | |
hash->export = ahash_no_export; | |
hash->import = ahash_no_import; | |
@@ -463,8 +464,10 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) | |
hash->finup = alg->finup ?: ahash_def_finup; | |
hash->digest = alg->digest; | |
- if (alg->setkey) | |
+ if (alg->setkey) { | |
hash->setkey = alg->setkey; | |
+ hash->has_setkey = true; | |
+ } | |
if (alg->export) | |
hash->export = alg->export; | |
if (alg->import) | |
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c | |
index b4c24fe..608a756 100644 | |
--- a/crypto/algif_hash.c | |
+++ b/crypto/algif_hash.c | |
@@ -34,6 +34,11 @@ struct hash_ctx { | |
struct ahash_request req; | |
}; | |
+struct algif_hash_tfm { | |
+ struct crypto_ahash *hash; | |
+ bool has_key; | |
+}; | |
+ | |
static int hash_sendmsg(struct socket *sock, struct msghdr *msg, | |
size_t ignored) | |
{ | |
@@ -235,19 +240,151 @@ static struct proto_ops algif_hash_ops = { | |
.accept = hash_accept, | |
}; | |
+static int hash_check_key(struct socket *sock) | |
+{ | |
+ int err = 0; | |
+ struct sock *psk; | |
+ struct alg_sock *pask; | |
+ struct algif_hash_tfm *tfm; | |
+ struct sock *sk = sock->sk; | |
+ struct alg_sock *ask = alg_sk(sk); | |
+ | |
+ lock_sock(sk); | |
+ if (ask->refcnt) | |
+ goto unlock_child; | |
+ | |
+ psk = ask->parent; | |
+ pask = alg_sk(ask->parent); | |
+ tfm = pask->private; | |
+ | |
+ err = -ENOKEY; | |
+ lock_sock_nested(psk, SINGLE_DEPTH_NESTING); | |
+ if (!tfm->has_key) | |
+ goto unlock; | |
+ | |
+ if (!pask->refcnt++) | |
+ sock_hold(psk); | |
+ | |
+ ask->refcnt = 1; | |
+ sock_put(psk); | |
+ | |
+ err = 0; | |
+ | |
+unlock: | |
+ release_sock(psk); | |
+unlock_child: | |
+ release_sock(sk); | |
+ | |
+ return err; | |
+} | |
+ | |
+static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg, | |
+ size_t size) | |
+{ | |
+ int err; | |
+ | |
+ err = hash_check_key(sock); | |
+ if (err) | |
+ return err; | |
+ | |
+ return hash_sendmsg(sock, msg, size); | |
+} | |
+ | |
+static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page, | |
+ int offset, size_t size, int flags) | |
+{ | |
+ int err; | |
+ | |
+ err = hash_check_key(sock); | |
+ if (err) | |
+ return err; | |
+ | |
+ return hash_sendpage(sock, page, offset, size, flags); | |
+} | |
+ | |
+static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg, | |
+ size_t ignored, int flags) | |
+{ | |
+ int err; | |
+ | |
+ err = hash_check_key(sock); | |
+ if (err) | |
+ return err; | |
+ | |
+ return hash_recvmsg(sock, msg, ignored, flags); | |
+} | |
+ | |
+static int hash_accept_nokey(struct socket *sock, struct socket *newsock, | |
+ int flags) | |
+{ | |
+ int err; | |
+ | |
+ err = hash_check_key(sock); | |
+ if (err) | |
+ return err; | |
+ | |
+ return hash_accept(sock, newsock, flags); | |
+} | |
+ | |
+static struct proto_ops algif_hash_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, | |
+ .setsockopt = sock_no_setsockopt, | |
+ .poll = sock_no_poll, | |
+ | |
+ .release = af_alg_release, | |
+ .sendmsg = hash_sendmsg_nokey, | |
+ .sendpage = hash_sendpage_nokey, | |
+ .recvmsg = hash_recvmsg_nokey, | |
+ .accept = hash_accept_nokey, | |
+}; | |
+ | |
static void *hash_bind(const char *name, u32 type, u32 mask) | |
{ | |
- return crypto_alloc_ahash(name, type, mask); | |
+ struct algif_hash_tfm *tfm; | |
+ struct crypto_ahash *hash; | |
+ | |
+ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); | |
+ if (!tfm) | |
+ return ERR_PTR(-ENOMEM); | |
+ | |
+ hash = crypto_alloc_ahash(name, type, mask); | |
+ if (IS_ERR(hash)) { | |
+ kfree(tfm); | |
+ return ERR_CAST(hash); | |
+ } | |
+ | |
+ tfm->hash = hash; | |
+ | |
+ return tfm; | |
} | |
static void hash_release(void *private) | |
{ | |
- crypto_free_ahash(private); | |
+ struct algif_hash_tfm *tfm = private; | |
+ | |
+ crypto_free_ahash(tfm->hash); | |
+ kfree(tfm); | |
} | |
static int hash_setkey(void *private, const u8 *key, unsigned int keylen) | |
{ | |
- return crypto_ahash_setkey(private, key, keylen); | |
+ struct algif_hash_tfm *tfm = private; | |
+ int err; | |
+ | |
+ err = crypto_ahash_setkey(tfm->hash, key, keylen); | |
+ tfm->has_key = !err; | |
+ | |
+ return err; | |
} | |
static void hash_sock_destruct(struct sock *sk) | |
@@ -261,12 +398,14 @@ static void hash_sock_destruct(struct sock *sk) | |
af_alg_release_parent(sk); | |
} | |
-static int hash_accept_parent(void *private, struct sock *sk) | |
+static int hash_accept_parent_nokey(void *private, struct sock *sk) | |
{ | |
struct hash_ctx *ctx; | |
struct alg_sock *ask = alg_sk(sk); | |
- unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private); | |
- unsigned ds = crypto_ahash_digestsize(private); | |
+ struct algif_hash_tfm *tfm = private; | |
+ struct crypto_ahash *hash = tfm->hash; | |
+ unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash); | |
+ unsigned ds = crypto_ahash_digestsize(hash); | |
ctx = sock_kmalloc(sk, len, GFP_KERNEL); | |
if (!ctx) | |
@@ -286,7 +425,7 @@ static int hash_accept_parent(void *private, struct sock *sk) | |
ask->private = ctx; | |
- ahash_request_set_tfm(&ctx->req, private); | |
+ ahash_request_set_tfm(&ctx->req, hash); | |
ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, | |
af_alg_complete, &ctx->completion); | |
@@ -295,12 +434,24 @@ static int hash_accept_parent(void *private, struct sock *sk) | |
return 0; | |
} | |
+static int hash_accept_parent(void *private, struct sock *sk) | |
+{ | |
+ struct algif_hash_tfm *tfm = private; | |
+ | |
+ if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash)) | |
+ return -ENOKEY; | |
+ | |
+ return hash_accept_parent_nokey(private, sk); | |
+} | |
+ | |
static const struct af_alg_type algif_type_hash = { | |
.bind = hash_bind, | |
.release = hash_release, | |
.setkey = hash_setkey, | |
.accept = hash_accept_parent, | |
+ .accept_nokey = hash_accept_parent_nokey, | |
.ops = &algif_hash_ops, | |
+ .ops_nokey = &algif_hash_ops_nokey, | |
.name = "hash", | |
.owner = THIS_MODULE | |
}; | |
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c | |
index eaa9f9b..31dbe95 100644 | |
--- a/crypto/algif_skcipher.c | |
+++ b/crypto/algif_skcipher.c | |
@@ -31,6 +31,11 @@ struct skcipher_sg_list { | |
struct scatterlist sg[0]; | |
}; | |
+struct skcipher_tfm { | |
+ struct crypto_skcipher *skcipher; | |
+ bool has_key; | |
+}; | |
+ | |
struct skcipher_ctx { | |
struct list_head tsgl; | |
struct af_alg_sgl rsgl; | |
@@ -748,19 +753,139 @@ static struct proto_ops algif_skcipher_ops = { | |
.poll = skcipher_poll, | |
}; | |
+static int skcipher_check_key(struct socket *sock) | |
+{ | |
+ int err = 0; | |
+ struct sock *psk; | |
+ struct alg_sock *pask; | |
+ struct skcipher_tfm *tfm; | |
+ struct sock *sk = sock->sk; | |
+ struct alg_sock *ask = alg_sk(sk); | |
+ | |
+ lock_sock(sk); | |
+ if (ask->refcnt) | |
+ goto unlock_child; | |
+ | |
+ psk = ask->parent; | |
+ pask = alg_sk(ask->parent); | |
+ tfm = pask->private; | |
+ | |
+ err = -ENOKEY; | |
+ lock_sock_nested(psk, SINGLE_DEPTH_NESTING); | |
+ if (!tfm->has_key) | |
+ goto unlock; | |
+ | |
+ if (!pask->refcnt++) | |
+ sock_hold(psk); | |
+ | |
+ ask->refcnt = 1; | |
+ sock_put(psk); | |
+ | |
+ err = 0; | |
+ | |
+unlock: | |
+ release_sock(psk); | |
+unlock_child: | |
+ release_sock(sk); | |
+ | |
+ 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) | |
{ | |
- return crypto_alloc_skcipher(name, type, mask); | |
+ struct skcipher_tfm *tfm; | |
+ struct crypto_skcipher *skcipher; | |
+ | |
+ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); | |
+ if (!tfm) | |
+ return ERR_PTR(-ENOMEM); | |
+ | |
+ skcipher = crypto_alloc_skcipher(name, type, mask); | |
+ if (IS_ERR(skcipher)) { | |
+ kfree(tfm); | |
+ return ERR_CAST(skcipher); | |
+ } | |
+ | |
+ tfm->skcipher = skcipher; | |
+ | |
+ return tfm; | |
} | |
static void skcipher_release(void *private) | |
{ | |
- crypto_free_skcipher(private); | |
+ struct skcipher_tfm *tfm = private; | |
+ | |
+ crypto_free_skcipher(tfm->skcipher); | |
+ kfree(tfm); | |
} | |
static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen) | |
{ | |
- return crypto_skcipher_setkey(private, key, keylen); | |
+ struct skcipher_tfm *tfm = private; | |
+ int err; | |
+ | |
+ err = crypto_skcipher_setkey(tfm->skcipher, key, keylen); | |
+ tfm->has_key = !err; | |
+ | |
+ return err; | |
} | |
static void skcipher_wait(struct sock *sk) | |
@@ -788,24 +913,26 @@ static void skcipher_sock_destruct(struct sock *sk) | |
af_alg_release_parent(sk); | |
} | |
-static int skcipher_accept_parent(void *private, struct sock *sk) | |
+static int skcipher_accept_parent_nokey(void *private, struct sock *sk) | |
{ | |
struct skcipher_ctx *ctx; | |
struct alg_sock *ask = alg_sk(sk); | |
- unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private); | |
+ struct skcipher_tfm *tfm = private; | |
+ struct crypto_skcipher *skcipher = tfm->skcipher; | |
+ unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher); | |
ctx = sock_kmalloc(sk, len, GFP_KERNEL); | |
if (!ctx) | |
return -ENOMEM; | |
- ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private), | |
+ ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher), | |
GFP_KERNEL); | |
if (!ctx->iv) { | |
sock_kfree_s(sk, ctx, len); | |
return -ENOMEM; | |
} | |
- memset(ctx->iv, 0, crypto_skcipher_ivsize(private)); | |
+ memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher)); | |
INIT_LIST_HEAD(&ctx->tsgl); | |
ctx->len = len; | |
@@ -818,7 +945,7 @@ static int skcipher_accept_parent(void *private, struct sock *sk) | |
ask->private = ctx; | |
- skcipher_request_set_tfm(&ctx->req, private); | |
+ skcipher_request_set_tfm(&ctx->req, skcipher); | |
skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, | |
af_alg_complete, &ctx->completion); | |
@@ -827,12 +954,24 @@ 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 && crypto_skcipher_has_setkey(tfm->skcipher)) | |
+ return -ENOKEY; | |
+ | |
+ return skcipher_accept_parent_nokey(private, sk); | |
+} | |
+ | |
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 | |
}; | |
diff --git a/crypto/shash.c b/crypto/shash.c | |
index ecb1e3d..88a27de 100644 | |
--- a/crypto/shash.c | |
+++ b/crypto/shash.c | |
@@ -355,8 +355,10 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm) | |
crt->finup = shash_async_finup; | |
crt->digest = shash_async_digest; | |
- if (alg->setkey) | |
+ if (alg->setkey) { | |
crt->setkey = shash_async_setkey; | |
+ crt->has_setkey = true; | |
+ } | |
if (alg->export) | |
crt->export = shash_async_export; | |
if (alg->import) | |
diff --git a/crypto/skcipher.c b/crypto/skcipher.c | |
index 7591928..d199c0b 100644 | |
--- a/crypto/skcipher.c | |
+++ b/crypto/skcipher.c | |
@@ -118,6 +118,7 @@ static int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm) | |
skcipher->decrypt = skcipher_decrypt_blkcipher; | |
skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher); | |
+ skcipher->has_setkey = calg->cra_blkcipher.max_keysize; | |
return 0; | |
} | |
@@ -210,6 +211,7 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) | |
skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher); | |
skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) + | |
sizeof(struct ablkcipher_request); | |
+ skcipher->has_setkey = calg->cra_ablkcipher.max_keysize; | |
return 0; | |
} | |
diff --git a/include/crypto/hash.h b/include/crypto/hash.h | |
index 3d69c93..6361892 100644 | |
--- a/include/crypto/hash.h | |
+++ b/include/crypto/hash.h | |
@@ -204,6 +204,7 @@ struct crypto_ahash { | |
unsigned int keylen); | |
unsigned int reqsize; | |
+ bool has_setkey; | |
struct crypto_tfm base; | |
}; | |
@@ -375,6 +376,11 @@ static inline void *ahash_request_ctx(struct ahash_request *req) | |
int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, | |
unsigned int keylen); | |
+static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm) | |
+{ | |
+ return tfm->has_setkey; | |
+} | |
+ | |
/** | |
* crypto_ahash_finup() - update and finalize message digest | |
* @req: reference to the ahash_request handle that holds all information | |
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h | |
index 018afb2..a2bfd78 100644 | |
--- a/include/crypto/if_alg.h | |
+++ b/include/crypto/if_alg.h | |
@@ -30,6 +30,9 @@ struct alg_sock { | |
struct sock *parent; | |
+ unsigned int refcnt; | |
+ unsigned int nokey_refcnt; | |
+ | |
const struct af_alg_type *type; | |
void *private; | |
}; | |
@@ -50,9 +53,11 @@ struct af_alg_type { | |
void (*release)(void *private); | |
int (*setkey)(void *private, const u8 *key, unsigned int keylen); | |
int (*accept)(void *private, struct sock *sk); | |
+ int (*accept_nokey)(void *private, struct sock *sk); | |
int (*setauthsize)(void *private, unsigned int authsize); | |
struct proto_ops *ops; | |
+ struct proto_ops *ops_nokey; | |
struct module *owner; | |
char name[14]; | |
}; | |
@@ -67,6 +72,7 @@ int af_alg_register_type(const struct af_alg_type *type); | |
int af_alg_unregister_type(const struct af_alg_type *type); | |
int af_alg_release(struct socket *sock); | |
+void af_alg_release_parent(struct sock *sk); | |
int af_alg_accept(struct sock *sk, struct socket *newsock); | |
int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len); | |
@@ -83,11 +89,6 @@ static inline struct alg_sock *alg_sk(struct sock *sk) | |
return (struct alg_sock *)sk; | |
} | |
-static inline void af_alg_release_parent(struct sock *sk) | |
-{ | |
- sock_put(alg_sk(sk)->parent); | |
-} | |
- | |
static inline void af_alg_init_completion(struct af_alg_completion *completion) | |
{ | |
init_completion(&completion->completion); | |
diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h | |
index d8dd41f..fd8742a 100644 | |
--- a/include/crypto/skcipher.h | |
+++ b/include/crypto/skcipher.h | |
@@ -61,6 +61,8 @@ struct crypto_skcipher { | |
unsigned int ivsize; | |
unsigned int reqsize; | |
+ bool has_setkey; | |
+ | |
struct crypto_tfm base; | |
}; | |
@@ -305,6 +307,11 @@ static inline int crypto_skcipher_setkey(struct crypto_skcipher *tfm, | |
return tfm->setkey(tfm, key, keylen); | |
} | |
+static inline bool crypto_skcipher_has_setkey(struct crypto_skcipher *tfm) | |
+{ | |
+ return tfm->has_setkey; | |
+} | |
+ | |
/** | |
* crypto_skcipher_reqtfm() - obtain cipher handle from request | |
* @req: skcipher_request out of which the cipher handle is to be obtained |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment