diff options
author | Kees Cook <keescook@chromium.org> | 2018-08-03 12:37:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-08-03 15:54:54 -0400 |
commit | a394b3af206c211b80b02e47c19aab763fd33b3d (patch) | |
tree | 5058bafa271239982d6b2776fb716947eb816978 | |
parent | eb9950eb31f56e57582a61c92073336d04a26542 (diff) |
ppp: mppe: Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this
removes the discouraged use of AHASH_REQUEST_ON_STACK (and associated
VLA) by switching to shash directly and keeping the associated descriptor
allocated with the regular state on the heap.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ppp/ppp_mppe.c | 56 |
1 files changed, 30 insertions, 26 deletions
diff --git a/drivers/net/ppp/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c index 6c7fd98cb00a..a205750b431b 100644 --- a/drivers/net/ppp/ppp_mppe.c +++ b/drivers/net/ppp/ppp_mppe.c | |||
@@ -96,7 +96,7 @@ static inline void sha_pad_init(struct sha_pad *shapad) | |||
96 | */ | 96 | */ |
97 | struct ppp_mppe_state { | 97 | struct ppp_mppe_state { |
98 | struct crypto_skcipher *arc4; | 98 | struct crypto_skcipher *arc4; |
99 | struct crypto_ahash *sha1; | 99 | struct shash_desc *sha1; |
100 | unsigned char *sha1_digest; | 100 | unsigned char *sha1_digest; |
101 | unsigned char master_key[MPPE_MAX_KEY_LEN]; | 101 | unsigned char master_key[MPPE_MAX_KEY_LEN]; |
102 | unsigned char session_key[MPPE_MAX_KEY_LEN]; | 102 | unsigned char session_key[MPPE_MAX_KEY_LEN]; |
@@ -136,25 +136,16 @@ struct ppp_mppe_state { | |||
136 | */ | 136 | */ |
137 | static void get_new_key_from_sha(struct ppp_mppe_state * state) | 137 | static void get_new_key_from_sha(struct ppp_mppe_state * state) |
138 | { | 138 | { |
139 | AHASH_REQUEST_ON_STACK(req, state->sha1); | 139 | crypto_shash_init(state->sha1); |
140 | struct scatterlist sg[4]; | 140 | crypto_shash_update(state->sha1, state->master_key, |
141 | unsigned int nbytes; | 141 | state->keylen); |
142 | 142 | crypto_shash_update(state->sha1, sha_pad->sha_pad1, | |
143 | sg_init_table(sg, 4); | 143 | sizeof(sha_pad->sha_pad1)); |
144 | 144 | crypto_shash_update(state->sha1, state->session_key, | |
145 | nbytes = setup_sg(&sg[0], state->master_key, state->keylen); | 145 | state->keylen); |
146 | nbytes += setup_sg(&sg[1], sha_pad->sha_pad1, | 146 | crypto_shash_update(state->sha1, sha_pad->sha_pad2, |
147 | sizeof(sha_pad->sha_pad1)); | 147 | sizeof(sha_pad->sha_pad2)); |
148 | nbytes += setup_sg(&sg[2], state->session_key, state->keylen); | 148 | crypto_shash_final(state->sha1, state->sha1_digest); |
149 | nbytes += setup_sg(&sg[3], sha_pad->sha_pad2, | ||
150 | sizeof(sha_pad->sha_pad2)); | ||
151 | |||
152 | ahash_request_set_tfm(req, state->sha1); | ||
153 | ahash_request_set_callback(req, 0, NULL, NULL); | ||
154 | ahash_request_set_crypt(req, sg, state->sha1_digest, nbytes); | ||
155 | |||
156 | crypto_ahash_digest(req); | ||
157 | ahash_request_zero(req); | ||
158 | } | 149 | } |
159 | 150 | ||
160 | /* | 151 | /* |
@@ -200,6 +191,7 @@ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) | |||
200 | static void *mppe_alloc(unsigned char *options, int optlen) | 191 | static void *mppe_alloc(unsigned char *options, int optlen) |
201 | { | 192 | { |
202 | struct ppp_mppe_state *state; | 193 | struct ppp_mppe_state *state; |
194 | struct crypto_shash *shash; | ||
203 | unsigned int digestsize; | 195 | unsigned int digestsize; |
204 | 196 | ||
205 | if (optlen != CILEN_MPPE + sizeof(state->master_key) || | 197 | if (optlen != CILEN_MPPE + sizeof(state->master_key) || |
@@ -217,13 +209,21 @@ static void *mppe_alloc(unsigned char *options, int optlen) | |||
217 | goto out_free; | 209 | goto out_free; |
218 | } | 210 | } |
219 | 211 | ||
220 | state->sha1 = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC); | 212 | shash = crypto_alloc_shash("sha1", 0, 0); |
221 | if (IS_ERR(state->sha1)) { | 213 | if (IS_ERR(shash)) |
222 | state->sha1 = NULL; | 214 | goto out_free; |
215 | |||
216 | state->sha1 = kmalloc(sizeof(*state->sha1) + | ||
217 | crypto_shash_descsize(shash), | ||
218 | GFP_KERNEL); | ||
219 | if (!state->sha1) { | ||
220 | crypto_free_shash(shash); | ||
223 | goto out_free; | 221 | goto out_free; |
224 | } | 222 | } |
223 | state->sha1->tfm = shash; | ||
224 | state->sha1->flags = 0; | ||
225 | 225 | ||
226 | digestsize = crypto_ahash_digestsize(state->sha1); | 226 | digestsize = crypto_shash_digestsize(shash); |
227 | if (digestsize < MPPE_MAX_KEY_LEN) | 227 | if (digestsize < MPPE_MAX_KEY_LEN) |
228 | goto out_free; | 228 | goto out_free; |
229 | 229 | ||
@@ -246,7 +246,10 @@ static void *mppe_alloc(unsigned char *options, int optlen) | |||
246 | 246 | ||
247 | out_free: | 247 | out_free: |
248 | kfree(state->sha1_digest); | 248 | kfree(state->sha1_digest); |
249 | crypto_free_ahash(state->sha1); | 249 | if (state->sha1) { |
250 | crypto_free_shash(state->sha1->tfm); | ||
251 | kzfree(state->sha1); | ||
252 | } | ||
250 | crypto_free_skcipher(state->arc4); | 253 | crypto_free_skcipher(state->arc4); |
251 | kfree(state); | 254 | kfree(state); |
252 | out: | 255 | out: |
@@ -261,7 +264,8 @@ static void mppe_free(void *arg) | |||
261 | struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; | 264 | struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; |
262 | if (state) { | 265 | if (state) { |
263 | kfree(state->sha1_digest); | 266 | kfree(state->sha1_digest); |
264 | crypto_free_ahash(state->sha1); | 267 | crypto_free_shash(state->sha1->tfm); |
268 | kzfree(state->sha1); | ||
265 | crypto_free_skcipher(state->arc4); | 269 | crypto_free_skcipher(state->arc4); |
266 | kfree(state); | 270 | kfree(state); |
267 | } | 271 | } |