diff options
author | Gerald Schaefer <gerald.schaefer@de.ibm.com> | 2013-11-19 11:12:47 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-12-12 01:36:26 -0500 |
commit | da94360f55be9d57c866f4d6b0861d9ecd1a1aeb (patch) | |
tree | d63fa01918c05d7216a85c5e8b97441757c6f27a /arch/s390 | |
parent | 87a226e9df5efd1c7d26756fab9e9f29a267ac47 (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.c | 31 |
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 | ||
56 | struct s390_xts_ctx { | 56 | struct 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 | ||