esp6.c 21.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/*
 * Copyright (C)2002 USAGI/WIDE Project
3
 *
L
Linus Torvalds 已提交
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.
8
 *
L
Linus Torvalds 已提交
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.
13
 *
L
Linus Torvalds 已提交
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
L
Linus Torvalds 已提交
16 17 18
 *
 * Authors
 *
19
 *	Mitsuru KANDA @USAGI       : IPv6 Support
20 21
 *	Kazunori MIYAZAWA @USAGI   :
 *	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
22
 *
23
 *	This file is derived from net/ipv4/esp.c
L
Linus Torvalds 已提交
24 25
 */

26 27
#define pr_fmt(fmt) "IPv6: " fmt

28 29
#include <crypto/aead.h>
#include <crypto/authenc.h>
30
#include <linux/err.h>
L
Linus Torvalds 已提交
31 32 33 34
#include <linux/module.h>
#include <net/ip.h>
#include <net/xfrm.h>
#include <net/esp.h>
35
#include <linux/scatterlist.h>
H
Herbert Xu 已提交
36
#include <linux/kernel.h>
L
Linus Torvalds 已提交
37 38
#include <linux/pfkeyv2.h>
#include <linux/random.h>
39
#include <linux/slab.h>
40
#include <linux/spinlock.h>
41
#include <net/ip6_route.h>
L
Linus Torvalds 已提交
42 43
#include <net/icmp.h>
#include <net/ipv6.h>
44
#include <net/protocol.h>
L
Linus Torvalds 已提交
45 46
#include <linux/icmpv6.h>

47 48
#include <linux/highmem.h>

49 50 51 52 53 54 55
struct esp_skb_cb {
	struct xfrm_skb_cb xfrm;
	void *tmp;
};

#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))

56 57
static u32 esp6_get_mtu(struct xfrm_state *x, int mtu);

58 59 60
/*
 * Allocate an AEAD request structure with extra space for SG and IV.
 *
61 62 63
 * 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.
64 65 66
 *
 * TODO: Use spare space in skb for this where possible.
 */
67
static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqihlen)
68 69 70
{
	unsigned int len;

71 72 73 74
	len = seqihlen;

	len += crypto_aead_ivsize(aead);

75 76 77 78 79 80
	if (len) {
		len += crypto_aead_alignmask(aead) &
		       ~(crypto_tfm_ctx_alignment() - 1);
		len = ALIGN(len, crypto_tfm_ctx_alignment());
	}

H
Herbert Xu 已提交
81
	len += sizeof(struct aead_request) + crypto_aead_reqsize(aead);
82 83 84 85 86 87 88
	len = ALIGN(len, __alignof__(struct scatterlist));

	len += sizeof(struct scatterlist) * nfrags;

	return kmalloc(len, GFP_ATOMIC);
}

89 90 91 92 93 94
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)
95 96
{
	return crypto_aead_ivsize(aead) ?
97 98
	       PTR_ALIGN((u8 *)tmp + seqhilen,
			 crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}

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));
}

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
{
	struct crypto_aead *aead = x->data;
	int seqhilen = 0;
	u8 *iv;
	struct aead_request *req;
	struct scatterlist *sg;

	if (x->props.flags & XFRM_STATE_ESN)
		seqhilen += sizeof(__be32);

	iv = esp_tmp_iv(aead, tmp, seqhilen);
	req = esp_tmp_req(aead, iv);

	/* Unref skb_frag_pages in the src scatterlist if necessary.
	 * Skip the first sg which comes from skb->data.
	 */
	if (req->src != req->dst)
		for (sg = sg_next(req->src); sg; sg = sg_next(sg))
			put_page(sg_page(sg));
}

