Blame view

net/ipv6/esp6.c 10.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   * Copyright (C)2002 USAGI/WIDE Project
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
3
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
8
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
13
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
19
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   * Authors
   *
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
20
   *	Mitsuru KANDA @USAGI       : IPv6 Support
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
   * 	Kazunori MIYAZAWA @USAGI   :
   * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
23
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
   * 	This file is derived from net/ipv4/esp.c
   */
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
26
  #include <linux/err.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
  #include <linux/module.h>
  #include <net/ip.h>
  #include <net/xfrm.h>
  #include <net/esp.h>
  #include <asm/scatterlist.h>
  #include <linux/crypto.h>
a02a64223   Herbert Xu   [IPSEC]: Use ALIG...
33
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
  #include <linux/pfkeyv2.h>
  #include <linux/random.h>
  #include <net/icmp.h>
  #include <net/ipv6.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
38
  #include <net/protocol.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
  #include <linux/icmpv6.h>
  
  static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
  {
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
  	struct ipv6hdr *top_iph;
  	struct ipv6_esp_hdr *esph;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
46
47
  	struct crypto_blkcipher *tfm;
  	struct blkcipher_desc desc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
  	struct sk_buff *trailer;
  	int blksize;
  	int clen;
  	int alen;
  	int nfrags;
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
53
  	u8 *tail;
ea2ae17d6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
54
55
56
  	struct esp_data *esp = x->data;
  	int hdr_len = (skb_transport_offset(skb) +
  		       sizeof(*esph) + esp->conf.ivlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
60
61
62
63
64
65
66
67
68
  
  	/* Strip IP+ESP header. */
  	__skb_pull(skb, hdr_len);
  
  	/* Now skb is pure payload to encrypt */
  	err = -ENOMEM;
  
  	/* Round to block size */
  	clen = skb->len;
  
  	alen = esp->auth.icv_trunc_len;
  	tfm = esp->conf.tfm;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
69
70
71
  	desc.tfm = tfm;
  	desc.flags = 0;
  	blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
a02a64223   Herbert Xu   [IPSEC]: Use ALIG...
72
  	clen = ALIGN(clen + 2, blksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  	if (esp->conf.padlen)
a02a64223   Herbert Xu   [IPSEC]: Use ALIG...
74
  		clen = ALIGN(clen, esp->conf.padlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
  
  	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
  		goto error;
  	}
  
  	/* Fill padding... */
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
81
  	tail = skb_tail_pointer(trailer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
84
  	do {
  		int i;
  		for (i=0; i<clen-skb->len - 2; i++)
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
85
  			tail[i] = i + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  	} while (0);
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
87
  	tail[clen-skb->len - 2] = (clen - skb->len) - 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
  	pskb_put(skb, trailer, clen - skb->len);
  
  	top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len);
9c70220b7   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
91
  	esph = (struct ipv6_esp_hdr *)skb_transport_header(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  	top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
557922584   Patrick McHardy   [XFRM]: esp: fix ...
93
  	*(skb_tail_pointer(trailer) - 1) = *skb_network_header(skb);
d56f90a7c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
94
  	*skb_network_header(skb) = IPPROTO_ESP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
  
  	esph->spi = x->id.spi;
  	esph->seq_no = htonl(++x->replay.oseq);
9500e8a81   Jamal Hadi Salim   [IPSEC]: Sync ser...
98
  	xfrm_aevent_doreplay(x);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

e4bec827f   David S. Miller   [IPSEC] esp: Defe...
100
101
102
103
104
  	if (esp->conf.ivlen) {
  		if (unlikely(!esp->conf.ivinitted)) {
  			get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
  			esp->conf.ivinitted = 1;
  		}
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
105
  		crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
e4bec827f   David S. Miller   [IPSEC] esp: Defe...
106
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
114
115
116
  
  	do {
  		struct scatterlist *sg = &esp->sgbuf[0];
  
  		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
  			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
  			if (!sg)
  				goto error;
  		}
  		skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
117
  		err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
120
  		if (unlikely(sg != &esp->sgbuf[0]))
  			kfree(sg);
  	} while (0);
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
121
122
  	if (unlikely(err))
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  	if (esp->conf.ivlen) {
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
124
125
  		memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen);
  		crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
  	}
  
  	if (esp->auth.icv_full_len) {
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
129
130
131
  		err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
  				     sizeof(*esph) + esp->conf.ivlen + clen);
  		memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
  error:
  	return err;
  }
e695633e2   Herbert Xu   [IPSEC]: Kill unu...
136
  static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
  {
  	struct ipv6hdr *iph;
  	struct ipv6_esp_hdr *esph;
  	struct esp_data *esp = x->data;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
141
142
  	struct crypto_blkcipher *tfm = esp->conf.tfm;
  	struct blkcipher_desc desc = { .tfm = tfm };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  	struct sk_buff *trailer;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
144
  	int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  	int alen = esp->auth.icv_trunc_len;
  	int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
cfe1fc775   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
147
  	int hdr_len = skb_network_header_len(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  	int nfrags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
151
152
  	int ret = 0;
  
  	if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) {
  		ret = -EINVAL;
31a4ab930   Herbert Xu   [IPSEC] proto: Mo...
153
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
  	}
  
  	if (elen <= 0 || (elen & (blksize-1))) {
  		ret = -EINVAL;
31a4ab930   Herbert Xu   [IPSEC] proto: Mo...
158
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  
  	/* If integrity check is required, do this. */
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
162
  	if (esp->auth.icv_full_len) {
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
163
  		u8 sum[alen];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
165
166
167
  		ret = esp_mac_digest(esp, skb, 0, skb->len - alen);
  		if (ret)
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168

07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
169
  		if (skb_copy_bits(skb, skb->len - alen, sum, alen))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  			BUG();
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
171
  		if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  			x->stats.integrity_failed++;
  			ret = -EINVAL;
  			goto out;
  		}
  	}
  
  	if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0) {
  		ret = -EINVAL;
  		goto out;
  	}
  
  	skb->ip_summed = CHECKSUM_NONE;
  
  	esph = (struct ipv6_esp_hdr*)skb->data;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
186
  	iph = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
  
  	/* Get ivec. This can be wrong, check against another impls. */
  	if (esp->conf.ivlen)
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
190
  		crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191

1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
192
  	{
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
196
197
198
199
200
201
202
203
204
  		u8 nexthdr[2];
  		struct scatterlist *sg = &esp->sgbuf[0];
  		u8 padlen;
  
  		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
  			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
  			if (!sg) {
  				ret = -ENOMEM;
  				goto out;
  			}
  		}
  		skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen);
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
205
  		ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
  		if (unlikely(sg != &esp->sgbuf[0]))
  			kfree(sg);
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
208
209
  		if (unlikely(ret))
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
213
214
215
  
  		if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
  			BUG();
  
  		padlen = nexthdr[0];
  		if (padlen+2 >= elen) {
64ce20730   Patrick McHardy   [NET]: Make NETDE...
216
217
  			LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d
  ", padlen+2, elen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
  			ret = -EINVAL;
  			goto out;
  		}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
221
  		/* ... check padding bits here. Silly. :-) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
  
  		pskb_trim(skb, skb->len - alen - padlen - 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
  		ret = nexthdr[1];
  	}
967b05f64   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
226
227
  	__skb_pull(skb, sizeof(*esph) + esp->conf.ivlen);
  	skb_set_transport_header(skb, -hdr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
  	return ret;
  }
c5c252389   Patrick McHardy   [XFRM]: Optimize ...
231
  static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  {
  	struct esp_data *esp = x->data;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
234
  	u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
c5c252389   Patrick McHardy   [XFRM]: Optimize ...
235
236
  	u32 align = max_t(u32, blksize, esp->conf.padlen);
  	u32 rem;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

c5c252389   Patrick McHardy   [XFRM]: Optimize ...
238
239
240
241
242
  	mtu -= x->props.header_len + esp->auth.icv_trunc_len;
  	rem = mtu & (align - 1);
  	mtu &= ~(align - 1);
  
  	if (x->props.mode != XFRM_MODE_TUNNEL) {
d4875b049   Herbert Xu   [IPSEC] Fix block...
243
  		u32 padsize = ((blksize - 1) & 7) + 1;
c5c252389   Patrick McHardy   [XFRM]: Optimize ...
244
245
  		mtu -= blksize - padsize;
  		mtu += min_t(u32, blksize - padsize, rem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247

c5c252389   Patrick McHardy   [XFRM]: Optimize ...
248
  	return mtu - 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
  }
  
  static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
252
  		     int type, int code, int offset, __be32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
  {
  	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
  	struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset);
  	struct xfrm_state *x;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
257
  	if (type != ICMPV6_DEST_UNREACH &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
261
262
263
  	    type != ICMPV6_PKT_TOOBIG)
  		return;
  
  	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
  	if (!x)
  		return;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
264
265
  	printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
268
269
270
271
272
273
274
275
  			ntohl(esph->spi), NIP6(iph->daddr));
  	xfrm_state_put(x);
  }
  
  static void esp6_destroy(struct xfrm_state *x)
  {
  	struct esp_data *esp = x->data;
  
  	if (!esp)
  		return;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
276
  	crypto_free_blkcipher(esp->conf.tfm);
573dbd959   Jesper Juhl   [CRYPTO]: crypto_...
277
278
279
  	esp->conf.tfm = NULL;
  	kfree(esp->conf.ivec);
  	esp->conf.ivec = NULL;
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
280
  	crypto_free_hash(esp->auth.tfm);
573dbd959   Jesper Juhl   [CRYPTO]: crypto_...
281
282
283
  	esp->auth.tfm = NULL;
  	kfree(esp->auth.work_icv);
  	esp->auth.work_icv = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
  	kfree(esp);
  }
72cb6962a   Herbert Xu   [IPSEC]: Add xfrm...
286
  static int esp6_init_state(struct xfrm_state *x)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
  {
  	struct esp_data *esp = NULL;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
289
  	struct crypto_blkcipher *tfm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
292
293
294
295
296
297
298
299
300
  
  	/* null auth and encryption can have zero length keys */
  	if (x->aalg) {
  		if (x->aalg->alg_key_len > 512)
  			goto error;
  	}
  	if (x->ealg == NULL)
  		goto error;
  
  	if (x->encap)
  		goto error;
0c600eda4   Ingo Oeser   [IPV6]: Nearly co...
301
  	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
  	if (esp == NULL)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
  	if (x->aalg) {
  		struct xfrm_algo_desc *aalg_desc;
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
306
  		struct crypto_hash *hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
  
  		esp->auth.key = x->aalg->alg_key;
  		esp->auth.key_len = (x->aalg->alg_key_len+7)/8;
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
310
311
312
313
314
315
316
  		hash = crypto_alloc_hash(x->aalg->alg_name, 0,
  					 CRYPTO_ALG_ASYNC);
  		if (IS_ERR(hash))
  			goto error;
  
  		esp->auth.tfm = hash;
  		if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  			goto error;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
318

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
  		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
  		BUG_ON(!aalg_desc);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
321

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
07d4ee583   Herbert Xu   [IPSEC]: Use HMAC...
323
324
325
326
327
328
329
  		    crypto_hash_digestsize(hash)) {
  			NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu
  ",
  				 x->aalg->alg_name,
  				 crypto_hash_digestsize(hash),
  				 aalg_desc->uinfo.auth.icv_fullbits/8);
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
  		}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
