2014-11-21 05:29:36

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 0/7] crypto: AF_ALG: add AEAD and RNG support

Hi,

This patch set adds AEAD and RNG support to the AF_ALG interface
exported by the kernel crypto API. By extending AF_ALG with AEAD and RNG
support, all cipher types the kernel crypto API allows access to are
now accessible from userspace.

The RNG support is stand-alone.

The AEAD implementation is added to algif_skcipher.c to prevent
re-implementation of the memory moving logic.

The extension for the AEAD support can be summarized with the following
types of changes:

* select the correct crypto API functions (either the ablkcipher
or the aead functions)

* apply the additional data needed for AEAD at the right time
(associated data, authentication tag) -- this includes the addition
of user space interfaces to allow setting this data.

* add the calculation for the memory size needed for encryption and
decryption.

In addition, the patch set adds a getsockopt implementation to skcipher to
allow user space to inquire about properties of the ciphers (IV size,
block size, authentication data size). This extension would be needed for a
generic user space usage of these ciphers.

The new AEAD and RNG interfaces are fully tested with the test application
provided at [1]. That test application exercises all newly added user space
interfaces.


Stephan Mueller (7):
*tch set was tested on x86_64 and i386.

[1] http://www.chronox.de/libkcapi.html

Changes v2:
* rebase to current cryptodev-2.6 tree
* use memzero_explicit to zeroize AEAD associated data
* use sizeof for determining length of AEAD associated data
* update algif_rng.c covering all suggestions from Daniel Borkmann
<[email protected]>
* addition of patch 9: add digestsize interface for hashes
* addition of patch to update documentation covering the userspace interface
* change numbers of getsockopt options: separate them from sendmsg interface
definitions

Changes v3:
* remove getsockopt interface
* AEAD: associated data is set prepended to the plain/ciphertext
* AEAD: allowing arbitrary associated data lengths
* remove setkey patch as protection was already in the existing code

crypto: AF_ALG: add user space interface for AEAD
crypto: AF_ALG: extend data structuers for AEAD
crypto: AF_ALG: crypto API calls to inline functions
crypto: AF_ALG: add AEAD support
crypto: AF_ALG: add random number generator support
crypto: AF_ALG: enable RNG interface compilation
crypto: AF_ALG: document the user space interface

Documentation/crypto/crypto-API-userspace.txt | 70 +++++-
crypto/Kconfig | 9 +
crypto/Makefile | 1 +
crypto/af_alg.c | 12 +
crypto/algif_rng.c | 186 ++++++++++++++++
crypto/algif_skcipher.c | 308 +++++++++++++++++++++++---
include/crypto/if_alg.h | 2 +
include/uapi/linux/if_alg.h | 2 +
8 files changed, 559 insertions(+), 31 deletions(-)
create mode 100644 crypto/algif_rng.c

--
2.1.0


2014-11-21 05:42:39

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 7/7] crypto: AF_ALG: document the user space interface

The extension of the user space interface documentation covers all
aspects of the patchset, including:

* AEAD cipher interface

* RNG cipher interface

Signed-off-by: Stephan Mueller <[email protected]>
---
Documentation/crypto/crypto-API-userspace.txt | 70 ++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 2 deletions(-)

diff --git a/Documentation/crypto/crypto-API-userspace.txt b/Documentation/crypto/crypto-API-userspace.txt
index ac619cd..0646034 100644
--- a/Documentation/crypto/crypto-API-userspace.txt
+++ b/Documentation/crypto/crypto-API-userspace.txt
@@ -30,8 +30,9 @@ ciphers are accessible:

* Symmetric ciphers

-Note, AEAD ciphers are currently not supported via the symmetric cipher
-interface.
+ * AEAD ciphers
+
+ * Random number generators

The interface is provided via Netlink using the type AF_ALG. In addition, the
setsockopt option type is SOL_ALG. In case the user space header files do not
@@ -85,6 +86,7 @@ If a consumer on the other hand wants to maintain the plaintext and the
ciphertext in different memory locations, all a consumer needs to do is to
provide different memory pointers for the encryption and decryption operation.

+
Message digest API
==================

@@ -169,6 +171,69 @@ as large as to hold all blocks of the encrypted or decrypted data. If the output
data size is smaller, only as many blocks are returned that fit into that
output buffer size.

+
+AEAD cipher API
+===============
+
+The operation is identical to the symmetric cipher API. However, an AEAD
+cipher requires additional information, such as the authentication tag and
+the associated data. This data is to be supplied in addition to the normal
+symmetric cipher data like key and IV discussed for the symmetric ciphers.
+
+During initialization, the struct sockaddr data structure must be filled as
+follows:
+
+struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "aead", /* this selects the AEAD cipher */
+ .salg_name = "gcm(aes)" /* this is the cipher name */
+};
+
+The discussion about the sendmsg given for the symmetric cipher applies for
+the AEAD interface as well. In addition to the plaintext / ciphertext data and
+the IV, the following data must be supplied with the cmsghdr data structure:
+
+ * The AEAD authentication tag size is set with the flag
+ ALG_SET_AEAD_AUTHSIZE. The integer value of the authentication tag
+ size must be provided in the data field of the cmsghdr structure.
+
+ * The AEAD associated data is set with the flag ALG_SET_AEAD_ASSOC.
+ The data is set the same way as for the IV by supplying the associated
+ data in the data field of the cmsghdr structure.
+
+The authentication tag itself, however, is handled in a different way to comply
+with the specifics of the kernel crypto API and to avoid copying the
+authentication tag around in memory. The authentication tag is added to the
+memory that immediately follows the ciphertext.
+
+ * When performing an encryption operation, the resulting ciphertext
+ buffer will hold the tag as follows: ciphertext || tag. The consumer
+ must ensure that the ciphertext buffer is large enough to hold the
+ ciphertext together with the tag of the size set by the consumer using
+ the ALG_SET_AEAD_AUTHSIZE cmsghdr flag as discussed above.
+
+ * When performing a decryption operation, the initial ciphertext buffer
+ must hold the tag as follows: ciphertext || tag. The resulting
+ plaintext has the same size as the ciphertext.
+
+Note: Authentication errors during decryption are marked with a failing
+read/recv system call whose errno is set to EBADMSG.
+
+
+Random number generator API
+===========================
+
+Compared to the symmetric ciphers, the random number generator API is simple:
+it only supports the system calls of read/recv.
+
+The consumer must observe the returned size of the read/recv system calls and
+potentially make subsequent calls if the returned length of random numbers is
+smaller than the expected length.
+
+When initializing a random number generator instance, the AF_ALG interface
+handler ensures that it is appropriately seeded.
+
+
Setsockopt interface
====================

