diff options
Diffstat (limited to 'net/ipv4/ah4.c')
-rw-r--r-- | net/ipv4/ah4.c | 36 |
1 files changed, 24 insertions, 12 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 | } |