Linux cryptographic layer development
 help / color / mirror / Atom feed
* AEAD Question
From: Juan Pablo Nariño Mendoza @ 2016-10-26 16:17 UTC (permalink / raw)
  To: linux-crypto

Sorry in advance for making what shall be a basic question for this
list, but I have really ran out of ideas.

Can someone explain me please, how does the memory layout and sg lists
work for the IPSec case, with generated IV case?

As I understand, it is like this (ascii art)

AD | IV Space | Plain Text | Auth Tag
 ^                   ^
 |                    |
asg              sg

But I am having the AD overwritten, and the AUTH tag and encryption is
not correct? Could someone please point me in the right direction?
Thank you again

Regards

Juan

^ permalink raw reply

* Re: AEAD Question
From: Stephan Mueller @ 2016-10-26 16:32 UTC (permalink / raw)
  To: Juan Pablo Nariño Mendoza; +Cc: linux-crypto
In-Reply-To: <CAPSqeoJkTQ72cRaFk+sZGdCELUR6zFBbFdQsZE_B4DF=x374Og@mail.gmail.com>

Am Mittwoch, 26. Oktober 2016, 18:17:14 CEST schrieb Juan Pablo Nariño 
Mendoza:

Hi Juan,

> Sorry in advance for making what shall be a basic question for this
> list, but I have really ran out of ideas.
> 
> Can someone explain me please, how does the memory layout and sg lists
> work for the IPSec case, with generated IV case?
> 
> As I understand, it is like this (ascii art)
> 
> AD | IV Space | Plain Text | Auth Tag
>  ^                   ^
> 
> asg              sg

The memory layout is correct when using the RFC4106 cipher.

How you partition your physical memory with the SGL is your choice as long as 
your data in the SGL is lined up as you mentioned above.
> 
> But I am having the AD overwritten, and the AUTH tag and encryption is
> not correct? Could someone please point me in the right direction?
> Thank you again

Maybe the src and dst SGL somehow partially overlap?
> 
> Regards
> 
> Juan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Ciao
Stephan

^ permalink raw reply

* [PATCH 3/3] crypto: testmgr - Add missing tests for internal sha512-mb implementation
From: Marcelo Cerri @ 2016-10-26 17:04 UTC (permalink / raw)
  To: Herbert Xu, linux-crypto
  Cc: David S. Miller, linux-kernel, Stephan Mueller, Marcelo Cerri
In-Reply-To: <1477501485-18371-1-git-send-email-marcelo.cerri@canonical.com>

Add null tests for the internal algorithm to avoid errors when running
in FIPS mode.

Signed-off-by: Marcelo Cerri <marcelo.cerri@canonical.com>
---
 crypto/testmgr.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 58f903d..cfafd24 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2313,6 +2313,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
+		.alg = "__intel_sha512-mb",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "ansi_cprng",
 		.test = alg_test_cprng,
 		.suite = {
@@ -3766,6 +3770,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
+		.alg = "mcryptd(__intel_sha512-mb)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "md4",
 		.test = alg_test_hash,
 		.suite = {
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/3] crypto: testmgr - Add missing tests for internal sha*-mb implementations
From: Marcelo Cerri @ 2016-10-26 17:04 UTC (permalink / raw)
  To: Herbert Xu, linux-crypto
  Cc: David S. Miller, linux-kernel, Stephan Mueller, Marcelo Cerri

This series adds null tests for all sha*-mb internal algorithms so they can
be used in FIPS mode without further problems.

Since they are 3 separated modules I decided to use a separated commit for
each one.

Marcelo Cerri (3):
  crypto: testmgr - Add missing tests for internal sha1-mb
    implementation
  crypto: testmgr - Add missing tests for internal sha256-mb
    implementation
  crypto: testmgr - Add missing tests for internal sha512-mb
    implementation

 crypto/testmgr.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

-- 
2.7.4

^ permalink raw reply

* [PATCH 1/3] crypto: testmgr - Add missing tests for internal sha1-mb implementation
From: Marcelo Cerri @ 2016-10-26 17:04 UTC (permalink / raw)
  To: Herbert Xu, linux-crypto
  Cc: David S. Miller, linux-kernel, Stephan Mueller, Marcelo Cerri
In-Reply-To: <1477501485-18371-1-git-send-email-marcelo.cerri@canonical.com>

Add null tests for the internal algorithm to avoid errors when running
in FIPS mode.

Signed-off-by: Marcelo Cerri <marcelo.cerri@canonical.com>
---
 crypto/testmgr.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ded50b6..d999373 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2305,6 +2305,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
+		.alg = "__intel_sha1-mb",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "ansi_cprng",
 		.test = alg_test_cprng,
 		.suite = {
@@ -3750,6 +3754,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "mcryptd(__intel_sha1-mb)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "md4",
 		.test = alg_test_hash,
 		.suite = {
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/3] crypto: testmgr - Add missing tests for internal sha256-mb implementation
From: Marcelo Cerri @ 2016-10-26 17:04 UTC (permalink / raw)
  To: Herbert Xu, linux-crypto
  Cc: David S. Miller, linux-kernel, Stephan Mueller, Marcelo Cerri
In-Reply-To: <1477501485-18371-1-git-send-email-marcelo.cerri@canonical.com>

Add null tests for the internal algorithm to avoid errors when running
in FIPS mode.

Signed-off-by: Marcelo Cerri <marcelo.cerri@canonical.com>
---
 crypto/testmgr.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index d999373..58f903d 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2309,6 +2309,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
+		.alg = "__intel_sha256-mb",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "ansi_cprng",
 		.test = alg_test_cprng,
 		.suite = {
@@ -3758,6 +3762,10 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
+		.alg = "mcryptd(__intel_sha256-mb)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
 		.alg = "md4",
 		.test = alg_test_hash,
 		.suite = {
-- 
2.7.4

^ permalink raw reply related

* Re: linux-next: Tree for Oct 26 (crypto/acompress.ko)
From: Paul Gortmaker @ 2016-10-26 23:54 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Stephen Rothwell, linux-next@vger.kernel.org, LKML, linux-crypto,
	Herbert Xu
In-Reply-To: <052d917e-0442-0bbf-5b22-6506f832e30e@infradead.org>

On Wed, Oct 26, 2016 at 10:48 AM, Randy Dunlap <rdunlap@infradead.org> wrote:
> On 10/25/16 19:51, Stephen Rothwell wrote:
>> Hi all,
>>
>> There will probably be no linux-next releases next week while I attend
>> the Kernel Summit.
>>
>> Changes since 20161025:
>>
>
> on x864_64:
>
> ERROR: "crypto_acomp_scomp_alloc_ctx" [crypto/acompress.ko] undefined!
> ERROR: "crypto_acomp_scomp_free_ctx" [crypto/acompress.ko] undefined!
> ERROR: "crypto_init_scomp_ops_async" [crypto/acompress.ko] undefined!
>
>
> Full randconfig file is attached.

crypto/acompress.o ----> crypto/Makefile:obj-$(CONFIG_CRYPTO_ACOMP2)
+= acompress.o

crypto/Kconfig:config CRYPTO_ACOMP2
crypto/Kconfig: tristate

paul@builder:~/git/linux-head$ git grep crypto_acomp_scomp_alloc_ctx
crypto/acompress.c:             return crypto_acomp_scomp_alloc_ctx(req);
crypto/scompress.c:struct acomp_req
*crypto_acomp_scomp_alloc_ctx(struct acomp_req *req)
include/crypto/internal/scompress.h:struct acomp_req
*crypto_acomp_scomp_alloc_ctx(struct acomp_req *req);
paul@builder:~/git/linux-head$

So, no EXPORT_SYMBOL, and any .config which has ACOMP2=m will fail.

Paul.
--





>
> --
> ~Randy

^ permalink raw reply

* [PATCH] crypto: fix AEAD tag memory handling
From: Stephan Mueller @ 2016-10-27  1:00 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Mat Martineau

Hi Herbert,

for this patch, I have updated the testing for libkcapi accordingly and all
tests pass. I will push the libkcapi code 0.12 with that test code change
out shortly. Using the current upstream version of 0.11.1 will show failures
as it expects the correct recv return code. As stated below, that return
code has changed which implies that some of the tests will fail.

---8<---

For encryption, the AEAD ciphers require AAD || PT as input and generate
AAD || CT || Tag as output and vice versa for decryption. Prior to this
patch, the AF_ALG interface for AEAD ciphers requires the buffer to be
present as input for encryption. Similarly, the output buffer for
decryption required the presence of the tag buffer too. This implies
that the kernel reads / writes data buffers from/to user space
even though this operation is not required.

This patch changes the AF_ALG AEAD interface to be consistent with the
in-kernel AEAD cipher memory requirements.

In addition, the code now handles the situation where the provided
output buffer is too small by reducing the size of the processed
input buffer accordingly. Due to this handling, the changes are
transparent to user space with one exception: the return code of recv
indicates the processed of output buffer size. That output buffer has a
different size compared to before the patch which implies that the
return code of recv will also be different. For example, a decryption
operation uses 16 bytes AAD, 16 bytes CT and 16 bytes tag, the AF_ALG
AEAD interface before showed a recv return code of 48 (bytes) whereas
after this patch, the return code is 32 since the tag is not returned
any more.

Reported-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/algif_aead.c | 77 ++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 22 deletions(-)

diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 80a0f1a..c54bcb8 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -81,7 +81,11 @@ static inline bool aead_sufficient_data(struct aead_ctx *ctx)
 {
 	unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
 
-	return ctx->used >= ctx->aead_assoclen + as;
+	/*
+	 * The minimum amount of memory needed for an AEAD cipher is
+	 * the AAD and in case of decryption the tag.
+	 */
+	return ctx->used >= ctx->aead_assoclen + (ctx->enc ? 0 : as);
 }
 
 static void aead_reset_ctx(struct aead_ctx *ctx)
@@ -426,12 +430,15 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
 			goto unlock;
 	}
 
-	used = ctx->used;
-	outlen = used;
-
 	if (!aead_sufficient_data(ctx))
 		goto unlock;
 
+	used = ctx->used;
+	if (ctx->enc)
+		outlen = used + as;
+	else
+		outlen = used - as;
+
 	req = sock_kmalloc(sk, reqlen, GFP_KERNEL);
 	if (unlikely(!req))
 		goto unlock;
@@ -445,7 +452,7 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
 	aead_request_set_ad(req, ctx->aead_assoclen);
 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				  aead_async_cb, sk);
-	used -= ctx->aead_assoclen + (ctx->enc ? as : 0);
+	used -= ctx->aead_assoclen;
 
 	/* take over all tx sgls from ctx */
 	areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur,
@@ -461,7 +468,7 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
 	areq->tsgls = sgl->cur;
 
 	/* create rx sgls */
-	while (iov_iter_count(&msg->msg_iter)) {
+	while (outlen > usedpages && iov_iter_count(&msg->msg_iter)) {
 		size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
 				      (outlen - usedpages));
 
@@ -491,16 +498,20 @@ static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
 
 		last_rsgl = rsgl;
 
-		/* we do not need more iovecs as we have sufficient memory */
-		if (outlen <= usedpages)
-			break;
-
 		iov_iter_advance(&msg->msg_iter, err);
 	}
-	err = -EINVAL;
+
 	/* ensure output buffer is sufficiently large */
-	if (usedpages < outlen)
-		goto free;
+	if (usedpages < outlen) {
+		size_t less = outlen - usedpages;
+
+		if (used < less) {
+			err = -EINVAL;
+			goto unlock;
+		}
+		used -= less;
+		outlen -= less;
+	}
 
 	aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used,
 			       areq->iv);
@@ -571,6 +582,7 @@ static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
 			goto unlock;
 	}
 
+	/* data length provided by caller via sendmsg/sendpage */
 	used = ctx->used;
 
 	/*
@@ -585,16 +597,27 @@ static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
 	if (!aead_sufficient_data(ctx))
 		goto unlock;
 
-	outlen = used;
+	/*
+	 * Calculate the minimum output buffer size holding the result of the
+	 * cipher operation. When encrypting data, the receiving buffer is
+	 * larger by the tag length compared to the input buffer as the
+	 * encryption operation generates the tag. For decryption, the input
+	 * buffer provides the tag which is consumed resulting in only the
+	 * plaintext without a buffer for the tag returned to the caller.
+	 */
+	if (ctx->enc)
+		outlen = used + as;
+	else
+		outlen = used - as;
 
 	/*
 	 * The cipher operation input data is reduced by the associated data
 	 * length as this data is processed separately later on.
 	 */
-	used -= ctx->aead_assoclen + (ctx->enc ? as : 0);
+	used -= ctx->aead_assoclen;
 
 	/* convert iovecs of output buffers into scatterlists */
-	while (iov_iter_count(&msg->msg_iter)) {
+	while (outlen > usedpages && iov_iter_count(&msg->msg_iter)) {
 		size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
 				      (outlen - usedpages));
 
@@ -621,16 +644,26 @@ static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
 
 		last_rsgl = rsgl;
 
-		/* we do not need more iovecs as we have sufficient memory */
-		if (outlen <= usedpages)
-			break;
 		iov_iter_advance(&msg->msg_iter, err);
 	}
 
-	err = -EINVAL;
 	/* ensure output buffer is sufficiently large */
-	if (usedpages < outlen)
-		goto unlock;
+	if (usedpages < outlen) {
+		size_t less = outlen - usedpages;
+
+		if (used < less) {
+			err = -EINVAL;
+			goto unlock;
+		}
+
+		/*
+		 * Caller has smaller output buffer than needed, reduce
+		 * the input data length to be processed to fit the provided
+		 * output buffer.
+		 */
+		used -= less;
+		outlen -= less;
+	}
 
 	sg_mark_end(sgl->sg + sgl->cur - 1);
 	aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg,
-- 
2.7.4

^ permalink raw reply related

* [ANNOUNCE] libkcapi v0.12.0 released
From: Stephan Mueller @ 2016-10-27  1:54 UTC (permalink / raw)
  To: linux-crypto

Hi,

The Linux kernel exports a network interface of type AF_ALG to allow user 
space to utilize the kernel crypto API. libkcapi uses this network interface 
and exports an easy to use API so that a developer does not need to consider 
the low-level network interface handling. 

The library does not implement any low level cipher algorithms. All consumer 
requests are sent to the kernel for processing. Results from the kernel crypto 
API are returned to the consumer via the library API.

The kernel interface and therefore this library can be used by unprivileged 
processes.

The library code archive also provides a drop-in replacement for the command 
line tools of sha*sum, fipscheck/fipshmac and sha512hmac.

The source code and the documentation is available at [1].

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

Ciao
Stephan

^ permalink raw reply

* Re: [ANNOUNCE] libkcapi v0.12.0 released
From: Jeffrey Walton @ 2016-10-27  2:05 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: linux-crypto
In-Reply-To: <2974976.xU0nDqBFOZ@positron.chronox.de>

