2020-04-21 08:08:55

by Ondrej Mosnáček

[permalink] [raw]
Subject: libkcapi tests are failing on kernels 5.5+

Hi all,

the libkcapi [1] tests are failing on kernels 5.5-rc1 and above [2].
All encryption/decryption tests that use 'ctr(aes)' and a message size
that is not a multiple of 16 fail due to kcapi-enc returning different
output than expected.

It seems that it started with:
commit 5b0fe9552336338acb52756daf65dd7a4eeca73f
Author: Herbert Xu <[email protected]>
Date: Tue Sep 10 11:42:05 2019 +1000

crypto: algif_skcipher - Use chunksize instead of blocksize

Reverting the above commit makes the tests pass again.

Here is a one-line reproducer:
head -c 257 /dev/zero | kcapi-enc -vvv --pbkdfiter 1 -p "passwd" -s
"123" -e -c "ctr(aes)" --iv "0123456789abcdef0123456789abcdef"
>/dev/null

Output without revert:
[...]
libkcapi - Debug: AF_ALG: recvmsg syscall returned 256
kcapi-enc - Verbose: Removal of padding disabled
kcapi-enc - Verbose: 256 bytes of ciphertext created

Output with the revert and on older kernels:
[...]
libkcapi - Debug: AF_ALG: recvmsg syscall returned 257
kcapi-enc - Verbose: Removal of padding disabled
kcapi-enc - Verbose: 257 bytes of ciphertext created

I'm not familiar with the code in question, so I'm not sure if this is
a kernel bug or whether the change just exposed a bug in libkcapi.

Stephan, Herbert, can you please have a look?

Thanks,

Ondrej

[1] https://github.com/smuellerDD/libkcapi
[2] https://bugzilla.redhat.com/show_bug.cgi?id=1826022


2020-04-21 09:20:45

by Stephan Müller

[permalink] [raw]
Subject: Re: libkcapi tests are failing on kernels 5.5+

Am Dienstag, 21. April 2020, 10:08:14 CEST schrieb Ondrej Mosnáček:

Hi Ondrej,

> Hi all,
>
> the libkcapi [1] tests are failing on kernels 5.5-rc1 and above [2].
> All encryption/decryption tests that use 'ctr(aes)' and a message size
> that is not a multiple of 16 fail due to kcapi-enc returning different
> output than expected.

Confirmed.

On the recent kernels, the data generated by kcapi-enc contains trailing zero
bytes for data that is a fraction of the block size.

I think the issue is in the following kernel code in _skcipher_recvmsg:

unsigned int bs = crypto_skcipher_chunksize(tfm);

/*
* If more buffers are to be expected to be processed, process only
* full block size buffers.
*/
if (ctx->more || len < ctx->used)
len -= len % bs;


The kernel truncates the size to be processed to the chunk size. As the
chunksize returns the block size of the underlying cipher (e.g. AES -> 16),
the kernel code will not process non-aligned data.

Herbert, could you help me identifying what exactly was the root cause for the
patch 5b0fe9552336338acb52756daf65dd7a4eeca73f ? I.e. it seems that stream
ciphers made out of a block cipher would not generate the data part that is a
fraction of the block size (e.g. CTR, CTS).

Ciao
Stephan


2020-04-28 08:19:59

by Stephan Mueller

[permalink] [raw]
Subject: Re: libkcapi tests are failing on kernels 5.5+

Am Dienstag, 21. April 2020, 11:19:36 CEST schrieb Stephan Mueller:

Hi Herbert,

could you please help us with the answer to the question below?

> Am Dienstag, 21. April 2020, 10:08:14 CEST schrieb Ondrej Mosnáček:
>
> Hi Ondrej,
>
> > Hi all,
> >
> > the libkcapi [1] tests are failing on kernels 5.5-rc1 and above [2].
> > All encryption/decryption tests that use 'ctr(aes)' and a message size
> > that is not a multiple of 16 fail due to kcapi-enc returning different
> > output than expected.
>
> Confirmed.
>
> On the recent kernels, the data generated by kcapi-enc contains trailing
> zero bytes for data that is a fraction of the block size.
>
> I think the issue is in the following kernel code in _skcipher_recvmsg:
>
> unsigned int bs = crypto_skcipher_chunksize(tfm);
>
> /*
> * If more buffers are to be expected to be processed, process only
> * full block size buffers.
> */
> if (ctx->more || len < ctx->used)
> len -= len % bs;
>
>
> The kernel truncates the size to be processed to the chunk size. As the
> chunksize returns the block size of the underlying cipher (e.g. AES -> 16),
> the kernel code will not process non-aligned data.
>
> Herbert, could you help me identifying what exactly was the root cause for
> the patch 5b0fe9552336338acb52756daf65dd7a4eeca73f ? I.e. it seems that
> stream ciphers made out of a block cipher would not generate the data part
> that is a fraction of the block size (e.g. CTR, CTS).
>
> Ciao
> Stephan


Ciao
Stephan
--
atsec information security GmbH, Steinstraße 70, 81667 München, Germany
Phone: +49 89 442 49 830 - Fax: +49 89 442 49 831
Mobile DE: +49 172 216 55 78 - Mobile US: +1 737 346 1613
HRB: 129439 (Amtsgericht München)
GF: Salvatore la Pietra, Staffan Persson, Manuela Gambarotto
atsec it security news blog - atsec-information-security.blogspot.com



2020-05-05 07:59:59

by Herbert Xu

[permalink] [raw]
Subject: Re: libkcapi tests are failing on kernels 5.5+

On Tue, Apr 21, 2020 at 10:08:14AM +0200, Ondrej Mosnáček wrote:
> Hi all,
>
> the libkcapi [1] tests are failing on kernels 5.5-rc1 and above [2].
> All encryption/decryption tests that use 'ctr(aes)' and a message size
> that is not a multiple of 16 fail due to kcapi-enc returning different
> output than expected.
>
> It seems that it started with:
> commit 5b0fe9552336338acb52756daf65dd7a4eeca73f
> Author: Herbert Xu <[email protected]>
> Date: Tue Sep 10 11:42:05 2019 +1000
>
> crypto: algif_skcipher - Use chunksize instead of blocksize
>
> Reverting the above commit makes the tests pass again.
>
> Here is a one-line reproducer:
> head -c 257 /dev/zero | kcapi-enc -vvv --pbkdfiter 1 -p "passwd" -s
> "123" -e -c "ctr(aes)" --iv "0123456789abcdef0123456789abcdef"
> >/dev/null
>
> Output without revert:
> [...]
> libkcapi - Debug: AF_ALG: recvmsg syscall returned 256
> kcapi-enc - Verbose: Removal of padding disabled
> kcapi-enc - Verbose: 256 bytes of ciphertext created

OK, I tried it here and the problem is that kcapi-enc is setting
the flag SPLICE_F_MORE:

splice(4, NULL, 6, NULL, 257, SPLICE_F_MORE) = 257
write(2, "libkcapi - Debug: AF_ALG: splice"..., 54libkcapi - Debug: AF_ALG: splice syscall returned 257
) = 54
write(2, "kcapi-enc - Debug: Data size exp"..., 59kcapi-enc - Debug: Data size expected to be generated: 257
) = 59
recvmsg(6, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\363\212\340S\r\231\371+\234\320\"\360}%\244\242.\365iJ\304\257\210\f\366\20\257'F\5EP"..., iov_len=257}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 256

That flag means that the request is not finished and because of
the way CTR works we must wait for more input before returning
the next block (or partial block).

So kcapi-enc needs to unset the SPLICE_F_MORE to finish a request.

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

2020-05-05 08:06:30

by Stephan Müller

[permalink] [raw]
Subject: Re: libkcapi tests are failing on kernels 5.5+

Am Dienstag, 5. Mai 2020, 09:58:35 CEST schrieb Herbert Xu:

Hi Herbert,

> On Tue, Apr 21, 2020 at 10:08:14AM +0200, Ondrej Mosnáček wrote:
> > Hi all,
> >
> > the libkcapi [1] tests are failing on kernels 5.5-rc1 and above [2].
> > All encryption/decryption tests that use 'ctr(aes)' and a message size
> > that is not a multiple of 16 fail due to kcapi-enc returning different
> > output than expected.
> >
> > It seems that it started with:
> > commit 5b0fe9552336338acb52756daf65dd7a4eeca73f
> > Author: Herbert Xu <[email protected]>
> > Date: Tue Sep 10 11:42:05 2019 +1000
> >
> > crypto: algif_skcipher - Use chunksize instead of blocksize
> >
> > Reverting the above commit makes the tests pass again.
> >
> > Here is a one-line reproducer:
> > head -c 257 /dev/zero | kcapi-enc -vvv --pbkdfiter 1 -p "passwd" -s
> > "123" -e -c "ctr(aes)" --iv "0123456789abcdef0123456789abcdef"
> >
> > >/dev/null
> >
> > Output without revert:
> > [...]
> > libkcapi - Debug: AF_ALG: recvmsg syscall returned 256
> > kcapi-enc - Verbose: Removal of padding disabled
> > kcapi-enc - Verbose: 256 bytes of ciphertext created
>
> OK, I tried it here and the problem is that kcapi-enc is setting
> the flag SPLICE_F_MORE:
>
> splice(4, NULL, 6, NULL, 257, SPLICE_F_MORE) = 257
> write(2, "libkcapi - Debug: AF_ALG: splice"..., 54libkcapi - Debug: AF_ALG:
> splice syscall returned 257 ) = 54
> write(2, "kcapi-enc - Debug: Data size exp"..., 59kcapi-enc - Debug: Data
> size expected to be generated: 257 ) = 59
> recvmsg(6, {msg_name=NULL, msg_namelen=0,
> msg_iov=[{iov_base="\363\212\340S\r\231\371+\234\320\"\360}%\244\242.\365iJ
> \304\257\210\f\366\20\257'F\5EP"..., iov_len=257}], msg_iovlen=1,
> msg_controllen=0, msg_flags=0}, 0) = 256
>
> That flag means that the request is not finished and because of
> the way CTR works we must wait for more input before returning
> the next block (or partial block).
>
> So kcapi-enc needs to unset the SPLICE_F_MORE to finish a request.

Thanks a lot, let me work on that.
>
> Cheers,


Ciao
Stephan


2020-05-05 22:07:11

by Stephan Müller

[permalink] [raw]
Subject: Re: libkcapi tests are failing on kernels 5.5+

Am Dienstag, 5. Mai 2020, 09:58:35 CEST schrieb Herbert Xu:

Hi Herbert,


Issue is fixed in libkcapi with https://github.com/smuellerDD/libkcapi/commit/
2fdd3738c77b0db825b4bb94eef9a932aa5077de

Thanks.

Ciao
Stephan