@@ -190,6 +255,7 @@ optname:

- the hash cipher type (keyed message digests)

+
User space API example
======================

--
2.1.0

2014-11-21 05:33:38

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 6/7] crypto: AF_ALG: enable RNG interface compilation

Enable compilation of the RNG AF_ALG support and provide a Kconfig
option to compile the RNG AF_ALG support.

Signed-off-by: Stephan Mueller <[email protected]>
---
crypto/Kconfig | 9 +++++++++
crypto/Makefile | 1 +
2 files changed, 10 insertions(+)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 87bbc9c..e127323 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1505,6 +1505,15 @@ config CRYPTO_USER_API_SKCIPHER
This option enables the user-spaces interface for symmetric
key cipher algorithms.

+config CRYPTO_USER_API_RNG
+ tristate "User-space interface for random number generator algorithms"
+ depends on NET
+ select CRYPTO_RNG
+ select CRYPTO_USER_API
+ help
+ This option enables the user-spaces interface for random
+ number generator algorithms.
+
config CRYPTO_HASH_INFO
bool

diff --git a/crypto/Makefile b/crypto/Makefile
index 1445b91..ba19465 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
+obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o

#
# generic algorithms and the async_tx api
--
2.1.0

2014-11-21 05:42:48

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 2/7] crypto: AF_ALG: extend data structuers for AEAD

The data structure holding the state of an ongoing symmetric cipher
operation is extended by the data variables needed for AEAD.

The request data structures are encapsulated by a union as the symmetric
cipher implementation is either exclusively used for "normal" symmetric
ciphers or for AEAD ciphers.

In addition, the size of the associated data expected to be present in
the input data must be retained.

Signed-off-by: Stephan Mueller <[email protected]>
---
crypto/algif_skcipher.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 85e3bdb..49d5b08 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -46,7 +46,12 @@ struct skcipher_ctx {
bool merge;
bool enc;

- struct ablkcipher_request req;
+ bool aead;
+ size_t aead_assoclen;
+ union {
+ struct ablkcipher_request ablkcipher_req;
+ struct aead_request aead_req;
+ } u;
};

#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
--
2.1.0

2014-11-21 05:30:18

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 1/7] crypto: AF_ALG: add user space interface for AEAD

AEAD requires the following data in addition to normal symmetric
ciphers:

* Associated authentication data of arbitrary length and
length

* Authentication tag for decryption and length

* Length of authentication tag for encryption

The memory structure for the data received by the kernel via sendmsg
must follow this structure:

* Symmetric encryption input: plaintext
* Symmetric encryption output: ciphertext
* AEAD encryption input: assoc data || plaintext
* AEAD encryption output: cipherntext || auth tag
* Symmetric decryption input: ciphertext
* Symmetric decryption output: plaintext
* AEAD decryption input: assoc data || ciphertext || authtag
* AEAD decryption output: plaintext

Therefore, in addition to submitting the data, AEAD requires that
the associated data length and the tag length must be communicated.
The plaintext/ciphertext length can be derived from the other two size
fields. Therefore, This patch adds setting the associated data length
and tag length as part of the sendmsg communication.

Signed-off-by: Stephan Mueller <[email protected]>
---
crypto/af_alg.c | 12 ++++++++++++
include/crypto/if_alg.h | 2 ++
include/uapi/linux/if_alg.h | 2 ++
3 files changed, 16 insertions(+)

diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 6a3ad80..75eb88c 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -421,6 +421,18 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
con->op = *(u32 *)CMSG_DATA(cmsg);
break;