141 142 143
static void esp_output_done(struct crypto_async_request *base, int err)
{
	struct sk_buff *skb = base->data;
144
	struct xfrm_offload *xo = xfrm_offload(skb);
145
	void *tmp;
146 147 148 149 150 151
	struct xfrm_state *x;

	if (xo && (xo->flags & XFRM_DEV_RESUME))
		x = skb->sp->xvec[skb->sp->len - 1];
	else
		x = skb_dst(skb)->xfrm;
152

153 154 155
	tmp = ESP_SKB_CB(skb)->tmp;
	esp_ssg_unref(x, tmp);
	kfree(tmp);
156 157 158 159 160 161 162 163 164 165 166 167 168 169

	if (xo && (xo->flags & XFRM_DEV_RESUME)) {
		if (err) {
			XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR);
			kfree_skb(skb);
			return;
		}

		skb_push(skb, skb->data - skb_mac_header(skb));
		secpath_reset(skb);
		xfrm_dev_resume(skb);
	} else {
		xfrm_output_resume(skb, err);
	}
170 171
}

H
Herbert Xu 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
/* Move ESP header back into place. */
static void esp_restore_header(struct sk_buff *skb, unsigned int offset)
{
	struct ip_esp_hdr *esph = (void *)(skb->data + offset);
	void *tmp = ESP_SKB_CB(skb)->tmp;
	__be32 *seqhi = esp_tmp_seqhi(tmp);

	esph->seq_no = esph->spi;
	esph->spi = *seqhi;
}

static void esp_output_restore_header(struct sk_buff *skb)
{
	esp_restore_header(skb, skb_transport_offset(skb) - sizeof(__be32));
}

188
static struct ip_esp_hdr *esp_output_set_esn(struct sk_buff *skb,
S
Steffen Klassert 已提交
189
					     struct xfrm_state *x,
190 191 192 193 194 195 196 197
					     struct ip_esp_hdr *esph,
					     __be32 *seqhi)
{
	/* For ESN we move the header forward by 4 bytes to
	 * accomodate the high bits.  We will move it back after
	 * encryption.
	 */
	if ((x->props.flags & XFRM_STATE_ESN)) {
198 199
		struct xfrm_offload *xo = xfrm_offload(skb);

200 201
		esph = (void *)(skb_transport_header(skb) - sizeof(__be32));
		*seqhi = esph->spi;
202 203 204 205
		if (xo)
			esph->seq_no = htonl(xo->seq.hi);
		else
			esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
206 207 208 209 210 211 212
	}

	esph->spi = x->id.spi;

	return esph;
}

H
Herbert Xu 已提交
213 214 215 216 217 218 219 220
static void esp_output_done_esn(struct crypto_async_request *base, int err)
{
	struct sk_buff *skb = base->data;

	esp_output_restore_header(skb);
	esp_output_done(base, err);
}

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
{
	/* Fill padding... */
	if (tfclen) {
		memset(tail, 0, tfclen);
		tail += tfclen;
	}
	do {
		int i;
		for (i = 0; i < plen - 2; i++)
			tail[i] = i + 1;
	} while (0);
	tail[plen - 2] = plen - 2;
	tail[plen - 1] = proto;
}

S
Steffen Klassert 已提交
237
int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
L
Linus Torvalds 已提交
238
{
239
	u8 *tail;
240
	u8 *vaddr;
S
Steffen Klassert 已提交
241 242 243 244
	int nfrags;
	struct page *page;
	struct sk_buff *trailer;
	int tailen = esp->tailen;
245

246
	if (!skb_cloned(skb)) {
247
		if (tailen <= skb_tailroom(skb)) {
248 249 250 251 252 253 254 255 256 257 258
			nfrags = 1;
			trailer = skb;
			tail = skb_tail_pointer(trailer);

			goto skip_cow;
		} else if ((skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS)
			   && !skb_has_frag_list(skb)) {
			int allocsize;
			struct sock *sk = skb->sk;
			struct page_frag *pfrag = &x->xfrag;

S
Steffen Klassert 已提交
259 260
			esp->inplace = false;

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
			allocsize = ALIGN(tailen, L1_CACHE_BYTES);

			spin_lock_bh(&x->lock);

			if (unlikely(!skb_page_frag_refill(allocsize, pfrag, GFP_ATOMIC))) {
				spin_unlock_bh(&x->lock);
				goto cow;
			}

			page = pfrag->page;
			get_page(page);

			vaddr = kmap_atomic(page);

			tail = vaddr + pfrag->offset;

S
Steffen Klassert 已提交
277
			esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
278 279 280 281 282 283 284 285 286 287

			kunmap_atomic(vaddr);

			nfrags = skb_shinfo(skb)->nr_frags;

			__skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
					     tailen);
			skb_shinfo(skb)->nr_frags = ++nfrags;

			pfrag->offset = pfrag->offset + allocsize;
288 289 290

			spin_unlock_bh(&x->lock);

291 292 293 294 295 296
			nfrags++;

			skb->len += tailen;
			skb->data_len += tailen;
			skb->truesize += tailen;
			if (sk)
297
				refcount_add(tailen, &sk->sk_wmem_alloc);
298

S
Steffen Klassert 已提交
299
			goto out;
300
		}
J
Julia Lawall 已提交
301
	}
302

303
cow:
S
Steffen Klassert 已提交
304 305 306
	nfrags = skb_cow_data(skb, tailen, &trailer);
	if (nfrags < 0)
		goto out;
307
	tail = skb_tail_pointer(trailer);
308 309

skip_cow:
S
Steffen Klassert 已提交
310 311
	esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
	pskb_put(skb, trailer, tailen);
L
Linus Torvalds 已提交
312

S
Steffen Klassert 已提交
313 314 315 316
out:
	return nfrags;
}
EXPORT_SYMBOL_GPL(esp6_output_head);
L
Linus Torvalds 已提交
317

S
Steffen Klassert 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
{
	u8 *iv;
	int alen;
	void *tmp;
	int ivlen;
	int assoclen;
	int seqhilen;
	__be32 *seqhi;
	struct page *page;
	struct ip_esp_hdr *esph;
	struct aead_request *req;
	struct crypto_aead *aead;
	struct scatterlist *sg, *dsg;
	int err = -ENOMEM;

	assoclen = sizeof(struct ip_esp_hdr);
	seqhilen = 0;

	if (x->props.flags & XFRM_STATE_ESN) {
		seqhilen += sizeof(__be32);
		assoclen += sizeof(__be32);
	}
L
Linus Torvalds 已提交
341

S
Steffen Klassert 已提交
342 343 344 345 346
	aead = x->data;
	alen = crypto_aead_authsize(aead);
	ivlen = crypto_aead_ivsize(aead);

	tmp = esp_alloc_tmp(aead, esp->nfrags + 2, seqhilen);
347
	if (!tmp)
348
		goto error;
H
Herbert Xu 已提交
349

350 351 352 353 354
	seqhi = esp_tmp_seqhi(tmp);
	iv = esp_tmp_iv(aead, tmp, seqhilen);
	req = esp_tmp_req(aead, iv);
	sg = esp_req_sg(aead, req);

S
Steffen Klassert 已提交
355 356 357 358 359 360
	if (esp->inplace)
		dsg = sg;
	else
		dsg = &sg[esp->nfrags];

	esph = esp_output_set_esn(skb, x, ip_esp_hdr(skb), seqhi);
H
Herbert Xu 已提交
361

S
Steffen Klassert 已提交
362
	sg_init_table(sg, esp->nfrags);
363 364 365 366
	err = skb_to_sgvec(skb, sg,
		           (unsigned char *)esph - skb->data,
		           assoclen + ivlen + esp->clen + alen);
	if (unlikely(err < 0))
367
		goto error_free;
S
Steffen Klassert 已提交
368 369 370 371 372 373 374 375 376 377

	if (!esp->inplace) {
		int allocsize;
		struct page_frag *pfrag = &x->xfrag;

		allocsize = ALIGN(skb->data_len, L1_CACHE_BYTES);

		spin_lock_bh(&x->lock);
		if (unlikely(!skb_page_frag_refill(allocsize, pfrag, GFP_ATOMIC))) {
			spin_unlock_bh(&x->lock);
378
			goto error_free;
S
Steffen Klassert 已提交
379 380 381 382 383 384 385 386 387 388 389 390
		}

		skb_shinfo(skb)->nr_frags = 1;

		page = pfrag->page;
		get_page(page);
		/* replace page frags in skb with new page */
		__skb_fill_page_desc(skb, 0, page, pfrag->offset, skb->data_len);
		pfrag->offset = pfrag->offset + allocsize;
		spin_unlock_bh(&x->lock);

		sg_init_table(dsg, skb_shinfo(skb)->nr_frags + 1);
391 392 393 394
		err = skb_to_sgvec(skb, dsg,
			           (unsigned char *)esph - skb->data,
			           assoclen + ivlen + esp->clen + alen);
		if (unlikely(err < 0))
395
			goto error_free;
S
Steffen Klassert 已提交
396
	}
397

398 399 400 401 402
	if ((x->props.flags & XFRM_STATE_ESN))
		aead_request_set_callback(req, 0, esp_output_done_esn, skb);
	else
		aead_request_set_callback(req, 0, esp_output_done, skb);

S
Steffen Klassert 已提交
403
	aead_request_set_crypt(req, sg, dsg, ivlen + esp->clen, iv);
H
Herbert Xu 已提交
404 405 406
	aead_request_set_ad(req, assoclen);

	memset(iv, 0, ivlen);
S
Steffen Klassert 已提交
407
	memcpy(iv + ivlen - min(ivlen, 8), (u8 *)&esp->seqno + 8 - min(ivlen, 8),
H
Herbert Xu 已提交
408
	       min(ivlen, 8));
L
Linus Torvalds 已提交
409

410
	ESP_SKB_CB(skb)->tmp = tmp;
H
Herbert Xu 已提交
411 412 413 414
	err = crypto_aead_encrypt(req);

	switch (err) {
	case -EINPROGRESS:
415
		goto error;
L
Linus Torvalds 已提交
416

417
	case -ENOSPC:
418
		err = NET_XMIT_DROP;
H
Herbert Xu 已提交
419 420 421 422 423 424
		break;

	case 0:
		if ((x->props.flags & XFRM_STATE_ESN))
			esp_output_restore_header(skb);
	}
425

426 427
	if (sg != dsg)
		esp_ssg_unref(x, tmp);
428

429 430
error_free:
	kfree(tmp);
431 432 433
error:
	return err;
}
S
Steffen Klassert 已提交
434 435 436 437 438 439 440 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 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
EXPORT_SYMBOL_GPL(esp6_output_tail);

