aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2013-11-05 06:36:27 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2013-11-05 06:36:27 -0500
commitf262f0f5cad0c9eca61d1d383e3b67b57dcbe5ea (patch)
treec2751c06429179a5ac2fca4dabd001ef4e06b2d0 /arch
parent8ed49c7675e106bc23f34ac065d8add75e0e2f45 (diff)
crypto: s390 - Fix aes-cbc IV corruption
The cbc-aes-s390 algorithm incorrectly places the IV in the tfm data structure. As the tfm is shared between multiple threads, this introduces a possibility of data corruption. This patch fixes this by moving the parameter block containing the IV and key onto the stack (the block is 48 bytes long). The same bug exists elsewhere in the s390 crypto system and they will be fixed in subsequent patches. Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/crypto/aes_s390.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index b4dbade8ca24..2e4b5be31a1b 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -35,7 +35,6 @@ static u8 *ctrblk;
35static char keylen_flag; 35static char keylen_flag;
36 36
37struct s390_aes_ctx { 37struct s390_aes_ctx {
38 u8 iv[AES_BLOCK_SIZE];
39 u8 key[AES_MAX_KEY_SIZE]; 38 u8 key[AES_MAX_KEY_SIZE];
40 long enc; 39 long enc;
41 long dec; 40 long dec;
@@ -441,30 +440,36 @@ static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
441 return aes_set_key(tfm, in_key, key_len); 440 return aes_set_key(tfm, in_key, key_len);
442} 441}
443 442
444static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param, 443static int cbc_aes_crypt(struct blkcipher_desc *desc, long func,
445 struct blkcipher_walk *walk) 444 struct blkcipher_walk *walk)
446{ 445{
446 struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
447 int ret = blkcipher_walk_virt(desc, walk); 447 int ret = blkcipher_walk_virt(desc, walk);
448 unsigned int nbytes = walk->nbytes; 448 unsigned int nbytes = walk->nbytes;
449 struct {
450 u8 iv[AES_BLOCK_SIZE];
451 u8 key[AES_MAX_KEY_SIZE];
452 } param;
449 453
450 if (!nbytes) 454 if (!nbytes)
451 goto out; 455 goto out;
452 456
453 memcpy(param, walk->iv, AES_BLOCK_SIZE); 457 memcpy(param.iv, walk->iv, AES_BLOCK_SIZE);
458 memcpy(param.key, sctx->key, sctx->key_len);
454 do { 459 do {
455 /* only use complete blocks */ 460 /* only use complete blocks */
456 unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); 461 unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
457 u8 *out = walk->dst.virt.addr; 462 u8 *out = walk->dst.virt.addr;
458 u8 *in = walk->src.virt.addr; 463 u8 *in = walk->src.virt.addr;
459 464
460 ret = crypt_s390_kmc(func, param, out, in, n); 465 ret = crypt_s390_kmc(func, &param, out, in, n);
461 if (ret < 0 || ret != n) 466 if (ret < 0 || ret != n)
462 return -EIO; 467 return -EIO;
463 468
464 nbytes &= AES_BLOCK_SIZE - 1; 469 nbytes &= AES_BLOCK_SIZE - 1;
465 ret = blkcipher_walk_done(desc, walk, nbytes); 470 ret = blkcipher_walk_done(desc, walk, nbytes);
466 } while ((nbytes = walk->nbytes)); 471 } while ((nbytes = walk->nbytes));
467 memcpy(walk->iv, param, AES_BLOCK_SIZE); 472 memcpy(walk->iv, param.iv, AES_BLOCK_SIZE);
468 473
469out: 474out:
470 return ret; 475 return ret;
@@ -481,7 +486,7 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
481 return fallback_blk_enc(desc, dst, src, nbytes); 486 return fallback_blk_enc(desc, dst, src, nbytes);
482 487
483 blkcipher_walk_init(&walk, dst, src, nbytes); 488 blkcipher_walk_init(&walk, dst, src, nbytes);
484 return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk); 489 return cbc_aes_crypt(desc, sctx->enc, &walk);
485} 490}
486 491
487static int cbc_aes_decrypt(struct blkcipher_desc *desc, 492static int cbc_aes_decrypt(struct blkcipher_desc *desc,
@@ -495,7 +500,7 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
495 return fallback_blk_dec(desc, dst, src, nbytes); 500 return fallback_blk_dec(desc, dst, src, nbytes);
496 501
497 blkcipher_walk_init(&walk, dst, src, nbytes); 502 blkcipher_walk_init(&walk, dst, src, nbytes);
498 return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk); 503 return cbc_aes_crypt(desc, sctx->dec, &walk);
499} 504}
500 505
501static struct crypto_alg cbc_aes_alg = { 506static struct crypto_alg cbc_aes_alg = {