+ case ALG_SET_AEAD_AUTHSIZE:
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
+ return -EINVAL;
+ con->aead_authsize = *(u32 *)CMSG_DATA(cmsg);
+ break;
+
+ case ALG_SET_AEAD_ASSOCLEN:
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
+ return -EINVAL;
+ con->aead_assoclen = *(u32 *)CMSG_DATA(cmsg);
+ break;
+
default:
return -EINVAL;
}
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index d61c111..60ed1b7 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -42,6 +42,8 @@ struct af_alg_completion {
struct af_alg_control {
struct af_alg_iv *iv;
int op;
+ unsigned int aead_authsize;
+ unsigned int aead_assoclen;
};

struct af_alg_type {
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index 0f9acce..f2acd2f 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -32,6 +32,8 @@ struct af_alg_iv {
#define ALG_SET_KEY 1
#define ALG_SET_IV 2
#define ALG_SET_OP 3
+#define ALG_SET_AEAD_ASSOCLEN 4
+#define ALG_SET_AEAD_AUTHSIZE 5

/* Operations */
#define ALG_OP_DECRYPT 0
--
2.1.0

2014-11-21 05:30:49

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 3/7] crypto: AF_ALG: crypto API calls to inline functions

To avoid excessive branches and cluttering the code, all kernel crypto
API calls are extracted into separate inline functions. These functions
invoke either the ablkcipher or the aead crypto API function calls, as
necessary.

Signed-off-by: Stephan Mueller <[email protected]>
---
crypto/algif_skcipher.c | 143 ++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 125 insertions(+), 18 deletions(-)

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 49d5b08..9637365 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -244,14 +244,121 @@ static void skcipher_data_wakeup(struct sock *sk)
rcu_read_unlock();
}

+static inline bool skcipher_is_aead(struct crypto_tfm *tfm)
+{
+ return ((crypto_tfm_alg_type(tfm) & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_AEAD);
+}
+
+static inline unsigned int skcipher_crypto_ivsize(void *private)
+{
+ if (skcipher_is_aead(private))
+ return crypto_aead_ivsize(private);
+ else
+ return crypto_ablkcipher_ivsize(private);
+}
+
+static inline unsigned int skcipher_crypto_ivsize_ctx(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_ivsize(crypto_aead_reqtfm(&ctx->u.aead_req));
+ else
+ return crypto_ablkcipher_ivsize(
+ crypto_ablkcipher_reqtfm(&ctx->u.ablkcipher_req));
+}
+
+static inline unsigned int skcipher_crypto_blocksize(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_blocksize(
+ crypto_aead_reqtfm(&ctx->u.aead_req));
+ else
+ return crypto_ablkcipher_blocksize(
+ crypto_ablkcipher_reqtfm(&ctx->u.ablkcipher_req));
+}
+
+static inline unsigned int skcipher_crypto_reqsize(void *private)
+{
+ if (skcipher_is_aead(private))
+ return crypto_aead_reqsize(private);
+ else
+ return crypto_ablkcipher_reqsize(private);
+}
+
+static inline unsigned int skcipher_crypto_setkey(void *private, const u8 *key,
+ unsigned int keylen)
+{
+ if (skcipher_is_aead(private))
+ return crypto_aead_setkey(private, key, keylen);
+ else
+ return crypto_ablkcipher_setkey(private, key, keylen);
+}
+
+static inline void skcipher_crypto_free(void *private)
+{
+ if (skcipher_is_aead(private))
+ crypto_free_aead(private);
+ else
+ crypto_free_ablkcipher(private);
+}
+
+static inline void skcipher_request_set_tfm(struct skcipher_ctx *ctx, void *tfm)
+{
+ if (ctx->aead)
+ aead_request_set_tfm(&ctx->u.aead_req, tfm);
+ else
+ ablkcipher_request_set_tfm(&ctx->u.ablkcipher_req, tfm);
+}
+
+static inline int skcipher_crypto_encrypt(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_encrypt(&ctx->u.aead_req);
+ else
+ return crypto_ablkcipher_encrypt(&ctx->u.ablkcipher_req);
+}
+
+static inline int skcipher_crypto_decrypt(struct skcipher_ctx *ctx)
+{
+ if (ctx->aead)
+ return crypto_aead_decrypt(&ctx->u.aead_req);
+ else
+ return crypto_ablkcipher_decrypt(&ctx->u.ablkcipher_req);
+}
+
+static inline void skcipher_crypto_set_crypt(struct skcipher_ctx *ctx,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+ unsigned int cryptlen, u8 *iv)
+{
+ if (ctx->aead)
+ return aead_request_set_crypt(&ctx->u.aead_req, src, dst,
+ cryptlen, iv);
+ else
+ return ablkcipher_request_set_crypt(&ctx->u.ablkcipher_req, src,
+ dst, cryptlen, iv);
+}
+
+static inline void skcipher_request_set_callback(struct skcipher_ctx *ctx,
+ u32 flags,
+ crypto_completion_t complete,
+ void *data)
+{
+ if (ctx->aead)
+ aead_request_set_callback(&ctx->u.aead_req, flags, complete,
+ data);
+ else
+ ablkcipher_request_set_callback(&ctx->u.ablkcipher_req, flags,
+ complete, data);
+}
+
static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
- struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
- unsigned ivsize = crypto_ablkcipher_ivsize(tfm);
+ unsigned ivsize = skcipher_crypto_ivsize_ctx(ctx);
struct skcipher_sg_list *sgl;
struct af_alg_control con = {};
long copied = 0;
@@ -429,8 +536,7 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
- unsigned bs = crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(
- &ctx->req));
+ unsigned bs = skcipher_crypto_blocksize(ctx);
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
unsigned long iovlen;
@@ -480,8 +586,8 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,

err = af_alg_wait_for_completion(
ctx->enc ?
- crypto_ablkcipher_encrypt(&ctx->req) :
- crypto_ablkcipher_decrypt(&ctx->req),
+ skcipher_crypto_encrypt(ctx) :
+ skcipher_crypto_decrypt(ctx),
&ctx->completion);

free:
@@ -556,23 +662,23 @@ static void *skcipher_bind(const char *name, u32 type, u32 mask)

static void skcipher_release(void *private)
{
- crypto_free_ablkcipher(private);
+ skcipher_crypto_free(private);
}

static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
{
- return crypto_ablkcipher_setkey(private, key, keylen);
+ return skcipher_crypto_setkey(private, key, keylen);
}

static void skcipher_sock_destruct(struct sock *sk)
{
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
- struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
+ unsigned int ivlen = skcipher_crypto_ivsize_ctx(ctx);

skcipher_free_sgl(sk);
- memzero_explicit(ctx->iv, crypto_ablkcipher_ivsize(tfm));
- sock_kfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm));
+ memzero_explicit(ctx->iv, ivlen);
+ sock_kfree_s(sk, ctx->iv, ivlen);
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
}
@@ -581,20 +687,20 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
{
struct skcipher_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
- unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(private);
+ unsigned int len = sizeof(*ctx) + skcipher_crypto_reqsize(private);
+ unsigned int ivlen = skcipher_crypto_ivsize(private);

ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
return -ENOMEM;

- ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private),
- GFP_KERNEL);
+ ctx->iv = sock_kmalloc(sk, ivlen, GFP_KERNEL);
if (!ctx->iv) {
sock_kfree_s(sk, ctx, len);
return -ENOMEM;
}