static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
{
	int alen;
	int blksize;
	struct ip_esp_hdr *esph;
	struct crypto_aead *aead;
	struct esp_info esp;

	esp.inplace = true;

	esp.proto = *skb_mac_header(skb);
	*skb_mac_header(skb) = IPPROTO_ESP;

	/* skb is pure payload to encrypt */

	aead = x->data;
	alen = crypto_aead_authsize(aead);

	esp.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)
			esp.tfclen = padto - skb->len;
	}
	blksize = ALIGN(crypto_aead_blocksize(aead), 4);
	esp.clen = ALIGN(skb->len + 2 + esp.tfclen, blksize);
	esp.plen = esp.clen - skb->len - esp.tfclen;
	esp.tailen = esp.tfclen + esp.plen + alen;

	esp.nfrags = esp6_output_head(x, skb, &esp);
	if (esp.nfrags < 0)
		return esp.nfrags;

	esph = ip_esp_hdr(skb);
	esph->spi = x->id.spi;

	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
	esp.seqno = cpu_to_be64(XFRM_SKB_CB(skb)->seq.output.low +
			    ((u64)XFRM_SKB_CB(skb)->seq.output.hi << 32));

	skb_push(skb, -skb_network_offset(skb));

	return esp6_output_tail(x, skb, &esp);
}
483

484
static inline int esp_remove_trailer(struct sk_buff *skb)
485 486
{
	struct xfrm_state *x = xfrm_input_state(skb);
487
	struct xfrm_offload *xo = xfrm_offload(skb);
488
	struct crypto_aead *aead = x->data;
489
	int alen, hlen, elen;
490 491
	int padlen, trimlen;
	__wsum csumdiff;
492
	u8 nexthdr[2];
493
	int ret;
494

495 496 497
	alen = crypto_aead_authsize(aead);
	hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
	elen = skb->len - hlen;
L
Linus Torvalds 已提交
498

499 500
	if (xo && (xo->flags & XFRM_ESP_NO_TRAILER)) {
		ret = xo->proto;
501
		goto out;
502
	}
503

504 505
	ret = skb_copy_bits(skb, skb->len - alen - 2, nexthdr, 2);
	BUG_ON(ret);
L
Linus Torvalds 已提交
506

507
	ret = -EINVAL;
508 509
	padlen = nexthdr[0];
	if (padlen + 2 + alen >= elen) {
510 511
		net_dbg_ratelimited("ipsec esp packet is garbage padlen=%d, elen=%d\n",
				    padlen + 2, elen - alen);
512
		goto out;
L
Linus Torvalds 已提交
513 514
	}

515 516 517 518 519 520 521 522
	trimlen = alen + padlen + 2;
	if (skb->ip_summed == CHECKSUM_COMPLETE) {
		csumdiff = skb_checksum(skb, skb->len - trimlen, trimlen, 0);
		skb->csum = csum_block_sub(skb->csum, csumdiff,
					   skb->len - trimlen);
	}
	pskb_trim(skb, skb->len - trimlen);

523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
	ret = nexthdr[1];

out:
	return ret;
}