> The Linux kernel exports a network interface of type AF_ALG to allow user
> space to utilize the kernel crypto API. libkcapi uses this network interface
> and exports an easy to use API so that a developer does not need to consider
> the low-level network interface handling.
>
> The library does not implement any low level cipher algorithms. All consumer
> requests are sent to the kernel for processing. Results from the kernel crypto
> API are returned to the consumer via the library API.
>
> The kernel interface and therefore this library can be used by unprivileged
> processes.
>
> The library code archive also provides a drop-in replacement for the command
> line tools of sha*sum, fipscheck/fipshmac and sha512hmac.
>
> The source code and the documentation is available at [1].

That looks awesome Stephan.

How can user code reliably detect when the API is available? Are there
any preprocessor macros to guard code paths in userland? What are the
preprocessor macros we can use to guard it?

Jeff

^ permalink raw reply

* Re: [ANNOUNCE] libkcapi v0.12.0 released
From: Stephan Mueller @ 2016-10-27  2:52 UTC (permalink / raw)
  To: noloader; +Cc: linux-crypto
In-Reply-To: <CAH8yC8n+37D+4i6-WS8yZMLOm-LvMnVV93uWbPcOStwJRWvFWA@mail.gmail.com>

Am Mittwoch, 26. Oktober 2016, 22:05:28 CEST schrieb Jeffrey Walton:

Hi Jeffrey,

> > The Linux kernel exports a network interface of type AF_ALG to allow user
> > space to utilize the kernel crypto API. libkcapi uses this network
> > interface and exports an easy to use API so that a developer does not
> > need to consider the low-level network interface handling.
> > 
> > The library does not implement any low level cipher algorithms. All
> > consumer requests are sent to the kernel for processing. Results from the
> > kernel crypto API are returned to the consumer via the library API.
> > 
> > The kernel interface and therefore this library can be used by
> > unprivileged
> > processes.
> > 
> > The library code archive also provides a drop-in replacement for the
> > command line tools of sha*sum, fipscheck/fipshmac and sha512hmac.
> > 
> > The source code and the documentation is available at [1].
> 
> That looks awesome Stephan.
> 
> How can user code reliably detect when the API is available? Are there

The detection is done through the various _init calls such as 
kcapi_cipher_init. They will return an error if AF_ALG is not available. 
According to the documentation these calls return:

 * @return 0 upon success; ENOENT - algorithm not available;
 *          -EOPNOTSUPP - AF_ALG family not available;
 *          -EINVAL - accept syscall failed
 *          -ENOMEM - cipher handle cannot be allocated

Technically, the bind operation will fail if the respective AF_ALG interface 
is not available.

> any preprocessor macros to guard code paths in userland? What are the

There are no special guards. If AF_ALG is available, all user space processes 
can use it.

> preprocessor macros we can use to guard it?

I am not entirely sure I understand the question.
> 
> Jeff


Ciao
Stephan

^ permalink raw reply

* Re: linux-next: Tree for Oct 26 (crypto/acompress.ko)
From: Giovanni Cabiddu @ 2016-10-27  5:17 UTC (permalink / raw)
  To: Paul Gortmaker
  Cc: Randy Dunlap, Stephen Rothwell, linux-next@vger.kernel.org, LKML,
	linux-crypto, Herbert Xu
In-Reply-To: <CAP=VYLq=Zgaf5uhWVG68Hyha=gJ923ZkW+v7UsfsOJE53YxR0w@mail.gmail.com>

Hi,

On Wed, Oct 26, 2016 at 07:54:00PM -0400, Paul Gortmaker wrote:
> So, no EXPORT_SYMBOL, and any .config which has ACOMP2=m will fail.
I sent a patch for this:
https://patchwork.kernel.org/patch/9396503/

Regards,

--
Giovanni

^ permalink raw reply

* Re: [PATCH 6/6] Add support for AEAD algos.
From: Harsh Jain @ 2016-10-27 10:06 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: dan.carpenter, herbert, linux-crypto, jlulla, atul.gupta,
	yeshaswi, hariprasad
In-Reply-To: <1610250.DL5oKfbMjq@positron.chronox.de>