- memset(ctx->iv, 0, crypto_ablkcipher_ivsize(private));
+ memset(ctx->iv, 0, ivlen);

INIT_LIST_HEAD(&ctx->tsgl);
ctx->len = len;
@@ -602,13 +708,14 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
ctx->more = 0;
ctx->merge = 0;
ctx->enc = 0;
+ ctx->aead = skcipher_is_aead(private);
af_alg_init_completion(&ctx->completion);

ask->private = ctx;

- ablkcipher_request_set_tfm(&ctx->req, private);
- ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- af_alg_complete, &ctx->completion);
+ skcipher_request_set_tfm(ctx, private);
+ skcipher_request_set_callback(ctx, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ af_alg_complete, &ctx->completion);

sk->sk_destruct = skcipher_sock_destruct;

--
2.1.0

2014-11-21 05:32:52

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 5/7] crypto: AF_ALG: add random number generator support

This patch adds the random number generator support for AF_ALG.

A random number generator's purpose is to generate data without
requiring the caller to provide any data. Therefore, the AF_ALG
interface handler for RNGs only implements a callback handler for
recvmsg.

The following parameters provided with a recvmsg are processed by the
RNG callback handler:

* sock - to resolve the RNG context data structure accessing the
RNG instance private to the socket

* len - this parameter allows userspace callers to specify how
many random bytes the RNG shall produce and return. As the
kernel context for the RNG allocates a buffer of 128 bytes to
store random numbers before copying them to userspace, the len
parameter is checked that it is not larger than 128. If a
caller wants more random numbers, a new request for recvmsg
shall be made.

The size of 128 bytes is chose because of the following considerations:

* to increase the memory footprint of the kernel too much (note,
that would be 128 bytes per open socket)

* 128 is divisible by any typical cryptographic block size an
RNG may have

* A request for random numbers typically only shall supply small
amount of data like for keys or IVs that should only require
one invocation of the recvmsg function.

Note, during instantiation of the RNG, the code checks whether the RNG
implementation requires seeding. If so, the RNG is seeded with output
from get_random_bytes.

A fully working example using all aspects of the RNG interface is
provided at http://www.chronox.de/libkcapi.html

Signed-off-by: Stephan Mueller <[email protected]>
---
crypto/algif_rng.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
create mode 100644 crypto/algif_rng.c

diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
new file mode 100644
index 0000000..fc25869
--- /dev/null
+++ b/crypto/algif_rng.c
@@ -0,0 +1,186 @@
+/*
+ * algif_rng: User-space interface for random number generators
+ *
+ * This file provides the user-space API for random number generators.
+ *
+ * Copyright (C) 2014, Stephan Mueller <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2
+ * are required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <crypto/rng.h>
+#include <linux/random.h>
+#include <crypto/if_alg.h>
+#include <linux/net.h>
+#include <net/sock.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stephan Mueller <[email protected]>");
+MODULE_DESCRIPTION("User-space interface for random number generators");
+
+struct rng_ctx {
+#define MAXSIZE 128
+ u8 result[MAXSIZE];
+ unsigned int len;
+ struct crypto_rng *drng;
+};
+
+static int rng_recvmsg(struct kiocb *unused, struct socket *sock,
+ struct msghdr *msg, size_t len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
+ struct rng_ctx *ctx = ask->private;
+ int err = -EFAULT;
+
+ if (len == 0)
+ return 0;
+ if (len > MAXSIZE)
+ len = MAXSIZE;
+
+ lock_sock(sk);
+ len = crypto_rng_get_bytes(ctx->drng, ctx->result, len);
+ if (len < 0)
+ goto unlock;
+
+ err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
+ memzero_explicit(ctx->result, len);
+
+unlock:
+ release_sock(sk);
+
+ return err ? err : len;
+}
+
+static struct proto_ops algif_rng_ops = {
+ .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,
+ .poll = sock_no_poll,
+ .sendmsg = sock_no_sendmsg,
+ .sendpage = sock_no_sendpage,
+
+ .release = af_alg_release,
+ .recvmsg = rng_recvmsg,
+};
+
+static void *rng_bind(const char *name, u32 type, u32 mask)
+{
+ return crypto_alloc_rng(name, type, mask);
+}
+
+static void rng_release(void *private)
+{
+ crypto_free_rng(private);
+}
+
+static void rng_sock_destruct(struct sock *sk)
+{
+ struct alg_sock *ask = alg_sk(sk);
+ struct rng_ctx *ctx = ask->private;
+
+ memzero_explicit(ctx->result, sizeof(ctx->result));
+ sock_kfree_s(sk, ctx, ctx->len);
+ af_alg_release_parent(sk);
+}
+
+static int rng_accept_parent(void *private, struct sock *sk)
+{
+ struct rng_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+ unsigned int len = sizeof(*ctx);
+ int seedsize = crypto_rng_seedsize(private);
+ int ret = -ENOMEM;
+
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ memset(ctx->result, 0, sizeof(ctx->result));
+
+ ctx->len = len;
+
+ if (seedsize) {
+ u8 *buf = kmalloc(seedsize, GFP_KERNEL);
+ if (!buf)
+ goto err;
+ get_random_bytes(buf, seedsize);
+ ret = crypto_rng_reset(private, buf, len);
+ kzfree(buf);
+ if (ret)
+ goto err;
+ }
+
+ ctx->drng = private;
+ ask->private = ctx;
+ sk->sk_destruct = rng_sock_destruct;
+
+ return 0;
+
+err:
+ sock_kfree_s(sk, ctx, len);
+ return ret;
+}
+
+static const struct af_alg_type algif_type_rng = {
+ .bind = rng_bind,
+ .release = rng_release,
+ .accept = rng_accept_parent,
+ .ops = &algif_rng_ops,
+ .name = "rng",
+ .owner = THIS_MODULE
+};
+
+static int __init rng_init(void)
+{
+ return af_alg_register_type(&algif_type_rng);
+}
+
+void __exit rng_exit(void)
+{
+ int err = af_alg_unregister_type(&algif_type_rng);
+ BUG_ON(err);
+}
+
+module_init(rng_init);
+module_exit(rng_exit);
--
2.1.0

2014-11-21 05:32:16

by Stephan Müller

[permalink] [raw]
Subject: [PATCH v3 4/7] crypto: AF_ALG: add AEAD support

This patch adds the AEAD support for AF_ALG.

The AEAD implementation uses the entire memory handling and
infrastructure of the existing skcipher implementation.

To use AEAD, the user space consumer has to use the salg_type named
"aead". The AEAD extension only uses the bind callback as the key
differentiator. The previously added functions that select whether to
use AEAD or ablkcipher crypto API functions depend on the TFM type
allocated during the bind() call.

The addition of AEAD brings a bit of overhead to calculate the size of
the ciphertext, because the AEAD implementation of the kernel crypto API
makes implied assumption on the location of the authentication tag. When
performing an encryption, the tag will be added to the created
ciphertext (note, the tag is placed adjacent to the ciphertext). For
decryption, the caller must hand in the ciphertext with the tag appended
to the ciphertext. Therefore, the selection of the used memory
needs to add/subtract the tag size from the source/destination buffers
depending on the encryption type. The code is provided with comments
explainint when and how that operation is performed.

Note: The AF_ALG interface does not support zero length input data.
Such zero length input data may be used if one wants to access the hash
implementation of an AEAD directly (e.g. the GHASH of GCM or CMAC for
CCM). However, this is a use case that is not of interest. GHASH or
CMAC is directly available via the hash AF_ALG interface and we
therefore do not need to take precautions for this use case.

A fully working example using all aspects of AEAD is provided at
http://www.chronox.de/libkcapi.html

Signed-off-by: Stephan Mueller <[email protected]>
---
crypto/algif_skcipher.c | 158 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 148 insertions(+), 10 deletions(-)

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 9637365..26367f4 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -384,6 +384,9 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,

if (con.iv && con.iv->ivlen != ivsize)
return -EINVAL;
+
+ if (ctx->aead && !con.aead_authsize && !con.aead_assoclen)
+ return -EINVAL;
}

err = -EINVAL;
@@ -396,6 +399,16 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
ctx->enc = enc;
if (con.iv)
memcpy(ctx->iv, con.iv->iv, ivsize);
+ /* AEAD authentication data handling */
+ if (ctx->aead) {
+ if (con.aead_authsize)
+ err = crypto_aead_setauthsize(
+ crypto_aead_reqtfm(&ctx->u.aead_req),
+ con.aead_authsize);
+ if (err)
+ goto unlock;
+ ctx->aead_assoclen = con.aead_assoclen;
+ }
}