int esp6_input_done2(struct sk_buff *skb, int err)
{
	struct xfrm_state *x = xfrm_input_state(skb);
	struct xfrm_offload *xo = xfrm_offload(skb);
	struct crypto_aead *aead = x->data;
	int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
	int hdr_len = skb_network_header_len(skb);

	if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
		kfree(ESP_SKB_CB(skb)->tmp);

	if (unlikely(err))
		goto out;

	err = esp_remove_trailer(skb);
	if (unlikely(err < 0))
		goto out;

	skb_postpull_rcsum(skb, skb_network_header(skb),
			   skb_network_header_len(skb));
549
	skb_pull_rcsum(skb, hlen);
550 551 552 553
	if (x->props.mode == XFRM_MODE_TUNNEL)
		skb_reset_transport_header(skb);
	else
		skb_set_transport_header(skb, -hdr_len);
554 555 556 557 558 559

	/* RFC4303: Drop dummy packets without any error */
	if (err == IPPROTO_NONE)
		err = -EINVAL;

out:
L
Linus Torvalds 已提交
560 561
	return err;
}
S
Steffen Klassert 已提交
562
EXPORT_SYMBOL_GPL(esp6_input_done2);
L
Linus Torvalds 已提交
563

564 565 566 567
static void esp_input_done(struct crypto_async_request *base, int err)
{
	struct sk_buff *skb = base->data;

S
Steffen Klassert 已提交
568
	xfrm_input_resume(skb, esp6_input_done2(skb, err));
569 570
}

H
Herbert Xu 已提交
571 572 573 574 575 576
static void esp_input_restore_header(struct sk_buff *skb)
{
	esp_restore_header(skb, 0);
	__skb_pull(skb, 4);
}

577 578 579 580 581 582 583 584 585
static void esp_input_set_header(struct sk_buff *skb, __be32 *seqhi)
{
	struct xfrm_state *x = xfrm_input_state(skb);

	/* For ESN we move the header forward by 4 bytes to
	 * accomodate the high bits.  We will move it back after
	 * decryption.
	 */
	if ((x->props.flags & XFRM_STATE_ESN)) {
586 587
		struct ip_esp_hdr *esph = skb_push(skb, 4);

588 589 590 591 592 593
		*seqhi = esph->spi;
		esph->spi = esph->seq_no;
		esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
	}
}

H
Herbert Xu 已提交
594 595 596 597 598 599 600 601
static void esp_input_done_esn(struct crypto_async_request *base, int err)
{
	struct sk_buff *skb = base->data;

	esp_input_restore_header(skb);
	esp_input_done(base, err);
}

602
static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
L
Linus Torvalds 已提交
603
{
604
	struct ip_esp_hdr *esph;
605
	struct crypto_aead *aead = x->data;
606
	struct aead_request *req;
L
Linus Torvalds 已提交
607
	struct sk_buff *trailer;
H
Herbert Xu 已提交
608 609
	int ivlen = crypto_aead_ivsize(aead);
	int elen = skb->len - sizeof(*esph) - ivlen;
L
Linus Torvalds 已提交
610
	int nfrags;
611 612
	int assoclen;
	int seqhilen;
L
Linus Torvalds 已提交
613
	int ret = 0;
614
	void *tmp;
615
	__be32 *seqhi;
616 617
	u8 *iv;
	struct scatterlist *sg;
L
Linus Torvalds 已提交
618

H
Herbert Xu 已提交
619
	if (!pskb_may_pull(skb, sizeof(*esph) + ivlen)) {
L
Linus Torvalds 已提交
620
		ret = -EINVAL;
621
		goto out;
L
Linus Torvalds 已提交
622 623
	}

624
	if (elen <= 0) {
L
Linus Torvalds 已提交
625
		ret = -EINVAL;
626
		goto out;
L
Linus Torvalds 已提交
627 628
	}

629 630 631 632 633 634 635 636
	assoclen = sizeof(*esph);
	seqhilen = 0;

	if (x->props.flags & XFRM_STATE_ESN) {
		seqhilen += sizeof(__be32);
		assoclen += seqhilen;
	}

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
	if (!skb_cloned(skb)) {
		if (!skb_is_nonlinear(skb)) {
			nfrags = 1;

			goto skip_cow;
		} else if (!skb_has_frag_list(skb)) {
			nfrags = skb_shinfo(skb)->nr_frags;
			nfrags++;

			goto skip_cow;
		}
	}

	nfrags = skb_cow_data(skb, 0, &trailer);
	if (nfrags < 0) {
		ret = -EINVAL;
		goto out;
	}

skip_cow:
	ret = -ENOMEM;
H
Herbert Xu 已提交
658
	tmp = esp_alloc_tmp(aead, nfrags, seqhilen);
659 660
	if (!tmp)
		goto out;
L
Linus Torvalds 已提交
661

662
	ESP_SKB_CB(skb)->tmp = tmp;
663 664
	seqhi = esp_tmp_seqhi(tmp);
	iv = esp_tmp_iv(aead, tmp, seqhilen);
665
	req = esp_tmp_req(aead, iv);
H
Herbert Xu 已提交
666
	sg = esp_req_sg(aead, req);
L
Linus Torvalds 已提交
667

668
	esp_input_set_header(skb, seqhi);
L
Linus Torvalds 已提交
669

670
	sg_init_table(sg, nfrags);
671
	ret = skb_to_sgvec(skb, sg, 0, skb->len);
672 673
	if (unlikely(ret < 0)) {
		kfree(tmp);
674
		goto out;
675
	}
L
Linus Torvalds 已提交
676

677
	skb->ip_summed = CHECKSUM_NONE;
678

679
	if ((x->props.flags & XFRM_STATE_ESN))
H
Herbert Xu 已提交
680
		aead_request_set_callback(req, 0, esp_input_done_esn, skb);
681 682
	else
		aead_request_set_callback(req, 0, esp_input_done, skb);
H
Herbert Xu 已提交
683 684 685

	aead_request_set_crypt(req, sg, sg, elen + ivlen, iv);
	aead_request_set_ad(req, assoclen);
L
Linus Torvalds 已提交
686

687 688 689
	ret = crypto_aead_decrypt(req);
	if (ret == -EINPROGRESS)
		goto out;
690

H
Herbert Xu 已提交
691 692 693
	if ((x->props.flags & XFRM_STATE_ESN))
		esp_input_restore_header(skb);

S
Steffen Klassert 已提交
694
	ret = esp6_input_done2(skb, ret);
L
Linus Torvalds 已提交
695 696 697 698 699

out:
	return ret;
}

700
static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
L
Linus Torvalds 已提交
701
{
702 703
	struct crypto_aead *aead = x->data;
	u32 blksize = ALIGN(crypto_aead_blocksize(aead), 4);
704
	unsigned int net_adj;
L
Linus Torvalds 已提交
705

706 707 708 709
	if (x->props.mode != XFRM_MODE_TUNNEL)
		net_adj = sizeof(struct ipv6hdr);
	else
		net_adj = 0;
710

711
	return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
712
		 net_adj) & ~(blksize - 1)) + net_adj - 2;
L
Linus Torvalds 已提交
713 714
}

715 716
static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
		    u8 type, u8 code, int offset, __be32 info)
L
Linus Torvalds 已提交
717
{
A
Alexey Dobriyan 已提交
718
	struct net *net = dev_net(skb->dev);
719
	const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data;
720
	struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
L
Linus Torvalds 已提交
721 722
	struct xfrm_state *x;

723
	if (type != ICMPV6_PKT_TOOBIG &&
724
	    type != NDISC_REDIRECT)
725
		return 0;
L
Linus Torvalds 已提交
726

727 728
	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
			      esph->spi, IPPROTO_ESP, AF_INET6);
L
Linus Torvalds 已提交
729
	if (!x)
730
		return 0;
731 732

	if (type == NDISC_REDIRECT)
733 734
		ip6_redirect(skb, net, skb->dev->ifindex, 0,
			     sock_net_uid(net, NULL));
735
	else
736
		ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
L
Linus Torvalds 已提交
737
	xfrm_state_put(x);
738 739

	return 0;
L
Linus Torvalds 已提交
740 741 742 743
}

static void esp6_destroy(struct xfrm_state *x)
{
744
	struct crypto_aead *aead = x->data;
L
Linus Torvalds 已提交
745

746
	if (!aead)
L
Linus Torvalds 已提交
747 748
		return;

749
	crypto_free_aead(aead);
L
Linus Torvalds 已提交
750 751
}

752 753
static int esp_init_aead(struct xfrm_state *x)
{
H
Herbert Xu 已提交
754
	char aead_name[CRYPTO_MAX_ALG_NAME];
755 756 757
	struct crypto_aead *aead;
	int err;

H
Herbert Xu 已提交
758 759 760 761 762
	err = -ENAMETOOLONG;
	if (snprintf(aead_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
		     x->geniv, x->aead->alg_name) >= CRYPTO_MAX_ALG_NAME)
		goto error;

763
	aead = crypto_alloc_aead(aead_name, 0, 0);
764 765 766 767
	err = PTR_ERR(aead);
	if (IS_ERR(aead))
		goto error;

768
	x->data = aead;
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783

	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)
L
Linus Torvalds 已提交
784
{
785 786 787 788 789 790 791 792
	struct crypto_aead *aead;
	struct crypto_authenc_key_param *param;
	struct rtattr *rta;
	char *key;
	char *p;
	char authenc_name[CRYPTO_MAX_ALG_NAME];
	unsigned int keylen;
	int err;
L
Linus Torvalds 已提交
793

794
	err = -EINVAL;
795
	if (!x->ealg)
796
		goto error;
797

798
	err = -ENAMETOOLONG;
799 800 801

	if ((x->props.flags & XFRM_STATE_ESN)) {
		if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
H
Herbert Xu 已提交
802 803
			     "%s%sauthencesn(%s,%s)%s",
			     x->geniv ?: "", x->geniv ? "(" : "",
804
			     x->aalg ? x->aalg->alg_name : "digest_null",
H
Herbert Xu 已提交
805 806
			     x->ealg->alg_name,
			     x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME)
807 808 809
			goto error;
	} else {
		if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
H
Herbert Xu 已提交
810 811
			     "%s%sauthenc(%s,%s)%s",
			     x->geniv ?: "", x->geniv ? "(" : "",
812
			     x->aalg ? x->aalg->alg_name : "digest_null",
H
Herbert Xu 已提交
813 814
			     x->ealg->alg_name,
			     x->geniv ? ")" : "") >= CRYPTO_MAX_ALG_NAME)
815 816
			goto error;
	}
817

818
	aead = crypto_alloc_aead(authenc_name, 0, 0);
819 820 821 822
	err = PTR_ERR(aead);
	if (IS_ERR(aead))
		goto error;

823
	x->data = aead;
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838

	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));

L
Linus Torvalds 已提交
839 840 841
	if (x->aalg) {
		struct xfrm_algo_desc *aalg_desc;

842 843
		memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8);
		p += (x->aalg->alg_key_len + 7) / 8;
844

L
Linus Torvalds 已提交
845 846
		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
		BUG_ON(!aalg_desc);
847

848
		err = -EINVAL;
849
		if (aalg_desc->uinfo.auth.icv_fullbits / 8 !=
850
		    crypto_aead_authsize(aead)) {
851 852 853 854
			pr_info("ESP: %s digestsize %u != %hu\n",
				x->aalg->alg_name,
				crypto_aead_authsize(aead),
				aalg_desc->uinfo.auth.icv_fullbits / 8);
855
			goto free_key;
L
Linus Torvalds 已提交
856
		}
857

858
		err = crypto_aead_setauthsize(
859
			aead, x->aalg->alg_trunc_len / 8);
860 861
		if (err)
			goto free_key;
L
Linus Torvalds 已提交
862
	}
863 864 865 866 867 868 869 870 871

	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);

872 873 874 875 876 877 878 879 880 881 882 883 884
error:
	return err;
}

static int esp6_init_state(struct xfrm_state *x)
{
	struct crypto_aead *aead;
	u32 align;
	int err;

	if (x->encap)
		return -EINVAL;

885
	x->data = NULL;
886 887 888 889 890 891

	if (x->aead)
		err = esp_init_aead(x);
	else
		err = esp_init_authenc(x);

892
	if (err)
L
Linus Torvalds 已提交
893
		goto error;
894

895
	aead = x->data;
896

897 898
	x->props.header_len = sizeof(struct ip_esp_hdr) +
			      crypto_aead_ivsize(aead);
899 900
	switch (x->props.mode) {
	case XFRM_MODE_BEET:
901 902
		if (x->sel.family != AF_INET6)
			x->props.header_len += IPV4_BEET_PHMAXLEN +
903
					       (sizeof(struct ipv6hdr) - sizeof(struct iphdr));
904
		break;
905
	default:
906 907 908
	case XFRM_MODE_TRANSPORT:
		break;
	case XFRM_MODE_TUNNEL:
L
Linus Torvalds 已提交
909
		x->props.header_len += sizeof(struct ipv6hdr);
910
		break;
911
	}
912 913

	align = ALIGN(crypto_aead_blocksize(aead), 4);
914
	x->props.trailer_len = align + 1 + crypto_aead_authsize(aead);
L
Linus Torvalds 已提交
915 916

error:
917
	return err;
L
Linus Torvalds 已提交
918 919
}

920 921 922 923 924
static int esp6_rcv_cb(struct sk_buff *skb, int err)
{
	return 0;
}

925
static const struct xfrm_type esp6_type = {
L
Linus Torvalds 已提交
926
	.description	= "ESP6",
927 928
	.owner		= THIS_MODULE,
	.proto		= IPPROTO_ESP,
929
	.flags		= XFRM_TYPE_REPLAY_PROT,
L
Linus Torvalds 已提交
930 931
	.init_state	= esp6_init_state,
	.destructor	= esp6_destroy,
932
	.get_mtu	= esp6_get_mtu,
L
Linus Torvalds 已提交
933
	.input		= esp6_input,
934 935
	.output		= esp6_output,
	.hdr_offset	= xfrm6_find_1stfragopt,
L
Linus Torvalds 已提交
936 937
};

938 939 940
static struct xfrm6_protocol esp6_protocol = {
	.handler	=	xfrm6_rcv,
	.cb_handler	=	esp6_rcv_cb,
L
Linus Torvalds 已提交
941
	.err_handler	=	esp6_err,
942
	.priority	=	0,
L
Linus Torvalds 已提交
943 944 945 946 947
};

static int __init esp6_init(void)
{
	if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
948
		pr_info("%s: can't add xfrm type\n", __func__);
L
Linus Torvalds 已提交
949 950
		return -EAGAIN;
	}
951
	if (xfrm6_protocol_register(&esp6_protocol, IPPROTO_ESP) < 0) {
952
		pr_info("%s: can't add protocol\n", __func__);
L
Linus Torvalds 已提交
953 954 955 956 957 958 959 960 961
		xfrm_unregister_type(&esp6_type, AF_INET6);
		return -EAGAIN;
	}

	return 0;
}

static void __exit esp6_fini(void)
{
962
	if (xfrm6_protocol_deregister(&esp6_protocol, IPPROTO_ESP) < 0)
963
		pr_info("%s: can't remove protocol\n", __func__);
L
Linus Torvalds 已提交
964
	if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0)
965
		pr_info("%s: can't remove xfrm type\n", __func__);
L
Linus Torvalds 已提交
966 967 968 969 970 971
}

module_init(esp6_init);
module_exit(esp6_fini);

MODULE_LICENSE("GPL");
972
MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);