On 14-10-2016 19:54, Stephan Mueller wrote:
> Am Donnerstag, 13. Oktober 2016, 16:39:39 CEST schrieb Harsh Jain:
>
> Hi Harsh,
>
>> Add support for following AEAD algos.
>>  GCM,CCM,RFC4106,RFC4309,authenc(hmac(shaXXX),cbc(aes)).
>>
>> Signed-off-by: Harsh Jain <harsh@chelsio.com>
>> ---
>>  drivers/crypto/chelsio/Kconfig       |    1 +
>>  drivers/crypto/chelsio/chcr_algo.c   | 1466
>> +++++++++++++++++++++++++++++++++- drivers/crypto/chelsio/chcr_algo.h   |  
>> 16 +-
>>  drivers/crypto/chelsio/chcr_core.c   |    8 +-
>>  drivers/crypto/chelsio/chcr_core.h   |    2 -
>>  drivers/crypto/chelsio/chcr_crypto.h |   90 ++-
>>  6 files changed, 1541 insertions(+), 42 deletions(-)
>>
>> diff --git a/drivers/crypto/chelsio/Kconfig b/drivers/crypto/chelsio/Kconfig
>> index 4ce67fb..3e104f5 100644
>> --- a/drivers/crypto/chelsio/Kconfig
>> +++ b/drivers/crypto/chelsio/Kconfig
>> @@ -4,6 +4,7 @@ config CRYPTO_DEV_CHELSIO
>>  	select CRYPTO_SHA1
>>  	select CRYPTO_SHA256
>>  	select CRYPTO_SHA512
>> +	select CRYPTO_AUTHENC
>>  	---help---
>>  	  The Chelsio Crypto Co-processor driver for T6 adapters.
>>
>> diff --git a/drivers/crypto/chelsio/chcr_algo.c
>> b/drivers/crypto/chelsio/chcr_algo.c index 18385d6..cffc38f 100644
>> --- a/drivers/crypto/chelsio/chcr_algo.c
>> +++ b/drivers/crypto/chelsio/chcr_algo.c
>> @@ -54,6 +54,12 @@
>>  #include <crypto/algapi.h>
>>  #include <crypto/hash.h>
>>  #include <crypto/sha.h>
>> +#include <crypto/authenc.h>
>> +#include <crypto/internal/aead.h>
>> +#include <crypto/null.h>
>> +#include <crypto/internal/skcipher.h>
>> +#include <crypto/aead.h>
>> +#include <crypto/scatterwalk.h>
>>  #include <crypto/internal/hash.h>
>>
>>  #include "t4fw_api.h"
>> @@ -62,6 +68,11 @@
>>  #include "chcr_algo.h"
>>  #include "chcr_crypto.h"
>>
>> +static inline  struct chcr_aead_ctx *AEAD_CTX(struct chcr_context *ctx)
>> +{
>> +	return ctx->crypto_ctx->aeadctx;
>> +}
>> +
>>  static inline struct ablk_ctx *ABLK_CTX(struct chcr_context *ctx)
>>  {
>>  	return ctx->crypto_ctx->ablkctx;
>> @@ -72,6 +83,16 @@ static inline struct hmac_ctx *HMAC_CTX(struct
>> chcr_context *ctx) return ctx->crypto_ctx->hmacctx;
>>  }
>>
>> +static inline struct chcr_gcm_ctx *GCM_CTX(struct chcr_aead_ctx *gctx)
>> +{
>> +	return gctx->ctx->gcm;
>> +}
>> +
>> +static inline struct chcr_authenc_ctx *AUTHENC_CTX(struct chcr_aead_ctx
>> *gctx) +{
>> +	return gctx->ctx->authenc;
>> +}
>> +
>>  static inline struct uld_ctx *ULD_CTX(struct chcr_context *ctx)
>>  {
>>  	return ctx->dev->u_ctx;
>> @@ -94,12 +115,37 @@ static inline unsigned int sgl_len(unsigned int n)
>>  	return (3 * n) / 2 + (n & 1) + 2;
>>  }
>>
>> +static void chcr_verify_tag(struct aead_request *req, u8 *input, int *err)
>> +{
>> +	u8 temp[SHA512_DIGEST_SIZE];
>> +	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
>> +	int authsize = crypto_aead_authsize(tfm);
>> +	struct cpl_fw6_pld *fw6_pld;
>> +	int cmp = 0;
>> +
>> +	fw6_pld = (struct cpl_fw6_pld *)input;
>> +	if ((get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) ||
>> +	    (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_GCM)) {
>> +		cmp = memcmp(&fw6_pld->data[2], (fw6_pld + 1), authsize);
>> +	} else {
>> +
>> +		sg_pcopy_to_buffer(req->src, sg_nents(req->src), temp,
>> +				authsize, req->assoclen +
>> +				req->cryptlen - authsize);
> I am wondering whether the math is correct here in any case. It is permissible 
> that we have an AAD size of 0 and even a zero-sized ciphertext. How is such 
> scenario covered here?
Here we are trying to copy user supplied tag to local buffer(temp) for decrypt operation only. relative index of tag in src sg list
will not change when AAD is zero and in decrypt operation cryptlen > authsize.
>
>> +		cmp = memcmp(temp, (fw6_pld + 1), authsize);
> I would guess in both cases memcmp should be replaced with crypto_memneq
Yes can be done

>
>> +	}
>> +	if (cmp)
>> +		*err = -EBADMSG;
>> +	else
>> +		*err = 0;
> What do you think about memzero_explicit(tmp)?
No Idea why we needs explicitly setting of zero for local variable.  Please share some online resources to understand this.

>
>> +}
>> +
>>  /*
>>   *	chcr_handle_resp - Unmap the DMA buffers associated with the request
>>   *	@req: crypto request
>>   */
>>  int chcr_handle_resp(struct crypto_async_request *req, unsigned char
>> *input, -		     int error_status)
>> +			 int err)
>>  {
>>  	struct crypto_tfm *tfm = req->tfm;
>>  	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
>> @@ -109,11 +155,27 @@ int chcr_handle_resp(struct crypto_async_request *req,
>> unsigned char *input, unsigned int digestsize, updated_digestsize;
>>
>>  	switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
>> +	case CRYPTO_ALG_TYPE_AEAD:
>> +		ctx_req.req.aead_req = (struct aead_request *)req;
>> +		ctx_req.ctx.reqctx = aead_request_ctx(ctx_req.req.aead_req);
>> +		dma_unmap_sg(&u_ctx->lldi.pdev->dev, ctx_req.req.aead_req->dst,
>> +			     ctx_req.ctx.reqctx->dst_nents, DMA_FROM_DEVICE);
>> +		if (ctx_req.ctx.reqctx->skb) {
>> +			kfree_skb(ctx_req.ctx.reqctx->skb);
>> +			ctx_req.ctx.reqctx->skb = NULL;
>> +		}
>> +		if (ctx_req.ctx.reqctx->verify == VERIFY_SW) {
>> +			chcr_verify_tag(ctx_req.req.aead_req, input,
>> +					&err);
>> +			ctx_req.ctx.reqctx->verify = VERIFY_HW;
>> +		}
>> +		break;
>> +
>>  	case CRYPTO_ALG_TYPE_BLKCIPHER:
>>  		ctx_req.req.ablk_req = (struct ablkcipher_request *)req;
>>  		ctx_req.ctx.ablk_ctx =
>>  			ablkcipher_request_ctx(ctx_req.req.ablk_req);
>> -		if (!error_status) {
>> +		if (!err) {
>>  			fw6_pld = (struct cpl_fw6_pld *)input;
>>  			memcpy(ctx_req.req.ablk_req->info, &fw6_pld->data[2],
>>  			       AES_BLOCK_SIZE);
>> @@ -154,7 +216,7 @@ int chcr_handle_resp(struct crypto_async_request *req,
>> unsigned char *input, }
>>  		break;
>>  	}
>> -	return 0;
>> +	return err;
>>  }
>>
>>  /*
>> @@ -380,6 +442,14 @@ static inline int map_writesg_phys_cpl(struct device
>> *dev, return 0;
>>  }
>>
>> +static inline int get_aead_subtype(struct crypto_aead *aead)
>> +{
>> +	struct aead_alg *alg = crypto_aead_alg(aead);
>> +	struct chcr_alg_template *chcr_crypto_alg =
>> +		container_of(alg, struct chcr_alg_template, alg.aead);
>> +	return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK;
>> +}
>> +
>>  static inline int get_cryptoalg_subtype(struct crypto_tfm *tfm)
>>  {
>>  	struct crypto_alg *alg = tfm->__crt_alg;
>> @@ -447,7 +517,8 @@ static inline void create_wreq(struct chcr_context *ctx,
>> struct chcr_wr *chcr_req,
>>  			       void *req, struct sk_buff *skb,
>>  			       int kctx_len, int hash_sz,
>> -			       unsigned int phys_dsgl)
>> +			       int is_iv,
>> +			       unsigned int sc_len)
>>  {
>>  	struct uld_ctx *u_ctx = ULD_CTX(ctx);
>>  	int iv_loc = IV_DSGL;
>> @@ -472,7 +543,7 @@ static inline void create_wreq(struct chcr_context *ctx,
>> chcr_req->wreq.cookie = cpu_to_be64((uintptr_t)req);
>>  	chcr_req->wreq.rx_chid_to_rx_q_id =
>>  		FILL_WR_RX_Q_ID(ctx->dev->tx_channel_id, qid,
>> -				(hash_sz) ? IV_NOP : iv_loc);
>> +				is_iv ? iv_loc : IV_NOP);
>>
>>  	chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(ctx->dev->tx_channel_id);
>>  	chcr_req->ulptx.len = htonl((DIV_ROUND_UP((calc_tx_flits_ofld(skb) * 8),
>> @@ -481,10 +552,7 @@ static inline void create_wreq(struct chcr_context
>> *ctx, chcr_req->sc_imm.cmd_more = FILL_CMD_MORE(immdatalen);
>>  	chcr_req->sc_imm.len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) +
>>  				   sizeof(chcr_req->key_ctx) +
>> -				   kctx_len +
>> -				  ((hash_sz) ? DUMMY_BYTES :
>> -				  (sizeof(struct cpl_rx_phys_dsgl) +
>> -				   phys_dsgl)) + immdatalen);
>> +				   kctx_len + sc_len + immdatalen);
>>  }
>>
>>  /**
>> @@ -582,7 +650,8 @@ static struct sk_buff
>>  	memcpy(reqctx->iv, req->info, ivsize);
>>  	write_buffer_to_skb(skb, &frags, reqctx->iv, ivsize);
>>  	write_sg_to_skb(skb, &frags, req->src, req->nbytes);
>> -	create_wreq(ctx, chcr_req, req, skb, kctx_len, 0, phys_dsgl);
>> +	create_wreq(ctx, chcr_req, req, skb, kctx_len, 0, 1,
>> +			sizeof(struct cpl_rx_phys_dsgl) + phys_dsgl);
>>  	reqctx->skb = skb;
>>  	skb_get(skb);
>>  	return skb;
>> @@ -706,11 +775,11 @@ static int chcr_device_init(struct chcr_context *ctx)
>>  		}
>>  		u_ctx = ULD_CTX(ctx);
>>  		rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
>> -		ctx->dev->tx_channel_id = 0;
>>  		rxq_idx = ctx->dev->tx_channel_id * rxq_perchan;
>>  		rxq_idx += id % rxq_perchan;
>>  		spin_lock(&ctx->dev->lock_chcr_dev);
>>  		ctx->tx_channel_id = rxq_idx;
>> +		ctx->dev->tx_channel_id = !ctx->dev->tx_channel_id;
>>  		spin_unlock(&ctx->dev->lock_chcr_dev);
>>  	}
>>  out:
>> @@ -769,7 +838,7 @@ static inline void chcr_free_shash(struct crypto_shash
>> *base_hash) *	@req - Cipher req base
>>   */
>>  static struct sk_buff *create_hash_wr(struct ahash_request *req,
>> -					    struct hash_wr_param *param)
>> +				      struct hash_wr_param *param)
>>  {
>>  	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
>>  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
>> @@ -840,8 +909,8 @@ static struct sk_buff *create_hash_wr(struct
>> ahash_request *req, if (param->sg_len != 0)
>>  		write_sg_to_skb(skb, &frags, req->src, param->sg_len);
>>
>> -	create_wreq(ctx, chcr_req, req, skb, kctx_len, hash_size_in_response,
>> -		    0);
>> +	create_wreq(ctx, chcr_req, req, skb, kctx_len, hash_size_in_response, 0,
>> +			DUMMY_BYTES);
>>  	req_ctx->skb = skb;
>>  	skb_get(skb);
>>  	return skb;
>> @@ -1249,6 +1318,1149 @@ static void chcr_hmac_cra_exit(struct crypto_tfm
>> *tfm) }
>>  }
>>
>> +static int chcr_copy_assoc(struct aead_request *req,
>> +				struct chcr_aead_ctx *ctx)
>> +{
>> +	SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null);
>> +
>> +	skcipher_request_set_tfm(skreq, ctx->null);
>> +	skcipher_request_set_callback(skreq, aead_request_flags(req),
>> +			NULL, NULL);
>> +	skcipher_request_set_crypt(skreq, req->src, req->dst, req->assoclen,
>> +			NULL);
>> +
>> +	return crypto_skcipher_encrypt(skreq);
>> +}
>> +
>> +static unsigned char get_hmac(unsigned int authsize)
>> +{
>> +	switch (authsize) {
>> +	case ICV_8:
>> +		return CHCR_SCMD_HMAC_CTRL_PL1;
>> +	case ICV_10:
>> +		return CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
>> +	case ICV_12:
>> +		return CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
>> +	}
>> +	return CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
>> +}
>> +
>> +
>> +static struct sk_buff *create_authenc_wr(struct aead_request *req,
>> +					 unsigned short qid,
>> +					 int size,
>> +					 unsigned short op_type)
>> +{
>> +	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
>> +	struct chcr_context *ctx = crypto_aead_ctx(tfm);
>> +	struct uld_ctx *u_ctx = ULD_CTX(ctx);
>> +	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
>> +	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
>> +	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
>> +	struct sk_buff *skb = NULL;
>> +	struct chcr_wr *chcr_req;
>> +	struct cpl_rx_phys_dsgl *phys_cpl;
>> +	struct phys_sge_parm sg_param;
>> +	struct scatterlist *src, *dst;
>> +	struct scatterlist src_sg[2], dst_sg[2];
>> +	unsigned int frags = 0, transhdr_len;
>> +	unsigned int ivsize = crypto_aead_ivsize(tfm), dst_size = 0;
>> +	unsigned int   kctx_len = 0;
>> +	unsigned short stop_offset = 0;
>> +	unsigned int  assoclen = req->assoclen;
>> +	unsigned int  authsize = crypto_aead_authsize(tfm);
>> +	int err = 0;
>> +	int null = 0;
>> +	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
>> +		GFP_ATOMIC;
>> +
>> +	if (aeadctx->enckey_len == 0 || (req->cryptlen <= 0))
>> +		goto err;
>> +	src = scatterwalk_ffwd(src_sg, req->src, req->assoclen);
>> +	dst = src;
>> +	if (req->src != req->dst) {
>> +		err = chcr_copy_assoc(req, aeadctx);
>> +		if (err)
>> +			return ERR_PTR(err);
>> +		dst = scatterwalk_ffwd(dst_sg, req->dst, req->assoclen);
>> +	}
>> +	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_NULL) {
>> +		null = 1;
>> +		assoclen = 0;
>> +	}
>> +	reqctx->dst_nents = sg_nents_for_len(dst, req->cryptlen +
>> +					     (op_type ? -authsize : authsize));
>> +	if (reqctx->dst_nents <= 0) {
>> +		pr_err("AUTHENC:Invalid Destination sg entries\n");
>> +		goto err;
>> +	}
>> +	dst_size = get_space_for_phys_dsgl(reqctx->dst_nents);
>> +	kctx_len = (ntohl(KEY_CONTEXT_CTX_LEN_V(aeadctx->key_ctx_hdr)) << 4)
>> +		- sizeof(chcr_req->key_ctx);
>> +	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
>> +	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)), flags);
>> +	if (!skb)
>> +		goto err;
>> +
>> +	/* LLD is going to write the sge hdr. */
>> +	skb_reserve(skb, sizeof(struct sge_opaque_hdr));
>> +
>> +	/* Write WR */
>> +	chcr_req = (struct chcr_wr *) __skb_put(skb, transhdr_len);
>> +	memset(chcr_req, 0, transhdr_len);
>> +
>> +	stop_offset = (op_type == CHCR_ENCRYPT_OP) ? 0 : authsize;
>> +
>> +	/*
>> +	 * Input order	is AAD,IV and Payload. where IV should be included as
>> +	 * the part of authdata. All other fields should be filled according
>> +	 * to the hardware spec
>> +	 */
>> +	chcr_req->sec_cpl.op_ivinsrtofst =
>> +		FILL_SEC_CPL_OP_IVINSR(ctx->dev->tx_channel_id, 2,
>> +				       (ivsize ? (assoclen + 1) : 0));
>> +	chcr_req->sec_cpl.pldlen = htonl(assoclen + ivsize + req->cryptlen);
>> +	chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
>> +					assoclen ? 1 : 0, assoclen,
>> +					assoclen + ivsize + 1,
>> +					(stop_offset & 0x1F0) >> 4);
>> +	chcr_req->sec_cpl.cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(
>> +					stop_offset & 0xF,
>> +					null ? 0 : assoclen + ivsize + 1,
>> +					stop_offset, stop_offset);
>> +	chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(op_type,
>> +					(op_type == CHCR_ENCRYPT_OP) ? 1 : 0,
>> +					CHCR_SCMD_CIPHER_MODE_AES_CBC,
>> +					actx->auth_mode, aeadctx->hmac_ctrl,
>> +					ivsize >> 1);
>> +	chcr_req->sec_cpl.ivgen_hdrlen =  FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1,
>> +					 0, 1, dst_size);
>> +
>> +	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
>> +	if (op_type == CHCR_ENCRYPT_OP)
>> +		memcpy(chcr_req->key_ctx.key, aeadctx->key,
>> +		       aeadctx->enckey_len);
>> +	else
>> +		memcpy(chcr_req->key_ctx.key, actx->dec_rrkey,
>> +		       aeadctx->enckey_len);
>> +
>> +	memcpy(chcr_req->key_ctx.key + (DIV_ROUND_UP(aeadctx->enckey_len, 16) <<
>> +					4), actx->h_iopad, kctx_len -
>> +				(DIV_ROUND_UP(aeadctx->enckey_len, 16) << 4));
>> +
>> +	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
>> +	sg_param.nents = reqctx->dst_nents;
>> +	sg_param.obsize = req->cryptlen + (op_type ? -authsize : authsize);
> Just like above: is it ensured that we cannot have negative results here in 
> case cryptlen is less than authsize?
not handled. Will change accordingly.

>
>
> Ciao
> Stephan

^ permalink raw reply

* [PATCH] crypto: acomp: export all scomp interfaces
From: Arnd Bergmann @ 2016-10-27 14:09 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Arnd Bergmann, David S. Miller, Giovanni Cabiddu, linux-crypto,
	linux-kernel

The newly added scomp/acomp interface has a couple of functions
that should be exported to allow linking the two drivers
as loadable modules:

ERROR: "crypto_acomp_scomp_free_ctx" [crypto/acompress.ko] undefined!
ERROR: "crypto_acomp_scomp_alloc_ctx" [crypto/acompress.ko] undefined!
ERROR: "crypto_init_scomp_ops_async" [crypto/acompress.ko] undefined!

Alternatively, both of them could be combined into one loadable module.

Fixes: 1ab53a77b772 ("crypto: acomp - add driver-side scomp interface")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 crypto/scompress.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/crypto/scompress.c b/crypto/scompress.c
index 35e396d154b7..1f9cdcddb2ce 100644
--- a/crypto/scompress.c
+++ b/crypto/scompress.c
@@ -267,6 +267,7 @@ int crypto_init_scomp_ops_async(struct crypto_tfm *tfm)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(crypto_init_scomp_ops_async);
 
 struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req)
 {
@@ -286,6 +287,7 @@ struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req)
 
 	return req;
 }