while (size) {
@@ -539,15 +552,58 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
unsigned bs = skcipher_crypto_blocksize(ctx);
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
+ struct scatterlist assoc;
unsigned long iovlen;
struct iovec *iov;
int err = -EAGAIN;
int used;
long copied = 0;
+ unsigned int aead_authsize_enc = 0;
+ unsigned int aead_authsize_dec = 0;

lock_sock(sk);
+ /*
+ * AEAD memory structure: For encryption, the tag is appended to the
+ * ciphertext which implies that the memory allocated for the ciphertext
+ * must be increased by the tag length. For decryption, the tag
+ * is expected to be concatenated to the ciphertext. The plaintext
+ * therefore has a memory size of the ciphertext minus the tag length.
+ *
+ * Note: this memory calculation only works because we require the
+ * user space caller to:
+ * * perform encryption by invoking the recv function with a buffer
+ * length of ciphertext + tag size -- the send function can be
+ * invoked normally with just the plaintext.
+ * * perform a decryption by invoking the the write function with
+ * a buffer holding the ciphertext + tag (and setting the
+ * buffer size accordingly) -- the recv function can be invoked
+ * normally with just the space needed for the ciphertext.
+ * Though, the caller should check for EBADMSG to catch integiry
+ * violations.
+ *
+ * The memory structure for cipher operation has the following
+ * structure:
+ * Symmetric encryption input: plaintext
+ * Symmetric encryption output: ciphertext
+ * AEAD encryption input: assoc data || plaintext
+ * AEAD encryption output: cipherntext || auth tag
+ * Symmetric decryption input: ciphertext
+ * Symmetric decryption output: plaintext
+ * AEAD decryption input: assoc data || ciphertext || auth tag
+ * AEAD decryption output: plaintext
+ */
+ if (ctx->aead) {
+ if (ctx->enc)
+ aead_authsize_enc = crypto_aead_authsize(
+ crypto_aead_reqtfm(&ctx->u.aead_req));
+ else
+ aead_authsize_dec = crypto_aead_authsize(
+ crypto_aead_reqtfm(&ctx->u.aead_req));
+ }
+
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
iovlen--, iov++) {
+ /* size of the output data memory */
unsigned long seglen = iov->iov_len;
char __user *from = iov->iov_base;

@@ -559,14 +615,43 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
while (!sg->length)
sg++;

+ /* size of the input data memory */
used = ctx->used;
- if (!used) {
+ if (used <= ctx->aead_assoclen) {
err = skcipher_wait_for_data(sk, flags);
if (err)
goto unlock;
}

- used = min_t(unsigned long, used, seglen);
+ /*
+ * The cipher operation input data is reduced by
+ * the associated data length as the data pointers will
+ * be moved forward by the associated data length later
+ * on.
+ */
+ used -= ctx->aead_assoclen;
+ used = min_t(unsigned long,
+ /*
+ * In case of encryption, add
+ * the memory needed for the tag
+ * to the input data length to
+ * give the cipher the necessary
+ * space to add the tag.
+ */
+ used + aead_authsize_enc,
+ /*
+ * In case of decryption, add the
+ * memory needed for the tag
+ * calculations to the output
+ * buffer.
+ */
+ seglen + aead_authsize_dec);
+
+ if (used < aead_authsize_enc ||
+ seglen < aead_authsize_dec) {
+ err = -ENOMEM;
+ goto unlock;
+ }

used = af_alg_make_sg(&ctx->rsgl, from, used, 1);
err = used;
@@ -580,9 +665,29 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
if (!used)
goto free;

- ablkcipher_request_set_crypt(&ctx->req, sg,
- ctx->rsgl.sg, used,
- ctx->iv);
+ if (ctx->aead) {
+ /* first chunk of input is AD */
+ sg_init_table(&assoc, 2);
+ sg_set_page(&assoc, sg_page(sg),
+ ctx->aead_assoclen, 0);
+ aead_request_set_assoc(&ctx->u.aead_req, &assoc,
+ ctx->aead_assoclen);
+ /* point sg to cipher/plaintext */
+ sg_set_page(sg, sg_page(sg),
+ sg->length - ctx->aead_assoclen,
+ ctx->aead_assoclen);
+ }
+
+ /*
+ * See API specification of the AEAD API: for
+ * encryption, we need to tell the encrypt function
+ * what the size of the plaintext is. But we have
+ * ensured that we have sufficient memory allocated for
+ * the operation.
+ */
+ skcipher_crypto_set_crypt(ctx, sg, ctx->rsgl.sg,
+ used - aead_authsize_enc,
+ ctx->iv);

err = af_alg_wait_for_completion(
ctx->enc ?
@@ -596,10 +701,22 @@ free:
if (err)
goto unlock;

- copied += used;
- from += used;
- seglen -= used;
- skcipher_pull_sgl(sk, used);
+ /*
+ * Adjust the output buffer counters by only the size
+ * needed for the plaintext in case of a decryption
+ */
+ copied += (used - aead_authsize_dec);
+ from += (used - aead_authsize_dec);
+ seglen -= (used - aead_authsize_dec);
+ /*
+ * Adjust the input buffer by how much we have encrypted
+ * or decrypted. In case of encryption, we only credit
+ * the memory of the plaintext. The associated data
+ * is also released as a new cipher operation must
+ * provide new associated data.
+ */
+ skcipher_pull_sgl(sk, used - aead_authsize_enc +
+ ctx->aead_assoclen);
}
}

@@ -732,15 +849,36 @@ static const struct af_alg_type algif_type_skcipher = {
.owner = THIS_MODULE
};

+static void *aead_bind(const char *name, u32 type, u32 mask)
+{
+ return crypto_alloc_aead(name, type, mask);
+}
+
+static const struct af_alg_type algif_type_aead = {
+ .bind = aead_bind,
+ .release = skcipher_release,
+ .setkey = skcipher_setkey,
+ .accept = skcipher_accept_parent,
+ .ops = &algif_skcipher_ops,
+ .name = "aead",
+ .owner = THIS_MODULE
+};
+
static int __init algif_skcipher_init(void)
{
- return af_alg_register_type(&algif_type_skcipher);
+ int ret = af_alg_register_type(&algif_type_skcipher);
+
+ if (ret)
+ return ret;
+ return af_alg_register_type(&algif_type_aead);
}

static void __exit algif_skcipher_exit(void)
{
int err = af_alg_unregister_type(&algif_type_skcipher);
BUG_ON(err);
+ err = af_alg_unregister_type(&algif_type_aead);
+ BUG_ON(err);
}

module_init(algif_skcipher_init);
--
2.1.0

2014-11-24 14:26:39

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH v3 1/7] crypto: AF_ALG: add user space interface for AEAD

