diff options
Diffstat (limited to 'net/ipv4/esp4.c')
-rw-r--r-- | net/ipv4/esp4.c | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index fc2f8ce441de..b428489f6ccd 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.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> |
@@ -16,7 +17,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
16 | int err; | 17 | int err; |
17 | struct iphdr *top_iph; | 18 | struct iphdr *top_iph; |
18 | struct ip_esp_hdr *esph; | 19 | struct ip_esp_hdr *esph; |
19 | struct crypto_tfm *tfm; | 20 | struct crypto_blkcipher *tfm; |
21 | struct blkcipher_desc desc; | ||
20 | struct esp_data *esp; | 22 | struct esp_data *esp; |
21 | struct sk_buff *trailer; | 23 | struct sk_buff *trailer; |
22 | int blksize; | 24 | int blksize; |
@@ -36,7 +38,9 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
36 | esp = x->data; | 38 | esp = x->data; |
37 | alen = esp->auth.icv_trunc_len; | 39 | alen = esp->auth.icv_trunc_len; |
38 | tfm = esp->conf.tfm; | 40 | tfm = esp->conf.tfm; |
39 | blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); | 41 | desc.tfm = tfm; |
42 | desc.flags = 0; | ||
43 | blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); | ||
40 | clen = ALIGN(clen + 2, blksize); | 44 | clen = ALIGN(clen + 2, blksize); |
41 | if (esp->conf.padlen) | 45 | if (esp->conf.padlen) |
42 | clen = ALIGN(clen, esp->conf.padlen); | 46 | clen = ALIGN(clen, esp->conf.padlen); |
@@ -92,7 +96,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
92 | xfrm_aevent_doreplay(x); | 96 | xfrm_aevent_doreplay(x); |
93 | 97 | ||
94 | if (esp->conf.ivlen) | 98 | if (esp->conf.ivlen) |
95 | crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 99 | crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); |
96 | 100 | ||
97 | do { | 101 | do { |
98 | struct scatterlist *sg = &esp->sgbuf[0]; | 102 | struct scatterlist *sg = &esp->sgbuf[0]; |
@@ -103,26 +107,27 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
103 | goto error; | 107 | goto error; |
104 | } | 108 | } |
105 | skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); | 109 | skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); |
106 | crypto_cipher_encrypt(tfm, sg, sg, clen); | 110 | err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); |
107 | if (unlikely(sg != &esp->sgbuf[0])) | 111 | if (unlikely(sg != &esp->sgbuf[0])) |
108 | kfree(sg); | 112 | kfree(sg); |
109 | } while (0); | 113 | } while (0); |
110 | 114 | ||
115 | if (unlikely(err)) | ||
116 | goto error; | ||
117 | |||
111 | if (esp->conf.ivlen) { | 118 | if (esp->conf.ivlen) { |
112 | memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 119 | memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen); |
113 | crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 120 | crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen); |
114 | } | 121 | } |
115 | 122 | ||
116 | if (esp->auth.icv_full_len) { | 123 | if (esp->auth.icv_full_len) { |
117 | esp->auth.icv(esp, skb, (u8*)esph-skb->data, | 124 | err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data, |
118 | sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); | 125 | sizeof(*esph) + esp->conf.ivlen + clen); |
119 | pskb_put(skb, trailer, alen); | 126 | memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen); |
120 | } | 127 | } |
121 | 128 | ||
122 | ip_send_check(top_iph); | 129 | ip_send_check(top_iph); |
123 | 130 | ||
124 | err = 0; | ||
125 | |||
126 | error: | 131 | error: |
127 | return err; | 132 | return err; |
128 | } | 133 | } |
@@ -137,8 +142,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
137 | struct iphdr *iph; | 142 | struct iphdr *iph; |
138 | struct ip_esp_hdr *esph; | 143 | struct ip_esp_hdr *esph; |
139 | struct esp_data *esp = x->data; | 144 | struct esp_data *esp = x->data; |
145 | struct crypto_blkcipher *tfm = esp->conf.tfm; | ||
146 | struct blkcipher_desc desc = { .tfm = tfm }; | ||
140 | struct sk_buff *trailer; | 147 | struct sk_buff *trailer; |
141 | int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); | 148 | int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); |
142 | int alen = esp->auth.icv_trunc_len; | 149 | int alen = esp->auth.icv_trunc_len; |
143 | int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; | 150 | int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; |
144 | int nfrags; | 151 | int nfrags; |
@@ -146,6 +153,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
146 | u8 nexthdr[2]; | 153 | u8 nexthdr[2]; |
147 | struct scatterlist *sg; | 154 | struct scatterlist *sg; |
148 | int padlen; | 155 | int padlen; |
156 | int err; | ||
149 | 157 | ||
150 | if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) | 158 | if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) |
151 | goto out; | 159 | goto out; |
@@ -155,15 +163,16 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
155 | 163 | ||
156 | /* If integrity check is required, do this. */ | 164 | /* If integrity check is required, do this. */ |
157 | if (esp->auth.icv_full_len) { | 165 | if (esp->auth.icv_full_len) { |
158 | u8 sum[esp->auth.icv_full_len]; | 166 | u8 sum[alen]; |
159 | u8 sum1[alen]; | ||
160 | |||
161 | esp->auth.icv(esp, skb, 0, skb->len-alen, sum); | ||
162 | 167 | ||
163 | 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)) | ||
164 | BUG(); | 173 | BUG(); |
165 | 174 | ||
166 | if (unlikely(memcmp(sum, sum1, alen))) { | 175 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { |
167 | x->stats.integrity_failed++; | 176 | x->stats.integrity_failed++; |
168 | goto out; | 177 | goto out; |
169 | } | 178 | } |
@@ -178,7 +187,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
178 | 187 | ||
179 | /* Get ivec. This can be wrong, check against another impls. */ | 188 | /* Get ivec. This can be wrong, check against another impls. */ |
180 | if (esp->conf.ivlen) | 189 | if (esp->conf.ivlen) |
181 | crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); | 190 | crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen); |
182 | 191 | ||
183 | sg = &esp->sgbuf[0]; | 192 | sg = &esp->sgbuf[0]; |
184 | 193 | ||
@@ -188,9 +197,11 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
188 | goto out; | 197 | goto out; |
189 | } | 198 | } |
190 | skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); | 199 | skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); |
191 | crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); | 200 | err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); |
192 | if (unlikely(sg != &esp->sgbuf[0])) | 201 | if (unlikely(sg != &esp->sgbuf[0])) |
193 | kfree(sg); | 202 | kfree(sg); |
203 | if (unlikely(err)) | ||
204 | return err; | ||
194 | 205 | ||
195 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) | 206 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) |
196 | BUG(); | 207 | BUG(); |
@@ -254,7 +265,7 @@ out: | |||
254 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) | 265 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) |
255 | { | 266 | { |
256 | struct esp_data *esp = x->data; | 267 | struct esp_data *esp = x->data; |
257 | u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); | 268 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); |
258 | 269 | ||
259 | if (x->props.mode) { | 270 | if (x->props.mode) { |
260 | mtu = ALIGN(mtu + 2, blksize); | 271 | mtu = ALIGN(mtu + 2, blksize); |
@@ -293,11 +304,11 @@ static void esp_destroy(struct xfrm_state *x) | |||
293 | if (!esp) | 304 | if (!esp) |
294 | return; | 305 | return; |
295 | 306 | ||
296 | crypto_free_tfm(esp->conf.tfm); | 307 | crypto_free_blkcipher(esp->conf.tfm); |
297 | esp->conf.tfm = NULL; | 308 | esp->conf.tfm = NULL; |
298 | kfree(esp->conf.ivec); | 309 | kfree(esp->conf.ivec); |
299 | esp->conf.ivec = NULL; | 310 | esp->conf.ivec = NULL; |
300 | crypto_free_tfm(esp->auth.tfm); | 311 | crypto_free_hash(esp->auth.tfm); |
301 | esp->auth.tfm = NULL; | 312 | esp->auth.tfm = NULL; |
302 | kfree(esp->auth.work_icv); | 313 | kfree(esp->auth.work_icv); |
303 | esp->auth.work_icv = NULL; | 314 | esp->auth.work_icv = NULL; |
@@ -307,6 +318,7 @@ static void esp_destroy(struct xfrm_state *x) | |||
307 | static int esp_init_state(struct xfrm_state *x) | 318 | static int esp_init_state(struct xfrm_state *x) |
308 | { | 319 | { |
309 | struct esp_data *esp = NULL; | 320 | struct esp_data *esp = NULL; |
321 | struct crypto_blkcipher *tfm; | ||
310 | 322 | ||
311 | /* null auth and encryption can have zero length keys */ | 323 | /* null auth and encryption can have zero length keys */ |
312 | if (x->aalg) { | 324 | if (x->aalg) { |
@@ -322,22 +334,27 @@ static int esp_init_state(struct xfrm_state *x) | |||
322 | 334 | ||
323 | if (x->aalg) { | 335 | if (x->aalg) { |
324 | struct xfrm_algo_desc *aalg_desc; | 336 | struct xfrm_algo_desc *aalg_desc; |
337 | struct crypto_hash *hash; | ||
325 | 338 | ||
326 | esp->auth.key = x->aalg->alg_key; | 339 | esp->auth.key = x->aalg->alg_key; |
327 | esp->auth.key_len = (x->aalg->alg_key_len+7)/8; | 340 | esp->auth.key_len = (x->aalg->alg_key_len+7)/8; |
328 | esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); | 341 | hash = crypto_alloc_hash(x->aalg->alg_name, 0, |
329 | 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)) | ||
330 | goto error; | 348 | goto error; |
331 | esp->auth.icv = esp_hmac_digest; | ||
332 | 349 | ||
333 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); | 350 | aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); |
334 | BUG_ON(!aalg_desc); | 351 | BUG_ON(!aalg_desc); |
335 | 352 | ||
336 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != | 353 | if (aalg_desc->uinfo.auth.icv_fullbits/8 != |
337 | crypto_tfm_alg_digestsize(esp->auth.tfm)) { | 354 | crypto_hash_digestsize(hash)) { |
338 | NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", | 355 | NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", |
339 | x->aalg->alg_name, | 356 | x->aalg->alg_name, |
340 | crypto_tfm_alg_digestsize(esp->auth.tfm), | 357 | crypto_hash_digestsize(hash), |
341 | aalg_desc->uinfo.auth.icv_fullbits/8); | 358 | aalg_desc->uinfo.auth.icv_fullbits/8); |
342 | goto error; | 359 | goto error; |
343 | } | 360 | } |
@@ -351,13 +368,11 @@ static int esp_init_state(struct xfrm_state *x) | |||
351 | } | 368 | } |
352 | esp->conf.key = x->ealg->alg_key; | 369 | esp->conf.key = x->ealg->alg_key; |
353 | esp->conf.key_len = (x->ealg->alg_key_len+7)/8; | 370 | esp->conf.key_len = (x->ealg->alg_key_len+7)/8; |
354 | if (x->props.ealgo == SADB_EALG_NULL) | 371 | tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC); |
355 | esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); | 372 | if (IS_ERR(tfm)) |
356 | else | ||
357 | esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); | ||
358 | if (esp->conf.tfm == NULL) | ||
359 | goto error; | 373 | goto error; |
360 | esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); | 374 | esp->conf.tfm = tfm; |
375 | esp->conf.ivlen = crypto_blkcipher_ivsize(tfm); | ||
361 | esp->conf.padlen = 0; | 376 | esp->conf.padlen = 0; |
362 | if (esp->conf.ivlen) { | 377 | if (esp->conf.ivlen) { |
363 | esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); | 378 | esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); |
@@ -365,7 +380,7 @@ static int esp_init_state(struct xfrm_state *x) | |||
365 | goto error; | 380 | goto error; |
366 | get_random_bytes(esp->conf.ivec, esp->conf.ivlen); | 381 | get_random_bytes(esp->conf.ivec, esp->conf.ivlen); |
367 | } | 382 | } |
368 | if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) | 383 | if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) |
369 | goto error; | 384 | goto error; |
370 | x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; | 385 | x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; |
371 | if (x->props.mode) | 386 | if (x->props.mode) |