[PATCH v5 5/8] crypto: AF_ALG: add user space interface for RNG
From: Stephan Mueller <hidden>
Date: 2014-12-07 22:37:02
Also in:
linux-crypto, lkml
Subsystem:
crypto api, networking drivers, the rest · Maintainers:
Herbert Xu, "David S. Miller", Andrew Lunn, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Allow user space to seed / reset the RNG via a setsockopt. This patch reuses alg_setkey to copy data into the kernel. The alg_setkey is now used for two mechanisms: setkey and seeding. The function is extended by the providing the function pointer to the function handling the copied data. As the alg_setkey is now usable for more than just setkey, it is renamed to alg_setop. Signed-off-by: Stephan Mueller <redacted> --- crypto/af_alg.c | 29 +++++++++++++++++++---------- include/crypto/if_alg.h | 1 + include/uapi/linux/if_alg.h | 1 + 3 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 547c369..d1eb1e9 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c@@ -169,26 +169,27 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return 0; } -static int alg_setkey(struct sock *sk, char __user *ukey, - unsigned int keylen) +static int alg_setop(struct sock *sk, char __user *udata, + unsigned int datalen, + int (*handler)(void *private, const u8 *data, + unsigned int datalen)) { struct alg_sock *ask = alg_sk(sk); - const struct af_alg_type *type = ask->type; - u8 *key; + u8 *data; int err; - key = sock_kmalloc(sk, keylen, GFP_KERNEL); - if (!key) + data = sock_kmalloc(sk, datalen, GFP_KERNEL); + if (!data) return -ENOMEM; err = -EFAULT; - if (copy_from_user(key, ukey, keylen)) + if (copy_from_user(data, udata, datalen)) goto out; - err = type->setkey(ask->private, key, keylen); + err = handler(ask->private, data, datalen); out: - sock_kfree_s(sk, key, keylen); + sock_kfree_s(sk, data, datalen); return err; }
@@ -214,7 +215,7 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, if (!type->setkey) goto unlock; - err = alg_setkey(sk, optval, optlen); + err = alg_setop(sk, optval, optlen, type->setkey); break; case ALG_SET_AEAD_AUTHSIZE: if (sock->state == SS_CONNECTED)
@@ -222,6 +223,14 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, if (!type->setauthsize) goto unlock; err = type->setauthsize(ask->private, optlen); + break; + case ALG_SET_RNG_SEED: + if (sock->state == SS_CONNECTED) + goto unlock; + if (!type->setseed) + goto unlock; + + err = alg_setop(sk, optval, optlen, type->setseed); } unlock:
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 5c7b6c5..0808ed1 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h@@ -51,6 +51,7 @@ struct af_alg_type { int (*setkey)(void *private, const u8 *key, unsigned int keylen); int (*accept)(void *private, struct sock *sk); int (*setauthsize)(void *private, unsigned int authsize); + int (*setseed)(void *private, const u8 *seed, unsigned int seedlen); struct proto_ops *ops; struct module *owner;
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index f2acd2f..973dcca 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h@@ -34,6 +34,7 @@ struct af_alg_iv { #define ALG_SET_OP 3 #define ALG_SET_AEAD_ASSOCLEN 4 #define ALG_SET_AEAD_AUTHSIZE 5 +#define ALG_SET_RNG_SEED 6 /* Operations */ #define ALG_OP_DECRYPT 0
--
2.1.0