Linux cryptographic layer development
 help / color / mirror / Atom feed
* Re: [PATCH v6 3/6] crypto: AF_ALG -- add asymmetric cipher interface
From: Stephan Mueller @ 2016-06-09  9:28 UTC (permalink / raw)
  To: Mat Martineau
  Cc: Tadeusz Struk, dhowells, herbert, linux-api, marcel, linux-kernel,
	keyrings, linux-crypto, dwmw2, davem
In-Reply-To: <alpine.OSX.2.20.1606081135160.16651@mjmartin-mac01.local>

Am Mittwoch, 8. Juni 2016, 12:14:49 schrieb Mat Martineau:

Hi Mat,

> On Wed, 8 Jun 2016, Stephan Mueller wrote:
> > Am Dienstag, 7. Juni 2016, 17:28:07 schrieb Mat Martineau:
> > 
> > Hi Mat,
> > 
> >>> +	used = ctx->used;
> >>> +
> >>> +	/* convert iovecs of output buffers into scatterlists */
> >>> +	while (iov_iter_count(&msg->msg_iter)) {
> >>> +		/* make one iovec available as scatterlist */
> >>> +		err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter,
> >>> +				     iov_iter_count(&msg->msg_iter));
> >>> +		if (err < 0)
> >>> +			goto unlock;
> >>> +		usedpages += err;
> >>> +		/* chain the new scatterlist with previous one */
> >>> +		if (cnt)
> >>> +			af_alg_link_sg(&ctx->rsgl[cnt - 1], &ctx->rsgl[cnt]);
> >>> +
> >>> +		iov_iter_advance(&msg->msg_iter, err);
> >>> +		cnt++;
> >>> +	}
> >>> +
> >>> +	/* ensure output buffer is sufficiently large */
> >>> +	if (usedpages < akcipher_calcsize(ctx)) {
> >>> +		err = -EMSGSIZE;
> >>> +		goto unlock;
> >>> +	}
> >> 
> >> Why is the size of the output buffer enforced here instead of depending
> >> on
> >> the algorithm implementation?
> > 
> > akcipher_calcsize calls crypto_akcipher_maxsize to get the maximum size
> > the
> > algorithm generates as output during its operation.
> > 
> > The code ensures that the caller provided at least that amount of memory
> > for the kernel to store its data in. This check therefore is present to
> > ensure the kernel does not overstep memory boundaries in user space.
> 
> Yes, it's understood that the userspace buffer length must not be
> exceeded. But dst_len is part of the akcipher_request struct, so why does
> it need to be checked *here* when it is also checked later?

I am always uneasy when the kernel has a user space interface and expects 
layers deep down inside the kernel to check for user space related boundaries. 
Note, we do not hand the __user flag down, so sparse and other tools cannot 
detect whether a particular cipher implementation has the right checks.

I therefore always would like to check parameters at the interface handling 
logic. Cryptographers rightly should worry about their code implementing the 
cipher correctly. But I do not think that the cipher implementations should 
worry about security implications since they may be called from user space.
> 
> > What is your concern?
> 
> Userspace must allocate larger buffers than it knows are necessary for
> expected results.
> 
> It looks like the software rsa implementation handles shorter output
> buffers ok (mpi_write_to_sgl will return EOVERFLOW if the the buffer is
> too small), however I see at least one hardware rsa driver that requires
> the output buffer to be the maximum size. But this inconsistency might be
> best addressed within the software cipher or drivers rather than in
> recvmsg.

Is your concern that we have a double check check for lengths here? If yes, I 
think we can live with an additional if() here.

Or is your concern that the user space interface restricts things too much and 
thus prevents a valid use case?

Ciao
Stephan

^ permalink raw reply

* CTR mode: Kconfig cyclic dependency
From: Stephan Mueller @ 2016-06-09  9:07 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto

Hi Herbert,

during the finalization of my patch set for converting the CTR DRBG over to 
CTR AES, I ran into a Kconfig problem. Maybe you have an idea how to resolve 
it.

As the CTR DRBG now uses the CTR mode, I added "select CRYPTO_CTR" to 
CRYPTO_DRBG_CTR. This now lead to the following cyclic dependency:

crypto/Kconfig:1547:error: recursive dependency detected!
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
crypto/Kconfig:1547:    symbol CRYPTO_DRBG_MENU is selected by 
CRYPTO_RNG_DEFAULT
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
crypto/Kconfig:83:      symbol CRYPTO_RNG_DEFAULT is selected by CRYPTO_SEQIV
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
crypto/Kconfig:255:     symbol CRYPTO_SEQIV is selected by CRYPTO_CTR
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
crypto/Kconfig:286:     symbol CRYPTO_CTR is selected by CRYPTO_DRBG_CTR
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
crypto/Kconfig:1566:    symbol CRYPTO_DRBG_CTR depends on CRYPTO_DRBG_MENU

i.e. CRYPTO_RNG_DEFAULT -> CRYPTO_DRBG_MENU -> CRYPTO_CTR -> CRYPTO_SEQIV -> 
CRYPTO_RNG_DEFAULT

Thanks
Stephan

^ permalink raw reply

* Re: [PATCH v6 3/6] crypto: AF_ALG -- add asymmetric cipher interface
From: Mat Martineau @ 2016-06-08 19:14 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Mat Martineau, Tadeusz Struk, dhowells, herbert, linux-api,
	marcel, linux-kernel, keyrings, linux-crypto, dwmw2, davem
In-Reply-To: <6401187.24v903AfyY@tauon.atsec.com>


On Wed, 8 Jun 2016, Stephan Mueller wrote:

> Am Dienstag, 7. Juni 2016, 17:28:07 schrieb Mat Martineau:
>
> Hi Mat,
>
>>> +	used = ctx->used;
>>> +
>>> +	/* convert iovecs of output buffers into scatterlists */
>>> +	while (iov_iter_count(&msg->msg_iter)) {
>>> +		/* make one iovec available as scatterlist */
>>> +		err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter,
>>> +				     iov_iter_count(&msg->msg_iter));
>>> +		if (err < 0)
>>> +			goto unlock;
>>> +		usedpages += err;
>>> +		/* chain the new scatterlist with previous one */
>>> +		if (cnt)
>>> +			af_alg_link_sg(&ctx->rsgl[cnt - 1], &ctx->rsgl[cnt]);
>>> +
>>> +		iov_iter_advance(&msg->msg_iter, err);
>>> +		cnt++;
>>> +	}
>>> +
>>> +	/* ensure output buffer is sufficiently large */
>>> +	if (usedpages < akcipher_calcsize(ctx)) {
>>> +		err = -EMSGSIZE;
>>> +		goto unlock;
>>> +	}
>>
>> Why is the size of the output buffer enforced here instead of depending on
>> the algorithm implementation?
>
> akcipher_calcsize calls crypto_akcipher_maxsize to get the maximum size the
> algorithm generates as output during its operation.
>
> The code ensures that the caller provided at least that amount of memory for
> the kernel to store its data in. This check therefore is present to ensure the
> kernel does not overstep memory boundaries in user space.

Yes, it's understood that the userspace buffer length must not be 
exceeded. But dst_len is part of the akcipher_request struct, so why does 
it need to be checked *here* when it is also checked later?

> What is your concern?

Userspace must allocate larger buffers than it knows are necessary for 
expected results.

It looks like the software rsa implementation handles shorter output 
buffers ok (mpi_write_to_sgl will return EOVERFLOW if the the buffer is 
too small), however I see at least one hardware rsa driver that requires 
the output buffer to be the maximum size. But this inconsistency might be 
best addressed within the software cipher or drivers rather than in 
recvmsg.

^ permalink raw reply

* Re: [sparc] niagara2 cpu, opcodes not available message?
From: David Miller @ 2016-06-08 18:33 UTC (permalink / raw)
  To: matorola; +Cc: sparclinux, debian-sparc, linux-crypto
In-Reply-To: <CADxRZqwr9=9ZsrFR_8iC+f1Z=hSPi7Saj3uxB2=YmH42sVf6pQ@mail.gmail.com>

From: Anatoly Pugachev <matorola@gmail.com>
Date: Wed, 8 Jun 2016 20:30:40 +0300

> Can someone please tell, why do we get a bunch of the following
> messages on niagara2 cpu hardware (SPARC Enterprise T5120, T5220,
> T5140, and T5240 servers)
> 
> Asking, because I see the following lines on kernel boot (removing
> first field boot time stamp in cut):
> 
> mator@nvg5120:~/linux-sparc-boot-logs/t5120$ grep opcode
> dmesg-4.7.0-rc2+.log  | cut -f2- -d' ' | sort | uniq -c
>       4 aes_sparc64: sparc64 aes opcodes not available.
>       7 camellia_sparc64: sparc64 camellia opcodes not available.
>      37 crc32c_sparc64: sparc64 crc32c opcode not available.
>       5 des_sparc64: sparc64 des opcodes not available.
>       4 md5_sparc64: sparc64 md5 opcode not available.
>       1 sha1_sparc64: sparc64 sha1 opcode not available.
>       2 sha256_sparc64: sparc64 sha256 opcode not available.
>       3 sha512_sparc64: sparc64 sha512 opcode not available.

Because the drivers unconditionally try to load, check the CPU capabilites
and emit the log message if the cpu caps aren't present.

I don't see what the problem is, everying is working as designed.

^ permalink raw reply

* [RFC PATCH 14/15] hwrng: exynos - fixup IO accesors
From: Matthew Leach @ 2016-06-08 18:31 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Ben Dooks
  Cc: linux-samsung-soc, linux-arm-kernel, linux-kernel, Matt Mackall,
	linux-crypto
In-Reply-To: <20160608183110.13851-1-matthew@mattleach.net>

From: Ben Dooks <ben.dooks@codethink.co.uk>

The __raw IO functions are not endian safe, so use the readl_relaxed
and writel_relaxed versions of these.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
---
CC: Matt Mackall <mpm@selenic.com>
CC: Krzysztof Kozlowski <k.kozlowski@samsung.com>
CC: linux-crypto@vger.kernel.org
CC: linux-arm-kernel@lists.infradead.org
CC: linux-samsung-soc@vger.kernel.org
---
 drivers/char/hw_random/exynos-rng.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index ed44561..23d3585 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -45,12 +45,12 @@ struct exynos_rng {
 
 static u32 exynos_rng_readl(struct exynos_rng *rng, u32 offset)
 {
-	return	__raw_readl(rng->mem + offset);
+	return	readl_relaxed(rng->mem + offset);
 }
 
 static void exynos_rng_writel(struct exynos_rng *rng, u32 val, u32 offset)
 {
-	__raw_writel(val, rng->mem + offset);
+	writel_relaxed(val, rng->mem + offset);
 }
 
 static int exynos_rng_configure(struct exynos_rng *exynos_rng)
-- 
2.8.3

^ permalink raw reply related

* Re: [sparc] niagara2 cpu, opcodes not available message?
From: Anatoly Pugachev @ 2016-06-08 18:27 UTC (permalink / raw)
  To: sparclinux; +Cc: debian-sparc, linux-crypto
In-Reply-To: <CADxRZqwr9=9ZsrFR_8iC+f1Z=hSPi7Saj3uxB2=YmH42sVf6pQ@mail.gmail.com>

On Wed, Jun 8, 2016 at 8:30 PM, Anatoly Pugachev <matorola@gmail.com> wrote:
> Hello!
>
> Can someone please tell, why do we get a bunch of the following
> messages on niagara2 cpu hardware (SPARC Enterprise T5120, T5220,
> T5140, and T5240 servers)
>
> Asking, because I see the following lines on kernel boot (removing
> first field boot time stamp in cut):
>
> mator@nvg5120:~/linux-sparc-boot-logs/t5120$ grep opcode
> dmesg-4.7.0-rc2+.log  | cut -f2- -d' ' | sort | uniq -c
>       4 aes_sparc64: sparc64 aes opcodes not available.
>       7 camellia_sparc64: sparc64 camellia opcodes not available.
>      37 crc32c_sparc64: sparc64 crc32c opcode not available.
>       5 des_sparc64: sparc64 des opcodes not available.
>       4 md5_sparc64: sparc64 md5 opcode not available.
>       1 sha1_sparc64: sparc64 sha1 opcode not available.
>       2 sha256_sparc64: sparc64 sha256 opcode not available.
>       3 sha512_sparc64: sparc64 sha512 opcode not available.
>
> Can we probably remove this functionality/messages from niagara2 cpus,
> if it does not support it anyway?

Wasn't clear at all, I mean can we please change pr_info in
arch/sparc/crypto/ to pr_debug in xx_sparc64_mod_init() functions?
Thanks.

^ permalink raw reply

* Re: [sparc] niagara2 cpu, opcodes not available message?
From: Anatoly Pugachev @ 2016-06-08 17:57 UTC (permalink / raw)
  To: sparclinux; +Cc: linux-crypto, debian-sparc
In-Reply-To: <CADxRZqwr9=9ZsrFR_8iC+f1Z=hSPi7Saj3uxB2=YmH42sVf6pQ@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1203 bytes --]

On Jun 8, 2016 8:30 PM, "Anatoly Pugachev" <matorola@gmail.com> wrote:
>
> Hello!
>
> Can someone please tell, why do we get a bunch of the following
> messages on niagara2 cpu hardware (SPARC Enterprise T5120, T5220,
> T5140, and T5240 servers)
>
> Asking, because I see the following lines on kernel boot (removing
> first field boot time stamp in cut):
>
> mator@nvg5120:~/linux-sparc-boot-logs/t5120$ grep opcode
> dmesg-4.7.0-rc2+.log  | cut -f2- -d' ' | sort | uniq -c
>       4 aes_sparc64: sparc64 aes opcodes not available.
>       7 camellia_sparc64: sparc64 camellia opcodes not available.
>      37 crc32c_sparc64: sparc64 crc32c opcode not available.
>       5 des_sparc64: sparc64 des opcodes not available.
>       4 md5_sparc64: sparc64 md5 opcode not available.
>       1 sha1_sparc64: sparc64 sha1 opcode not available.
>       2 sha256_sparc64: sparc64 sha256 opcode not available.
>       3 sha512_sparc64: sparc64 sha512 opcode not available.
>
> Can we probably remove this functionality/messages from niagara2 cpus,
> if it does not support it anyway?

Wasn't clear at all, I mean can we please change pr_info in
arch/sparc/crypto/ to pr_debug in xx_sparc64_mod_init() functions?

[-- Attachment #2: Type: text/html, Size: 1515 bytes --]

^ permalink raw reply

* [sparc] niagara2 cpu, opcodes not available message?
From: Anatoly Pugachev @ 2016-06-08 17:30 UTC (permalink / raw)
  To: sparclinux; +Cc: debian-sparc, linux-crypto

Hello!

Can someone please tell, why do we get a bunch of the following
messages on niagara2 cpu hardware (SPARC Enterprise T5120, T5220,
T5140, and T5240 servers)

Asking, because I see the following lines on kernel boot (removing
first field boot time stamp in cut):

mator@nvg5120:~/linux-sparc-boot-logs/t5120$ grep opcode
dmesg-4.7.0-rc2+.log  | cut -f2- -d' ' | sort | uniq -c
      4 aes_sparc64: sparc64 aes opcodes not available.
      7 camellia_sparc64: sparc64 camellia opcodes not available.
     37 crc32c_sparc64: sparc64 crc32c opcode not available.
      5 des_sparc64: sparc64 des opcodes not available.
      4 md5_sparc64: sparc64 md5 opcode not available.
      1 sha1_sparc64: sparc64 sha1 opcode not available.
      2 sha256_sparc64: sparc64 sha256 opcode not available.
      3 sha512_sparc64: sparc64 sha512 opcode not available.

But linux kernel sources ( linux-2.6/arch/sparc/kernel/setup_64.c )
define crypto_hwcaps only for CPUs with the following capabilities:

static const char *crypto_hwcaps[] = {
        "aes", "des", "kasumi", "camellia", "md5", "sha1", "sha256",
        "sha512", "mpmul", "montmul", "montsqr", "crc32c",
};

and we don't have them in niagara2 cpu CAPS:

mator@nvg5120:~/linux-sparc-boot-logs/t5120$ grep CAPS dmesg-4.7.0-rc2+.log
[    0.000000] CPU CAPS: [flush,stbar,swap,muldiv,v9,blkinit,n2,mul32]
[    0.000000] CPU CAPS: [div32,v8plus,popc,vis,vis2,ASIBlkInit]

mator@nvg5120:~/linux-sparc-boot-logs/t5120$ egrep '^cpu|pmu' /proc/cpuinfo
cpu             : UltraSparc T2 (Niagara2)
pmu             : niagara2
cpucaps         :
flush,stbar,swap,muldiv,v9,blkinit,n2,mul32,div32,v8plus,popc,vis,vis2,ASIBlkInit


compare, for example, with sparc CPU which support crypto (T5 cpu,
landau is machine name):

mator@landau:~$ grep CAPS dmesg-4.6.1.txt
[    0.000000] CPU CAPS: [flush,stbar,swap,muldiv,v9,blkinit,n2,mul32]
[    0.000000] CPU CAPS: [div32,v8plus,popc,vis,vis2,ASIBlkInit,fmaf,vis3]
[    0.000000] CPU CAPS: [hpc,ima,pause,cbcond,aes,des,kasumi,camellia]
[    0.000000] CPU CAPS: [md5,sha1,sha256,sha512,mpmul,montmul,montsqr,crc32c]

mator@landau:~$ egrep '^cpu|pmu' /proc/cpuinfo
cpu             : UltraSparc T5 (Niagara5)
pmu             : niagara5
cpucaps         :
flush,stbar,swap,muldiv,v9,blkinit,n2,mul32,div32,v8plus,popc,vis,vis2,ASIBlkInit,fmaf,vis3,hpc,ima,pause,cbcond,aes,des,kasumi,camellia,md5,sha1,sha256,sha512,mpmul,montmul,montsqr,crc32c

mator@landau:~$ grep opcode dmesg-4.6.1.txt
[8537574.887049] aes_sparc64: Using sparc64 aes opcodes optimized AES
implementation
[8537574.887611] crc32c_sparc64: Using sparc64 crc32c opcode optimized
CRC32C implementation
[8537576.577455] sha1_sparc64: Using sparc64 sha1 opcode optimized
SHA-1 implementation
[8537576.578928] sha256_sparc64: Using sparc64 sha256 opcode optimized
SHA-256/SHA-224 implementation
[8537576.580908] sha512_sparc64: Using sparc64 sha512 opcode optimized
SHA-512/SHA-384 implementation
[8537576.582964] md5_sparc64: Using sparc64 md5 opcode optimized MD5
implementation
[8537576.596984] des_sparc64: Using sparc64 des opcodes optimized DES
implementation
[8537576.600503] camellia_sparc64: Using sparc64 camellia opcodes
optimized CAMELLIA implementation


I don't understand why niagara2 cpu getting HWCAP_SPARC_CRYPTO flag if
it does not support it.
Can we probably remove this functionality/messages from niagara2 cpus,
if it does not support it anyway?

mator@nvg5120:~$ lsmod | grep -c sparc64
0

mator@landau:~$ lsmod | grep -c sparc64
9




Thanks.

^ permalink raw reply

* [PATCH] crypto: ux500: memmove the right size
From: Linus Walleij @ 2016-06-08 12:56 UTC (permalink / raw)
  To: linux-crypto, Herbert Xu; +Cc: David Binderman, Linus Walleij, Joakim Bech

The hash buffer is really HASH_BLOCK_SIZE bytes, someone
must have thought that memmove takes n*u32 words by mistake.
Tests work as good/bad as before after this patch.

Cc: Joakim Bech <joakim.bech@linaro.org>
Reported-by: David Binderman <linuxdev.baldrick@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/crypto/ux500/hash/hash_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 574e87c7f2b8..9acccad26928 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -781,7 +781,7 @@ static int hash_process_data(struct hash_device_data *device_data,
 						&device_data->state);
 				memmove(req_ctx->state.buffer,
 					device_data->state.buffer,
-					HASH_BLOCK_SIZE / sizeof(u32));
+					HASH_BLOCK_SIZE);
 				if (ret) {
 					dev_err(device_data->dev,
 						"%s: hash_resume_state() failed!\n",
@@ -832,7 +832,7 @@ static int hash_process_data(struct hash_device_data *device_data,
 
 			memmove(device_data->state.buffer,
 				req_ctx->state.buffer,
-				HASH_BLOCK_SIZE / sizeof(u32));
+				HASH_BLOCK_SIZE);
 			if (ret) {
 				dev_err(device_data->dev, "%s: hash_save_state() failed!\n",
 					__func__);
-- 
2.4.11

^ permalink raw reply related

* Re: linux-4.6/drivers/crypto/ux500/hash/hash_core.c: 2 * possible bad size ?
From: Linus Walleij @ 2016-06-08 12:52 UTC (permalink / raw)
  To: Herbert Xu, Joakim Bech
  Cc: David Binderman, David S. Miller, linux-crypto@vger.kernel.org,
	linux-kernel@vger.kernel.org, David Binderman, Andreas Westin
In-Reply-To: <20160518074650.GA6097@gondor.apana.org.au>

On Wed, May 18, 2016 at 9:46 AM, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Mon, May 16, 2016 at 07:13:12PM +0100, David Binderman wrote:
>> Hello there,
>>
>> 1.
>>
>> linux-4.6/drivers/crypto/ux500/hash/hash_core.c:784]: (warning) Division by
>> result of sizeof(). memmove() expects a size in bytes, did you intend to
>> multiply instead?
>>
>> Source code is
>>
>>                 memmove(req_ctx->state.buffer,
>>                     device_data->state.buffer,
>>                     HASH_BLOCK_SIZE / sizeof(u32));
>>
>> Maybe better code
>>
>>                 memmove(req_ctx->state.buffer,
>>                     device_data->state.buffer,
>>                     HASH_BLOCK_SIZE);

Yeah obviously the latter as in hash_alg.h:

struct hash_state {
(...)
    u32        buffer[HASH_BLOCK_SIZE / sizeof(u32)];

That could just as well be an u8 of HASH_BLOCK_SIZE.

Sending a patch for this.

>> linux-4.6/drivers/crypto/ux500/hash/hash_core.c:835]: (warning) Division by
>> result of sizeof(). memmove() expects a size in bytes, did you intend to
>> multiply instead?
>>
>> Duplicate.
>
> Thanks for noticing these bugs.  This driver hasn't been maintained
> since 2012, so unless someone steps up I'm going to just delete it.

I'm trying to take a look at it because I'm using this platform
for tests and it's nice to have all features enabled.

And it has some problems (I added prints to also print successful tests):

[    3.864746] alg: hash: Test 1 SUCCEEDED for sha1-ux500
[    3.870147] alg: hash: Test 2 SUCCEEDED for sha1-ux500
[    3.875610] alg: hash: Test 3 SUCCEEDED for sha1-ux500
[    3.881408] alg: hash: Test 4 SUCCEEDED for sha1-ux500
[    3.886596] alg: hash: Chunking test 1 SUCCEEDED for sha1-ux500
[    3.892639] alg: hash: Chunking test 2 FAILED for sha1-ux500
[    3.898284] result:
[    3.900421] 00000000: 76 b4 ed 2f d7 11 1d c8 64 4c 38 b0 f8 27 19 89
[    3.906860] 00000010: 58 1e bb 3a
[    3.915588] expected:
[    3.917846] 00000000: 97 01 11 c4 e7 7b cc 88 cc 20 45 9c 02 b6 9b 4a
[    3.928314] 00000010: a8 f5 82 17
[    3.937255] alg: hash: Test 1 SUCCEEDED for sha256-ux500
[    3.948089] alg: hash: Test 2 SUCCEEDED for sha256-ux500
[    3.961944] alg: hash: Test 3 SUCCEEDED for sha256-ux500
[    3.967590] alg: hash: Test 4 SUCCEEDED for sha256-ux500
[    3.973083] alg: hash: Chunking test 1 SUCCEEDED for sha256-ux500
[    3.979248] alt: hash: Failed to export() for sha256-ux500
[    3.984802] hash: partial update failed on test 1 for sha256-ux500: ret=38
[    3.992004] alg: hash: Test 1 SUCCEEDED for hmac-sha1-ux500
[    3.997650] alg: hash: Test 2 SUCCEEDED for hmac-sha1-ux500
[    4.003356] alg: hash: Test 3 SUCCEEDED for hmac-sha1-ux500
[    4.009002] alg: hash: Test 4 SUCCEEDED for hmac-sha1-ux500
[    4.014678] alg: hash: Test 5 SUCCEEDED for hmac-sha1-ux500
[    4.020385] alg: hash: Test 6 SUCCEEDED for hmac-sha1-ux500
[    4.026062] alg: hash: Chunking test 1 SUCCEEDED for hmac-sha1-ux500
[    4.032470] alt: hash: Failed to export() for hmac-sha1-ux500
[    4.038208] hash: partial update failed on test 1 for hmac-sha1-ux500: ret=38
[    4.045623] alg: hash: Test 1 SUCCEEDED for hmac-sha256-ux500
[    4.051483] alg: hash: Test 2 SUCCEEDED for hmac-sha256-ux500
[    4.057342] alg: hash: Test 3 SUCCEEDED for hmac-sha256-ux500
[    4.063201] alg: hash: Test 4 SUCCEEDED for hmac-sha256-ux500
[    4.069030] alg: hash: Test 5 SUCCEEDED for hmac-sha256-ux500
[    4.074890] alg: hash: Test 6 SUCCEEDED for hmac-sha256-ux500
[    4.080780] alg: hash: Test 7 SUCCEEDED for hmac-sha256-ux500
[    4.086608] alg: hash: Test 8 SUCCEEDED for hmac-sha256-ux500
[    4.092468] alg: hash: Test 9 SUCCEEDED for hmac-sha256-ux500
[    4.098297] alg: hash: Chunking test 1 SUCCEEDED for hmac-sha256-ux500
[    4.104888] alt: hash: Failed to export() for hmac-sha256-ux500
[    4.110809] hash: partial update failed on test 1 for
hmac-sha256-ux500: ret=38
[    4.118164] hash1 hash1: successfully registered
[    4.123687] alg: No test for aes (aes-ux500)
[    4.132354] alg: No test for des (des-ux500)
[    4.136749] alg: No test for des3_ede (des3_ede-ux500)
[    4.151306] alg: skcipher: Test 1 failed (invalid result) on
encryption for cbc-des-ux500
[    4.159484] 00000000: 03 91 6b cc 4a f6 3a 53 9c 4d 2e 2b 91 83 44 f6
[    4.165954] 00000010: aa 6a 15 6a dc b5 e0 3d
[    4.170501] cryp1 cryp1: successfully registered

The simple tests always work, it's those stressful ones that create
problems.

Joakim: did you have a memory of this code working? Should
I check the vendor tree for fixes?

Yours,
Linus Walleij

^ permalink raw reply

* Re: AES-NI: slower than aes-generic?
From: Stephan Mueller @ 2016-06-08 12:21 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Sandy Harris, Stephan Mueller, linux-crypto
In-Reply-To: <20160527021429.GA21331@thunk.org>

Am Donnerstag, 26. Mai 2016, 22:14:29 schrieb Theodore Ts'o:

Hi Theodore,

> On Thu, May 26, 2016 at 08:49:39PM +0200, Stephan Mueller wrote:
> > Using the kernel crypto API one can relieve the CPU of the crypto work, if
> > a hardware or assembler implementation is available. This may be of
> > particular interest for smaller systems. So, for smaller systems (where
> > kernel bloat is bad, but where now these days more and more hardware
> > crypto support is added), we must weigh the kernel bloat (of 3 or 4
> > additional C files for the basic kernel crypto API logic) against
> > relieving the CPU of work.
> 
> There are a number of caveats with using hardware acceleration; one is
> that many hardware accelerators are optimized for bulk data
> encryption, and so key scheduling, or switching between key schedules,
> can have a higher overhead that a pure software implementation.

As a followup: I tweaked the DRBG side a bit to use the full speed of the AES-
NI implementation. With that tweak, the initial finding does not apply any 
more.

I depending on the request size, I now get more than 800 MB/s (increase by 
more than 450% compared to the initial implementation) from the AES-NI 
implementation. Hence, the frequent key schedule update seems to be not too 
much of an issue.

Ciao
Stephan

^ permalink raw reply

* Re: [PATCH v5 1/3] crypto: Key-agreement Protocol Primitives API (KPP)
From: Salvatore Benedetto @ 2016-06-08 11:45 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto
In-Reply-To: <20160608025451.GB12283@gondor.apana.org.au>

On Wed, Jun 08, 2016 at 10:54:51AM +0800, Herbert Xu wrote:
> On Thu, Jun 02, 2016 at 12:06:48PM +0000, Benedetto, Salvatore wrote:
> >
> > Off the top of my head, with ECDH when the user gets a EGAIN, he wants
> > to reset the secret key only, not the params.
> 
> I don't see any performance benefit in changing one and not the
> other.  Besides, you could always check the params in the algo
> and only update if necessary.
>

I'm OK with merging set_params and set_key and allow the user to
pass either both, or only the key in which case params previously
set are reused, although I don't see any particular benefit with this.

> > > >  * generate_public_key() - It generates the public key to be sent to
> > > >    the other counterpart involved in the key-agreement session. The
> > > >    function has to be called after set_params() and set_secret()
> > > >  * generate_secret() - It generates the shared secret for the session
> > > 
> > > Ditto, we only need one operation and that is multiplication by the secret.
> > 
> > Sorry, but I don't understand your point.
> > We do always need one math operation with different params.
> 
> Look at your actual implementations of DH and ECDH, they are the
> same except for the multiplicand, which is fixed to G for the
> public key.
> 
> Now you could argue that having to reparse G every time could be
> bad for performance, but that's easily fixed by making the case
> of a zero-length input value an implicit request to use G.
> 
> Even better, just drop G from the params and you won't need to
> reparse it or do anything special.
> 
> The point of all this is to make the lives of future driver authors
> simpler, the less they have to do the less that could go wrong.

I really would like to keep the interface as it is because it's
very clear what each function does. I'm OK with remapping both
function to the same one, and if src is zero, g/G will be used.

Keep in mind that while for DH g is always provided by the user,
for ECDH G is a public value which we already have and I don't see
why the user should pass that.

Having said that, are you OK with as far as the interface goes
to only merge set_param and set_key, and keeping the rest as it is?
For the implementation of DH and ECDH I'll merge the two operations
functions into one as you suggested. If so, I'll send a new version.

Thanks for your inputs.

Regards,
Salvatore

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

^ permalink raw reply

* RE: [PATCH v3] crypto: rsa - return raw integers for the ASN.1 parser
From: Tudor-Dan Ambarus @ 2016-06-08 10:20 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: herbert@gondor.apana.org.au, linux-crypto@vger.kernel.org
In-Reply-To: <4389374.qHp8yZtTYB@tauon.atsec.com>

Hi Stephan,

> >  int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> >  	      const void *value, size_t vlen)
> >  {
> >  	struct rsa_key *key = context;
> > +	const u8 *ptr = value;
> > +	int ret;
> >
> > -	key->n = mpi_read_raw_data(value, vlen);
> > +	while (!*ptr && vlen) {
> > +		ptr++;
> > +		vlen--;
> > +	}
> 
> As you do this operation 3 times, isn't an inline better here?

Actually this operation makes sense only for n to determine its length.
I will remove the while from rsa_get_e/d. 

> 
> >
> > -	if (!key->n)
> > -		return -ENOMEM;
> > +	/* invalid key provided */
> > +	if (!ptr)
> > +		return -EINVAL;
> 
> Hm, you check the pointer here, but you dereference it already above. So, I
> guess you want to move that check to the beginning of the function?

Sure. Thank you for reviewing!
ta

^ permalink raw reply

* Re: [RFC] DRBG: which shall be default?
From: Stephan Mueller @ 2016-06-08  9:32 UTC (permalink / raw)
  To: tadeusz.struk; +Cc: Herbert Xu, linux-crypto
In-Reply-To: <20160608091500.GA14329@gondor.apana.org.au>

Am Mittwoch, 8. Juni 2016, 17:15:00 schrieb Herbert Xu:

Hi Herbert, Tadeusz,

> On Wed, Jun 08, 2016 at 11:07:42AM +0200, Stephan Mueller wrote:
> > No, it does not:
> > 
> > #ifdef CONFIG_X86_64
> 
> Well there is no fundamental reason why we can't do it on 32-bit.
> Even if we just did the counter increment in C this would still
> beat ctr(aes-aesni) by many orders of magnitude.

I would think that the performance boost on 64 bit should warrant an official 
patch set.
> 
> So if you really care about the performance on x86-32 then perhaps
> you should send a patch to implement ctr-aes-aesni for it.

Maybe Intel can shed some light on this:

Tadeusz, can you please help me understand why the ctr-aes-aesni is only 
defined for 64 bit?

Thanks
Stephan

^ permalink raw reply

* Re: [RFC] DRBG: which shall be default?
From: Herbert Xu @ 2016-06-08  9:15 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: linux-crypto
In-Reply-To: <2066130.uIxle5Vnoa@tauon.atsec.com>

On Wed, Jun 08, 2016 at 11:07:42AM +0200, Stephan Mueller wrote:
>
> No, it does not:
> 
> #ifdef CONFIG_X86_64

Well there is no fundamental reason why we can't do it on 32-bit.
Even if we just did the counter increment in C this would still
beat ctr(aes-aesni) by many orders of magnitude.

So if you really care about the performance on x86-32 then perhaps
you should send a patch to implement ctr-aes-aesni for it.

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

^ permalink raw reply

* Re: [RFC] DRBG: which shall be default?
From: Stephan Mueller @ 2016-06-08  9:07 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto
In-Reply-To: <20160608090354.GA14241@gondor.apana.org.au>

Am Mittwoch, 8. Juni 2016, 17:03:54 schrieb Herbert Xu:

Hi Herbert,

> On Wed, Jun 08, 2016 at 10:58:37AM +0200, Stephan Mueller wrote:
> > Indeed, I used ctr(aes-aesni) instead of ctr-aes-aesni according to the
> > refcnt in /proc/crypto. The reason was that I used the sync skcipher API
> > which naturally excludes the ctr-aes-aesni.
> > 
> > When changing it to really use ctr-aes-aesni, I get: between 450%
> > performance gains (for 4096 bytes -- 780 MB/s(!)) and 4% gain (for 16
> > bytes).
> > 
> > Though, on 32 bit with ctr(aes-aesni) -- which is a blkcipher -- I get a
> > performance degradation of 10% (4096 bytes) and 20% (16 bytes).
> > 
> > Any ideas on how to handle the blkcipher in a better way?
> 
> You should always use ctr-aes-aesni, ctr(aes-aesni) makes no sense.
> 
> So I don't quite understand why you need to handle blkcipher, does
> ctr-aes-aesni not work on 32-bit?

No, it does not:

#ifdef CONFIG_X86_64
}, {
        .cra_name               = "__ctr-aes-aesni",
        .cra_driver_name        = "__driver-ctr-aes-aesni",
...
}, {
        .cra_name               = "ctr(aes)",
        .cra_driver_name        = "ctr-aes-aesni",


==> ctr-aes-aesni is not available in 32 bit. Only aes-aesni is available in 
32 bit so the system defaults to ctr(aes-aesni).

Note, in my tests I use a generic code that requests ctr(aes). I am not arch-
specific in the code. The discussion above is the analysis of the kernel 
crypto API's decisions.

Ciao
Stephan

^ permalink raw reply

* Re: [RFC] DRBG: which shall be default?
From: Herbert Xu @ 2016-06-08  9:03 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: linux-crypto
In-Reply-To: <16106560.DqOinPzzUs@positron.chronox.de>

On Wed, Jun 08, 2016 at 10:58:37AM +0200, Stephan Mueller wrote:
>
> Indeed, I used ctr(aes-aesni) instead of ctr-aes-aesni according to the refcnt 
> in /proc/crypto. The reason was that I used the sync skcipher API which 
> naturally excludes the ctr-aes-aesni.
> 
> When changing it to really use ctr-aes-aesni, I get: between 450% performance 
> gains (for 4096 bytes -- 780 MB/s(!)) and 4% gain (for 16 bytes).
> 
> Though, on 32 bit with ctr(aes-aesni) -- which is a blkcipher -- I get a 
> performance degradation of 10% (4096 bytes) and 20% (16 bytes).
> 
> Any ideas on how to handle the blkcipher in a better way?

You should always use ctr-aes-aesni, ctr(aes-aesni) makes no sense.

So I don't quite understand why you need to handle blkcipher, does
ctr-aes-aesni not work on 32-bit?

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

^ permalink raw reply

* Re: [RFC] DRBG: which shall be default?
From: Stephan Mueller @ 2016-06-08  8:58 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto
In-Reply-To: <20160608080055.GA13686@gondor.apana.org.au>

Am Mittwoch, 8. Juni 2016, 16:00:55 schrieb Herbert Xu:

Hi Herbert,

> On Wed, Jun 08, 2016 at 09:56:42AM +0200, Stephan Mueller wrote:
> > The performance with ctr-aes-aesni on 64 bit is as follows -- I used my
> > LRNG implementation for testing for which I already have performance
> > measurements:
> > 
> > - generating smaller lengths (I tested up to 128 bytes) of random numbers
> > (which is the vast majority of random numbers to be generated), the
> > performance is even worse by 10 to 15%
> > 
> > - generating larger lengths (tested with 4096 bytes) of random numbers,
> > the
> > performance increases by 3%
> > 
> > Using ctr(aes-aesni) on 32 bit, the numbers are generally worse by 5 to
> > 10%.
> ctr(aes-aesni) is not the same thing as ctr-aes-aesni, the former
> being just another way of doing what you were doing.  So did you
> actually test the real optimised version which is ctr-aes-aesni?

Indeed, I used ctr(aes-aesni) instead of ctr-aes-aesni according to the refcnt 
in /proc/crypto. The reason was that I used the sync skcipher API which 
naturally excludes the ctr-aes-aesni.

When changing it to really use ctr-aes-aesni, I get: between 450% performance 
gains (for 4096 bytes -- 780 MB/s(!)) and 4% gain (for 16 bytes).

Though, on 32 bit with ctr(aes-aesni) -- which is a blkcipher -- I get a 
performance degradation of 10% (4096 bytes) and 20% (16 bytes).

Any ideas on how to handle the blkcipher in a better way?

Ciao
Stephan

^ permalink raw reply

* Re: [PATCH v2 0/7] crypto: talitos - implementation of AEAD for SEC1
From: Herbert Xu @ 2016-06-08  8:29 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Kim Phillips, David S Miller, linux-kernel, linuxppc-dev,
	linux-crypto
In-Reply-To: <cover.1464390094.git.christophe.leroy@c-s.fr>

On Mon, Jun 06, 2016 at 01:20:31PM +0200, Christophe Leroy wrote:
> This set of patches provides the implementation of AEAD for
> talitos SEC1.

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH v6 7/8] crypto: acomp - add support for deflate via scomp
From: Giovanni Cabiddu @ 2016-06-08  8:16 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>

This patch implements an scomp backend for the deflate compression
algorithm. This way, deflate is exposed through the acomp api.

Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
 crypto/Kconfig   |    1 +
 crypto/deflate.c |  111 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 102 insertions(+), 10 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 09c88ba..b617c5d 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1502,6 +1502,7 @@ comment "Compression"
 config CRYPTO_DEFLATE
 	tristate "Deflate compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select ZLIB_INFLATE
 	select ZLIB_DEFLATE
 	help
diff --git a/crypto/deflate.c b/crypto/deflate.c
index 95d8d37..f942cb3 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/net.h>
+#include <crypto/internal/scompress.h>
 
 #define DEFLATE_DEF_LEVEL		Z_DEFAULT_COMPRESSION
 #define DEFLATE_DEF_WINBITS		11
@@ -101,9 +102,8 @@ static void deflate_decomp_exit(struct deflate_ctx *ctx)
 	vfree(ctx->decomp_stream.workspace);
 }
 
-static int deflate_init(struct crypto_tfm *tfm)
+static int __deflate_init(void *ctx)
 {
-	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
 	int ret;
 
 	ret = deflate_comp_init(ctx);
@@ -116,19 +116,55 @@ out:
 	return ret;
 }
 
-static void deflate_exit(struct crypto_tfm *tfm)
+static void *deflate_alloc_ctx(struct crypto_scomp *tfm)
+{
+	struct deflate_ctx *ctx;
+	int ret;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	ret = __deflate_init(ctx);
+	if (ret) {
+		kfree(ctx);
+		return ERR_PTR(ret);
+	}
+
+	return ctx;
+}
+
+static int deflate_init(struct crypto_tfm *tfm)
 {
 	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
 
+	return __deflate_init(ctx);
+}
+
+static void __deflate_exit(void *ctx)
+{
 	deflate_comp_exit(ctx);
 	deflate_decomp_exit(ctx);
 }
 
-static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
-			    unsigned int slen, u8 *dst, unsigned int *dlen)
+static void deflate_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	__deflate_exit(ctx);
+	kzfree(ctx);
+}
+
+static void deflate_exit(struct crypto_tfm *tfm)
+{
+	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	__deflate_exit(ctx);
+}
+
+static int __deflate_compress(const u8 *src, unsigned int slen,
+			      u8 *dst, unsigned int *dlen, void *ctx)
 {
 	int ret = 0;
-	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+	struct deflate_ctx *dctx = ctx;
 	struct z_stream_s *stream = &dctx->comp_stream;
 
 	ret = zlib_deflateReset(stream);
@@ -153,12 +189,27 @@ out:
 	return ret;
 }
 
-static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
-			      unsigned int slen, u8 *dst, unsigned int *dlen)
+static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
+			    unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+
+	return __deflate_compress(src, slen, dst, dlen, dctx);
+}
+
+static int deflate_scompress(struct crypto_scomp *tfm, const u8 *src,
+			     unsigned int slen, u8 *dst, unsigned int *dlen,
+			     void *ctx)
+{
+	return __deflate_compress(src, slen, dst, dlen, ctx);
+}
+
+static int __deflate_decompress(const u8 *src, unsigned int slen,
+				u8 *dst, unsigned int *dlen, void *ctx)
 {
 
 	int ret = 0;
-	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+	struct deflate_ctx *dctx = ctx;
 	struct z_stream_s *stream = &dctx->decomp_stream;
 
 	ret = zlib_inflateReset(stream);
@@ -194,6 +245,21 @@ out:
 	return ret;
 }
 
+static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+
+	return __deflate_decompress(src, slen, dst, dlen, dctx);
+}
+
+static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+			       unsigned int slen, u8 *dst, unsigned int *dlen,
+			       void *ctx)
+{
+	return __deflate_decompress(src, slen, dst, dlen, ctx);
+}
+
 static struct crypto_alg alg = {
 	.cra_name		= "deflate",
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
@@ -206,14 +272,39 @@ static struct crypto_alg alg = {
 	.coa_decompress  	= deflate_decompress } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= deflate_alloc_ctx,
+	.free_ctx		= deflate_free_ctx,
+	.compress		= deflate_scompress,
+	.decompress		= deflate_sdecompress,
+	.base			= {
+		.cra_name	= "deflate",
+		.cra_driver_name = "deflate-scomp",
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init deflate_mod_init(void)
 {
-	return crypto_register_alg(&alg);
+	int ret;
+
+	ret = crypto_register_alg(&alg);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg);
+		return ret;
+	}
+
+	return ret;
 }
 
 static void __exit deflate_mod_fini(void)
 {
 	crypto_unregister_alg(&alg);
+	crypto_unregister_scomp(&scomp);
 }
 
 module_init(deflate_mod_init);
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v6 8/8] crypto: acomp - update testmgr with support for acomp
From: Giovanni Cabiddu @ 2016-06-08  8:16 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>

This patch adds tests to the test manager for algorithms exposed through
the acomp api

Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
 crypto/testmgr.c |  158 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 145 insertions(+), 13 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index c727fb0..fc47716 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -32,6 +32,7 @@
 #include <crypto/rng.h>
 #include <crypto/drbg.h>
 #include <crypto/akcipher.h>
+#include <crypto/acompress.h>
 
 #include "internal.h"
 
@@ -1423,6 +1424,121 @@ out:
 	return ret;
 }
 
+static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
+		      struct comp_testvec *dtemplate, int ctcount, int dtcount)
+{
+	const char *algo = crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
+	unsigned int i;
+	char output[COMP_BUF_SIZE];
+	int ret;
+	struct scatterlist src, dst;
+	struct acomp_req *req;
+	struct tcrypt_result result;
+
+	for (i = 0; i < ctcount; i++) {
+		unsigned int dlen = COMP_BUF_SIZE;
+		int ilen = ctemplate[i].inlen;
+
+		memset(output, 0, sizeof(output));
+		init_completion(&result.completion);
+		sg_init_one(&src, ctemplate[i].input, ilen);
+		sg_init_one(&dst, output, dlen);
+
+		req = acomp_request_alloc(tfm);
+		if (!req) {
+			pr_err("alg: acomp: request alloc failed for %s\n",
+			       algo);
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		acomp_request_set_params(req, &src, &dst, ilen, dlen);
+		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					   tcrypt_complete, &result);
+
+		ret = wait_async_op(&result, crypto_acomp_compress(req));
+		if (ret) {
+			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
+			       i + 1, algo, -ret);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (req->dlen != ctemplate[i].outlen) {
+			pr_err("alg: acomp: Compression test %d failed for %s: output len = %d\n",
+			       i + 1, algo, req->dlen);
+			ret = -EINVAL;
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (memcmp(output, ctemplate[i].output, req->dlen)) {
+			pr_err("alg: acomp: Compression test %d failed for %s\n",
+			       i + 1, algo);
+			hexdump(output, req->dlen);
+			ret = -EINVAL;
+			acomp_request_free(req);
+			goto out;
+		}
+
+		acomp_request_free(req);
+	}
+
+	for (i = 0; i < dtcount; i++) {
+		unsigned int dlen = COMP_BUF_SIZE;
+		int ilen = dtemplate[i].inlen;
+
+		memset(output, 0, sizeof(output));
+		init_completion(&result.completion);
+		sg_init_one(&src, dtemplate[i].input, ilen);
+		sg_init_one(&dst, output, dlen);
+
+		req = acomp_request_alloc(tfm);
+		if (!req) {
+			pr_err("alg: acomp: request alloc failed for %s\n",
+			       algo);
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		acomp_request_set_params(req, &src, &dst, ilen, dlen);
+		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					   tcrypt_complete, &result);
+
+		ret = wait_async_op(&result, crypto_acomp_decompress(req));
+		if (ret) {
+			pr_err("alg: acomp: decompression failed on test %d for %s: ret=%d\n",
+			       i + 1, algo, -ret);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (req->dlen != dtemplate[i].outlen) {
+			pr_err("alg: acomp: Decompression test %d failed for %s: output len = %d\n",
+			       i + 1, algo, req->dlen);
+			ret = -EINVAL;
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (memcmp(output, dtemplate[i].output, req->dlen)) {
+			pr_err("alg: acomp: Decompression test %d failed for %s\n",
+			       i + 1, algo);
+			hexdump(output, req->dlen);
+			ret = -EINVAL;
+			acomp_request_free(req);
+			goto out;
+		}
+
+		acomp_request_free(req);
+	}
+
+	ret = 0;
+
+out:
+	return ret;
+}
+
 static int test_cprng(struct crypto_rng *tfm, struct cprng_testvec *template,
 		      unsigned int tcount)
 {
@@ -1574,22 +1690,38 @@ out:
 static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
-	struct crypto_comp *tfm;
+	struct crypto_comp *comp;
+	struct crypto_acomp *acomp;
 	int err;
+	u32 algo_type = type & CRYPTO_ALG_TYPE_ACOMPRESS_MASK;
+
+	if (algo_type == CRYPTO_ALG_TYPE_ACOMPRESS) {
+		acomp = crypto_alloc_acomp(driver, type, mask);
+		if (IS_ERR(acomp)) {
+			pr_err("alg: acomp: Failed to load transform for %s: %ld\n",
+			       driver, PTR_ERR(acomp));
+			return PTR_ERR(acomp);
+		}
+		err = test_acomp(acomp, desc->suite.comp.comp.vecs,
+				 desc->suite.comp.decomp.vecs,
+				 desc->suite.comp.comp.count,
+				 desc->suite.comp.decomp.count);
+		crypto_free_acomp(acomp);
+	} else {
+		comp = crypto_alloc_comp(driver, type, mask);
+		if (IS_ERR(comp)) {
+			pr_err("alg: comp: Failed to load transform for %s: %ld\n",
+			       driver, PTR_ERR(comp));
+			return PTR_ERR(comp);
+		}
 
-	tfm = crypto_alloc_comp(driver, type, mask);
-	if (IS_ERR(tfm)) {
-		printk(KERN_ERR "alg: comp: Failed to load transform for %s: "
-		       "%ld\n", driver, PTR_ERR(tfm));
-		return PTR_ERR(tfm);
-	}
-
-	err = test_comp(tfm, desc->suite.comp.comp.vecs,
-			desc->suite.comp.decomp.vecs,
-			desc->suite.comp.comp.count,
-			desc->suite.comp.decomp.count);
+		err = test_comp(comp, desc->suite.comp.comp.vecs,
+				desc->suite.comp.decomp.vecs,
+				desc->suite.comp.comp.count,
+				desc->suite.comp.decomp.count);
 
-	crypto_free_comp(tfm);
+		crypto_free_comp(comp);
+	}
 	return err;
 }
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v6 6/8] crypto: acomp - add support for 842 via scomp
From: Giovanni Cabiddu @ 2016-06-08  8:16 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>

This patch implements an scomp backend for the 842 compression algorithm.
This way, 842 is exposed through the acomp api.

Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
 crypto/842.c   |   82 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 crypto/Kconfig |    1 +
 2 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/crypto/842.c b/crypto/842.c
index 98e387e..a954ed3 100644
--- a/crypto/842.c
+++ b/crypto/842.c
@@ -31,11 +31,46 @@
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <linux/sw842.h>
+#include <crypto/internal/scompress.h>
 
 struct crypto842_ctx {
-	char wmem[SW842_MEM_COMPRESS];	/* working memory for compress */
+	void *wmem;	/* working memory for compress */
 };
 
+static void *crypto842_alloc_ctx(struct crypto_scomp *tfm)
+{
+	void *ctx;
+
+	ctx = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	return ctx;
+}
+
+static int crypto842_init(struct crypto_tfm *tfm)
+{
+	struct crypto842_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->wmem = crypto842_alloc_ctx(NULL);
+	if (IS_ERR(ctx->wmem))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void crypto842_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	kfree(ctx);
+}
+
+static void crypto842_exit(struct crypto_tfm *tfm)
+{
+	struct crypto842_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto842_free_ctx(NULL, ctx->wmem);
+}
+
 static int crypto842_compress(struct crypto_tfm *tfm,
 			      const u8 *src, unsigned int slen,
 			      u8 *dst, unsigned int *dlen)
@@ -45,6 +80,13 @@ static int crypto842_compress(struct crypto_tfm *tfm,
 	return sw842_compress(src, slen, dst, dlen, ctx->wmem);
 }
 
+static int crypto842_scompress(struct crypto_scomp *tfm,
+			       const u8 *src, unsigned int slen,
+			       u8 *dst, unsigned int *dlen, void *ctx)
+{
+	return sw842_compress(src, slen, dst, dlen, ctx);
+}
+
 static int crypto842_decompress(struct crypto_tfm *tfm,
 				const u8 *src, unsigned int slen,
 				u8 *dst, unsigned int *dlen)
@@ -52,27 +94,61 @@ static int crypto842_decompress(struct crypto_tfm *tfm,
 	return sw842_decompress(src, slen, dst, dlen);
 }
 
+static int crypto842_sdecompress(struct crypto_scomp *tfm,
+				 const u8 *src, unsigned int slen,
+				 u8 *dst, unsigned int *dlen, void *ctx)
+{
+	return sw842_decompress(src, slen, dst, dlen);
+}
+
 static struct crypto_alg alg = {
 	.cra_name		= "842",
 	.cra_driver_name	= "842-generic",
 	.cra_priority		= 100,
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
-	.cra_ctxsize		= sizeof(struct crypto842_ctx),
 	.cra_module		= THIS_MODULE,
+	.cra_init		= crypto842_init,
+	.cra_exit		= crypto842_exit,
 	.cra_u			= { .compress = {
 	.coa_compress		= crypto842_compress,
 	.coa_decompress		= crypto842_decompress } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= crypto842_alloc_ctx,
+	.free_ctx		= crypto842_free_ctx,
+	.compress		= crypto842_scompress,
+	.decompress		= crypto842_sdecompress,
+	.base			= {
+		.cra_name	= "842",
+		.cra_driver_name = "842-scomp",
+		.cra_priority	 = 100,
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init crypto842_mod_init(void)
 {
-	return crypto_register_alg(&alg);
+	int ret;
+
+	ret = crypto_register_alg(&alg);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg);
+		return ret;
+	}
+
+	return ret;
 }
 module_init(crypto842_mod_init);
 
 static void __exit crypto842_mod_exit(void)
 {
 	crypto_unregister_alg(&alg);
+	crypto_unregister_scomp(&scomp);
 }
 module_exit(crypto842_mod_exit);
 
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 59570da..09c88ba 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1522,6 +1522,7 @@ config CRYPTO_LZO
 config CRYPTO_842
 	tristate "842 compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select 842_COMPRESS
 	select 842_DECOMPRESS
 	help
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v6 5/8] crypto: acomp - add support for lz4hc via scomp
From: Giovanni Cabiddu @ 2016-06-08  8:16 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>

This patch implements an scomp backend for the lz4hc compression algorithm.
This way, lz4hc is exposed through the acomp api.

Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
 crypto/Kconfig |    1 +
 crypto/lz4hc.c |   92 +++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 114d43b..59570da 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1539,6 +1539,7 @@ config CRYPTO_LZ4
 config CRYPTO_LZ4HC
 	tristate "LZ4HC compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select LZ4HC_COMPRESS
 	select LZ4_DECOMPRESS
 	help
diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c
index a1d3b5b..75ffc4a 100644
--- a/crypto/lz4hc.c
+++ b/crypto/lz4hc.c
@@ -22,37 +22,53 @@
 #include <linux/crypto.h>
 #include <linux/vmalloc.h>
 #include <linux/lz4.h>
+#include <crypto/internal/scompress.h>
 
 struct lz4hc_ctx {
 	void *lz4hc_comp_mem;
 };
 
+static void *lz4hc_alloc_ctx(struct crypto_scomp *tfm)
+{
+	void *ctx;
+
+	ctx = vmalloc(LZ4HC_MEM_COMPRESS);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	return ctx;
+}
+
 static int lz4hc_init(struct crypto_tfm *tfm)
 {
 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	ctx->lz4hc_comp_mem = vmalloc(LZ4HC_MEM_COMPRESS);
-	if (!ctx->lz4hc_comp_mem)
+	ctx->lz4hc_comp_mem = lz4hc_alloc_ctx(NULL);
+	if (IS_ERR(ctx->lz4hc_comp_mem))
 		return -ENOMEM;
 
 	return 0;
 }
 
+static void lz4hc_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	vfree(ctx);
+}
+
 static void lz4hc_exit(struct crypto_tfm *tfm)
 {
 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	vfree(ctx->lz4hc_comp_mem);
+	lz4hc_free_ctx(NULL, ctx->lz4hc_comp_mem);
 }
 
-static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			    unsigned int slen, u8 *dst, unsigned int *dlen)
+static int __lz4hc_compress_crypto(const u8 *src, unsigned int slen,
+				   u8 *dst, unsigned int *dlen, void *ctx)
 {
-	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
 	size_t tmp_len = *dlen;
 	int err;
 
-	err = lz4hc_compress(src, slen, dst, &tmp_len, ctx->lz4hc_comp_mem);
+	err = lz4hc_compress(src, slen, dst, &tmp_len, ctx);
 
 	if (err < 0)
 		return -EINVAL;
@@ -61,8 +77,25 @@ static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
 	return 0;
 }
 
-static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			      unsigned int slen, u8 *dst, unsigned int *dlen)
+static int lz4hc_scompress(struct crypto_scomp *tfm, const u8 *src,
+			   unsigned int slen, u8 *dst, unsigned int *dlen,
+			   void *ctx)
+{
+	return __lz4hc_compress_crypto(src, slen, dst, dlen, ctx);
+}
+
+static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+				 unsigned int slen, u8 *dst,
+				 unsigned int *dlen)
+{
+	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	return __lz4hc_compress_crypto(src, slen, dst, dlen,
+					ctx->lz4hc_comp_mem);
+}
+
+static int __lz4hc_decompress_crypto(const u8 *src, unsigned int slen,
+				     u8 *dst, unsigned int *dlen, void *ctx)
 {
 	int err;
 	size_t tmp_len = *dlen;
@@ -76,6 +109,20 @@ static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
 	return err;
 }
 
+static int lz4hc_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+			     unsigned int slen, u8 *dst, unsigned int *dlen,
+			     void *ctx)
+{
+	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
+static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+				   unsigned int slen, u8 *dst,
+				   unsigned int *dlen)
+{
+	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
 static struct crypto_alg alg_lz4hc = {
 	.cra_name		= "lz4hc",
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
@@ -89,14 +136,39 @@ static struct crypto_alg alg_lz4hc = {
 	.coa_decompress		= lz4hc_decompress_crypto } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= lz4hc_alloc_ctx,
+	.free_ctx		= lz4hc_free_ctx,
+	.compress		= lz4hc_scompress,
+	.decompress		= lz4hc_sdecompress,
+	.base			= {
+		.cra_name	= "lz4hc",
+		.cra_driver_name = "lz4hc-scomp",
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init lz4hc_mod_init(void)
 {
-	return crypto_register_alg(&alg_lz4hc);
+	int ret;
+
+	ret = crypto_register_alg(&alg_lz4hc);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg_lz4hc);
+		return ret;
+	}
+
+	return ret;
 }
 
 static void __exit lz4hc_mod_fini(void)
 {
 	crypto_unregister_alg(&alg_lz4hc);
+	crypto_unregister_scomp(&scomp);
 }
 
 module_init(lz4hc_mod_init);
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v6 4/8] crypto: acomp - add support for lz4 via scomp
From: Giovanni Cabiddu @ 2016-06-08  8:16 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>

This patch implements an scomp backend for the lz4 compression algorithm.
This way, lz4 is exposed through the acomp api.

Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
 crypto/Kconfig |    1 +
 crypto/lz4.c   |   91 +++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 08075c1..114d43b 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1530,6 +1530,7 @@ config CRYPTO_842
 config CRYPTO_LZ4
 	tristate "LZ4 compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select LZ4_COMPRESS
 	select LZ4_DECOMPRESS
 	help
diff --git a/crypto/lz4.c b/crypto/lz4.c
index aefbcea..99c1b2c 100644
--- a/crypto/lz4.c
+++ b/crypto/lz4.c
@@ -23,36 +23,53 @@
 #include <linux/crypto.h>
 #include <linux/vmalloc.h>
 #include <linux/lz4.h>
+#include <crypto/internal/scompress.h>
 
 struct lz4_ctx {
 	void *lz4_comp_mem;
 };
 
+static void *lz4_alloc_ctx(struct crypto_scomp *tfm)
+{
+	void *ctx;
+
+	ctx = vmalloc(LZ4_MEM_COMPRESS);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	return ctx;
+}
+
 static int lz4_init(struct crypto_tfm *tfm)
 {
 	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	ctx->lz4_comp_mem = vmalloc(LZ4_MEM_COMPRESS);
-	if (!ctx->lz4_comp_mem)
+	ctx->lz4_comp_mem = lz4_alloc_ctx(NULL);
+	if (IS_ERR(ctx->lz4_comp_mem))
 		return -ENOMEM;
 
 	return 0;
 }
 
+static void lz4_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	vfree(ctx);
+}
+
 static void lz4_exit(struct crypto_tfm *tfm)
 {
 	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
-	vfree(ctx->lz4_comp_mem);
+
+	lz4_free_ctx(NULL, ctx->lz4_comp_mem);
 }
 
-static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			    unsigned int slen, u8 *dst, unsigned int *dlen)
+static int __lz4_compress_crypto(const u8 *src, unsigned int slen,
+				 u8 *dst, unsigned int *dlen, void *ctx)
 {
-	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
 	size_t tmp_len = *dlen;
 	int err;
 
-	err = lz4_compress(src, slen, dst, &tmp_len, ctx->lz4_comp_mem);
+	err = lz4_compress(src, slen, dst, &tmp_len, ctx);
 
 	if (err < 0)
 		return -EINVAL;
@@ -61,8 +78,23 @@ static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
 	return 0;
 }
 
-static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			      unsigned int slen, u8 *dst, unsigned int *dlen)
+static int lz4_scompress(struct crypto_scomp *tfm, const u8 *src,
+			 unsigned int slen, u8 *dst, unsigned int *dlen,
+			 void *ctx)
+{
+	return __lz4_compress_crypto(src, slen, dst, dlen, ctx);
+}
+
+static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+			       unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	return __lz4_compress_crypto(src, slen, dst, dlen, ctx->lz4_comp_mem);
+}
+
+static int __lz4_decompress_crypto(const u8 *src, unsigned int slen,
+				   u8 *dst, unsigned int *dlen, void *ctx)
 {
 	int err;
 	size_t tmp_len = *dlen;
@@ -76,6 +108,20 @@ static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
 	return err;
 }
 
+static int lz4_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+			   unsigned int slen, u8 *dst, unsigned int *dlen,
+			   void *ctx)
+{
+	return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
+static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+				 unsigned int slen, u8 *dst,
+				 unsigned int *dlen)
+{
+	return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
 static struct crypto_alg alg_lz4 = {
 	.cra_name		= "lz4",
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
@@ -89,14 +135,39 @@ static struct crypto_alg alg_lz4 = {
 	.coa_decompress		= lz4_decompress_crypto } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= lz4_alloc_ctx,
+	.free_ctx		= lz4_free_ctx,
+	.compress		= lz4_scompress,
+	.decompress		= lz4_sdecompress,
+	.base			= {
+		.cra_name	= "lz4",
+		.cra_driver_name = "lz4-scomp",
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init lz4_mod_init(void)
 {
-	return crypto_register_alg(&alg_lz4);
+	int ret;
+
+	ret = crypto_register_alg(&alg_lz4);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg_lz4);
+		return ret;
+	}
+
+	return ret;
 }
 
 static void __exit lz4_mod_fini(void)
 {
 	crypto_unregister_alg(&alg_lz4);
+	crypto_unregister_scomp(&scomp);
 }
 
 module_init(lz4_mod_init);
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v6 2/8] crypto: add driver-side scomp interface
From: Giovanni Cabiddu @ 2016-06-08  8:16 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>

Add a synchronous back-end (scomp) to acomp. This allows to easily expose
the already present compression algorithms in LKCF via acomp

Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
 crypto/Makefile                     |    1 +
 crypto/acompress.c                  |   49 +++++++-
 crypto/scompress.c                  |  252 +++++++++++++++++++++++++++++++++++
 include/crypto/acompress.h          |   32 ++---
 include/crypto/internal/acompress.h |   15 ++
 include/crypto/internal/scompress.h |  134 +++++++++++++++++++
 include/linux/crypto.h              |    2 +
 7 files changed, 463 insertions(+), 22 deletions(-)
 create mode 100644 crypto/scompress.c
 create mode 100644 include/crypto/internal/scompress.h

diff --git a/crypto/Makefile b/crypto/Makefile
index e817b38..fc8fcfe 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 
 obj-$(CONFIG_CRYPTO_ACOMP2) += acompress.o
+obj-$(CONFIG_CRYPTO_ACOMP2) += scompress.o
 
 $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
 $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
diff --git a/crypto/acompress.c b/crypto/acompress.c
index f24fef3..a5e6cf1 100644
--- a/crypto/acompress.c
+++ b/crypto/acompress.c
@@ -22,8 +22,11 @@
 #include <linux/cryptouser.h>
 #include <net/netlink.h>
 #include <crypto/internal/acompress.h>
+#include <crypto/internal/scompress.h>
 #include "internal.h"
 
+static const struct crypto_type crypto_acomp_type;
+
 #ifdef CONFIG_NET
 static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
@@ -67,6 +70,13 @@ static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
 	struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
 	struct acomp_alg *alg = crypto_acomp_alg(acomp);
 
+	if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
+		return crypto_init_scomp_ops_async(tfm);
+
+	acomp->compress = alg->compress;
+	acomp->decompress = alg->decompress;
+	acomp->reqsize = alg->reqsize;
+
 	if (alg->exit)
 		acomp->base.exit = crypto_acomp_exit_tfm;
 
@@ -76,15 +86,25 @@ static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
 	return 0;
 }
 
+unsigned int crypto_acomp_extsize(struct crypto_alg *alg)
+{
+	int extsize = crypto_alg_extsize(alg);
+
+	if (alg->cra_type != &crypto_acomp_type)
+		extsize += sizeof(struct crypto_scomp *);
+
+	return extsize;
+}
+
 static const struct crypto_type crypto_acomp_type = {
-	.extsize = crypto_alg_extsize,
+	.extsize = crypto_acomp_extsize,
 	.init_tfm = crypto_acomp_init_tfm,
 #ifdef CONFIG_PROC_FS
 	.show = crypto_acomp_show,
 #endif
 	.report = crypto_acomp_report,
 	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
-	.maskset = CRYPTO_ALG_TYPE_MASK,
+	.maskset = CRYPTO_ALG_TYPE_ACOMPRESS_MASK,
 	.type = CRYPTO_ALG_TYPE_ACOMPRESS,
 	.tfmsize = offsetof(struct crypto_acomp, base),
 };
@@ -96,6 +116,31 @@ struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type,
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_acomp);
 
+struct acomp_req *acomp_request_alloc(struct crypto_acomp *acomp)
+{
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+	struct acomp_req *req;
+
+	req = __acomp_request_alloc(acomp);
+	if (req && (tfm->__crt_alg->cra_type != &crypto_acomp_type))
+		return crypto_acomp_scomp_alloc_ctx(req);
+
+	return req;
+}
+EXPORT_SYMBOL_GPL(acomp_request_alloc);
+
+void acomp_request_free(struct acomp_req *req)
+{
+	struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+
+	if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
+		crypto_acomp_scomp_free_ctx(req);
+
+	__acomp_request_free(req);
+}
+EXPORT_SYMBOL_GPL(acomp_request_free);
+
 int crypto_register_acomp(struct acomp_alg *alg)
 {
 	struct crypto_alg *base = &alg->base;
diff --git a/crypto/scompress.c b/crypto/scompress.c
new file mode 100644
index 0000000..850b427
--- /dev/null
+++ b/crypto/scompress.c
@@ -0,0 +1,252 @@
+/*
+ * Synchronous Compression operations
+ *
+ * Copyright 2015 LG Electronics Inc.
+ * Copyright (c) 2016, Intel Corporation
+ * Author: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/internal/acompress.h>
+#include <crypto/internal/scompress.h>
+#include "internal.h"
+
+static const struct crypto_type crypto_scomp_type;
+
+#ifdef CONFIG_NET
+static int crypto_scomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rscomp;
+
+	strncpy(rscomp.type, "scomp", sizeof(rscomp.type));
+
+	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		    sizeof(struct crypto_report_comp), &rscomp))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_scomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
+static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
+	__attribute__ ((unused));
+
+static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
+{
+	seq_puts(m, "type         : scomp\n");
+}
+
+static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static void *scomp_map(struct scatterlist *sg, unsigned int len,
+		       gfp_t gfp_flags)
+{
+	void *buf;
+
+	if (sg_is_last(sg))
+		return kmap_atomic(sg_page(sg)) + sg->offset;
+
+	buf = kmalloc(len, gfp_flags);
+	if (!buf)
+		return NULL;
+
+	scatterwalk_map_and_copy(buf, sg, 0, len, 0);
+
+	return buf;
+}
+
+static void scomp_unmap(struct scatterlist *sg, void *buf, unsigned int len)
+{
+	if (!buf)
+		return;
+
+	if (sg_is_last(sg)) {
+		kunmap_atomic(buf);
+		return;
+	}
+
+	scatterwalk_map_and_copy(buf, sg, 0, len, 1);
+	kfree(buf);
+}
+
+static int scomp_acomp_comp_decomp(struct acomp_req *req, int comp_dir)
+{
+	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+	void **tfm_ctx = acomp_tfm_ctx(tfm);
+	struct crypto_scomp *scomp = *tfm_ctx;
+	gfp_t gfp_flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+			  GFP_KERNEL : GFP_ATOMIC;
+	void **ctx = acomp_request_ctx(req);
+	unsigned int slen = req->slen;
+	unsigned int dlen = req->dlen;
+	u8 *src;
+	u8 *dst;
+	int ret;
+
+	src = scomp_map(req->src, slen, gfp_flags);
+	if (!src) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	dst = scomp_map(req->dst, dlen, gfp_flags);
+	if (!dst) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (comp_dir)
+		ret = crypto_scomp_compress(scomp, src, slen, dst, &dlen,
+					    *ctx);
+	else
+		ret = crypto_scomp_decompress(scomp, src, slen, dst, &dlen,
+					      *ctx);
+
+	req->dlen = dlen;
+
+out:
+	scomp_unmap(req->src, src, 0);
+	scomp_unmap(req->dst, dst, (ret < 0) ? 0 : dlen);
+
+	return ret;
+}
+
+static int scomp_acomp_compress(struct acomp_req *req)
+{
+	return scomp_acomp_comp_decomp(req, 1);
+}
+
+static int scomp_acomp_decompress(struct acomp_req *req)
+{
+	return scomp_acomp_comp_decomp(req, 0);
+}
+
+static void crypto_exit_scomp_ops_async(struct crypto_tfm *tfm)
+{
+	struct crypto_scomp **ctx = crypto_tfm_ctx(tfm);
+
+	crypto_free_scomp(*ctx);
+}
+
+int crypto_init_scomp_ops_async(struct crypto_tfm *tfm)
+{
+	struct crypto_alg *calg = tfm->__crt_alg;
+	struct crypto_acomp *crt = __crypto_acomp_tfm(tfm);
+	struct crypto_scomp **ctx = crypto_tfm_ctx(tfm);
+	struct crypto_scomp *scomp;
+
+	if (!crypto_mod_get(calg))
+		return -EAGAIN;
+
+	scomp = crypto_create_tfm(calg, &crypto_scomp_type);
+	if (IS_ERR(scomp)) {
+		crypto_mod_put(calg);
+		return PTR_ERR(scomp);
+	}
+
+	*ctx = scomp;
+	tfm->exit = crypto_exit_scomp_ops_async;
+
+	crt->compress = scomp_acomp_compress;
+	crt->decompress = scomp_acomp_decompress;
+	crt->reqsize = sizeof(void *);
+
+	return 0;
+}
+
+struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req)
+{
+	struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+	struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
+	struct crypto_scomp *scomp = *tfm_ctx;
+	void *ctx;
+
+	ctx = crypto_scomp_alloc_ctx(scomp);
+	if (IS_ERR(ctx)) {
+		kfree(req);
+		return NULL;
+	}
+
+	*req->__ctx = ctx;
+
+	return req;
+}
+
+void crypto_acomp_scomp_free_ctx(struct acomp_req *req)
+{
+	struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+	struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
+	struct crypto_scomp *scomp = *tfm_ctx;
+	void *ctx = *req->__ctx;
+
+	if (ctx)
+		crypto_scomp_free_ctx(scomp, ctx);
+}
+
+static const struct crypto_type crypto_scomp_type = {
+	.extsize = crypto_alg_extsize,
+	.init_tfm = crypto_scomp_init_tfm,
+#ifdef CONFIG_PROC_FS
+	.show = crypto_scomp_show,
+#endif
+	.report = crypto_scomp_report,
+	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
+	.maskset = CRYPTO_ALG_TYPE_MASK,
+	.type = CRYPTO_ALG_TYPE_SCOMPRESS,
+	.tfmsize = offsetof(struct crypto_scomp, base),
+};
+
+struct crypto_scomp *crypto_alloc_scomp(const char *alg_name, u32 type,
+					u32 mask)
+{
+	return crypto_alloc_tfm(alg_name, &crypto_scomp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_scomp);
+
+int crypto_register_scomp(struct scomp_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+
+	base->cra_type = &crypto_scomp_type;
+	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+	base->cra_flags |= CRYPTO_ALG_TYPE_SCOMPRESS;
+
+	return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_scomp);
+
+int crypto_unregister_scomp(struct scomp_alg *alg)
+{
+	return crypto_unregister_alg(&alg->base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_scomp);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Synchronous compression type");
diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h
index f4e2f96..93f938d 100644
--- a/include/crypto/acompress.h
+++ b/include/crypto/acompress.h
@@ -38,9 +38,15 @@ struct acomp_req {
  * struct crypto_acomp - user-instantiated objects which encapsulate
  * algorithms and core processing logic
  *
- * @base: Common crypto API algorithm data structure
+ * @compress:   Function performs a compress operation
+ * @decompress: Function performs a de-compress operation
+ * @reqsize:	Context size for (de)compression requests
+ * @base:	Common crypto API algorithm data structure
  */
 struct crypto_acomp {
+	int (*compress)(struct acomp_req *req);
+	int (*decompress)(struct acomp_req *req);
+	unsigned int reqsize;
 	struct crypto_tfm base;
 };
 
@@ -119,7 +125,7 @@ static inline struct acomp_alg *crypto_acomp_alg(struct crypto_acomp *tfm)
 
 static inline unsigned int crypto_acomp_reqsize(struct crypto_acomp *tfm)
 {
-	return crypto_acomp_alg(tfm)->reqsize;
+	return tfm->reqsize;
 }
 
 static inline void acomp_request_set_tfm(struct acomp_req *req,
@@ -159,26 +165,14 @@ static inline int crypto_has_acomp(const char *alg_name, u32 type, u32 mask)
  *
  * Return: allocated handle in case of success or NULL in case of an error.
  */
-static inline struct acomp_req *acomp_request_alloc(struct crypto_acomp *tfm)
-{
-	struct acomp_req *req;
-
-	req = kzalloc(sizeof(*req) + crypto_acomp_reqsize(tfm), GFP_KERNEL);
-	if (likely(req))
-		acomp_request_set_tfm(req, tfm);
-
-	return req;
-}
+struct acomp_req *acomp_request_alloc(struct crypto_acomp *tfm);
 
 /**
  * acomp_request_free() -- zeroize and free asynchronous (de)compression request
  *
  * @req: request to free
  */
-static inline void acomp_request_free(struct acomp_req *req)
-{
-	kzfree(req);
-}
+void acomp_request_free(struct acomp_req *req);
 
 /**
  * acomp_request_set_callback() -- Sets an asynchronous callback
@@ -236,9 +230,8 @@ static inline void acomp_request_set_params(struct acomp_req *req,
 static inline int crypto_acomp_compress(struct acomp_req *req)
 {
 	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
-	struct acomp_alg *alg = crypto_acomp_alg(tfm);
 
-	return alg->compress(req);
+	return tfm->compress(req);
 }
 
 /**
@@ -253,9 +246,8 @@ static inline int crypto_acomp_compress(struct acomp_req *req)
 static inline int crypto_acomp_decompress(struct acomp_req *req)
 {
 	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
-	struct acomp_alg *alg = crypto_acomp_alg(tfm);
 
-	return alg->decompress(req);
+	return tfm->decompress(req);
 }
 
 #endif
diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h
index 294f2ee..267afdd5 100644
--- a/include/crypto/internal/acompress.h
+++ b/include/crypto/internal/acompress.h
@@ -39,6 +39,21 @@ static inline const char *acomp_alg_name(struct crypto_acomp *tfm)
 	return crypto_acomp_tfm(tfm)->__crt_alg->cra_name;
 }
 
+static inline struct acomp_req *__acomp_request_alloc(struct crypto_acomp *tfm)
+{
+	struct acomp_req *req;
+
+	req = kzalloc(sizeof(*req) + crypto_acomp_reqsize(tfm), GFP_KERNEL);
+	if (likely(req))
+		acomp_request_set_tfm(req, tfm);
+	return req;
+}
+
+static inline void __acomp_request_free(struct acomp_req *req)
+{
+	kzfree(req);
+}
+
 /**
  * crypto_register_acomp() -- Register asynchronous compression algorithm
  *
diff --git a/include/crypto/internal/scompress.h b/include/crypto/internal/scompress.h
new file mode 100644
index 0000000..a88fc8d
--- /dev/null
+++ b/include/crypto/internal/scompress.h
@@ -0,0 +1,134 @@
+/*
+ * Synchronous Compression operations
+ *
+ * Copyright 2015 LG Electronics Inc.
+ * Copyright (c) 2016, Intel Corporation
+ * Author: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_SCOMP_INT_H
+#define _CRYPTO_SCOMP_INT_H
+#include <linux/crypto.h>
+
+struct crypto_scomp {
+	struct crypto_tfm base;
+};
+
+/**
+ * struct scomp_alg - synchronous compression algorithm
+ *
+ * @alloc_ctx:	Function allocates algorithm specific context
+ * @free_ctx:	Function frees context allocated with alloc_ctx
+ * @compress:	Function performs a compress operation
+ * @decompress:	Function performs a de-compress operation
+ * @init:	Initialize the cryptographic transformation object.
+ *		This function is used to initialize the cryptographic
+ *		transformation object. This function is called only once at
+ *		the instantiation time, right after the transformation context
+ *		was allocated. In case the cryptographic hardware has some
+ *		special requirements which need to be handled by software, this
+ *		function shall check for the precise requirement of the
+ *		transformation and put any software fallbacks in place.
+ * @exit:	Deinitialize the cryptographic transformation object. This is a
+ *		counterpart to @init, used to remove various changes set in
+ *		@init.
+ * @base:	Common crypto API algorithm data structure
+ */
+struct scomp_alg {
+	void *(*alloc_ctx)(struct crypto_scomp *tfm);
+	void (*free_ctx)(struct crypto_scomp *tfm, void *ctx);
+	int (*compress)(struct crypto_scomp *tfm, const u8 *src,
+			unsigned int slen, u8 *dst, unsigned int *dlen,
+			void *ctx);
+	int (*decompress)(struct crypto_scomp *tfm, const u8 *src,
+			  unsigned int slen, u8 *dst, unsigned int *dlen,
+			  void *ctx);
+	struct crypto_alg base;
+};
+
+static inline struct scomp_alg *__crypto_scomp_alg(struct crypto_alg *alg)
+{
+	return container_of(alg, struct scomp_alg, base);
+}
+
+static inline struct crypto_scomp *__crypto_scomp_tfm(struct crypto_tfm *tfm)
+{
+	return container_of(tfm, struct crypto_scomp, base);
+}
+
+static inline struct crypto_tfm *crypto_scomp_tfm(struct crypto_scomp *tfm)
+{
+	return &tfm->base;
+}
+
+static inline void crypto_free_scomp(struct crypto_scomp *tfm)
+{
+	crypto_destroy_tfm(tfm, crypto_scomp_tfm(tfm));
+}
+
+static inline struct scomp_alg *crypto_scomp_alg(struct crypto_scomp *tfm)
+{
+	return __crypto_scomp_alg(crypto_scomp_tfm(tfm)->__crt_alg);
+}
+
+static inline void *crypto_scomp_alloc_ctx(struct crypto_scomp *tfm)
+{
+	return crypto_scomp_alg(tfm)->alloc_ctx(tfm);
+}
+
+static inline void crypto_scomp_free_ctx(struct crypto_scomp *tfm,
+					 void *ctx)
+{
+	return crypto_scomp_alg(tfm)->free_ctx(tfm, ctx);
+}
+
+static inline int crypto_scomp_compress(struct crypto_scomp *tfm,
+					const u8 *src, unsigned int slen,
+					u8 *dst, unsigned int *dlen, void *ctx)
+{
+	return crypto_scomp_alg(tfm)->compress(tfm, src, slen, dst, dlen, ctx);
+}
+
+static inline int crypto_scomp_decompress(struct crypto_scomp *tfm,
+					  const u8 *src, unsigned int slen,
+					  u8 *dst, unsigned int *dlen,
+					  void *ctx)
+{
+	return crypto_scomp_alg(tfm)->decompress(tfm, src, slen, dst, dlen,
+						 ctx);
+}
+
+int crypto_init_scomp_ops_async(struct crypto_tfm *tfm);
+struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req);
+void crypto_acomp_scomp_free_ctx(struct acomp_req *req);
+
+/**
+ * crypto_register_scomp() -- Register synchronous compression algorithm
+ *
+ * Function registers an implementation of a synchronous
+ * compression algorithm
+ *
+ * @alg:	algorithm definition
+ *
+ * Return: zero on success; error code in case of error
+ */
+int crypto_register_scomp(struct scomp_alg *alg);
+
+/**
+ * crypto_unregister_scomp() -- Unregister synchronous compression algorithm
+ *
+ * Function unregisters an implementation of a synchronous
+ * compression algorithm
+ *
+ * @alg:	algorithm definition
+ *
+ * Return: zero on success; error code in case of error
+ */
+int crypto_unregister_scomp(struct scomp_alg *alg);
+
+#endif
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 7987323..23ceb0b 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -49,6 +49,7 @@
 #define CRYPTO_ALG_TYPE_ABLKCIPHER	0x00000005
 #define CRYPTO_ALG_TYPE_GIVCIPHER	0x00000006
 #define CRYPTO_ALG_TYPE_ACOMPRESS	0x00000008
+#define CRYPTO_ALG_TYPE_SCOMPRESS	0x0000000a
 #define CRYPTO_ALG_TYPE_RNG		0x0000000c
 #define CRYPTO_ALG_TYPE_AKCIPHER	0x0000000d
 #define CRYPTO_ALG_TYPE_DIGEST		0x0000000e
@@ -59,6 +60,7 @@
 #define CRYPTO_ALG_TYPE_HASH_MASK	0x0000000e
 #define CRYPTO_ALG_TYPE_AHASH_MASK	0x0000000e
 #define CRYPTO_ALG_TYPE_BLKCIPHER_MASK	0x0000000c
+#define CRYPTO_ALG_TYPE_ACOMPRESS_MASK	0x0000000c
 
 #define CRYPTO_ALG_LARVAL		0x00000010
 #define CRYPTO_ALG_DEAD			0x00000020
-- 
1.7.4.1

^ 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