1
0

crypto: crypto4xx - block ciphers should only accept complete blocks

The hardware automatically zero pads incomplete block ciphers
blocks without raising any errors. This is a screw-up. This
was noticed by CONFIG_CRYPTO_MANAGER_EXTRA_TESTS tests that
sent a incomplete blocks and expect them to fail.

This fixes:
cbc-aes-ppc4xx encryption unexpectedly succeeded on test vector
"random: len=2409 klen=32"; expected_error=-22, cfg="random:
may_sleep use_digest src_divs=[96.90%@+2295, 2.34%@+4066,
0.32%@alignmask+12, 0.34%@+4087, 0.9%@alignmask+1787, 0.1%@+3767]
iv_offset=6"

ecb-aes-ppc4xx encryption unexpectedly succeeded on test vector
"random: len=1011 klen=32"; expected_error=-22, cfg="random:
may_sleep use_digest src_divs=[100.0%@alignmask+20]
dst_divs=[3.12%@+3001, 96.88%@+4070]"

Cc: Eric Biggers <ebiggers@kernel.org>
Cc: stable@vger.kernel.org [4.19, 5.0 and 5.1]
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Este cometimento está contido em:
Christian Lamparter
2019-05-18 23:28:12 +02:00
cometido por Herbert Xu
ascendente 70c4997f34
cometimento 0f7a813740
3 ficheiros modificados com 39 adições e 23 eliminações

Ver ficheiro

@@ -76,12 +76,16 @@ static void set_dynamic_sa_command_1(struct dynamic_sa_ctl *sa, u32 cm,
}
static inline int crypto4xx_crypt(struct skcipher_request *req,
const unsigned int ivlen, bool decrypt)
const unsigned int ivlen, bool decrypt,
bool check_blocksize)
{
struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(cipher);
__le32 iv[AES_IV_SIZE];
if (check_blocksize && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE))
return -EINVAL;
if (ivlen)
crypto4xx_memcpy_to_le32(iv, req->iv, ivlen);
@@ -90,24 +94,34 @@ static inline int crypto4xx_crypt(struct skcipher_request *req,
ctx->sa_len, 0, NULL);
}
int crypto4xx_encrypt_noiv(struct skcipher_request *req)
int crypto4xx_encrypt_noiv_block(struct skcipher_request *req)
{
return crypto4xx_crypt(req, 0, false);
return crypto4xx_crypt(req, 0, false, true);
}
int crypto4xx_encrypt_iv(struct skcipher_request *req)
int crypto4xx_encrypt_iv_stream(struct skcipher_request *req)
{
return crypto4xx_crypt(req, AES_IV_SIZE, false);
return crypto4xx_crypt(req, AES_IV_SIZE, false, false);
}
int crypto4xx_decrypt_noiv(struct skcipher_request *req)
int crypto4xx_decrypt_noiv_block(struct skcipher_request *req)
{
return crypto4xx_crypt(req, 0, true);
return crypto4xx_crypt(req, 0, true, true);
}
int crypto4xx_decrypt_iv(struct skcipher_request *req)
int crypto4xx_decrypt_iv_stream(struct skcipher_request *req)
{
return crypto4xx_crypt(req, AES_IV_SIZE, true);
return crypto4xx_crypt(req, AES_IV_SIZE, true, false);
}
int crypto4xx_encrypt_iv_block(struct skcipher_request *req)
{
return crypto4xx_crypt(req, AES_IV_SIZE, false, true);
}
int crypto4xx_decrypt_iv_block(struct skcipher_request *req)
{
return crypto4xx_crypt(req, AES_IV_SIZE, true, true);
}
/**
@@ -278,8 +292,8 @@ crypto4xx_ctr_crypt(struct skcipher_request *req, bool encrypt)
return ret;
}
return encrypt ? crypto4xx_encrypt_iv(req)
: crypto4xx_decrypt_iv(req);
return encrypt ? crypto4xx_encrypt_iv_stream(req)
: crypto4xx_decrypt_iv_stream(req);
}
static int crypto4xx_sk_setup_fallback(struct crypto4xx_ctx *ctx,