From: Elena Petrova <lenaptr@google.com>
To: linux-crypto@vger.kernel.org
Cc: "Elena Petrova" <lenaptr@google.com>,
"Eric Biggers" <ebiggers@kernel.org>,
"Stephan Müller" <smueller@chronox.de>,
"Ard Biesheuvel" <ardb@kernel.org>
Subject: [PATCH v2] crypto: af_alg - add extra parameters for DRBG interface
Date: Thu, 16 Jul 2020 17:40:28 +0100 [thread overview]
Message-ID: <20200716164028.1805047-1-lenaptr@google.com> (raw)
In-Reply-To: <CABvBcwY44BPa+TaDwxWaEogpg3Kdkq8o9cR5gSqNGF-o6d3jrw@mail.gmail.com>
Extending the userspace RNG interface:
1. adding ALG_SET_DRBG_ENTROPY setsockopt option for entropy input;
2. using sendmsg syscall for specifying the additional data.
Signed-off-by: Elena Petrova <lenaptr@google.com>
---
libkcapi patch for testing:
https://github.com/Len0k/libkcapi/commit/6f095d270b982008f419078614c15caa592cb531
Updates in v2:
1) Adding CONFIG_CRYPTO_CAVS_DRBG around setentropy.
2) Requiring CAP_SYS_ADMIN for entropy reset.
3) Locking for send and recv.
4) Length checks added for send and setentropy; send and setentropy now return
number of bytes accepted.
5) Minor code style corrections.
Documentation/crypto/userspace-if.rst | 17 +++-
crypto/Kconfig | 8 ++
crypto/af_alg.c | 8 ++
crypto/algif_rng.c | 112 ++++++++++++++++++++++++--
include/crypto/if_alg.h | 3 +-
include/uapi/linux/if_alg.h | 1 +
6 files changed, 139 insertions(+), 10 deletions(-)
diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst
index ff86befa61e0..c3695d2c7e0b 100644
--- a/Documentation/crypto/userspace-if.rst
+++ b/Documentation/crypto/userspace-if.rst
@@ -296,15 +296,23 @@ follows:
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
- .salg_type = "rng", /* this selects the symmetric cipher */
- .salg_name = "drbg_nopr_sha256" /* this is the cipher name */
+ .salg_type = "rng", /* this selects the random number generator */
+ .salg_name = "drbg_nopr_sha256" /* this is the RNG name */
};
Depending on the RNG type, the RNG must be seeded. The seed is provided
using the setsockopt interface to set the key. For example, the
ansi_cprng requires a seed. The DRBGs do not require a seed, but may be
-seeded.
+seeded. The seed is also known as a *Personalization String* in DRBG800-90A
+standard.
+
+For the purpose of CAVS testing, the concatenation of *Entropy* and *Nonce*
+can be provided to the RNG via ALG_SET_DRBG_ENTROPY setsockopt interface. This
+requires a kernel built with CONFIG_CRYPTO_CAVS_DRBG, and CAP_SYS_ADMIN
+permission.
+
+*Additional Data* can be provided using the send()/sendmsg() system calls.
Using the read()/recvmsg() system calls, random numbers can be obtained.
The kernel generates at most 128 bytes in one call. If user space
@@ -377,6 +385,9 @@ mentioned optname:
provided ciphertext is assumed to contain an authentication tag of
the given size (see section about AEAD memory layout below).
+- ALG_SET_DRBG_ENTROPY -- Setting the entropy of the random number generator.
+ This option is applicable to RNG cipher type only.
+
User space API example
----------------------
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 091c0a0bbf26..8484617596d1 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1896,6 +1896,14 @@ config CRYPTO_STATS
config CRYPTO_HASH_INFO
bool
+config CRYPTO_CAVS_DRBG
+ tristate "Enable CAVS testing of DRBG"
+ depends on CRYPTO_USER_API_RNG && CRYPTO_DRBG
+ help
+ This option enables the resetting of DRBG entropy via the user-space
+ interface. This should only be enabled for CAVS testing. You should say
+ no unless you know what this is.
+
source "lib/crypto/Kconfig"
source "drivers/crypto/Kconfig"
source "crypto/asymmetric_keys/Kconfig"
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index b1cd3535c525..27d6248ca447 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -260,6 +260,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_DRBG_ENTROPY:
+ if (sock->state == SS_CONNECTED)
+ goto unlock;
+ if (!type->setentropy)
+ goto unlock;
+
+ err = type->setentropy(ask->private, optval, optlen);
}
unlock:
diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
index 087c0ad09d38..8a3b0eb45a85 100644
--- a/crypto/algif_rng.c
+++ b/crypto/algif_rng.c
@@ -38,6 +38,7 @@
* DAMAGE.
*/
+#include <linux/capability.h>
#include <linux/module.h>
#include <crypto/rng.h>
#include <linux/random.h>
@@ -53,8 +54,22 @@ struct rng_ctx {
#define MAXSIZE 128
unsigned int len;
struct crypto_rng *drng;
+ u8 *addtl;
+ size_t addtl_len;
};
+struct rng_parent_ctx {
+ struct crypto_rng *drng;
+ u8 *entropy;
+};
+
+static void rng_reset_addtl(struct rng_ctx *ctx)
+{
+ kzfree(ctx->addtl);
+ ctx->addtl = NULL;
+ ctx->addtl_len = 0;
+}
+
static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
int flags)
{
@@ -65,6 +80,7 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
int genlen = 0;
u8 result[MAXSIZE];
+ lock_sock(sock->sk);
if (len == 0)
return 0;
if (len > MAXSIZE)
@@ -82,16 +98,45 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
* seeding as they automatically seed. The X9.31 DRNG will return
* an error if it was not seeded properly.
*/
- genlen = crypto_rng_get_bytes(ctx->drng, result, len);
+ genlen = crypto_rng_generate(ctx->drng, ctx->addtl, ctx->addtl_len,
+ result, len);
if (genlen < 0)
return genlen;
err = memcpy_to_msg(msg, result, len);
memzero_explicit(result, len);
+ rng_reset_addtl(ctx);
+ release_sock(sock->sk);
return err ? err : len;
}
+static int rng_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
+{
+ int err;
+ struct alg_sock *ask = alg_sk(sock->sk);
+ struct rng_ctx *ctx = ask->private;
+
+ lock_sock(sock->sk);
+ if (len > MAXSIZE)
+ len = MAXSIZE;
+
+ rng_reset_addtl(ctx);
+ ctx->addtl = kmalloc(len, GFP_KERNEL);
+ if (!ctx->addtl)
+ return -ENOMEM;
+
+ err = memcpy_from_msg(ctx->addtl, msg, len);
+ if (err) {
+ rng_reset_addtl(ctx);
+ return err;
+ }
+ ctx->addtl_len = len;
+ release_sock(sock->sk);
+
+ return len;
+}
+
static struct proto_ops algif_rng_ops = {
.family = PF_ALG,
@@ -106,21 +151,41 @@ static struct proto_ops algif_rng_ops = {
.bind = sock_no_bind,
.accept = sock_no_accept,
.setsockopt = sock_no_setsockopt,
- .sendmsg = sock_no_sendmsg,
.sendpage = sock_no_sendpage,
.release = af_alg_release,
.recvmsg = rng_recvmsg,
+ .sendmsg = rng_sendmsg,
};
static void *rng_bind(const char *name, u32 type, u32 mask)
{
- return crypto_alloc_rng(name, type, mask);
+ struct rng_parent_ctx *pctx;
+ struct crypto_rng *rng;
+
+ pctx = kzalloc(sizeof(*pctx), GFP_KERNEL);
+ if (!pctx)
+ return ERR_PTR(-ENOMEM);
+
+ rng = crypto_alloc_rng(name, type, mask);
+ if (IS_ERR(rng)) {
+ kfree(pctx);
+ return ERR_CAST(rng);
+ }
+
+ pctx->drng = rng;
+ return pctx;
}
static void rng_release(void *private)
{
- crypto_free_rng(private);
+ struct rng_parent_ctx *pctx = private;
+
+ if (unlikely(!pctx))
+ return;
+ crypto_free_rng(pctx->drng);
+ kzfree(pctx->entropy);
+ kzfree(pctx);
}
static void rng_sock_destruct(struct sock *sk)
@@ -128,6 +193,7 @@ static void rng_sock_destruct(struct sock *sk)
struct alg_sock *ask = alg_sk(sk);
struct rng_ctx *ctx = ask->private;
+ rng_reset_addtl(ctx);
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
}
@@ -135,6 +201,7 @@ static void rng_sock_destruct(struct sock *sk)
static int rng_accept_parent(void *private, struct sock *sk)
{
struct rng_ctx *ctx;
+ struct rng_parent_ctx *pctx = private;
struct alg_sock *ask = alg_sk(sk);
unsigned int len = sizeof(*ctx);
@@ -150,7 +217,9 @@ static int rng_accept_parent(void *private, struct sock *sk)
* state of the RNG.
*/
- ctx->drng = private;
+ ctx->drng = pctx->drng;
+ ctx->addtl = NULL;
+ ctx->addtl_len = 0;
ask->private = ctx;
sk->sk_destruct = rng_sock_destruct;
@@ -159,18 +228,49 @@ static int rng_accept_parent(void *private, struct sock *sk)
static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen)
{
+ struct rng_parent_ctx *pctx = private;
/*
* Check whether seedlen is of sufficient size is done in RNG
* implementations.
*/
- return crypto_rng_reset(private, seed, seedlen);
+ return crypto_rng_reset(pctx->drng, seed, seedlen);
+}
+
+#ifdef CONFIG_CRYPTO_CAVS_DRBG
+static int rng_setentropy(void *private, const u8 *entropy, unsigned int len)
+{
+ struct rng_parent_ctx *pctx = private;
+ u8 *kentropy = NULL;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (pctx->entropy)
+ return -EINVAL;
+
+ if (len > MAXSIZE)
+ len = MAXSIZE;
+
+ if (len) {
+ kentropy = memdup_user(entropy, len);
+ if (IS_ERR(kentropy))
+ return PTR_ERR(kentropy);
+ }
+
+ crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
+ pctx->entropy = kentropy;
+ return len;
}
+#endif
static const struct af_alg_type algif_type_rng = {
.bind = rng_bind,
.release = rng_release,
.accept = rng_accept_parent,
.setkey = rng_setkey,
+#ifdef CONFIG_CRYPTO_CAVS_DRBG
+ .setentropy = rng_setentropy,
+#endif
.ops = &algif_rng_ops,
.name = "rng",
.owner = THIS_MODULE
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 56527c85d122..312fdb3469cf 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -46,6 +46,7 @@ struct af_alg_type {
void *(*bind)(const char *name, u32 type, u32 mask);
void (*release)(void *private);
int (*setkey)(void *private, const u8 *key, unsigned int keylen);
+ int (*setentropy)(void *private, const u8 *entropy, unsigned int len);
int (*accept)(void *private, struct sock *sk);
int (*accept_nokey)(void *private, struct sock *sk);
int (*setauthsize)(void *private, unsigned int authsize);
@@ -123,7 +124,7 @@ struct af_alg_async_req {
* @tsgl_list: Link to TX SGL
* @iv: IV for cipher operation
* @aead_assoclen: Length of AAD for AEAD cipher operations
- * @completion: Work queue for synchronous operation
+ * @wait: Wait on completion of async crypto ops
* @used: TX bytes sent to kernel. This variable is used to
* ensure that user space cannot cause the kernel
* to allocate too much memory in sendmsg operation.
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index bc2bcdec377b..60b7c2efd921 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -35,6 +35,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_DRBG_ENTROPY 6
/* Operations */
#define ALG_OP_DECRYPT 0
--
2.27.0.389.gc38d7665816-goog
next prev parent reply other threads:[~2020-07-16 16:40 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-13 16:48 [PATCH 0/1] crypto: af_alg - add extra parameters for DRBG interface Elena Petrova
2020-07-13 16:48 ` [PATCH 1/1] " Elena Petrova
2020-07-13 17:10 ` Eric Biggers
2020-07-16 14:23 ` Elena Petrova
2020-07-16 16:40 ` Elena Petrova [this message]
2020-07-20 17:35 ` [PATCH v2] " Stephan Mueller
2020-07-21 12:55 ` Elena Petrova
2020-07-21 13:18 ` Stephan Mueller
2020-07-28 16:16 ` Elena Petrova
2020-07-20 17:42 ` Stephan Müller
2020-07-22 15:59 ` Eric Biggers
2020-07-28 15:51 ` [PATCH v3] " Elena Petrova
2020-07-28 17:36 ` Eric Biggers
2020-07-29 15:45 ` [PATCH v4] " Elena Petrova
2020-07-29 19:26 ` Stephan Müller
2020-07-31 7:23 ` Herbert Xu
2020-08-03 14:48 ` Elena Petrova
2020-08-03 15:10 ` Stephan Mueller
2020-08-03 15:30 ` Elena Petrova
2020-08-04 2:18 ` Herbert Xu
2020-07-13 17:25 ` [PATCH 1/1] " Eric Biggers
2020-07-31 7:26 ` Herbert Xu
2020-08-13 16:00 ` Elena Petrova
2020-08-13 16:01 ` [PATCH v4] " Elena Petrova
2020-08-13 16:04 ` Elena Petrova
2020-08-13 16:08 ` [PATCH v5] " Elena Petrova
2020-08-13 19:32 ` Eric Biggers
2020-08-21 4:24 ` Herbert Xu
2020-09-08 17:04 ` [PATCH v6] " Elena Petrova
2020-09-09 4:35 ` Eric Biggers
2020-09-09 18:29 ` [PATCH v7] " Elena Petrova
2020-09-09 21:00 ` Eric Biggers
2020-09-16 11:07 ` [PATCH v8] " Elena Petrova
2020-09-18 6:43 ` Herbert Xu
2020-09-18 15:42 ` [PATCH v9] " Elena Petrova
2020-09-25 8:16 ` Herbert Xu
2020-09-08 17:23 ` [PATCH v5] " Elena Petrova
2020-09-08 17:18 ` Elena Petrova
2020-07-14 5:17 ` [PATCH 0/1] " Stephan Mueller
2020-07-14 15:23 ` Elena Petrova
2020-07-14 15:34 ` Stephan Mueller
2020-07-16 14:41 ` Elena Petrova
2020-07-16 14:49 ` Stephan Mueller
2020-07-16 14:59 ` Stephan Mueller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200716164028.1805047-1-lenaptr@google.com \
--to=lenaptr@google.com \
--cc=ardb@kernel.org \
--cc=ebiggers@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=smueller@chronox.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).