diff options
-rw-r--r-- | include/net/ah.h | 29 | ||||
-rw-r--r-- | include/net/esp.h | 28 | ||||
-rw-r--r-- | include/net/xfrm.h | 9 | ||||
-rw-r--r-- | net/ipv4/ah4.c | 36 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 36 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 35 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 42 | ||||
-rw-r--r-- | net/xfrm/xfrm_algo.c | 40 |
8 files changed, 158 insertions, 97 deletions
diff --git a/include/net/ah.h b/include/net/ah.h index 8e27c9ba8b84..8f257c159902 100644 --- a/include/net/ah.h +++ b/include/net/ah.h | |||
@@ -15,22 +15,29 @@ struct ah_data | |||
15 | int icv_full_len; | 15 | int icv_full_len; |
16 | int icv_trunc_len; | 16 | int icv_trunc_len; |
17 | 17 | ||
18 | void (*icv)(struct ah_data*, | 18 | struct crypto_hash *tfm; |
19 | struct sk_buff *skb, u8 *icv); | ||
20 | |||
21 | struct crypto_tfm *tfm; | ||
22 | }; | 19 | }; |
23 | 20 | ||
24 | static inline void | 21 | static inline int ah_mac_digest(struct ah_data *ahp, struct sk_buff *skb, |
25 | ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) | 22 | u8 *auth_data) |
26 | { | 23 | { |
27 | struct crypto_tfm *tfm = ahp->tfm; | 24 | struct hash_desc desc; |
25 | int err; | ||
26 | |||
27 | desc.tfm = ahp->tfm; | ||
28 | desc.flags = 0; | ||
28 | 29 | ||
29 | memset(auth_data, 0, ahp->icv_trunc_len); | 30 | memset(auth_data, 0, ahp->icv_trunc_len); |
30 | crypto_hmac_init(tfm, ahp->key, &ahp->key_len); | 31 | err = crypto_hash_init(&desc); |
31 | skb_icv_walk(skb, tfm, 0, skb->len, crypto_hmac_update); | 32 | if (unlikely(err)) |
32 | crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv); | 33 | goto out; |
33 | memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len); | 34 | err = skb_icv_walk(skb, &desc, 0, skb->len, crypto_hash_update); |
35 | if (unlikely(err)) | ||
36 | goto out; | ||
37 | err = crypto_hash_final(&desc, ahp->work_icv); | ||
38 | |||
39 | out: | ||
40 | return err; | ||
34 | } | 41 | } |
35 | 42 | ||
36 | #endif | 43 | #endif |
diff --git a/include/net/esp.h b/include/net/esp.h index af2ff18700c7..064366d66eea 100644 --- a/include/net/esp.h +++ b/include/net/esp.h | |||
@@ -35,7 +35,7 @@ struct esp_data | |||
35 | void (*icv)(struct esp_data*, | 35 | void (*icv)(struct esp_data*, |
36 | struct sk_buff *skb, | 36 | struct sk_buff *skb, |
37 | int offset, int len, u8 *icv); | 37 | int offset, int len, u8 *icv); |
38 | struct crypto_tfm *tfm; | 38 | struct crypto_hash *tfm; |
39 | } auth; | 39 | } auth; |
40 | }; | 40 | }; |
41 | 41 | ||
@@ -43,18 +43,22 @@ extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, | |||
43 | extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); | 43 | extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); |
44 | extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); | 44 | extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); |
45 | 45 | ||
46 | static inline void | 46 | static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb, |
47 | esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, | 47 | int offset, int len) |
48 | int len, u8 *auth_data) | ||
49 | { | 48 | { |
50 | struct crypto_tfm *tfm = esp->auth.tfm; | 49 | struct hash_desc desc; |
51 | char *icv = esp->auth.work_icv; | 50 | int err; |
52 | 51 | ||
53 | memset(auth_data, 0, esp->auth.icv_trunc_len); | 52 | desc.tfm = esp->auth.tfm; |
54 | crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len); | 53 | desc.flags = 0; |
55 | skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update); | 54 | |
56 | crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv); | 55 | err = crypto_hash_init(&desc); |
57 | memcpy(auth_data, icv, esp->auth.icv_trunc_len); | 56 | if (unlikely(err)) |
57 | return err; | ||
58 | err = skb_icv_walk(skb, &desc, offset, len, crypto_hash_update); | ||
59 | if (unlikely(err)) | ||
60 | return err; | ||
61 | return crypto_hash_final(&desc, esp->auth.work_icv); | ||
58 | } | 62 | } |
59 | 63 | ||
60 | #endif | 64 | #endif |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e9114e41affc..3ecd9fa1ed4b 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -984,12 +984,13 @@ extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe); | |||
984 | extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe); | 984 | extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe); |
985 | extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe); | 985 | extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe); |
986 | 986 | ||
987 | struct crypto_tfm; | 987 | struct hash_desc; |
988 | struct scatterlist; | 988 | struct scatterlist; |
989 | typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int); | 989 | typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *, |
990 | unsigned int); | ||
990 | 991 | ||
991 | extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, | 992 | extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm, |
992 | int offset, int len, icv_update_fn_t icv_update); | 993 | int offset, int len, icv_update_fn_t icv_update); |
993 | 994 | ||
994 | static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, | 995 | static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, |
995 | int family) | 996 | int family) |
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 | } |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 9d4831bd4335..00ffa7bc6c9f 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -213,7 +213,10 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
213 | ah->spi = x->id.spi; | 213 | ah->spi = x->id.spi; |
214 | ah->seq_no = htonl(++x->replay.oseq); | 214 | ah->seq_no = htonl(++x->replay.oseq); |
215 | xfrm_aevent_doreplay(x); | 215 | xfrm_aevent_doreplay(x); |
216 | ahp->icv(ahp, skb, ah->auth_data); | 216 | err = ah_mac_digest(ahp, skb, ah->auth_data); |
217 | if (err) | ||
218 | goto error_free_iph; | ||
219 | memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len); | ||
217 | 220 | ||
218 | err = 0; | 221 | err = 0; |
219 | 222 | ||
@@ -251,6 +254,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
251 | u16 hdr_len; | 254 | u16 hdr_len; |
252 | u16 ah_hlen; | 255 | u16 ah_hlen; |
253 | int nexthdr; | 256 | int nexthdr; |
257 | int err = -EINVAL; | ||
254 | 258 | ||
255 | if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) | 259 | if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) |
256 | goto out; | 260 | goto out; |
@@ -292,8 +296,11 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
292 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); | 296 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); |
293 | memset(ah->auth_data, 0, ahp->icv_trunc_len); | 297 | memset(ah->auth_data, 0, ahp->icv_trunc_len); |
294 | skb_push(skb, hdr_len); | 298 | skb_push(skb, hdr_len); |
295 | ahp->icv(ahp, skb, ah->auth_data); | 299 | err = ah_mac_digest(ahp, skb, ah->auth_data); |
296 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { | 300 | if (err) |
301 | goto free_out; | ||
302 | err = -EINVAL; | ||
303 | if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { | ||
297 | LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); | 304 | LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); |
298 | x->stats.integrity_failed++; | 305 | x->stats.integrity_failed++; |
299 | goto free_out; | 306 | goto free_out; |
@@ -310,7 +317,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
310 | free_out: | 317 | free_out: |
311 | kfree(tmp_hdr); | 318 | kfree(tmp_hdr); |
312 | out: | 319 | out: |
313 | return -EINVAL; | 320 | return err; |
314 | } | 321 | } |
315 | 322 | ||
316 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 323 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
@@ -338,6 +345,7 @@ static int ah6_init_state(struct xfrm_state *x) | |||
338 | { | 345 | { |
339 | struct ah_data *ahp = NULL; | 346 | struct ah_data *ahp = NULL; |
340 | struct xfrm_algo_desc *aalg_desc; | 347 | struct xfrm_algo_desc *aalg_desc; |
348 | struct crypto_hash *tfm; | ||
341 | 349 | ||
342 | if (!x->aalg) | 350 | if (!x->aalg) |
343 | goto error; | 351 | goto error; |
@@ -355,24 +363,27 @@ static int ah6_init_state(struct xfrm_state *x) | |||
355 | 363 | ||
356 | ahp->key = x->aalg->alg_key; | 364 | ahp->key = x->aalg->alg_key; |
357 | ahp->key_len = (x->aalg->alg_key_len+7)/8; | 365 | ahp->key_len = (x->aalg->alg_key_len+7)/8; |
358 | ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); | 366 | tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC); |
359 | if (!ahp->tfm) | 367 | if (IS_ERR(tfm)) |
368 | goto error; | ||
369 | |||
370 | ahp->tfm = tfm; | ||
371 | if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len)) | ||
360 | goto error; | 372 | goto error; |
361 | ahp->icv = ah_hmac_digest; | ||
362 | 373 | ||
363 | /* | 374 | /* |
364 | * Lookup the algorithm description maintained by xfrm_algo, | 375 | * Lookup the algorithm description maintained by xfrm_algo, |
365 | * verify crypto transform properties, and store information | 376 | * verify crypto transform properties, and store information |
366 | * we need for AH processing. This lookup cannot fail here | 377 | * we need for AH processing. This lookup cannot fail here |
367 | * after a successful crypto_alloc_tfm(). | 378 | * after a successful crypto_alloc_hash(). |
368 | */ | 379 | */ |
369 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); | 380 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); |
370 | BUG_ON(!aalg_desc); | 381 | BUG_ON(!aalg_desc); |
371 | 382 | ||
372 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != | 383 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != |
373 | crypto_tfm_alg_digestsize(ahp->tfm)) { | 384 | crypto_hash_digestsize(tfm)) { |
374 | printk(KERN_INFO "AH: %s digestsize %u != %hu\n", | 385 | printk(KERN_INFO "AH: %s digestsize %u != %hu\n", |
375 | x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), | 386 | x->aalg->alg_name, crypto_hash_digestsize(tfm), |
376 | aalg_desc->uinfo.auth.icv_fullbits/8); | 387 | aalg_desc->uinfo.auth.icv_fullbits/8); |
377 | goto error; | 388 | goto error; |
378 | } | 389 | } |
@@ -396,7 +407,7 @@ static int ah6_init_state(struct xfrm_state *x) | |||
396 | error: | 407 | error: |
397 | if (ahp) { | 408 | if (ahp) { |
398 | kfree(ahp->work_icv); | 409 | kfree(ahp->work_icv); |
399 | crypto_free_tfm(ahp->tfm); | 410 | crypto_free_hash(ahp->tfm); |
400 | kfree(ahp); | 411 | kfree(ahp); |
401 | } | 412 | } |
402 | return -EINVAL; | 413 | return -EINVAL; |
@@ -411,7 +422,7 @@ static void ah6_destroy(struct xfrm_state *x) | |||
411 | 422 | ||
412 | kfree(ahp->work_icv); | 423 | kfree(ahp->work_icv); |
413 | ahp->work_icv = NULL; | 424 | ahp->work_icv = NULL; |
414 | crypto_free_tfm(ahp->tfm); | 425 | crypto_free_hash(ahp->tfm); |
415 | ahp->tfm = NULL; | 426 | ahp->tfm = NULL; |
416 | kfree(ahp); | 427 | kfree(ahp); |
417 | } | 428 | } |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 46a7e687948e..2ebfd281e721 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -125,9 +125,9 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
125 | } | 125 | } |
126 | 126 | ||
127 | if (esp->auth.icv_full_len) { | 127 | if (esp->auth.icv_full_len) { |
128 | esp->auth.icv(esp, skb, (u8*)esph-skb->data, | 128 | err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data, |
129 | sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); | 129 | sizeof(*esph) + esp->conf.ivlen + clen); |
130 | pskb_put(skb, trailer, alen); | 130 | memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen); |
131 | } | 131 | } |
132 | 132 | ||
133 | error: | 133 | error: |
@@ -162,15 +162,16 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
162 | 162 | ||
163 | /* If integrity check is required, do this. */ | 163 | /* If integrity check is required, do this. */ |
164 | if (esp->auth.icv_full_len) { | 164 | if (esp->auth.icv_full_len) { |
165 | u8 sum[esp->auth.icv_full_len]; | 165 | u8 sum[alen]; |
166 | u8 sum1[alen]; | ||
167 | 166 | ||
168 | esp->auth.icv(esp, skb, 0, skb->len-alen, sum); | 167 | ret = esp_mac_digest(esp, skb, 0, skb->len - alen); |
168 | if (ret) | ||
169 | goto out; | ||
169 | 170 | ||
170 | if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) | 171 | if (skb_copy_bits(skb, skb->len - alen, sum, alen)) |
171 | BUG(); | 172 | BUG(); |
172 | 173 | ||
173 | if (unlikely(memcmp(sum, sum1, alen))) { | 174 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { |
174 | x->stats.integrity_failed++; | 175 | x->stats.integrity_failed++; |
175 | ret = -EINVAL; | 176 | ret = -EINVAL; |
176 | goto out; | 177 | goto out; |
@@ -279,7 +280,7 @@ static void esp6_destroy(struct xfrm_state *x) | |||
279 | esp->conf.tfm = NULL; | 280 | esp->conf.tfm = NULL; |
280 | kfree(esp->conf.ivec); | 281 | kfree(esp->conf.ivec); |
281 | esp->conf.ivec = NULL; | 282 | esp->conf.ivec = NULL; |
282 | crypto_free_tfm(esp->auth.tfm); | 283 | crypto_free_hash(esp->auth.tfm); |
283 | esp->auth.tfm = NULL; | 284 | esp->auth.tfm = NULL; |
284 | kfree(esp->auth.work_icv); | 285 | kfree(esp->auth.work_icv); |
285 | esp->auth.work_icv = NULL; | 286 | esp->auth.work_icv = NULL; |
@@ -308,24 +309,29 @@ static int esp6_init_state(struct xfrm_state *x) | |||
308 | 309 | ||
309 | if (x->aalg) { | 310 | if (x->aalg) { |
310 | struct xfrm_algo_desc *aalg_desc; | 311 | struct xfrm_algo_desc *aalg_desc; |
312 | struct crypto_hash *hash; | ||
311 | 313 | ||
312 | esp->auth.key = x->aalg->alg_key; | 314 | esp->auth.key = x->aalg->alg_key; |
313 | esp->auth.key_len = (x->aalg->alg_key_len+7)/8; | 315 | esp->auth.key_len = (x->aalg->alg_key_len+7)/8; |
314 | esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); | 316 | hash = crypto_alloc_hash(x->aalg->alg_name, 0, |
315 | if (esp->auth.tfm == NULL) | 317 | CRYPTO_ALG_ASYNC); |
318 | if (IS_ERR(hash)) | ||
319 | goto error; | ||
320 | |||
321 | esp->auth.tfm = hash; | ||
322 | if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len)) | ||
316 | goto error; | 323 | goto error; |
317 | esp->auth.icv = esp_hmac_digest; | ||
318 | 324 | ||
319 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); | 325 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); |
320 | BUG_ON(!aalg_desc); | 326 | BUG_ON(!aalg_desc); |
321 | 327 | ||
322 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != | 328 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != |
323 | crypto_tfm_alg_digestsize(esp->auth.tfm)) { | 329 | crypto_hash_digestsize(hash)) { |
324 | printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", | 330 | NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", |
325 | x->aalg->alg_name, | 331 | x->aalg->alg_name, |
326 | crypto_tfm_alg_digestsize(esp->auth.tfm), | 332 | crypto_hash_digestsize(hash), |
327 | aalg_desc->uinfo.auth.icv_fullbits/8); | 333 | aalg_desc->uinfo.auth.icv_fullbits/8); |
328 | goto error; | 334 | goto error; |
329 | } | 335 | } |
330 | 336 | ||
331 | esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; | 337 | esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; |
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 9b03d8497fba..87918f281bb4 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c | |||
@@ -30,7 +30,8 @@ | |||
30 | */ | 30 | */ |
31 | static struct xfrm_algo_desc aalg_list[] = { | 31 | static struct xfrm_algo_desc aalg_list[] = { |
32 | { | 32 | { |
33 | .name = "digest_null", | 33 | .name = "hmac(digest_null)", |
34 | .compat = "digest_null", | ||
34 | 35 | ||
35 | .uinfo = { | 36 | .uinfo = { |
36 | .auth = { | 37 | .auth = { |
@@ -47,7 +48,8 @@ static struct xfrm_algo_desc aalg_list[] = { | |||
47 | } | 48 | } |
48 | }, | 49 | }, |
49 | { | 50 | { |
50 | .name = "md5", | 51 | .name = "hmac(md5)", |
52 | .compat = "md5", | ||
51 | 53 | ||
52 | .uinfo = { | 54 | .uinfo = { |
53 | .auth = { | 55 | .auth = { |
@@ -64,7 +66,8 @@ static struct xfrm_algo_desc aalg_list[] = { | |||
64 | } | 66 | } |
65 | }, | 67 | }, |
66 | { | 68 | { |
67 | .name = "sha1", | 69 | .name = "hmac(sha1)", |
70 | .compat = "sha1", | ||
68 | 71 | ||
69 | .uinfo = { | 72 | .uinfo = { |
70 | .auth = { | 73 | .auth = { |
@@ -81,7 +84,8 @@ static struct xfrm_algo_desc aalg_list[] = { | |||
81 | } | 84 | } |
82 | }, | 85 | }, |
83 | { | 86 | { |
84 | .name = "sha256", | 87 | .name = "hmac(sha256)", |
88 | .compat = "sha256", | ||
85 | 89 | ||
86 | .uinfo = { | 90 | .uinfo = { |
87 | .auth = { | 91 | .auth = { |
@@ -98,7 +102,8 @@ static struct xfrm_algo_desc aalg_list[] = { | |||
98 | } | 102 | } |
99 | }, | 103 | }, |
100 | { | 104 | { |
101 | .name = "ripemd160", | 105 | .name = "hmac(ripemd160)", |
106 | .compat = "ripemd160", | ||
102 | 107 | ||
103 | .uinfo = { | 108 | .uinfo = { |
104 | .auth = { | 109 | .auth = { |
@@ -480,11 +485,12 @@ EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); | |||
480 | 485 | ||
481 | /* Move to common area: it is shared with AH. */ | 486 | /* Move to common area: it is shared with AH. */ |
482 | 487 | ||
483 | void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, | 488 | int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, |
484 | int offset, int len, icv_update_fn_t icv_update) | 489 | int offset, int len, icv_update_fn_t icv_update) |
485 | { | 490 | { |
486 | int start = skb_headlen(skb); | 491 | int start = skb_headlen(skb); |
487 | int i, copy = start - offset; | 492 | int i, copy = start - offset; |
493 | int err; | ||
488 | struct scatterlist sg; | 494 | struct scatterlist sg; |
489 | 495 | ||
490 | /* Checksum header. */ | 496 | /* Checksum header. */ |
@@ -496,10 +502,12 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, | |||
496 | sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; | 502 | sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; |
497 | sg.length = copy; | 503 | sg.length = copy; |
498 | 504 | ||
499 | icv_update(tfm, &sg, 1); | 505 | err = icv_update(desc, &sg, copy); |
506 | if (unlikely(err)) | ||
507 | return err; | ||
500 | 508 | ||
501 | if ((len -= copy) == 0) | 509 | if ((len -= copy) == 0) |
502 | return; | 510 | return 0; |
503 | offset += copy; | 511 | offset += copy; |
504 | } | 512 | } |
505 | 513 | ||
@@ -519,10 +527,12 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, | |||
519 | sg.offset = frag->page_offset + offset-start; | 527 | sg.offset = frag->page_offset + offset-start; |
520 | sg.length = copy; | 528 | sg.length = copy; |
521 | 529 | ||
522 | icv_update(tfm, &sg, 1); | 530 | err = icv_update(desc, &sg, copy); |
531 | if (unlikely(err)) | ||
532 | return err; | ||
523 | 533 | ||
524 | if (!(len -= copy)) | 534 | if (!(len -= copy)) |
525 | return; | 535 | return 0; |
526 | offset += copy; | 536 | offset += copy; |
527 | } | 537 | } |
528 | start = end; | 538 | start = end; |
@@ -540,15 +550,19 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, | |||
540 | if ((copy = end - offset) > 0) { | 550 | if ((copy = end - offset) > 0) { |
541 | if (copy > len) | 551 | if (copy > len) |
542 | copy = len; | 552 | copy = len; |
543 | skb_icv_walk(list, tfm, offset-start, copy, icv_update); | 553 | err = skb_icv_walk(list, desc, offset-start, |
554 | copy, icv_update); | ||
555 | if (unlikely(err)) | ||
556 | return err; | ||
544 | if ((len -= copy) == 0) | 557 | if ((len -= copy) == 0) |
545 | return; | 558 | return 0; |
546 | offset += copy; | 559 | offset += copy; |
547 | } | 560 | } |
548 | start = end; | 561 | start = end; |
549 | } | 562 | } |
550 | } | 563 | } |
551 | BUG_ON(len); | 564 | BUG_ON(len); |
565 | return 0; | ||
552 | } | 566 | } |
553 | EXPORT_SYMBOL_GPL(skb_icv_walk); | 567 | EXPORT_SYMBOL_GPL(skb_icv_walk); |
554 | 568 | ||