On Fri, Nov 21, 2014 at 06:30:18AM +0100, Stephan Mueller wrote:
>
> @@ -421,6 +421,18 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
> con->op = *(u32 *)CMSG_DATA(cmsg);
> break;
>
> + case ALG_SET_AEAD_AUTHSIZE:
> + if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
> + return -EINVAL;
> + con->aead_authsize = *(u32 *)CMSG_DATA(cmsg);
> + break;

This is a tfm attribute so it should go into setsockopt.

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2014-11-24 14:29:46

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH v3 4/7] crypto: AF_ALG: add AEAD support

On Fri, Nov 21, 2014 at 06:32:16AM +0100, Stephan Mueller wrote:
> This patch adds the AEAD support for AF_ALG.
>
> The AEAD implementation uses the entire memory handling and
> infrastructure of the existing skcipher implementation.
>
> To use AEAD, the user space consumer has to use the salg_type named
> "aead". The AEAD extension only uses the bind callback as the key
> differentiator. The previously added functions that select whether to
> use AEAD or ablkcipher crypto API functions depend on the TFM type
> allocated during the bind() call.
>
> The addition of AEAD brings a bit of overhead to calculate the size of
> the ciphertext, because the AEAD implementation of the kernel crypto API
> makes implied assumption on the location of the authentication tag. When
> performing an encryption, the tag will be added to the created
> ciphertext (note, the tag is placed adjacent to the ciphertext). For
> decryption, the caller must hand in the ciphertext with the tag appended
> to the ciphertext. Therefore, the selection of the used memory
> needs to add/subtract the tag size from the source/destination buffers
> depending on the encryption type. The code is provided with comments
> explainint when and how that operation is performed.
>
> Note: The AF_ALG interface does not support zero length input data.
> Such zero length input data may be used if one wants to access the hash
> implementation of an AEAD directly (e.g. the GHASH of GCM or CMAC for
> CCM). However, this is a use case that is not of interest. GHASH or
> CMAC is directly available via the hash AF_ALG interface and we
> therefore do not need to take precautions for this use case.
>
> A fully working example using all aspects of AEAD is provided at
> http://www.chronox.de/libkcapi.html
>
> Signed-off-by: Stephan Mueller <[email protected]>

I appreciate the effort to share code, but shoe-horning AEAD into
algif_skcipher is just too ugly.

How about let's just start with a separate algif_aead and then
add helpers to merge common code as applicable?

Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2014-11-24 14:31:58

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] crypto: AF_ALG: add random number generator support

On Fri, Nov 21, 2014 at 06:32:52AM +0100, Stephan Mueller wrote:
> This patch adds the random number generator support for AF_ALG.
>
> A random number generator's purpose is to generate data without
> requiring the caller to provide any data. Therefore, the AF_ALG
> interface handler for RNGs only implements a callback handler for
> recvmsg.
>
> The following parameters provided with a recvmsg are processed by the
> RNG callback handler:
>
> * sock - to resolve the RNG context data structure accessing the
> RNG instance private to the socket
>
> * len - this parameter allows userspace callers to specify how
> many random bytes the RNG shall produce and return. As the
> kernel context for the RNG allocates a buffer of 128 bytes to
> store random numbers before copying them to userspace, the len
> parameter is checked that it is not larger than 128. If a
> caller wants more random numbers, a new request for recvmsg
> shall be made.
>
> The size of 128 bytes is chose because of the following considerations:
>
> * to increase the memory footprint of the kernel too much (note,
> that would be 128 bytes per open socket)
>
> * 128 is divisible by any typical cryptographic block size an
> RNG may have
>
> * A request for random numbers typically only shall supply small
> amount of data like for keys or IVs that should only require
> one invocation of the recvmsg function.
>
> Note, during instantiation of the RNG, the code checks whether the RNG
> implementation requires seeding. If so, the RNG is seeded with output
> from get_random_bytes.
>
> A fully working example using all aspects of the RNG interface is
> provided at http://www.chronox.de/libkcapi.html
>
> Signed-off-by: Stephan Mueller <[email protected]>

Sorry but who is going to use this and for what purpose?

Every other algif interface exports real hardware features that
cannot otherwise be accessed from user-space. All crypto RNGs
are by definition software-only, so what is the point of this?

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2014-11-24 14:58:34

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH v3 4/7] crypto: AF_ALG: add AEAD support

Am Montag, 24. November 2014, 22:29:46 schrieb Herbert Xu:

Hi Herbert,

>On Fri, Nov 21, 2014 at 06:32:16AM +0100, Stephan Mueller wrote:
>> This patch adds the AEAD support for AF_ALG.
>>
>> The AEAD implementation uses the entire memory handling and
>> infrastructure of the existing skcipher implementation.
>>
>> To use AEAD, the user space consumer has to use the salg_type named
>> "aead". The AEAD extension only uses the bind callback as the key
>> differentiator. The previously added functions that select whether to
>> use AEAD or ablkcipher crypto API functions depend on the TFM type
>> allocated during the bind() call.
>>
>> The addition of AEAD brings a bit of overhead to calculate the size
>> of
>> the ciphertext, because the AEAD implementation of the kernel crypto
>> API makes implied assumption on the location of the authentication
>> tag. When performing an encryption, the tag will be added to the
>> created ciphertext (note, the tag is placed adjacent to the
>> ciphertext). For decryption, the caller must hand in the ciphertext
>> with the tag appended to the ciphertext. Therefore, the selection of
>> the used memory needs to add/subtract the tag size from the
>> source/destination buffers depending on the encryption type. The
>> code is provided with comments explainint when and how that
>> operation is performed.
>>
>> Note: The AF_ALG interface does not support zero length input data.
>> Such zero length input data may be used if one wants to access the
>> hash implementation of an AEAD directly (e.g. the GHASH of GCM or
>> CMAC for CCM). However, this is a use case that is not of interest.
>> GHASH or CMAC is directly available via the hash AF_ALG interface
>> and we therefore do not need to take precautions for this use case.
>>
>> A fully working example using all aspects of AEAD is provided at
>> http://www.chronox.de/libkcapi.html
>>
>> Signed-off-by: Stephan Mueller <[email protected]>
>
>I appreciate the effort to share code, but shoe-horning AEAD into
>algif_skcipher is just too ugly.

Ok. But in the code you see that skcipher is a 100% subset of AEAD. For
AEAD, all we need to do in addition to normal symmetric ciphers is to
select the AEAD kernel crypto API calls, to locate and use the AD and to
ensure we have the right memory size to process the tag.

How about the following:

Use algif_skcipher.c as the common code which requires:

- function pointers for the kernel crypto API backends

- function pointers for the AEAD specific handling which are invoked at
the right places -- they are NULL in case of skcipher
>
>How about let's just start with a separate algif_aead and then
>add helpers to merge common code as applicable?

When we have a separate algif_aead, then I guess we want to allow
skcipher and aead to be configured and compiled independently.

That raises the question where the common code should go? I would not
suggest to put it into a header file. However, when adding it to a C
file, how do you propose it should be considered in the Makefile. That C
file needs to be compile once with either skcipher or aead.
>
>Thanks,


Ciao
Stephan

2014-11-24 15:08:55

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH v3 5/7] crypto: AF_ALG: add random number generator support

Am Montag, 24. November 2014, 22:31:50 schrieb Herbert Xu:

Hi Herbert,