+EXPORT_SYMBOL_GPL(crypto_acomp_scomp_alloc_ctx);
 
 void crypto_acomp_scomp_free_ctx(struct acomp_req *req)
 {
@@ -298,6 +300,7 @@ void crypto_acomp_scomp_free_ctx(struct acomp_req *req)
 	if (ctx)
 		crypto_scomp_free_ctx(scomp, ctx);
 }
+EXPORT_SYMBOL_GPL(crypto_acomp_scomp_free_ctx);
 
 static const struct crypto_type crypto_scomp_type = {
 	.extsize = crypto_alg_extsize,
-- 
2.9.0

^ permalink raw reply related

* [PATCH stable 3.10.y 00/18] Backport crypto fixes.
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin

While fuzzing our 3.10 based kernel we observed some crashes, e.g:
      http://lkml.kernel.org/r/<CACT4Y+aE-pNUnCLbDQkFQ9Y7QivN_g6hEuS7t1RpknPHFmHg+g@mail.gmail.com>

It appears that 3.10-stable lacks some crypto related fixes. Here is my attempt
to backport them.
Many patches didn't apply cleanly, so to make sure that my conflict resolution
is correct I compared it with other stable trees.

Ard Biesheuvel (1):
  crypto: cryptd - initialize child shash_desc on import

Herbert Xu (17):
  crypto: algif_skcipher - Require setkey before accept(2)
  crypto: af_alg - Disallow bind/setkey/... after accept(2)
  crypto: af_alg - Add nokey compatibility path
  crypto: algif_skcipher - Add nokey compatibility path
  crypto: hash - Add crypto_ahash_has_setkey
  crypto: algif_hash - Require setkey before accept(2)
  crypto: skcipher - Add crypto_skcipher_has_setkey
  crypto: algif_skcipher - Add key check exception for cipher_null
  crypto: af_alg - Allow af_af_alg_release_parent to be called on nokey
    path
  crypto: algif_hash - Remove custom release parent function
  crypto: algif_skcipher - Remove custom release parent function
  crypto: af_alg - Forbid bind(2) when nokey child sockets are present
  crypto: algif_hash - Fix race condition in hash_check_key
  crypto: algif_skcipher - Fix race condition in skcipher_check_key
  crypto: algif_skcipher - Load TX SG list after waiting
  crypto: shash - Fix has_key setting
  crypto: skcipher - Fix blkcipher walk OOM crash

 crypto/ablkcipher.c     |   2 +
 crypto/af_alg.c         |  51 +++++++++++++-
 crypto/ahash.c          |   5 +-
 crypto/algif_hash.c     | 165 ++++++++++++++++++++++++++++++++++++++++++++--
 crypto/algif_skcipher.c | 172 +++++++++++++++++++++++++++++++++++++++++++-----
 crypto/blkcipher.c      |   4 +-
 crypto/cryptd.c         |   9 ++-
 crypto/shash.c          |   5 +-
 include/crypto/hash.h   |   6 ++
 include/crypto/if_alg.h |  11 ++--
 include/linux/crypto.h  |   8 +++
 11 files changed, 400 insertions(+), 38 deletions(-)

-- 
2.7.3

^ permalink raw reply

* [PATCH stable 3.10.y 06/18] crypto: algif_hash - Require setkey before accept(2)
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 6de62f15b581f920ade22d758f4c338311c2f0d4 upstream.

Hash implementations that require a key may crash if you use
them without setting a key.  This patch adds the necessary checks
so that if you do attempt to use them without a key that we return
-ENOKEY instead of proceeding.

This patch also adds a compatibility path to support old applications
that do acept(2) before setkey.

Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/algif_hash.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 193 insertions(+), 8 deletions(-)

diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index c542c0d8..7bc3f89 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 kiocb *unused, struct socket *sock,
 			struct msghdr *msg, size_t ignored)
 {
@@ -248,22 +253,151 @@ static struct proto_ops algif_hash_ops = {
 	.accept		=	hash_accept,
 };
 
+static int hash_check_key(struct socket *sock)
+{
+	int err;
+	struct sock *psk;
+	struct alg_sock *pask;
+	struct algif_hash_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 hash_sendmsg_nokey(struct kiocb *unused, struct socket *sock,
+			      struct msghdr *msg, size_t size)
+{
+	int err;
+
+	err = hash_check_key(sock);
+	if (err)
+		return err;
+
+	return hash_sendmsg(unused, 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 kiocb *unused, 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(unused, 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)
+static void hash_sock_destruct_common(struct sock *sk)
 {
 	struct alg_sock *ask = alg_sk(sk);
 	struct hash_ctx *ctx = ask->private;
@@ -271,15 +405,40 @@ static void hash_sock_destruct(struct sock *sk)
 	sock_kfree_s(sk, ctx->result,
 		     crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
 	sock_kfree_s(sk, ctx, ctx->len);
+}
+
+static void hash_sock_destruct(struct sock *sk)
+{
+	hash_sock_destruct_common(sk);
 	af_alg_release_parent(sk);
 }
 
-static int hash_accept_parent(void *private, struct sock *sk)
+static void hash_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 hash_sock_destruct_nokey(struct sock *sk)
+{
+	hash_sock_destruct_common(sk);
+	hash_release_parent_nokey(sk);
+}
+
+static int hash_accept_parent_common(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)
@@ -299,7 +458,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);
 
@@ -308,12 +467,38 @@ 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_common(private, sk);
+}
+
+static int hash_accept_parent_nokey(void *private, struct sock *sk)
+{
+	int err;
+
+	err = hash_accept_parent_common(private, sk);
+	if (err)
+		goto out;
+
+	sk->sk_destruct = hash_sock_destruct_nokey;
+
+out:
+	return err;
+}
+
 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
 };
-- 
2.7.3

^ permalink raw reply related

* [PATCH stable 3.10.y 07/18] crypto: skcipher - Add crypto_skcipher_has_setkey
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit a1383cd86a062fc798899ab20f0ec2116cce39cb upstream.

This patch adds a way for skcipher users to determine whether a key
is required by a transform.

Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/ablkcipher.c    | 2 ++
 crypto/blkcipher.c     | 1 +
 include/linux/crypto.h | 8 ++++++++
 3 files changed, 11 insertions(+)

diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index ebcec74..2b6dd74 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -379,6 +379,7 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
 	}
 	crt->base = __crypto_ablkcipher_cast(tfm);
 	crt->ivsize = alg->ivsize;
+	crt->has_setkey = alg->max_keysize;
 
 	return 0;
 }