331

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
  		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
  		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
334

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
339
340
  		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
  		if (!esp->auth.work_icv)
  			goto error;
  	}
  	esp->conf.key = x->ealg->alg_key;
  	esp->conf.key_len = (x->ealg->alg_key_len+7)/8;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
341
342
  	tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC);
  	if (IS_ERR(tfm))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  		goto error;
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
344
345
  	esp->conf.tfm = tfm;
  	esp->conf.ivlen = crypto_blkcipher_ivsize(tfm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
  	esp->conf.padlen = 0;
  	if (esp->conf.ivlen) {
  		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
  		if (unlikely(esp->conf.ivec == NULL))
  			goto error;
e4bec827f   David S. Miller   [IPSEC] esp: Defe...
351
  		esp->conf.ivinitted = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  	}
6b7326c84   Herbert Xu   [IPSEC] ESP: Use ...
353
  	if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
  		goto error;
  	x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
7e49e6de3   Masahide NAKAMURA   [XFRM]: Add XFRM_...
356
  	if (x->props.mode == XFRM_MODE_TUNNEL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
  		x->props.header_len += sizeof(struct ipv6hdr);
  	x->data = esp;
  	return 0;
  
  error:
  	x->data = esp;
  	esp6_destroy(x);
  	x->data = NULL;
  	return -EINVAL;
  }
  
  static struct xfrm_type esp6_type =
  {
  	.description	= "ESP6",
  	.owner	     	= THIS_MODULE,
  	.proto	     	= IPPROTO_ESP,
  	.init_state	= esp6_init_state,
  	.destructor	= esp6_destroy,
c5c252389   Patrick McHardy   [XFRM]: Optimize ...
375
  	.get_mtu	= esp6_get_mtu,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  	.input		= esp6_input,
aee5adb43   Masahide NAKAMURA   [XFRM] STATE: Add...
377
378
  	.output		= esp6_output,
  	.hdr_offset	= xfrm6_find_1stfragopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  };
  
  static struct inet6_protocol esp6_protocol = {
  	.handler 	=	xfrm6_rcv,
  	.err_handler	=	esp6_err,
  	.flags		=	INET6_PROTO_NOPOLICY,
  };
  
  static int __init esp6_init(void)
  {
  	if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
  		printk(KERN_INFO "ipv6 esp init: can't add xfrm type
  ");
  		return -EAGAIN;
  	}
  	if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) {
  		printk(KERN_INFO "ipv6 esp init: can't add protocol
  ");
  		xfrm_unregister_type(&esp6_type, AF_INET6);
  		return -EAGAIN;
  	}
  
  	return 0;
  }
  
  static void __exit esp6_fini(void)
  {
  	if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0)
  		printk(KERN_INFO "ipv6 esp close: can't remove protocol
  ");
  	if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0)
  		printk(KERN_INFO "ipv6 esp close: can't remove xfrm type
  ");
  }
  
  module_init(esp6_init);
  module_exit(esp6_fini);
  
  MODULE_LICENSE("GPL");
d3d6dd3ad   Masahide NAKAMURA   [XFRM]: Add modul...
418
  MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);