>On Fri, Nov 21, 2014 at 06:32:52AM +0100, Stephan Mueller wrote:
>> This patch adds the random number generator support for AF_ALG.
>>
>> A random number generator's purpose is to generate data without
>> requiring the caller to provide any data. Therefore, the AF_ALG
>> interface handler for RNGs only implements a callback handler for
>> recvmsg.
>>
>> The following parameters provided with a recvmsg are processed by the
>>
>> RNG callback handler:
>> * sock - to resolve the RNG context data structure accessing
>> the
>>
>> RNG instance private to the socket
>>
>> * len - this parameter allows userspace callers to specify
>> how
>>
>> many random bytes the RNG shall produce and return. As the
>> kernel context for the RNG allocates a buffer of 128 bytes
>> to
>> store random numbers before copying them to userspace, the
>> len
>> parameter is checked that it is not larger than 128. If a
>> caller wants more random numbers, a new request for recvmsg
>> shall be made.
>>
>> The size of 128 bytes is chose because of the following
considerations:
>> * to increase the memory footprint of the kernel too much
>> (note,
>>
>> that would be 128 bytes per open socket)
>>
>> * 128 is divisible by any typical cryptographic block size an
>>
>> RNG may have
>>
>> * A request for random numbers typically only shall supply
>> small
>>
>> amount of data like for keys or IVs that should only
>> require
>> one invocation of the recvmsg function.
>>
>> Note, during instantiation of the RNG, the code checks whether the
>> RNG
>> implementation requires seeding. If so, the RNG is seeded with output
>> from get_random_bytes.
>>
>> A fully working example using all aspects of the RNG interface is
>> provided at http://www.chronox.de/libkcapi.html
>>
>> Signed-off-by: Stephan Mueller <[email protected]>
>
>Sorry but who is going to use this and for what purpose?
>
>Every other algif interface exports real hardware features that
>cannot otherwise be accessed from user-space. All crypto RNGs
>are by definition software-only, so what is the point of this?


My idea is twofold: The software-RNGs currently available (X9.31 and
DRBG) use other ciphers as backends. Therefore, they can be considered
as transforms on top of these backend ciphers. Now, if these backend
ciphers are available in kernel mode only, currently only these in-
kernel RNGs can use the hardware.

With the consideration of AEAD, all ciphers supported by the kernel
crypto API are available to user space. That means, there is no need for
an additional crypto library in user space in addition to provide
hardware access. The RNG part is there to complement the case for not
needing an additional crypto lib in user space.

Ciao
Stephan

2014-11-24 20:55:18

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH v3 4/7] crypto: AF_ALG: add AEAD support

Am Montag, 24. November 2014, 22:29:46 schrieb Herbert Xu:

Hi Herbert,

> On Fri, Nov 21, 2014 at 06:32:16AM +0100, Stephan Mueller wrote:
> > This patch adds the AEAD support for AF_ALG.
> >
> > The AEAD implementation uses the entire memory handling and
> > infrastructure of the existing skcipher implementation.
> >
> > To use AEAD, the user space consumer has to use the salg_type named
> > "aead". The AEAD extension only uses the bind callback as the key
> > differentiator. The previously added functions that select whether to
> > use AEAD or ablkcipher crypto API functions depend on the TFM type
> > allocated during the bind() call.
> >
> > The addition of AEAD brings a bit of overhead to calculate the size of
> > the ciphertext, because the AEAD implementation of the kernel crypto API
> > makes implied assumption on the location of the authentication tag. When
> > performing an encryption, the tag will be added to the created
> > ciphertext (note, the tag is placed adjacent to the ciphertext). For
> > decryption, the caller must hand in the ciphertext with the tag appended
> > to the ciphertext. Therefore, the selection of the used memory
> > needs to add/subtract the tag size from the source/destination buffers
> > depending on the encryption type. The code is provided with comments
> > explainint when and how that operation is performed.
> >
> > Note: The AF_ALG interface does not support zero length input data.
> > Such zero length input data may be used if one wants to access the hash
> > implementation of an AEAD directly (e.g. the GHASH of GCM or CMAC for
> > CCM). However, this is a use case that is not of interest. GHASH or
> > CMAC is directly available via the hash AF_ALG interface and we
> > therefore do not need to take precautions for this use case.
> >
> > A fully working example using all aspects of AEAD is provided at
> > http://www.chronox.de/libkcapi.html
> >
> > Signed-off-by: Stephan Mueller <[email protected]>
>
> I appreciate the effort to share code, but shoe-horning AEAD into
> algif_skcipher is just too ugly.
>
> How about let's just start with a separate algif_aead and then
> add helpers to merge common code as applicable?

Instead of creating a separate algif_aead file, may I propose that the inline
functions wrapping the kernel crypto API calls to keep them in a separate
header file. That should remove code that distracts from the real
functionality.

The only AEAD code that is left is the memory handling in the recvmsg and
setting the AD in sendmsg.

Thanks
>
> Thanks,


--
Ciao
Stephan

2014-11-25 14:58:56

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH v3 4/7] crypto: AF_ALG: add AEAD support

On Mon, Nov 24, 2014 at 03:58:34PM +0100, Stephan Mueller wrote:
> Ok. But in the code you see that skcipher is a 100% subset of AEAD. For
> AEAD, all we need to do in addition to normal symmetric ciphers is to
> select the AEAD kernel crypto API calls, to locate and use the AD and to
> ensure we have the right memory size to process the tag.

There is still one fundamental difference between AEAD and ciphers.
Namely that ciphers can operate as you go while AEAD requests must
be done in one lot. So that should make the AEAD code simpler vs.
ciphers.

I think the best course of action for now is to start with sharing
no code and then chop bits off as we see fit.

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2014-11-25 15:08:35

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH v3 4/7] crypto: AF_ALG: add AEAD support

Am Dienstag, 25. November 2014, 22:58:50 schrieb Herbert Xu:

Hi Herbert,

>On Mon, Nov 24, 2014 at 03:58:34PM +0100, Stephan Mueller wrote:
>> Ok. But in the code you see that skcipher is a 100% subset of AEAD.
>> For AEAD, all we need to do in addition to normal symmetric ciphers
>> is to select the AEAD kernel crypto API calls, to locate and use the
>> AD and to ensure we have the right memory size to process the tag.
>
>There is still one fundamental difference between AEAD and ciphers.
>Namely that ciphers can operate as you go while AEAD requests must
>be done in one lot. So that should make the AEAD code simpler vs.
>ciphers.

Yes, that is a key difference.
>
>I think the best course of action for now is to start with sharing
>no code and then chop bits off as we see fit.

Ok, I will create a new patch set with a separate algif_aead.c. I guess
the entire sgl handling logic will be gone in AEAD.
>
>Cheers,


Ciao
Stephan