Blame view
net/ipv6/esp6.c
15.7 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 |
/* * Copyright (C)2002 USAGI/WIDE Project |
1ab1457c4 [NET] IPV6: Fix w... |
3 |
* |
1da177e4c 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 [NET] IPV6: Fix w... |
8 |
* |
1da177e4c 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 [NET] IPV6: Fix w... |
13 |
* |
1da177e4c 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 [NET] IPV6: Fix w... |
20 |
* Mitsuru KANDA @USAGI : IPv6 Support |
1da177e4c Linux-2.6.12-rc2 |
21 22 |
* Kazunori MIYAZAWA @USAGI : * Kunihiro Ishiguro <kunihiro@ipinfusion.com> |
1ab1457c4 [NET] IPV6: Fix w... |
23 |
* |
1da177e4c Linux-2.6.12-rc2 |
24 25 |
* This file is derived from net/ipv4/esp.c */ |
38320c70d [IPSEC]: Use cryp... |
26 27 |
#include <crypto/aead.h> #include <crypto/authenc.h> |
6b7326c84 [IPSEC] ESP: Use ... |
28 |
#include <linux/err.h> |
1da177e4c Linux-2.6.12-rc2 |
29 30 31 32 |
#include <linux/module.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/esp.h> |
72998d8c8 [INET] ESP: Must ... |
33 |
#include <linux/scatterlist.h> |
a02a64223 [IPSEC]: Use ALIG... |
34 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
35 36 |
#include <linux/pfkeyv2.h> #include <linux/random.h> |
38320c70d [IPSEC]: Use cryp... |
37 |
#include <linux/slab.h> |
b7c6538cd [IPSEC]: Move sta... |
38 |
#include <linux/spinlock.h> |
1da177e4c Linux-2.6.12-rc2 |
39 40 |
#include <net/icmp.h> #include <net/ipv6.h> |
14c850212 [INET_SOCK]: Move... |
41 |
#include <net/protocol.h> |
1da177e4c Linux-2.6.12-rc2 |
42 |
#include <linux/icmpv6.h> |
38320c70d [IPSEC]: Use cryp... |
43 44 45 46 47 48 |
struct esp_skb_cb { struct xfrm_skb_cb xfrm; void *tmp; }; #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0])) |
040253c93 xfrm: Traffic Flo... |
49 |
static u32 esp6_get_mtu(struct xfrm_state *x, int mtu); |
38320c70d [IPSEC]: Use cryp... |
50 51 52 |
/* * Allocate an AEAD request structure with extra space for SG and IV. * |
d212a4c29 esp6: Add support... |
53 54 55 |
* For alignment considerations the upper 32 bits of the sequence number are * placed at the front, if present. Followed by the IV, the request and finally * the SG list. |
38320c70d [IPSEC]: Use cryp... |
56 57 58 |
* * TODO: Use spare space in skb for this where possible. */ |
d212a4c29 esp6: Add support... |
59 |
static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqihlen) |
38320c70d [IPSEC]: Use cryp... |
60 61 |
{ unsigned int len; |
d212a4c29 esp6: Add support... |
62 63 64 |
len = seqihlen; len += crypto_aead_ivsize(aead); |
38320c70d [IPSEC]: Use cryp... |
65 66 67 68 69 70 71 72 73 74 75 76 77 |
if (len) { len += crypto_aead_alignmask(aead) & ~(crypto_tfm_ctx_alignment() - 1); len = ALIGN(len, crypto_tfm_ctx_alignment()); } len += sizeof(struct aead_givcrypt_request) + crypto_aead_reqsize(aead); len = ALIGN(len, __alignof__(struct scatterlist)); len += sizeof(struct scatterlist) * nfrags; return kmalloc(len, GFP_ATOMIC); } |
d212a4c29 esp6: Add support... |
78 79 80 81 82 83 |
static inline __be32 *esp_tmp_seqhi(void *tmp) { return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32)); } static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen) |
38320c70d [IPSEC]: Use cryp... |
84 85 |
{ return crypto_aead_ivsize(aead) ? |
d212a4c29 esp6: Add support... |
86 87 |
PTR_ALIGN((u8 *)tmp + seqhilen, crypto_aead_alignmask(aead) + 1) : tmp + seqhilen; |
38320c70d [IPSEC]: Use cryp... |
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
} static inline struct aead_givcrypt_request *esp_tmp_givreq( struct crypto_aead *aead, u8 *iv) { struct aead_givcrypt_request *req; req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead), crypto_tfm_ctx_alignment()); aead_givcrypt_set_tfm(req, aead); return req; } static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv) { struct aead_request *req; req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead), crypto_tfm_ctx_alignment()); aead_request_set_tfm(req, aead); return req; } static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead, struct aead_request *req) { return (void *)ALIGN((unsigned long)(req + 1) + crypto_aead_reqsize(aead), __alignof__(struct scatterlist)); } static inline struct scatterlist *esp_givreq_sg( struct crypto_aead *aead, struct aead_givcrypt_request *req) { return (void *)ALIGN((unsigned long)(req + 1) + crypto_aead_reqsize(aead), __alignof__(struct scatterlist)); } static void esp_output_done(struct crypto_async_request *base, int err) { struct sk_buff *skb = base->data; kfree(ESP_SKB_CB(skb)->tmp); xfrm_output_resume(skb, err); } |
1da177e4c Linux-2.6.12-rc2 |
134 135 136 |
static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) { int err; |
87bdc48d3 [IPSEC]: Get rid ... |
137 |
struct ip_esp_hdr *esph; |
38320c70d [IPSEC]: Use cryp... |
138 139 140 141 |
struct crypto_aead *aead; struct aead_givcrypt_request *req; struct scatterlist *sg; struct scatterlist *asg; |
1da177e4c Linux-2.6.12-rc2 |
142 |
struct sk_buff *trailer; |
38320c70d [IPSEC]: Use cryp... |
143 |
void *tmp; |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 |
int blksize; int clen; int alen; |
040253c93 xfrm: Traffic Flo... |
147 148 |
int plen; int tfclen; |
1da177e4c Linux-2.6.12-rc2 |
149 |
int nfrags; |
d212a4c29 esp6: Add support... |
150 151 152 |
int assoclen; int sglists; int seqhilen; |
38320c70d [IPSEC]: Use cryp... |
153 |
u8 *iv; |
27a884dc3 [SK_BUFF]: Conver... |
154 |
u8 *tail; |
d212a4c29 esp6: Add support... |
155 |
__be32 *seqhi; |
ea2ae17d6 [SK_BUFF]: Introd... |
156 |
struct esp_data *esp = x->data; |
1da177e4c Linux-2.6.12-rc2 |
157 |
|
7b277b1a5 [IPSEC]: Set skb-... |
158 |
/* skb is pure payload to encrypt */ |
1da177e4c Linux-2.6.12-rc2 |
159 |
err = -ENOMEM; |
38320c70d [IPSEC]: Use cryp... |
160 161 |
aead = esp->aead; alen = crypto_aead_authsize(aead); |
040253c93 xfrm: Traffic Flo... |
162 163 164 165 166 167 168 169 170 |
tfclen = 0; if (x->tfcpad) { struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); u32 padto; padto = min(x->tfcpad, esp6_get_mtu(x, dst->child_mtu_cached)); if (skb->len < padto) tfclen = padto - skb->len; } |
38320c70d [IPSEC]: Use cryp... |
171 |
blksize = ALIGN(crypto_aead_blocksize(aead), 4); |
040253c93 xfrm: Traffic Flo... |
172 |
clen = ALIGN(skb->len + 2 + tfclen, blksize); |
38320c70d [IPSEC]: Use cryp... |
173 174 |
if (esp->padlen) clen = ALIGN(clen, esp->padlen); |
040253c93 xfrm: Traffic Flo... |
175 |
plen = clen - skb->len - tfclen; |
1da177e4c Linux-2.6.12-rc2 |
176 |
|
040253c93 xfrm: Traffic Flo... |
177 178 |
err = skb_cow_data(skb, tfclen + plen + alen, &trailer); if (err < 0) |
1da177e4c Linux-2.6.12-rc2 |
179 |
goto error; |
38320c70d [IPSEC]: Use cryp... |
180 |
nfrags = err; |
d212a4c29 esp6: Add support... |
181 182 183 184 185 186 187 188 189 190 191 |
assoclen = sizeof(*esph); sglists = 1; seqhilen = 0; if (x->props.flags & XFRM_STATE_ESN) { sglists += 2; seqhilen += sizeof(__be32); assoclen += seqhilen; } tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); |
38320c70d [IPSEC]: Use cryp... |
192 193 |
if (!tmp) goto error; |
d212a4c29 esp6: Add support... |
194 195 |
seqhi = esp_tmp_seqhi(tmp); iv = esp_tmp_iv(aead, tmp, seqhilen); |
38320c70d [IPSEC]: Use cryp... |
196 197 |
req = esp_tmp_givreq(aead, iv); asg = esp_givreq_sg(aead, req); |
d212a4c29 esp6: Add support... |
198 |
sg = asg + sglists; |
1da177e4c Linux-2.6.12-rc2 |
199 200 |
/* Fill padding... */ |
27a884dc3 [SK_BUFF]: Conver... |
201 |
tail = skb_tail_pointer(trailer); |
040253c93 xfrm: Traffic Flo... |
202 203 204 205 |
if (tfclen) { memset(tail, 0, tfclen); tail += tfclen; } |
1da177e4c Linux-2.6.12-rc2 |
206 207 |
do { int i; |
040253c93 xfrm: Traffic Flo... |
208 |
for (i = 0; i < plen - 2; i++) |
27a884dc3 [SK_BUFF]: Conver... |
209 |
tail[i] = i + 1; |
1da177e4c Linux-2.6.12-rc2 |
210 |
} while (0); |
040253c93 xfrm: Traffic Flo... |
211 212 |
tail[plen - 2] = plen - 2; tail[plen - 1] = *skb_mac_header(skb); |
38320c70d [IPSEC]: Use cryp... |
213 |
pskb_put(skb, trailer, clen - skb->len + alen); |
1da177e4c Linux-2.6.12-rc2 |
214 |
|
7b277b1a5 [IPSEC]: Set skb-... |
215 |
skb_push(skb, -skb_network_offset(skb)); |
87bdc48d3 [IPSEC]: Get rid ... |
216 |
esph = ip_esp_hdr(skb); |
007f0211a [IPSEC]: Store IP... |
217 |
*skb_mac_header(skb) = IPPROTO_ESP; |
1da177e4c Linux-2.6.12-rc2 |
218 219 |
esph->spi = x->id.spi; |
1ce3644ad xfrm: Use separat... |
220 |
esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); |
1da177e4c Linux-2.6.12-rc2 |
221 |
|
38320c70d [IPSEC]: Use cryp... |
222 223 224 225 |
sg_init_table(sg, nfrags); skb_to_sgvec(skb, sg, esph->enc_data + crypto_aead_ivsize(aead) - skb->data, clen + alen); |
d212a4c29 esp6: Add support... |
226 227 228 229 230 231 232 233 234 |
if ((x->props.flags & XFRM_STATE_ESN)) { sg_init_table(asg, 3); sg_set_buf(asg, &esph->spi, sizeof(__be32)); *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi); sg_set_buf(asg + 1, seqhi, seqhilen); sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32)); } else sg_init_one(asg, esph, sizeof(*esph)); |
b7c6538cd [IPSEC]: Move sta... |
235 |
|
38320c70d [IPSEC]: Use cryp... |
236 237 |
aead_givcrypt_set_callback(req, 0, esp_output_done, skb); aead_givcrypt_set_crypt(req, sg, sg, clen, iv); |
d212a4c29 esp6: Add support... |
238 |
aead_givcrypt_set_assoc(req, asg, assoclen); |
b318e0e4e [IPSEC]: Fix bogu... |
239 |
aead_givcrypt_set_giv(req, esph->enc_data, |
1ce3644ad xfrm: Use separat... |
240 |
XFRM_SKB_CB(skb)->seq.output.low); |
1da177e4c Linux-2.6.12-rc2 |
241 |
|
38320c70d [IPSEC]: Use cryp... |
242 243 244 245 |
ESP_SKB_CB(skb)->tmp = tmp; err = crypto_aead_givencrypt(req); if (err == -EINPROGRESS) goto error; |
1da177e4c Linux-2.6.12-rc2 |
246 |
|
38320c70d [IPSEC]: Use cryp... |
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
if (err == -EBUSY) err = NET_XMIT_DROP; kfree(tmp); error: return err; } static int esp_input_done2(struct sk_buff *skb, int err) { struct xfrm_state *x = xfrm_input_state(skb); struct esp_data *esp = x->data; struct crypto_aead *aead = esp->aead; int alen = crypto_aead_authsize(aead); int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead); int elen = skb->len - hlen; int hdr_len = skb_network_header_len(skb); int padlen; u8 nexthdr[2]; kfree(ESP_SKB_CB(skb)->tmp); |
1da177e4c Linux-2.6.12-rc2 |
269 |
|
6b7326c84 [IPSEC] ESP: Use ... |
270 |
if (unlikely(err)) |
38320c70d [IPSEC]: Use cryp... |
271 |
goto out; |
6b7326c84 [IPSEC] ESP: Use ... |
272 |
|
38320c70d [IPSEC]: Use cryp... |
273 274 |
if (skb_copy_bits(skb, skb->len - alen - 2, nexthdr, 2)) BUG(); |
1da177e4c Linux-2.6.12-rc2 |
275 |
|
38320c70d [IPSEC]: Use cryp... |
276 277 278 279 280 281 282 |
err = -EINVAL; padlen = nexthdr[0]; if (padlen + 2 + alen >= elen) { LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage " "padlen=%d, elen=%d ", padlen + 2, elen - alen); goto out; |
1da177e4c Linux-2.6.12-rc2 |
283 |
} |
38320c70d [IPSEC]: Use cryp... |
284 |
/* ... check padding bits here. Silly. :-) */ |
b7c6538cd [IPSEC]: Move sta... |
285 |
|
38320c70d [IPSEC]: Use cryp... |
286 287 288 289 290 291 292 293 294 295 296 |
pskb_trim(skb, skb->len - alen - padlen - 2); __skb_pull(skb, hlen); skb_set_transport_header(skb, -hdr_len); err = nexthdr[1]; /* RFC4303: Drop dummy packets without any error */ if (err == IPPROTO_NONE) err = -EINVAL; out: |
1da177e4c Linux-2.6.12-rc2 |
297 298 |
return err; } |
38320c70d [IPSEC]: Use cryp... |
299 300 301 302 303 304 |
static void esp_input_done(struct crypto_async_request *base, int err) { struct sk_buff *skb = base->data; xfrm_input_resume(skb, esp_input_done2(skb, err)); } |
e695633e2 [IPSEC]: Kill unu... |
305 |
static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
306 |
{ |
87bdc48d3 [IPSEC]: Get rid ... |
307 |
struct ip_esp_hdr *esph; |
1da177e4c Linux-2.6.12-rc2 |
308 |
struct esp_data *esp = x->data; |
38320c70d [IPSEC]: Use cryp... |
309 310 |
struct crypto_aead *aead = esp->aead; struct aead_request *req; |
1da177e4c Linux-2.6.12-rc2 |
311 |
struct sk_buff *trailer; |
38320c70d [IPSEC]: Use cryp... |
312 |
int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead); |
1da177e4c Linux-2.6.12-rc2 |
313 |
int nfrags; |
d212a4c29 esp6: Add support... |
314 315 316 |
int assoclen; int sglists; int seqhilen; |
1da177e4c Linux-2.6.12-rc2 |
317 |
int ret = 0; |
38320c70d [IPSEC]: Use cryp... |
318 |
void *tmp; |
d212a4c29 esp6: Add support... |
319 |
__be32 *seqhi; |
38320c70d [IPSEC]: Use cryp... |
320 321 322 |
u8 *iv; struct scatterlist *sg; struct scatterlist *asg; |
1da177e4c Linux-2.6.12-rc2 |
323 |
|
920fc941a [ESP]: Ensure IV ... |
324 |
if (!pskb_may_pull(skb, sizeof(*esph) + crypto_aead_ivsize(aead))) { |
1da177e4c Linux-2.6.12-rc2 |
325 |
ret = -EINVAL; |
31a4ab930 [IPSEC] proto: Mo... |
326 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
327 |
} |
38320c70d [IPSEC]: Use cryp... |
328 |
if (elen <= 0) { |
1da177e4c Linux-2.6.12-rc2 |
329 |
ret = -EINVAL; |
31a4ab930 [IPSEC] proto: Mo... |
330 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
331 |
} |
1da177e4c Linux-2.6.12-rc2 |
332 |
|
0ebea8ef3 [IPSEC]: Move sta... |
333 334 335 336 |
if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0) { ret = -EINVAL; goto out; } |
38320c70d [IPSEC]: Use cryp... |
337 |
ret = -ENOMEM; |
d212a4c29 esp6: Add support... |
338 339 340 341 342 343 344 345 346 347 348 349 |
assoclen = sizeof(*esph); sglists = 1; seqhilen = 0; if (x->props.flags & XFRM_STATE_ESN) { sglists += 2; seqhilen += sizeof(__be32); assoclen += seqhilen; } tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); |
38320c70d [IPSEC]: Use cryp... |
350 351 |
if (!tmp) goto out; |
1da177e4c Linux-2.6.12-rc2 |
352 |
|
38320c70d [IPSEC]: Use cryp... |
353 |
ESP_SKB_CB(skb)->tmp = tmp; |
d212a4c29 esp6: Add support... |
354 355 |
seqhi = esp_tmp_seqhi(tmp); iv = esp_tmp_iv(aead, tmp, seqhilen); |
38320c70d [IPSEC]: Use cryp... |
356 357 |
req = esp_tmp_req(aead, iv); asg = esp_req_sg(aead, req); |
c0a56e64a esp6: Fix scatter... |
358 |
sg = asg + sglists; |
1da177e4c Linux-2.6.12-rc2 |
359 |
|
38320c70d [IPSEC]: Use cryp... |
360 |
skb->ip_summed = CHECKSUM_NONE; |
1da177e4c Linux-2.6.12-rc2 |
361 |
|
87bdc48d3 [IPSEC]: Get rid ... |
362 |
esph = (struct ip_esp_hdr *)skb->data; |
1da177e4c Linux-2.6.12-rc2 |
363 364 |
/* Get ivec. This can be wrong, check against another impls. */ |
38320c70d [IPSEC]: Use cryp... |
365 |
iv = esph->enc_data; |
0ebea8ef3 [IPSEC]: Move sta... |
366 |
|
38320c70d [IPSEC]: Use cryp... |
367 368 |
sg_init_table(sg, nfrags); skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen); |
d212a4c29 esp6: Add support... |
369 370 371 372 373 374 375 376 377 |
if ((x->props.flags & XFRM_STATE_ESN)) { sg_init_table(asg, 3); sg_set_buf(asg, &esph->spi, sizeof(__be32)); *seqhi = XFRM_SKB_CB(skb)->seq.input.hi; sg_set_buf(asg + 1, seqhi, seqhilen); sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32)); } else sg_init_one(asg, esph, sizeof(*esph)); |
0ebea8ef3 [IPSEC]: Move sta... |
378 |
|
38320c70d [IPSEC]: Use cryp... |
379 380 |
aead_request_set_callback(req, 0, esp_input_done, skb); aead_request_set_crypt(req, sg, sg, elen, iv); |
d212a4c29 esp6: Add support... |
381 |
aead_request_set_assoc(req, asg, assoclen); |
1da177e4c Linux-2.6.12-rc2 |
382 |
|
38320c70d [IPSEC]: Use cryp... |
383 384 385 |
ret = crypto_aead_decrypt(req); if (ret == -EINPROGRESS) goto out; |
95a02cfd4 [IPv6] ESP: Disca... |
386 |
|
38320c70d [IPSEC]: Use cryp... |
387 |
ret = esp_input_done2(skb, ret); |
1da177e4c Linux-2.6.12-rc2 |
388 389 |
out: |
1da177e4c Linux-2.6.12-rc2 |
390 391 |
return ret; } |
c5c252389 [XFRM]: Optimize ... |
392 |
static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) |
1da177e4c Linux-2.6.12-rc2 |
393 394 |
{ struct esp_data *esp = x->data; |
38320c70d [IPSEC]: Use cryp... |
395 396 |
u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4); u32 align = max_t(u32, blksize, esp->padlen); |
c5c252389 [XFRM]: Optimize ... |
397 |
u32 rem; |
1da177e4c Linux-2.6.12-rc2 |
398 |
|
38320c70d [IPSEC]: Use cryp... |
399 |
mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); |
c5c252389 [XFRM]: Optimize ... |
400 401 402 403 |
rem = mtu & (align - 1); mtu &= ~(align - 1); if (x->props.mode != XFRM_MODE_TUNNEL) { |
d4875b049 [IPSEC] Fix block... |
404 |
u32 padsize = ((blksize - 1) & 7) + 1; |
c5c252389 [XFRM]: Optimize ... |
405 406 |
mtu -= blksize - padsize; mtu += min_t(u32, blksize - padsize, rem); |
1da177e4c Linux-2.6.12-rc2 |
407 |
} |
1da177e4c Linux-2.6.12-rc2 |
408 |
|
c5c252389 [XFRM]: Optimize ... |
409 |
return mtu - 2; |
1da177e4c Linux-2.6.12-rc2 |
410 411 412 |
} static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
d5fdd6bab ipv6: Use correct... |
413 |
u8 type, u8 code, int offset, __be32 info) |
1da177e4c Linux-2.6.12-rc2 |
414 |
{ |
4fb236bac netns xfrm: AH/ES... |
415 |
struct net *net = dev_net(skb->dev); |
b71d1d426 inet: constify ip... |
416 |
const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; |
87bdc48d3 [IPSEC]: Get rid ... |
417 |
struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset); |
1da177e4c Linux-2.6.12-rc2 |
418 |
struct xfrm_state *x; |
1ab1457c4 [NET] IPV6: Fix w... |
419 |
if (type != ICMPV6_DEST_UNREACH && |
1da177e4c Linux-2.6.12-rc2 |
420 421 |
type != ICMPV6_PKT_TOOBIG) return; |
b71d1d426 inet: constify ip... |
422 423 |
x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); |
1da177e4c Linux-2.6.12-rc2 |
424 425 |
if (!x) return; |
5b095d989 net: replace %p6 ... |
426 427 |
printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6 ", |
0c6ce78ab net: replace uses... |
428 |
ntohl(esph->spi), &iph->daddr); |
1da177e4c Linux-2.6.12-rc2 |
429 430 431 432 433 434 435 436 437 |
xfrm_state_put(x); } static void esp6_destroy(struct xfrm_state *x) { struct esp_data *esp = x->data; if (!esp) return; |
38320c70d [IPSEC]: Use cryp... |
438 |
crypto_free_aead(esp->aead); |
1da177e4c Linux-2.6.12-rc2 |
439 440 |
kfree(esp); } |
1a6509d99 [IPSEC]: Add supp... |
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 |
static int esp_init_aead(struct xfrm_state *x) { struct esp_data *esp = x->data; struct crypto_aead *aead; int err; aead = crypto_alloc_aead(x->aead->alg_name, 0, 0); err = PTR_ERR(aead); if (IS_ERR(aead)) goto error; esp->aead = aead; err = crypto_aead_setkey(aead, x->aead->alg_key, (x->aead->alg_key_len + 7) / 8); if (err) goto error; err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8); if (err) goto error; error: return err; } static int esp_init_authenc(struct xfrm_state *x) |
1da177e4c Linux-2.6.12-rc2 |
468 |
{ |
1a6509d99 [IPSEC]: Add supp... |
469 |
struct esp_data *esp = x->data; |
38320c70d [IPSEC]: Use cryp... |
470 471 472 473 474 475 |
struct crypto_aead *aead; struct crypto_authenc_key_param *param; struct rtattr *rta; char *key; char *p; char authenc_name[CRYPTO_MAX_ALG_NAME]; |
38320c70d [IPSEC]: Use cryp... |
476 477 |
unsigned int keylen; int err; |
1da177e4c Linux-2.6.12-rc2 |
478 |
|
1a6509d99 [IPSEC]: Add supp... |
479 |
err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
480 |
if (x->ealg == NULL) |
1a6509d99 [IPSEC]: Add supp... |
481 |
goto error; |
38320c70d [IPSEC]: Use cryp... |
482 |
|
1a6509d99 [IPSEC]: Add supp... |
483 |
err = -ENAMETOOLONG; |
d212a4c29 esp6: Add support... |
484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
if ((x->props.flags & XFRM_STATE_ESN)) { if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authencesn(%s,%s)", x->aalg ? x->aalg->alg_name : "digest_null", x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) goto error; } else { if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)", x->aalg ? x->aalg->alg_name : "digest_null", x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME) goto error; } |
38320c70d [IPSEC]: Use cryp... |
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 |
aead = crypto_alloc_aead(authenc_name, 0, 0); err = PTR_ERR(aead); if (IS_ERR(aead)) goto error; esp->aead = aead; keylen = (x->aalg ? (x->aalg->alg_key_len + 7) / 8 : 0) + (x->ealg->alg_key_len + 7) / 8 + RTA_SPACE(sizeof(*param)); err = -ENOMEM; key = kmalloc(keylen, GFP_KERNEL); if (!key) goto error; p = key; rta = (void *)p; rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM; rta->rta_len = RTA_LENGTH(sizeof(*param)); param = RTA_DATA(rta); p += RTA_SPACE(sizeof(*param)); |
1da177e4c Linux-2.6.12-rc2 |
519 520 |
if (x->aalg) { struct xfrm_algo_desc *aalg_desc; |
38320c70d [IPSEC]: Use cryp... |
521 522 |
memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8); p += (x->aalg->alg_key_len + 7) / 8; |
1ab1457c4 [NET] IPV6: Fix w... |
523 |
|
1da177e4c Linux-2.6.12-rc2 |
524 525 |
aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); |
1ab1457c4 [NET] IPV6: Fix w... |
526 |
|
38320c70d [IPSEC]: Use cryp... |
527 |
err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
528 |
if (aalg_desc->uinfo.auth.icv_fullbits/8 != |
38320c70d [IPSEC]: Use cryp... |
529 |
crypto_aead_authsize(aead)) { |
07d4ee583 [IPSEC]: Use HMAC... |
530 531 532 |
NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu ", x->aalg->alg_name, |
38320c70d [IPSEC]: Use cryp... |
533 |
crypto_aead_authsize(aead), |
07d4ee583 [IPSEC]: Use HMAC... |
534 |
aalg_desc->uinfo.auth.icv_fullbits/8); |
38320c70d [IPSEC]: Use cryp... |
535 |
goto free_key; |
1da177e4c Linux-2.6.12-rc2 |
536 |
} |
1ab1457c4 [NET] IPV6: Fix w... |
537 |
|
38320c70d [IPSEC]: Use cryp... |
538 |
err = crypto_aead_setauthsize( |
8f8a088c2 xfrm: Use the use... |
539 |
aead, x->aalg->alg_trunc_len / 8); |
38320c70d [IPSEC]: Use cryp... |
540 541 |
if (err) goto free_key; |
1da177e4c Linux-2.6.12-rc2 |
542 |
} |
38320c70d [IPSEC]: Use cryp... |
543 |
|
38320c70d [IPSEC]: Use cryp... |
544 545 546 547 548 549 550 |
param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8); memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8); err = crypto_aead_setkey(aead, key, keylen); free_key: kfree(key); |
1a6509d99 [IPSEC]: Add supp... |
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
error: return err; } static int esp6_init_state(struct xfrm_state *x) { struct esp_data *esp; struct crypto_aead *aead; u32 align; int err; if (x->encap) return -EINVAL; esp = kzalloc(sizeof(*esp), GFP_KERNEL); if (esp == NULL) return -ENOMEM; x->data = esp; if (x->aead) err = esp_init_aead(x); else err = esp_init_authenc(x); |
38320c70d [IPSEC]: Use cryp... |
575 |
if (err) |
1da177e4c Linux-2.6.12-rc2 |
576 |
goto error; |
38320c70d [IPSEC]: Use cryp... |
577 |
|
1a6509d99 [IPSEC]: Add supp... |
578 579 580 |
aead = esp->aead; esp->padlen = 0; |
38320c70d [IPSEC]: Use cryp... |
581 582 |
x->props.header_len = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead); |
ca68145f1 [IPSEC]: Disallow... |
583 584 |
switch (x->props.mode) { case XFRM_MODE_BEET: |
abf5cdb89 ipsec: Interfamil... |
585 586 587 588 |
if (x->sel.family != AF_INET6) x->props.header_len += IPV4_BEET_PHMAXLEN + (sizeof(struct ipv6hdr) - sizeof(struct iphdr)); break; |
ca68145f1 [IPSEC]: Disallow... |
589 590 591 |
case XFRM_MODE_TRANSPORT: break; case XFRM_MODE_TUNNEL: |
1da177e4c Linux-2.6.12-rc2 |
592 |
x->props.header_len += sizeof(struct ipv6hdr); |
ea2c47b42 [IPSEC] IPV6: Fix... |
593 |
break; |
ca68145f1 [IPSEC]: Disallow... |
594 595 596 |
default: goto error; } |
38320c70d [IPSEC]: Use cryp... |
597 598 599 600 601 |
align = ALIGN(crypto_aead_blocksize(aead), 4); if (esp->padlen) align = max_t(u32, align, esp->padlen); x->props.trailer_len = align + 1 + crypto_aead_authsize(esp->aead); |
1da177e4c Linux-2.6.12-rc2 |
602 603 |
error: |
38320c70d [IPSEC]: Use cryp... |
604 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
605 |
} |
533cb5b0a [XFRM]: constify ... |
606 |
static const struct xfrm_type esp6_type = |
1da177e4c Linux-2.6.12-rc2 |
607 608 609 610 |
{ .description = "ESP6", .owner = THIS_MODULE, .proto = IPPROTO_ESP, |
436a0a402 [IPSEC]: Move out... |
611 |
.flags = XFRM_TYPE_REPLAY_PROT, |
1da177e4c Linux-2.6.12-rc2 |
612 613 |
.init_state = esp6_init_state, .destructor = esp6_destroy, |
c5c252389 [XFRM]: Optimize ... |
614 |
.get_mtu = esp6_get_mtu, |
1da177e4c Linux-2.6.12-rc2 |
615 |
.input = esp6_input, |
aee5adb43 [XFRM] STATE: Add... |
616 617 |
.output = esp6_output, .hdr_offset = xfrm6_find_1stfragopt, |
1da177e4c Linux-2.6.12-rc2 |
618 |
}; |
41135cc83 net: constify str... |
619 |
static const struct inet6_protocol esp6_protocol = { |
1da177e4c Linux-2.6.12-rc2 |
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 |
.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 [XFRM]: Add modul... |
656 |
MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP); |