diff options
author | Marcelo Cerri <marcelo.cerri@canonical.com> | 2016-09-28 12:42:10 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2016-10-02 10:26:42 -0400 |
commit | 80da44c29d997e28c4442825f35f4ac339813877 (patch) | |
tree | 07d05485c86275960e270a968ded8baded310d2a | |
parent | a397ba829d7f8aff4c90af3704573a28ccd61a59 (diff) |
crypto: vmx - Fix memory corruption caused by p8_ghash
This patch changes the p8_ghash driver to use ghash-generic as a fixed
fallback implementation. This allows the correct value of descsize to be
defined directly in its shash_alg structure and avoids problems with
incorrect buffer sizes when its state is exported or imported.
Reported-by: Jan Stancek <jstancek@redhat.com>
Fixes: cc333cd68dfa ("crypto: vmx - Adding GHASH routines for VMX module")
Cc: stable@vger.kernel.org
Signed-off-by: Marcelo Cerri <marcelo.cerri@canonical.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/crypto/vmx/ghash.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/drivers/crypto/vmx/ghash.c b/drivers/crypto/vmx/ghash.c index 6c999cb01b80..27a94a119009 100644 --- a/drivers/crypto/vmx/ghash.c +++ b/drivers/crypto/vmx/ghash.c | |||
@@ -26,16 +26,13 @@ | |||
26 | #include <linux/hardirq.h> | 26 | #include <linux/hardirq.h> |
27 | #include <asm/switch_to.h> | 27 | #include <asm/switch_to.h> |
28 | #include <crypto/aes.h> | 28 | #include <crypto/aes.h> |
29 | #include <crypto/ghash.h> | ||
29 | #include <crypto/scatterwalk.h> | 30 | #include <crypto/scatterwalk.h> |
30 | #include <crypto/internal/hash.h> | 31 | #include <crypto/internal/hash.h> |
31 | #include <crypto/b128ops.h> | 32 | #include <crypto/b128ops.h> |
32 | 33 | ||
33 | #define IN_INTERRUPT in_interrupt() | 34 | #define IN_INTERRUPT in_interrupt() |
34 | 35 | ||
35 | #define GHASH_BLOCK_SIZE (16) | ||
36 | #define GHASH_DIGEST_SIZE (16) | ||
37 | #define GHASH_KEY_LEN (16) | ||
38 | |||
39 | void gcm_init_p8(u128 htable[16], const u64 Xi[2]); | 36 | void gcm_init_p8(u128 htable[16], const u64 Xi[2]); |
40 | void gcm_gmult_p8(u64 Xi[2], const u128 htable[16]); | 37 | void gcm_gmult_p8(u64 Xi[2], const u128 htable[16]); |
41 | void gcm_ghash_p8(u64 Xi[2], const u128 htable[16], | 38 | void gcm_ghash_p8(u64 Xi[2], const u128 htable[16], |
@@ -55,16 +52,11 @@ struct p8_ghash_desc_ctx { | |||
55 | 52 | ||
56 | static int p8_ghash_init_tfm(struct crypto_tfm *tfm) | 53 | static int p8_ghash_init_tfm(struct crypto_tfm *tfm) |
57 | { | 54 | { |
58 | const char *alg; | 55 | const char *alg = "ghash-generic"; |
59 | struct crypto_shash *fallback; | 56 | struct crypto_shash *fallback; |
60 | struct crypto_shash *shash_tfm = __crypto_shash_cast(tfm); | 57 | struct crypto_shash *shash_tfm = __crypto_shash_cast(tfm); |
61 | struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm); | 58 | struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm); |
62 | 59 | ||
63 | if (!(alg = crypto_tfm_alg_name(tfm))) { | ||
64 | printk(KERN_ERR "Failed to get algorithm name.\n"); | ||
65 | return -ENOENT; | ||
66 | } | ||
67 | |||
68 | fallback = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); | 60 | fallback = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); |
69 | if (IS_ERR(fallback)) { | 61 | if (IS_ERR(fallback)) { |
70 | printk(KERN_ERR | 62 | printk(KERN_ERR |
@@ -78,10 +70,18 @@ static int p8_ghash_init_tfm(struct crypto_tfm *tfm) | |||
78 | crypto_shash_set_flags(fallback, | 70 | crypto_shash_set_flags(fallback, |
79 | crypto_shash_get_flags((struct crypto_shash | 71 | crypto_shash_get_flags((struct crypto_shash |
80 | *) tfm)); | 72 | *) tfm)); |
81 | ctx->fallback = fallback; | ||
82 | 73 | ||
83 | shash_tfm->descsize = sizeof(struct p8_ghash_desc_ctx) | 74 | /* Check if the descsize defined in the algorithm is still enough. */ |
84 | + crypto_shash_descsize(fallback); | 75 | if (shash_tfm->descsize < sizeof(struct p8_ghash_desc_ctx) |
76 | + crypto_shash_descsize(fallback)) { | ||
77 | printk(KERN_ERR | ||
78 | "Desc size of the fallback implementation (%s) does not match the expected value: %lu vs %u\n", | ||
79 | alg, | ||
80 | shash_tfm->descsize - sizeof(struct p8_ghash_desc_ctx), | ||
81 | crypto_shash_descsize(fallback)); | ||
82 | return -EINVAL; | ||
83 | } | ||
84 | ctx->fallback = fallback; | ||
85 | 85 | ||
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
@@ -113,7 +113,7 @@ static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key, | |||
113 | { | 113 | { |
114 | struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(tfm)); | 114 | struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(tfm)); |
115 | 115 | ||
116 | if (keylen != GHASH_KEY_LEN) | 116 | if (keylen != GHASH_BLOCK_SIZE) |
117 | return -EINVAL; | 117 | return -EINVAL; |
118 | 118 | ||
119 | preempt_disable(); | 119 | preempt_disable(); |
@@ -211,7 +211,8 @@ struct shash_alg p8_ghash_alg = { | |||
211 | .update = p8_ghash_update, | 211 | .update = p8_ghash_update, |
212 | .final = p8_ghash_final, | 212 | .final = p8_ghash_final, |
213 | .setkey = p8_ghash_setkey, | 213 | .setkey = p8_ghash_setkey, |
214 | .descsize = sizeof(struct p8_ghash_desc_ctx), | 214 | .descsize = sizeof(struct p8_ghash_desc_ctx) |
215 | + sizeof(struct ghash_desc_ctx), | ||
215 | .base = { | 216 | .base = { |
216 | .cra_name = "ghash", | 217 | .cra_name = "ghash", |
217 | .cra_driver_name = "p8_ghash", | 218 | .cra_driver_name = "p8_ghash", |