Commit 9dda2769 authored by Gerald Schaefer's avatar Gerald Schaefer Committed by Herbert Xu

crypto: s390 - Fix aes-xts parameter corruption

Some s390 crypto algorithms incorrectly use the crypto_tfm structure to
store private data. As the tfm can be shared among multiple threads, this
can result in data corruption.

This patch fixes aes-xts by moving the xts and pcc parameter blocks from
the tfm onto the stack (48 + 96 bytes).

Cc: stable@vger.kernel.org
Signed-off-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 935e99a3
...@@ -55,8 +55,7 @@ struct pcc_param { ...@@ -55,8 +55,7 @@ struct pcc_param {
struct s390_xts_ctx { struct s390_xts_ctx {
u8 key[32]; u8 key[32];
u8 xts_param[16]; u8 pcc_key[32];
struct pcc_param pcc;
long enc; long enc;
long dec; long dec;
int key_len; int key_len;
...@@ -591,7 +590,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, ...@@ -591,7 +590,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
xts_ctx->enc = KM_XTS_128_ENCRYPT; xts_ctx->enc = KM_XTS_128_ENCRYPT;
xts_ctx->dec = KM_XTS_128_DECRYPT; xts_ctx->dec = KM_XTS_128_DECRYPT;
memcpy(xts_ctx->key + 16, in_key, 16); memcpy(xts_ctx->key + 16, in_key, 16);
memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16); memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16);
break; break;
case 48: case 48:
xts_ctx->enc = 0; xts_ctx->enc = 0;
...@@ -602,7 +601,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, ...@@ -602,7 +601,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
xts_ctx->enc = KM_XTS_256_ENCRYPT; xts_ctx->enc = KM_XTS_256_ENCRYPT;
xts_ctx->dec = KM_XTS_256_DECRYPT; xts_ctx->dec = KM_XTS_256_DECRYPT;
memcpy(xts_ctx->key, in_key, 32); memcpy(xts_ctx->key, in_key, 32);
memcpy(xts_ctx->pcc.key, in_key + 32, 32); memcpy(xts_ctx->pcc_key, in_key + 32, 32);
break; break;
default: default:
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
...@@ -621,29 +620,33 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func, ...@@ -621,29 +620,33 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
unsigned int nbytes = walk->nbytes; unsigned int nbytes = walk->nbytes;
unsigned int n; unsigned int n;
u8 *in, *out; u8 *in, *out;
void *param; struct pcc_param pcc_param;
struct {
u8 key[32];
u8 init[16];
} xts_param;
if (!nbytes) if (!nbytes)
goto out; goto out;
memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block)); memset(pcc_param.block, 0, sizeof(pcc_param.block));
memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit)); memset(pcc_param.bit, 0, sizeof(pcc_param.bit));
memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts)); memset(pcc_param.xts, 0, sizeof(pcc_param.xts));
memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak)); memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
param = xts_ctx->pcc.key + offset; memcpy(pcc_param.key, xts_ctx->pcc_key, 32);
ret = crypt_s390_pcc(func, param); ret = crypt_s390_pcc(func, &pcc_param.key[offset]);
if (ret < 0) if (ret < 0)
return -EIO; return -EIO;
memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16); memcpy(xts_param.key, xts_ctx->key, 32);
param = xts_ctx->key + offset; memcpy(xts_param.init, pcc_param.xts, 16);
do { do {
/* only use complete blocks */ /* only use complete blocks */
n = nbytes & ~(AES_BLOCK_SIZE - 1); n = nbytes & ~(AES_BLOCK_SIZE - 1);
out = walk->dst.virt.addr; out = walk->dst.virt.addr;
in = walk->src.virt.addr; in = walk->src.virt.addr;
ret = crypt_s390_km(func, param, out, in, n); ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n);
if (ret < 0 || ret != n) if (ret < 0 || ret != n)
return -EIO; return -EIO;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment