aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorGerald Schaefer <gerald.schaefer@de.ibm.com>2013-11-19 11:12:47 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-12-12 01:36:26 -0500
commitda94360f55be9d57c866f4d6b0861d9ecd1a1aeb (patch)
treed63fa01918c05d7216a85c5e8b97441757c6f27a /arch/s390
parent87a226e9df5efd1c7d26756fab9e9f29a267ac47 (diff)
crypto: s390 - Fix aes-xts parameter corruption
commit 9dda2769af4f3f3093434648c409bb351120d9e8 upstream. 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). Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/crypto/aes_s390.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 2e4b5be31a1b..94e20dd2729f 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -55,8 +55,7 @@ struct pcc_param {
55 55
56struct s390_xts_ctx { 56struct s390_xts_ctx {
57 u8 key[32]; 57 u8 key[32];
58 u8 xts_param[16]; 58 u8 pcc_key[32];
59 struct pcc_param pcc;
60 long enc; 59 long enc;
61 long dec; 60 long dec;
62 int key_len; 61 int key_len;
@@ -591,7 +590,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
591 xts_ctx->enc = KM_XTS_128_ENCRYPT; 590 xts_ctx->enc = KM_XTS_128_ENCRYPT;
592 xts_ctx->dec = KM_XTS_128_DECRYPT; 591 xts_ctx->dec = KM_XTS_128_DECRYPT;
593 memcpy(xts_ctx->key + 16, in_key, 16); 592 memcpy(xts_ctx->key + 16, in_key, 16);
594 memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16); 593 memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16);
595 break; 594 break;
596 case 48: 595 case 48:
597 xts_ctx->enc = 0; 596 xts_ctx->enc = 0;
@@ -602,7 +601,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
602 xts_ctx->enc = KM_XTS_256_ENCRYPT; 601 xts_ctx->enc = KM_XTS_256_ENCRYPT;
603 xts_ctx->dec = KM_XTS_256_DECRYPT; 602 xts_ctx->dec = KM_XTS_256_DECRYPT;
604 memcpy(xts_ctx->key, in_key, 32); 603 memcpy(xts_ctx->key, in_key, 32);
605 memcpy(xts_ctx->pcc.key, in_key + 32, 32); 604 memcpy(xts_ctx->pcc_key, in_key + 32, 32);
606 break; 605 break;
607 default: 606 default:
608 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 607 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -621,29 +620,33 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
621 unsigned int nbytes = walk->nbytes; 620 unsigned int nbytes = walk->nbytes;
622 unsigned int n; 621 unsigned int n;
623 u8 *in, *out; 622 u8 *in, *out;
624 void *param; 623 struct pcc_param pcc_param;
624 struct {
625 u8 key[32];
626 u8 init[16];
627 } xts_param;
625 628
626 if (!nbytes) 629 if (!nbytes)
627 goto out; 630 goto out;
628 631
629 memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block)); 632 memset(pcc_param.block, 0, sizeof(pcc_param.block));
630 memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit)); 633 memset(pcc_param.bit, 0, sizeof(pcc_param.bit));
631 memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts)); 634 memset(pcc_param.xts, 0, sizeof(pcc_param.xts));
632 memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak)); 635 memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
633 param = xts_ctx->pcc.key + offset; 636 memcpy(pcc_param.key, xts_ctx->pcc_key, 32);
634 ret = crypt_s390_pcc(func, param); 637 ret = crypt_s390_pcc(func, &pcc_param.key[offset]);
635 if (ret < 0) 638 if (ret < 0)
636 return -EIO; 639 return -EIO;
637 640
638 memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16); 641 memcpy(xts_param.key, xts_ctx->key, 32);
639 param = xts_ctx->key + offset; 642 memcpy(xts_param.init, pcc_param.xts, 16);
640 do { 643 do {
641 /* only use complete blocks */ 644 /* only use complete blocks */
642 n = nbytes & ~(AES_BLOCK_SIZE - 1); 645 n = nbytes & ~(AES_BLOCK_SIZE - 1);
643 out = walk->dst.virt.addr; 646 out = walk->dst.virt.addr;
644 in = walk->src.virt.addr; 647 in = walk->src.virt.addr;
645 648
646 ret = crypt_s390_km(func, param, out, in, n); 649 ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n);
647 if (ret < 0 || ret != n) 650 if (ret < 0 || ret != n)
648 return -EIO; 651 return -EIO;
649 652