Skip to content
Snippets Groups Projects
Commit c31a8719 authored by Eric Biggers's avatar Eric Biggers Committed by Herbert Xu
Browse files

crypto: cts - don't support empty messages

My patches to make testmgr fuzz algorithms against their generic
implementation detected that the arm64 implementations of
"cts(cbc(aes))" handle empty messages differently from the cts template.
Namely, the arm64 implementations forbids (with -EINVAL) all messages
shorter than the block size, including the empty message; but the cts
template permits empty messages as a special case.

No user should be CTS-encrypting/decrypting empty messages, but we need
to keep the behavior consistent.  Unfortunately, as noted in the source
of OpenSSL's CTS implementation [1], there's no common specification for
CTS.  This makes it somewhat debatable what the behavior should be.

However, all CTS specifications seem to agree that messages shorter than
the block size are not allowed, and OpenSSL follows this in both CTS
conventions it implements.  It would also simplify the user-visible
semantics to have empty messages no longer be a special case.

Therefore, make the cts template return -EINVAL on *all* messages
shorter than the block size, including the empty message.

[1] https://github.com/openssl/openssl/blob/master/crypto/modes/cts128.c



Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent c5c46887
No related branches found
No related tags found
No related merge requests found
...@@ -152,12 +152,14 @@ static int crypto_cts_encrypt(struct skcipher_request *req) ...@@ -152,12 +152,14 @@ static int crypto_cts_encrypt(struct skcipher_request *req)
struct skcipher_request *subreq = &rctx->subreq; struct skcipher_request *subreq = &rctx->subreq;
int bsize = crypto_skcipher_blocksize(tfm); int bsize = crypto_skcipher_blocksize(tfm);
unsigned int nbytes = req->cryptlen; unsigned int nbytes = req->cryptlen;
int cbc_blocks = (nbytes + bsize - 1) / bsize - 1;
unsigned int offset; unsigned int offset;
skcipher_request_set_tfm(subreq, ctx->child); skcipher_request_set_tfm(subreq, ctx->child);
if (cbc_blocks <= 0) { if (nbytes < bsize)
return -EINVAL;
if (nbytes == bsize) {
skcipher_request_set_callback(subreq, req->base.flags, skcipher_request_set_callback(subreq, req->base.flags,
req->base.complete, req->base.complete,
req->base.data); req->base.data);
...@@ -166,7 +168,7 @@ static int crypto_cts_encrypt(struct skcipher_request *req) ...@@ -166,7 +168,7 @@ static int crypto_cts_encrypt(struct skcipher_request *req)
return crypto_skcipher_encrypt(subreq); return crypto_skcipher_encrypt(subreq);
} }
offset = cbc_blocks * bsize; offset = rounddown(nbytes - 1, bsize);
rctx->offset = offset; rctx->offset = offset;
skcipher_request_set_callback(subreq, req->base.flags, skcipher_request_set_callback(subreq, req->base.flags,
...@@ -244,13 +246,15 @@ static int crypto_cts_decrypt(struct skcipher_request *req) ...@@ -244,13 +246,15 @@ static int crypto_cts_decrypt(struct skcipher_request *req)
struct skcipher_request *subreq = &rctx->subreq; struct skcipher_request *subreq = &rctx->subreq;
int bsize = crypto_skcipher_blocksize(tfm); int bsize = crypto_skcipher_blocksize(tfm);
unsigned int nbytes = req->cryptlen; unsigned int nbytes = req->cryptlen;
int cbc_blocks = (nbytes + bsize - 1) / bsize - 1;
unsigned int offset; unsigned int offset;
u8 *space; u8 *space;
skcipher_request_set_tfm(subreq, ctx->child); skcipher_request_set_tfm(subreq, ctx->child);
if (cbc_blocks <= 0) { if (nbytes < bsize)
return -EINVAL;
if (nbytes == bsize) {
skcipher_request_set_callback(subreq, req->base.flags, skcipher_request_set_callback(subreq, req->base.flags,
req->base.complete, req->base.complete,
req->base.data); req->base.data);
...@@ -264,10 +268,10 @@ static int crypto_cts_decrypt(struct skcipher_request *req) ...@@ -264,10 +268,10 @@ static int crypto_cts_decrypt(struct skcipher_request *req)
space = crypto_cts_reqctx_space(req); space = crypto_cts_reqctx_space(req);
offset = cbc_blocks * bsize; offset = rounddown(nbytes - 1, bsize);
rctx->offset = offset; rctx->offset = offset;
if (cbc_blocks <= 1) if (offset <= bsize)
memcpy(space, req->iv, bsize); memcpy(space, req->iv, bsize);
else else
scatterwalk_map_and_copy(space, req->src, offset - 2 * bsize, scatterwalk_map_and_copy(space, req->src, offset - 2 * bsize,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment