diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/ah4.c | 36 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 36 |
2 files changed, 45 insertions, 27 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 1366bc6ce6a5..2b98943e6b02 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <linux/err.h> | ||
1 | #include <linux/module.h> | 2 | #include <linux/module.h> |
2 | #include <net/ip.h> | 3 | #include <net/ip.h> |
3 | #include <net/xfrm.h> | 4 | #include <net/xfrm.h> |
@@ -97,7 +98,10 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) | |||
97 | ah->spi = x->id.spi; | 98 | ah->spi = x->id.spi; |
98 | ah->seq_no = htonl(++x->replay.oseq); | 99 | ah->seq_no = htonl(++x->replay.oseq); |
99 | xfrm_aevent_doreplay(x); | 100 | xfrm_aevent_doreplay(x); |
100 | ahp->icv(ahp, skb, ah->auth_data); | 101 | err = ah_mac_digest(ahp, skb, ah->auth_data); |
102 | if (err) | ||
103 | goto error; | ||
104 | memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len); | ||
101 | 105 | ||
102 | top_iph->tos = iph->tos; | 106 | top_iph->tos = iph->tos; |
103 | top_iph->ttl = iph->ttl; | 107 | top_iph->ttl = iph->ttl; |
@@ -119,6 +123,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
119 | { | 123 | { |
120 | int ah_hlen; | 124 | int ah_hlen; |
121 | int ihl; | 125 | int ihl; |
126 | int err = -EINVAL; | ||
122 | struct iphdr *iph; | 127 | struct iphdr *iph; |
123 | struct ip_auth_hdr *ah; | 128 | struct ip_auth_hdr *ah; |
124 | struct ah_data *ahp; | 129 | struct ah_data *ahp; |
@@ -166,8 +171,11 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
166 | 171 | ||
167 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); | 172 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); |
168 | skb_push(skb, ihl); | 173 | skb_push(skb, ihl); |
169 | ahp->icv(ahp, skb, ah->auth_data); | 174 | err = ah_mac_digest(ahp, skb, ah->auth_data); |
170 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { | 175 | if (err) |
176 | goto out; | ||
177 | err = -EINVAL; | ||
178 | if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { | ||
171 | x->stats.integrity_failed++; | 179 | x->stats.integrity_failed++; |
172 | goto out; | 180 | goto out; |
173 | } | 181 | } |
@@ -179,7 +187,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
179 | return 0; | 187 | return 0; |
180 | 188 | ||
181 | out: | 189 | out: |
182 | return -EINVAL; | 190 | return err; |
183 | } | 191 | } |
184 | 192 | ||
185 | static void ah4_err(struct sk_buff *skb, u32 info) | 193 | static void ah4_err(struct sk_buff *skb, u32 info) |
@@ -204,6 +212,7 @@ static int ah_init_state(struct xfrm_state *x) | |||
204 | { | 212 | { |
205 | struct ah_data *ahp = NULL; | 213 | struct ah_data *ahp = NULL; |
206 | struct xfrm_algo_desc *aalg_desc; | 214 | struct xfrm_algo_desc *aalg_desc; |
215 | struct crypto_hash *tfm; | ||
207 | 216 | ||
208 | if (!x->aalg) | 217 | if (!x->aalg) |
209 | goto error; | 218 | goto error; |
@@ -221,24 +230,27 @@ static int ah_init_state(struct xfrm_state *x) | |||
221 | 230 | ||
222 | ahp->key = x->aalg->alg_key; | 231 | ahp->key = x->aalg->alg_key; |
223 | ahp->key_len = (x->aalg->alg_key_len+7)/8; | 232 | ahp->key_len = (x->aalg->alg_key_len+7)/8; |
224 | ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); | 233 | tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC); |
225 | if (!ahp->tfm) | 234 | if (IS_ERR(tfm)) |
235 | goto error; | ||
236 | |||
237 | ahp->tfm = tfm; | ||
238 | if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len)) | ||
226 | goto error; | 239 | goto error; |
227 | ahp->icv = ah_hmac_digest; | ||
228 | 240 | ||
229 | /* | 241 | /* |
230 | * Lookup the algorithm description maintained by xfrm_algo, | 242 | * Lookup the algorithm description maintained by xfrm_algo, |
231 | * verify crypto transform properties, and store information | 243 | * verify crypto transform properties, and store information |
232 | * we need for AH processing. This lookup cannot fail here | 244 | * we need for AH processing. This lookup cannot fail here |
233 | * after a successful crypto_alloc_tfm(). | 245 | * after a successful crypto_alloc_hash(). |
234 | */ | 246 | */ |
235 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); | 247 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); |
236 | BUG_ON(!aalg_desc); | 248 | BUG_ON(!aalg_desc); |
237 | 249 | ||
238 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != | 250 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != |
239 | crypto_tfm_alg_digestsize(ahp->tfm)) { | 251 | crypto_hash_digestsize(tfm)) { |
240 | printk(KERN_INFO "AH: %s digestsize %u != %hu\n", | 252 | printk(KERN_INFO "AH: %s digestsize %u != %hu\n", |
241 | x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), | 253 | x->aalg->alg_name, crypto_hash_digestsize(tfm), |
242 | aalg_desc->uinfo.auth.icv_fullbits/8); | 254 | aalg_desc->uinfo.auth.icv_fullbits/8); |
243 | goto error; | 255 | goto error; |
244 | } | 256 | } |
@@ -262,7 +274,7 @@ static int ah_init_state(struct xfrm_state *x) | |||
262 | error: | 274 | error: |
263 | if (ahp) { | 275 | if (ahp) { |
264 | kfree(ahp->work_icv); | 276 | kfree(ahp->work_icv); |
265 | crypto_free_tfm(ahp->tfm); | 277 | crypto_free_hash(ahp->tfm); |
266 | kfree(ahp); | 278 | kfree(ahp); |
267 | } | 279 | } |
268 | return -EINVAL; | 280 | return -EINVAL; |
@@ -277,7 +289,7 @@ static void ah_destroy(struct xfrm_state *x) | |||
277 | 289 | ||
278 | kfree(ahp->work_icv); | 290 | kfree(ahp->work_icv); |
279 | ahp->work_icv = NULL; | 291 | ahp->work_icv = NULL; |
280 | crypto_free_tfm(ahp->tfm); | 292 | crypto_free_hash(ahp->tfm); |
281 | ahp->tfm = NULL; | 293 | ahp->tfm = NULL; |
282 | kfree(ahp); | 294 | kfree(ahp); |
283 | } | 295 | } |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 7c63ae494742..b428489f6ccd 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -121,9 +121,9 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
121 | } | 121 | } |
122 | 122 | ||
123 | if (esp->auth.icv_full_len) { | 123 | if (esp->auth.icv_full_len) { |
124 | esp->auth.icv(esp, skb, (u8*)esph-skb->data, | 124 | err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data, |
125 | sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); | 125 | sizeof(*esph) + esp->conf.ivlen + clen); |
126 | pskb_put(skb, trailer, alen); | 126 | memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen); |
127 | } | 127 | } |
128 | 128 | ||
129 | ip_send_check(top_iph); | 129 | ip_send_check(top_iph); |
@@ -163,15 +163,16 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
163 | 163 | ||
164 | /* If integrity check is required, do this. */ | 164 | /* If integrity check is required, do this. */ |
165 | if (esp->auth.icv_full_len) { | 165 | if (esp->auth.icv_full_len) { |
166 | u8 sum[esp->auth.icv_full_len]; | 166 | u8 sum[alen]; |
167 | u8 sum1[alen]; | ||
168 | |||
169 | esp->auth.icv(esp, skb, 0, skb->len-alen, sum); | ||
170 | 167 | ||
171 | if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) | 168 | err = esp_mac_digest(esp, skb, 0, skb->len - alen); |
169 | if (err) | ||
170 | goto out; | ||
171 | |||
172 | if (skb_copy_bits(skb, skb->len - alen, sum, alen)) | ||
172 | BUG(); | 173 | BUG(); |
173 | 174 | ||
174 | if (unlikely(memcmp(sum, sum1, alen))) { | 175 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { |
175 | x->stats.integrity_failed++; | 176 | x->stats.integrity_failed++; |
176 | goto out; | 177 | goto out; |
177 | } | 178 | } |
@@ -307,7 +308,7 @@ static void esp_destroy(struct xfrm_state *x) | |||
307 | esp->conf.tfm = NULL; | 308 | esp->conf.tfm = NULL; |
308 | kfree(esp->conf.ivec); | 309 | kfree(esp->conf.ivec); |
309 | esp->conf.ivec = NULL; | 310 | esp->conf.ivec = NULL; |
310 | crypto_free_tfm(esp->auth.tfm); | 311 | crypto_free_hash(esp->auth.tfm); |
311 | esp->auth.tfm = NULL; | 312 | esp->auth.tfm = NULL; |
312 | kfree(esp->auth.work_icv); | 313 | kfree(esp->auth.work_icv); |
313 | esp->auth.work_icv = NULL; | 314 | esp->auth.work_icv = NULL; |
@@ -333,22 +334,27 @@ static int esp_init_state(struct xfrm_state *x) | |||
333 | 334 | ||
334 | if (x->aalg) { | 335 | if (x->aalg) { |
335 | struct xfrm_algo_desc *aalg_desc; | 336 | struct xfrm_algo_desc *aalg_desc; |
337 | struct crypto_hash *hash; | ||
336 | 338 | ||
337 | esp->auth.key = x->aalg->alg_key; | 339 | esp->auth.key = x->aalg->alg_key; |
338 | esp->auth.key_len = (x->aalg->alg_key_len+7)/8; | 340 | esp->auth.key_len = (x->aalg->alg_key_len+7)/8; |
339 | esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); | 341 | hash = crypto_alloc_hash(x->aalg->alg_name, 0, |
340 | if (esp->auth.tfm == NULL) | 342 | CRYPTO_ALG_ASYNC); |
343 | if (IS_ERR(hash)) | ||
344 | goto error; | ||
345 | |||
346 | esp->auth.tfm = hash; | ||
347 | if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len)) | ||
341 | goto error; | 348 | goto error; |
342 | esp->auth.icv = esp_hmac_digest; | ||
343 | 349 | ||
344 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); | 350 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); |
345 | BUG_ON(!aalg_desc); | 351 | BUG_ON(!aalg_desc); |
346 | 352 | ||
347 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != | 353 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != |
348 | crypto_tfm_alg_digestsize(esp->auth.tfm)) { | 354 | crypto_hash_digestsize(hash)) { |
349 | NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", | 355 | NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", |
350 | x->aalg->alg_name, | 356 | x->aalg->alg_name, |
351 | crypto_tfm_alg_digestsize(esp->auth.tfm), | 357 | crypto_hash_digestsize(hash), |
352 | aalg_desc->uinfo.auth.icv_fullbits/8); | 358 | aalg_desc->uinfo.auth.icv_fullbits/8); |
353 | goto error; | 359 | goto error; |
354 | } | 360 | } |