aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/esp4.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-09-22 20:10:23 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-22 20:10:23 -0400
commit28eb177dfa5982d132edceed891cb3885df258bb (patch)
tree5f8fdc37ad1d8d0793e9c47da7d908b97c814ffb /net/ipv4/esp4.c
parentfd8ae94eea9bb4269d6dff1b47b9dc741bd70d0b (diff)
parentdb392219c5f572610645696e3672f6ea38783a65 (diff)
Merge branch 'master' into upstream
Conflicts: net/ieee80211/ieee80211_crypt_tkip.c net/ieee80211/ieee80211_crypt_wep.c
Diffstat (limited to 'net/ipv4/esp4.c')
-rw-r--r--net/ipv4/esp4.c85
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
126error: 131error:
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:
254static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) 265static 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)
307static int esp_init_state(struct xfrm_state *x) 318static 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)