@@ -460,6 +461,7 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
 	crt->givdecrypt = alg->givdecrypt ?: no_givdecrypt;
 	crt->base = __crypto_ablkcipher_cast(tfm);
 	crt->ivsize = alg->ivsize;
+	crt->has_setkey = alg->max_keysize;
 
 	return 0;
 }
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index a79e7e9..37af08e 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -458,6 +458,7 @@ static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm)
 	}
 	crt->base = __crypto_ablkcipher_cast(tfm);
 	crt->ivsize = alg->ivsize;
+	crt->has_setkey = alg->max_keysize;
 
 	return 0;
 }
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 2b00d92..61dd0b1 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -354,6 +354,7 @@ struct ablkcipher_tfm {
 
 	unsigned int ivsize;
 	unsigned int reqsize;
+	bool has_setkey;
 };
 
 struct aead_tfm {
@@ -664,6 +665,13 @@ static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
 	return crt->setkey(crt->base, key, keylen);
 }
 
+static inline bool crypto_ablkcipher_has_setkey(struct crypto_ablkcipher *tfm)
+{
+	struct ablkcipher_tfm *crt = crypto_ablkcipher_crt(tfm);
+
+	return crt->has_setkey;
+}
+
 static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
 	struct ablkcipher_request *req)
 {
-- 
2.7.3

^ permalink raw reply related

* [PATCH stable 3.10.y 08/18] crypto: algif_skcipher - Add key check exception for cipher_null
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 6e8d8ecf438792ecf7a3207488fb4eebc4edb040 upstream.

This patch adds an exception to the key check so that cipher_null
users may continue to use algif_skcipher without setting a key.

Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/algif_skcipher.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index db5f0f0..4677a45 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -759,7 +759,7 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
 {
 	struct skcipher_tfm *tfm = private;
 
-	if (!tfm->has_key)
+	if (!tfm->has_key && crypto_ablkcipher_has_setkey(tfm->skcipher))
 		return -ENOKEY;
 
 	return skcipher_accept_parent_common(private, sk);
-- 
2.7.3

^ permalink raw reply related

* [PATCH stable 3.10.y 11/18] crypto: algif_skcipher - Remove custom release parent function
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit d7b65aee1e7b4c87922b0232eaba56a8a143a4a0 upstream.

This patch removes the custom release parent function as the
generic af_alg_release_parent now works for nokey sockets too.

Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/algif_skcipher.c | 43 +++----------------------------------------
 1 file changed, 3 insertions(+), 40 deletions(-)

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 4677a45..a7800b7 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -681,7 +681,7 @@ static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
 	return err;
 }
 
-static void skcipher_sock_destruct_common(struct sock *sk)
+static void skcipher_sock_destruct(struct sock *sk)
 {
 	struct alg_sock *ask = alg_sk(sk);
 	struct skcipher_ctx *ctx = ask->private;
@@ -690,33 +690,10 @@ static void skcipher_sock_destruct_common(struct sock *sk)
 	skcipher_free_sgl(sk);
 	sock_kfree_s(sk, ctx->iv, crypto_ablkcipher_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 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)
+static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
 {
 	struct skcipher_ctx *ctx;
 	struct alg_sock *ask = alg_sk(sk);
@@ -762,21 +739,7 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
 	if (!tfm->has_key && crypto_ablkcipher_has_setkey(tfm->skcipher))
 		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;
+	return skcipher_accept_parent_nokey(private, sk);
 }
 
 static const struct af_alg_type algif_type_skcipher = {
-- 
2.7.3

^ permalink raw reply related

* [PATCH stable 3.10.y 12/18] crypto: af_alg - Forbid bind(2) when nokey child sockets are present
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit a6a48c565f6f112c6983e2a02b1602189ed6e26e upstream.

This patch forbids the calling of bind(2) when there are child
sockets created by accept(2) in existence, even if they are created
on the nokey path.

This is needed as those child sockets have references to the tfm
object which bind(2) will destroy.

Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/af_alg.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 2f8fd84..68ec1ac 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -130,19 +130,16 @@ EXPORT_SYMBOL_GPL(af_alg_release);
 void af_alg_release_parent(struct sock *sk)
 {
 	struct alg_sock *ask = alg_sk(sk);
-	bool last;
+	unsigned int nokey = ask->nokey_refcnt;
+	bool last = nokey && !ask->refcnt;
 
 	sk = ask->parent;
-
-	if (ask->nokey_refcnt && !ask->refcnt) {
-		sock_put(sk);
-		return;
-	}
-
 	ask = alg_sk(sk);
 
 	lock_sock(sk);
-	last = !--ask->refcnt;
+	ask->nokey_refcnt -= nokey;
+	if (!last)
+		last = !--ask->refcnt;
 	release_sock(sk);
 
 	if (last)
@@ -185,7 +182,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
 	err = -EBUSY;
 	lock_sock(sk);
-	if (ask->refcnt)
+	if (ask->refcnt | ask->nokey_refcnt)
 		goto unlock;
 
 	swap(ask->type, type);
@@ -296,6 +293,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
 
 	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;
-- 
2.7.3

^ permalink raw reply related

* [PATCH stable 3.10.y 18/18] crypto: skcipher - Fix blkcipher walk OOM crash
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit acdb04d0b36769b3e05990c488dc74d8b7ac8060 upstream.

When we need to allocate a temporary blkcipher_walk_next and it
fails, the code is supposed to take the slow path of processing
the data block by block.  However, due to an unrelated change
we instead end up dereferencing the NULL pointer.

This patch fixes it by moving the unrelated bsize setting out
of the way so that we enter the slow path as inteded.

Fixes: 7607bd8ff03b ("[CRYPTO] blkcipher: Added blkcipher_walk_virt_block")
Cc: stable@vger.kernel.org
Reported-by: xiakaixu <xiakaixu@huawei.com>
Reported-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/blkcipher.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 37af08e..39b09f25 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -238,6 +238,8 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc,
 		return blkcipher_walk_done(desc, walk, -EINVAL);
 	}
 
+	bsize = min(walk->blocksize, n);
+
 	walk->flags &= ~(BLKCIPHER_WALK_SLOW | BLKCIPHER_WALK_COPY |
 			 BLKCIPHER_WALK_DIFF);
 	if (!scatterwalk_aligned(&walk->in, alignmask) ||
@@ -250,7 +252,6 @@ static int blkcipher_walk_next(struct blkcipher_desc *desc,
 		}
 	}
 
-	bsize = min(walk->blocksize, n);
 	n = scatterwalk_clamp(&walk->in, n);
 	n = scatterwalk_clamp(&walk->out, n);
 
-- 
2.7.3

^ permalink raw reply related

* Re: AEAD Question
From: Juan Pablo Nariño Mendoza @ 2016-10-27  8:05 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: linux-crypto
In-Reply-To: <1536924.VKbsE1YqZP@positron.chronox.de>

Hello Stephan
Thank you for your fast answer

My idea is to do zero copy encryption and the cipher I am using is
authenc(hmac(sha1),cbc(aes).

The layout of my buffer is

espHeader(AD) || IV || plaintext || Integrity (TAG)

As I see it, the SGs do point to the same buffer, but they do not overlap

Below, some parts of my code


// Prepare data
sg_init_table(sg,ARRAY_SIZE(sg));


sg_set_buf(&sg[1],cipherText_p,espHdrLen);
sg_set_buf(&sg[0],cipherText_p+espHdrLen+ivLen,plen+intLen);

// Put plaintext in cipherText + espHdr + ivLen
// put esp header info in ciphertext

req_p = aead_givcrypt_alloc(aead_p,GFP_KERNEL);
aead_givcrypt_set_callback(req_p,0,hwencpoc_testCipher_cb,cipherText_p);
aead_givcrypt_set_crypt(req_p,&sg[0],&sg[0],plen,iv_p);
aead_givcrypt_set_assoc(req_p,&sg[1],espHdrLen);
aead_givcrypt_set_giv(req_p,cipherText_p+espHdrLen,0);

ret=crypto_aead_givencrypt(req_p);


However, when I get the callback, the associated data has been
overwritten (first 8 bytes of the cipherText buffer), and the
integrity is wrong. The IV and the encryption are correct. What I am
doing wrong? Thank you again

Juan

2016-10-26 18:32 GMT+02:00 Stephan Mueller <smueller@chronox.de>:
> Am Mittwoch, 26. Oktober 2016, 18:17:14 CEST schrieb Juan Pablo Nariño
> Mendoza:
>
> Hi Juan,
>
>> Sorry in advance for making what shall be a basic question for this
>> list, but I have really ran out of ideas.
>>
>> Can someone explain me please, how does the memory layout and sg lists
>> work for the IPSec case, with generated IV case?
>>
>> As I understand, it is like this (ascii art)
>>
>> AD | IV Space | Plain Text | Auth Tag
>>  ^                   ^
>>
>> asg              sg
>
> The memory layout is correct when using the RFC4106 cipher.
>
> How you partition your physical memory with the SGL is your choice as long as
> your data in the SGL is lined up as you mentioned above.
>>
>> But I am having the AD overwritten, and the AUTH tag and encryption is
>> not correct? Could someone please point me in the right direction?
>> Thank you again
>
> Maybe the src and dst SGL somehow partially overlap?
>>
>> Regards
>>
>> Juan
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
> Ciao
> Stephan

^ permalink raw reply

* Re: [PATCH stable 3.10.y 00/18] Backport crypto fixes.
From: Willy Tarreau @ 2016-10-27 15:06 UTC (permalink / raw)
  To: Andrey Ryabinin; +Cc: stable, Herbert Xu, linux-crypto
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

Hi Andrey,

On Thu, Oct 27, 2016 at 05:29:33PM +0300, Andrey Ryabinin wrote:
> While fuzzing our 3.10 based kernel we observed some crashes, e.g:
>       http://lkml.kernel.org/r/<CACT4Y+aE-pNUnCLbDQkFQ9Y7QivN_g6hEuS7t1RpknPHFmHg+g@mail.gmail.com>
> 
> It appears that 3.10-stable lacks some crypto related fixes. Here is my attempt
> to backport them.
> Many patches didn't apply cleanly, so to make sure that my conflict resolution
> is correct I compared it with other stable trees.
(...)

Thanks a lot for doing this! I'm queueing them for next 3.10 and will merge
them unless I receive a nack for any of them.

Best regards,
Willy

^ permalink raw reply

* [PATCH stable 3.10.y 03/18] crypto: af_alg - Add nokey compatibility path
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit 37766586c965d63758ad542325a96d5384f4a8c9 upstream.

This patch adds a compatibility path to support old applications
that do acept(2) before setkey.

Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/af_alg.c         | 13 ++++++++++++-
 include/crypto/if_alg.h |  2 ++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 0ca108f..de130c2 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;
@@ -257,6 +259,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
 	const struct af_alg_type *type;
 	struct sock *sk2;
 	int err;
+	bool nokey;
 
 	lock_sock(sk);
 	type = ask->type;
@@ -275,12 +278,17 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
 	security_sk_clone(sk, sk2);
 
 	err = type->accept(ask->private, 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;
 
-	if (!ask->refcnt++)
+	if (nokey || !ask->refcnt++)
 		sock_hold(sk);
 	alg_sk(sk2)->parent = sk;
 	alg_sk(sk2)->type = type;
@@ -288,6 +296,9 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
 	newsock->ops = type->ops;
 	newsock->state = SS_CONNECTED;
 
+	if (nokey)
+		newsock->ops = type->ops_nokey;
+
 	err = 0;
 
 unlock:
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 2f38daa..9e6a2f3 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -51,8 +51,10 @@ 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);
 
 	struct proto_ops *ops;
+	struct proto_ops *ops_nokey;
 	struct module *owner;
 	char name[14];
 };
-- 
2.7.3

^ permalink raw reply related

* [PATCH stable 3.10.y 01/18] crypto: algif_skcipher - Require setkey before accept(2)
From: Andrey Ryabinin @ 2016-10-27 14:29 UTC (permalink / raw)
  To: Willy Tarreau, stable; +Cc: Herbert Xu, linux-crypto, Andrey Ryabinin
In-Reply-To: <1477578591-28924-1-git-send-email-aryabinin@virtuozzo.com>

From: Herbert Xu <herbert@gondor.apana.org.au>

commit dd504589577d8e8e70f51f997ad487a4cb6c026f upstream.

Some cipher implementations will crash if you try to use them
without calling setkey first.  This patch adds a check so that
the accept(2) call will fail with -ENOKEY if setkey hasn't been
done on the socket yet.

Cc: stable@vger.kernel.org
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 crypto/algif_skcipher.c | 51 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 9 deletions(-)

diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 83187f4..c4c121a 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_ablkcipher *skcipher;
+	bool has_key;
+};
+
 struct skcipher_ctx {
 	struct list_head tsgl;
 	struct af_alg_sgl rsgl;
@@ -546,17 +551,41 @@ static struct proto_ops algif_skcipher_ops = {
 
 static void *skcipher_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_ablkcipher(name, type, mask);
+	struct skcipher_tfm *tfm;
+	struct crypto_ablkcipher *skcipher;
+
+	tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+	if (!tfm)
+		return ERR_PTR(-ENOMEM);
+
+	skcipher = crypto_alloc_ablkcipher(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_ablkcipher(private);
+	struct skcipher_tfm *tfm = private;
+
+	crypto_free_ablkcipher(tfm->skcipher);
+	kfree(tfm);
 }
 
 static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_ablkcipher_setkey(private, key, keylen);
+	struct skcipher_tfm *tfm = private;
+	int err;
+
+	err = crypto_ablkcipher_setkey(tfm->skcipher, key, keylen);
+	tfm->has_key = !err;
+
+	return err;
 }
 
 static void skcipher_sock_destruct(struct sock *sk)
@@ -575,20 +604,24 @@ 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);
+	struct skcipher_tfm *tfm = private;
+	struct crypto_ablkcipher *skcipher = tfm->skcipher;
+	unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(skcipher);
+
+	if (!tfm->has_key)
+		return -ENOKEY;
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
-
-	ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private),
+	ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(skcipher),
 			       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, crypto_ablkcipher_ivsize(skcipher));
 
 	INIT_LIST_HEAD(&ctx->tsgl);
 	ctx->len = len;
@@ -600,9 +633,9 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
 
 	ask->private = ctx;
 
-	ablkcipher_request_set_tfm(&ctx->req, private);
+	ablkcipher_request_set_tfm(&ctx->req, skcipher);
 	ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-					af_alg_complete, &ctx->completion);
+				      af_alg_complete, &ctx->completion);
 
 	sk->sk_destruct = skcipher_sock_destruct;
 
-- 
2.7.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox