aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-03-31 16:04:20 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-08 02:42:55 -0400
commitc31a871985cac1a594a7e61e7ab808c0f81845ee (patch)
tree9568d0b3776f19b7619fb369cd4551bfb2f60fa8 /crypto
parentc5c46887cfe7d0dff743d9eda7c91de625e96960 (diff)
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: Eric Biggers <ebiggers@google.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/cts.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/crypto/cts.c b/crypto/cts.c
index 4e28d83ae37d..9441da797bb9 100644
--- a/crypto/cts.c
+++ b/crypto/cts.c
@@ -152,12 +152,14 @@ static int crypto_cts_encrypt(struct skcipher_request *req)
152 struct skcipher_request *subreq = &rctx->subreq; 152 struct skcipher_request *subreq = &rctx->subreq;
153 int bsize = crypto_skcipher_blocksize(tfm); 153 int bsize = crypto_skcipher_blocksize(tfm);
154 unsigned int nbytes = req->cryptlen; 154 unsigned int nbytes = req->cryptlen;
155 int cbc_blocks = (nbytes + bsize - 1) / bsize - 1;
156 unsigned int offset; 155 unsigned int offset;
157 156
158 skcipher_request_set_tfm(subreq, ctx->child); 157 skcipher_request_set_tfm(subreq, ctx->child);
159 158
160 if (cbc_blocks <= 0) { 159 if (nbytes < bsize)
160 return -EINVAL;
161
162 if (nbytes == bsize) {
161 skcipher_request_set_callback(subreq, req->base.flags, 163 skcipher_request_set_callback(subreq, req->base.flags,
162 req->base.complete, 164 req->base.complete,
163 req->base.data); 165 req->base.data);
@@ -166,7 +168,7 @@ static int crypto_cts_encrypt(struct skcipher_request *req)
166 return crypto_skcipher_encrypt(subreq); 168 return crypto_skcipher_encrypt(subreq);
167 } 169 }
168 170
169 offset = cbc_blocks * bsize; 171 offset = rounddown(nbytes - 1, bsize);
170 rctx->offset = offset; 172 rctx->offset = offset;
171 173
172 skcipher_request_set_callback(subreq, req->base.flags, 174 skcipher_request_set_callback(subreq, req->base.flags,
@@ -244,13 +246,15 @@ static int crypto_cts_decrypt(struct skcipher_request *req)
244 struct skcipher_request *subreq = &rctx->subreq; 246 struct skcipher_request *subreq = &rctx->subreq;
245 int bsize = crypto_skcipher_blocksize(tfm); 247 int bsize = crypto_skcipher_blocksize(tfm);
246 unsigned int nbytes = req->cryptlen; 248 unsigned int nbytes = req->cryptlen;
247 int cbc_blocks = (nbytes + bsize - 1) / bsize - 1;
248 unsigned int offset; 249 unsigned int offset;
249 u8 *space; 250 u8 *space;
250 251
251 skcipher_request_set_tfm(subreq, ctx->child); 252 skcipher_request_set_tfm(subreq, ctx->child);
252 253
253 if (cbc_blocks <= 0) { 254 if (nbytes < bsize)
255 return -EINVAL;
256
257 if (nbytes == bsize) {
254 skcipher_request_set_callback(subreq, req->base.flags, 258 skcipher_request_set_callback(subreq, req->base.flags,
255 req->base.complete, 259 req->base.complete,
256 req->base.data); 260 req->base.data);
@@ -264,10 +268,10 @@ static int crypto_cts_decrypt(struct skcipher_request *req)
264 268
265 space = crypto_cts_reqctx_space(req); 269 space = crypto_cts_reqctx_space(req);
266 270
267 offset = cbc_blocks * bsize; 271 offset = rounddown(nbytes - 1, bsize);
268 rctx->offset = offset; 272 rctx->offset = offset;
269 273
270 if (cbc_blocks <= 1) 274 if (offset <= bsize)
271 memcpy(space, req->iv, bsize); 275 memcpy(space, req->iv, bsize);
272 else 276 else
273 scatterwalk_map_and_copy(space, req->src, offset - 2 * bsize, 277 scatterwalk_map_and_copy(space, req->src, offset - 2 * bsize,