xref: /openbmc/linux/net/ipv4/ah4.c (revision 71de0a05)
1 // SPDX-License-Identifier: GPL-2.0-only
2 #define pr_fmt(fmt) "IPsec: " fmt
3 
4 #include <crypto/algapi.h>
5 #include <crypto/hash.h>
6 #include <linux/err.h>
7 #include <linux/module.h>
8 #include <linux/slab.h>
9 #include <net/ip.h>
10 #include <net/xfrm.h>
11 #include <net/ah.h>
12 #include <linux/crypto.h>
13 #include <linux/pfkeyv2.h>
14 #include <linux/scatterlist.h>
15 #include <net/icmp.h>
16 #include <net/protocol.h>
17 
18 struct ah_skb_cb {
19 	struct xfrm_skb_cb xfrm;
20 	void *tmp;
21 };
22 
23 #define AH_SKB_CB(__skb) ((struct ah_skb_cb *)&((__skb)->cb[0]))
24 
25 static void *ah_alloc_tmp(struct crypto_ahash *ahash, int nfrags,
26 			  unsigned int size)
27 {
28 	unsigned int len;
29 
30 	len = size + crypto_ahash_digestsize(ahash) +
31 	      (crypto_ahash_alignmask(ahash) &
32 	       ~(crypto_tfm_ctx_alignment() - 1));
33 
34 	len = ALIGN(len, crypto_tfm_ctx_alignment());
35 
36 	len += sizeof(struct ahash_request) + crypto_ahash_reqsize(ahash);
37 	len = ALIGN(len, __alignof__(struct scatterlist));
38 
39 	len += sizeof(struct scatterlist) * nfrags;
40 
41 	return kmalloc(len, GFP_ATOMIC);
42 }
43 
44 static inline u8 *ah_tmp_auth(void *tmp, unsigned int offset)
45 {
46 	return tmp + offset;
47 }
48 
49 static inline u8 *ah_tmp_icv(struct crypto_ahash *ahash, void *tmp,
50 			     unsigned int offset)
51 {
52 	return PTR_ALIGN((u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
53 }
54 
55 static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash,
56 					       u8 *icv)
57 {
58 	struct ahash_request *req;
59 
60 	req = (void *)PTR_ALIGN(icv + crypto_ahash_digestsize(ahash),
61 				crypto_tfm_ctx_alignment());
62 
63 	ahash_request_set_tfm(req, ahash);
64 
65 	return req;
66 }
67 
68 static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash,
69 					     struct ahash_request *req)
70 {
71 	return (void *)ALIGN((unsigned long)(req + 1) +
72 			     crypto_ahash_reqsize(ahash),
73 			     __alignof__(struct scatterlist));
74 }
75 
76 /* Clear mutable options and find final destination to substitute
77  * into IP header for icv calculation. Options are already checked
78  * for validity, so paranoia is not required. */
79 
80 static int ip_clear_mutable_options(const struct iphdr *iph, __be32 *daddr)
81 {
82 	unsigned char *optptr = (unsigned char *)(iph+1);
83 	int  l = iph->ihl*4 - sizeof(struct iphdr);
84 	int  optlen;
85 
86 	while (l > 0) {
87 		switch (*optptr) {
88 		case IPOPT_END:
89 			return 0;
90 		case IPOPT_NOOP:
91 			l--;
92 			optptr++;
93 			continue;
94 		}
95 		optlen = optptr[1];
96 		if (optlen<2 || optlen>l)
97 			return -EINVAL;
98 		switch (*optptr) {
99 		case IPOPT_SEC:
100 		case 0x85:	/* Some "Extended Security" crap. */
101 		case IPOPT_CIPSO:
102 		case IPOPT_RA:
103 		case 0x80|21:	/* RFC1770 */
104 			break;
105 		case IPOPT_LSRR:
106 		case IPOPT_SSRR:
107 			if (optlen < 6)
108 				return -EINVAL;
109 			memcpy(daddr, optptr+optlen-4, 4);
110 			fallthrough;
111 		default:
112 			memset(optptr, 0, optlen);
113 		}
114 		l -= optlen;
115 		optptr += optlen;
116 	}
117 	return 0;
118 }
119 
120 static void ah_output_done(void *data, int err)
121 {
122 	u8 *icv;
123 	struct iphdr *iph;
124 	struct sk_buff *skb = data;
125 	struct xfrm_state *x = skb_dst(skb)->xfrm;
126 	struct ah_data *ahp = x->data;
127 	struct iphdr *top_iph = ip_hdr(skb);
128 	struct ip_auth_hdr *ah = ip_auth_hdr(skb);
129 	int ihl = ip_hdrlen(skb);
130 
131 	iph = AH_SKB_CB(skb)->tmp;
132 	icv = ah_tmp_icv(ahp->ahash, iph, ihl);
133 	memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
134 
135 	top_iph->tos = iph->tos;
136 	top_iph->ttl = iph->ttl;
137 	top_iph->frag_off = iph->frag_off;
138 	if (top_iph->ihl != 5) {
139 		top_iph->daddr = iph->daddr;
140 		memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
141 	}
142 
143 	kfree(AH_SKB_CB(skb)->tmp);
144 	xfrm_output_resume(skb->sk, skb, err);
145 }
146 
147 static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
148 {
149 	int err;
150 	int nfrags;
151 	int ihl;
152 	u8 *icv;
153 	struct sk_buff *trailer;
154 	struct crypto_ahash *ahash;
155 	struct ahash_request *req;
156 	struct scatterlist *sg;
157 	struct iphdr *iph, *top_iph;
158 	struct ip_auth_hdr *ah;
159 	struct ah_data *ahp;
160 	int seqhi_len = 0;
161 	__be32 *seqhi;
162 	int sglists = 0;
163 	struct scatterlist *seqhisg;
164 
165 	ahp = x->data;
166 	ahash = ahp->ahash;
167 
168 	if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
169 		goto out;
170 	nfrags = err;
171 
172 	skb_push(skb, -skb_network_offset(skb));
173 	ah = ip_auth_hdr(skb);
174 	ihl = ip_hdrlen(skb);
175 
176 	if (x->props.flags & XFRM_STATE_ESN) {
177 		sglists = 1;
178 		seqhi_len = sizeof(*seqhi);
179 	}
180 	err = -ENOMEM;
181 	iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl + seqhi_len);
182 	if (!iph)
183 		goto out;
184 	seqhi = (__be32 *)((char *)iph + ihl);
185 	icv = ah_tmp_icv(ahash, seqhi, seqhi_len);
186 	req = ah_tmp_req(ahash, icv);
187 	sg = ah_req_sg(ahash, req);
188 	seqhisg = sg + nfrags;
189 
190 	memset(ah->auth_data, 0, ahp->icv_trunc_len);
191 
192 	top_iph = ip_hdr(skb);
193 
194 	iph->tos = top_iph->tos;
195 	iph->ttl = top_iph->ttl;
196 	iph->frag_off = top_iph->frag_off;
197 
198 	if (top_iph->ihl != 5) {
199 		iph->daddr = top_iph->daddr;
200 		memcpy(iph+1, top_iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
201 		err = ip_clear_mutable_options(top_iph, &top_iph->daddr);
202 		if (err)
203 			goto out_free;
204 	}
205 
206 	ah->nexthdr = *skb_mac_header(skb);
207 	*skb_mac_header(skb) = IPPROTO_AH;
208 
209 	top_iph->tos = 0;
210 	top_iph->tot_len = htons(skb->len);
211 	top_iph->frag_off = 0;
212 	top_iph->ttl = 0;
213 	top_iph->check = 0;
214 
215 	if (x->props.flags & XFRM_STATE_ALIGN4)
216 		ah->hdrlen  = (XFRM_ALIGN4(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
217 	else
218 		ah->hdrlen  = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
219 
220 	ah->reserved = 0;
221 	ah->spi = x->id.spi;
222 	ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
223 
224 	sg_init_table(sg, nfrags + sglists);
225 	err = skb_to_sgvec_nomark(skb, sg, 0, skb->len);
226 	if (unlikely(err < 0))
227 		goto out_free;
228 
229 	if (x->props.flags & XFRM_STATE_ESN) {
230 		/* Attach seqhi sg right after packet payload */
231 		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
232 		sg_set_buf(seqhisg, seqhi, seqhi_len);
233 	}
234 	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
235 	ahash_request_set_callback(req, 0, ah_output_done, skb);
236 
237 	AH_SKB_CB(skb)->tmp = iph;
238 
239 	err = crypto_ahash_digest(req);
240 	if (err) {
241 		if (err == -EINPROGRESS)
242 			goto out;
243 
244 		if (err == -ENOSPC)
245 			err = NET_XMIT_DROP;
246 		goto out_free;
247 	}
248 
249 	memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
250 
251 	top_iph->tos = iph->tos;
252 	top_iph->ttl = iph->ttl;
253 	top_iph->frag_off = iph->frag_off;
254 	if (top_iph->ihl != 5) {
255 		top_iph->daddr = iph->daddr;
256 		memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
257 	}
258 
259 out_free:
260 	kfree(iph);
261 out:
262 	return err;
263 }
264 
265 static void ah_input_done(void *data, int err)
266 {
267 	u8 *auth_data;
268 	u8 *icv;
269 	struct iphdr *work_iph;
270 	struct sk_buff *skb = data;
271 	struct xfrm_state *x = xfrm_input_state(skb);
272 	struct ah_data *ahp = x->data;
273 	struct ip_auth_hdr *ah = ip_auth_hdr(skb);
274 	int ihl = ip_hdrlen(skb);
275 	int ah_hlen = (ah->hdrlen + 2) << 2;
276 
277 	if (err)
278 		goto out;
279 
280 	work_iph = AH_SKB_CB(skb)->tmp;
281 	auth_data = ah_tmp_auth(work_iph, ihl);
282 	icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
283 
284 	err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
285 	if (err)
286 		goto out;
287 
288 	err = ah->nexthdr;
289 
290 	skb->network_header += ah_hlen;
291 	memcpy(skb_network_header(skb), work_iph, ihl);
292 	__skb_pull(skb, ah_hlen + ihl);
293 
294 	if (x->props.mode == XFRM_MODE_TUNNEL)
295 		skb_reset_transport_header(skb);
296 	else
297 		skb_set_transport_header(skb, -ihl);
298 out:
299 	kfree(AH_SKB_CB(skb)->tmp);
300 	xfrm_input_resume(skb, err);
301 }
302 
303 static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
304 {
305 	int ah_hlen;
306 	int ihl;
307 	int nexthdr;
308 	int nfrags;
309 	u8 *auth_data;
310 	u8 *icv;
311 	struct sk_buff *trailer;
312 	struct crypto_ahash *ahash;
313 	struct ahash_request *req;
314 	struct scatterlist *sg;
315 	struct iphdr *iph, *work_iph;
316 	struct ip_auth_hdr *ah;
317 	struct ah_data *ahp;
318 	int err = -ENOMEM;
319 	int seqhi_len = 0;
320 	__be32 *seqhi;
321 	int sglists = 0;
322 	struct scatterlist *seqhisg;
323 
324 	if (!pskb_may_pull(skb, sizeof(*ah)))
325 		goto out;
326 
327 	ah = (struct ip_auth_hdr *)skb->data;
328 	ahp = x->data;
329 	ahash = ahp->ahash;
330 
331 	nexthdr = ah->nexthdr;
332 	ah_hlen = (ah->hdrlen + 2) << 2;
333 
334 	if (x->props.flags & XFRM_STATE_ALIGN4) {
335 		if (ah_hlen != XFRM_ALIGN4(sizeof(*ah) + ahp->icv_full_len) &&
336 		    ah_hlen != XFRM_ALIGN4(sizeof(*ah) + ahp->icv_trunc_len))
337 			goto out;
338 	} else {
339 		if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
340 		    ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len))
341 			goto out;
342 	}
343 
344 	if (!pskb_may_pull(skb, ah_hlen))
345 		goto out;
346 
347 	/* We are going to _remove_ AH header to keep sockets happy,
348 	 * so... Later this can change. */
349 	if (skb_unclone(skb, GFP_ATOMIC))
350 		goto out;
351 
352 	skb->ip_summed = CHECKSUM_NONE;
353 
354 
355 	if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
356 		goto out;
357 	nfrags = err;
358 
359 	ah = (struct ip_auth_hdr *)skb->data;
360 	iph = ip_hdr(skb);
361 	ihl = ip_hdrlen(skb);
362 
363 	if (x->props.flags & XFRM_STATE_ESN) {
364 		sglists = 1;
365 		seqhi_len = sizeof(*seqhi);
366 	}
367 
368 	work_iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl +
369 				ahp->icv_trunc_len + seqhi_len);
370 	if (!work_iph) {
371 		err = -ENOMEM;
372 		goto out;
373 	}
374 
375 	seqhi = (__be32 *)((char *)work_iph + ihl);
376 	auth_data = ah_tmp_auth(seqhi, seqhi_len);
377 	icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
378 	req = ah_tmp_req(ahash, icv);
379 	sg = ah_req_sg(ahash, req);
380 	seqhisg = sg + nfrags;
381 
382 	memcpy(work_iph, iph, ihl);
383 	memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
384 	memset(ah->auth_data, 0, ahp->icv_trunc_len);
385 
386 	iph->ttl = 0;
387 	iph->tos = 0;
388 	iph->frag_off = 0;
389 	iph->check = 0;
390 	if (ihl > sizeof(*iph)) {
391 		__be32 dummy;
392 		err = ip_clear_mutable_options(iph, &dummy);
393 		if (err)
394 			goto out_free;
395 	}
396 
397 	skb_push(skb, ihl);
398 
399 	sg_init_table(sg, nfrags + sglists);
400 	err = skb_to_sgvec_nomark(skb, sg, 0, skb->len);
401 	if (unlikely(err < 0))
402 		goto out_free;
403 
404 	if (x->props.flags & XFRM_STATE_ESN) {
405 		/* Attach seqhi sg right after packet payload */
406 		*seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
407 		sg_set_buf(seqhisg, seqhi, seqhi_len);
408 	}
409 	ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
410 	ahash_request_set_callback(req, 0, ah_input_done, skb);
411 
412 	AH_SKB_CB(skb)->tmp = work_iph;
413 
414 	err = crypto_ahash_digest(req);
415 	if (err) {
416 		if (err == -EINPROGRESS)
417 			goto out;
418 
419 		goto out_free;
420 	}
421 
422 	err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
423 	if (err)
424 		goto out_free;
425 
426 	skb->network_header += ah_hlen;
427 	memcpy(skb_network_header(skb), work_iph, ihl);
428 	__skb_pull(skb, ah_hlen + ihl);
429 	if (x->props.mode == XFRM_MODE_TUNNEL)
430 		skb_reset_transport_header(skb);
431 	else
432 		skb_set_transport_header(skb, -ihl);
433 
434 	err = nexthdr;
435 
436 out_free:
437 	kfree (work_iph);
438 out:
439 	return err;
440 }
441 
442 static int ah4_err(struct sk_buff *skb, u32 info)
443 {
444 	struct net *net = dev_net(skb->dev);
445 	const struct iphdr *iph = (const struct iphdr *)skb->data;
446 	struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
447 	struct xfrm_state *x;
448 
449 	switch (icmp_hdr(skb)->type) {
450 	case ICMP_DEST_UNREACH:
451 		if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
452 			return 0;
453 		break;
454 	case ICMP_REDIRECT:
455 		break;
456 	default:
457 		return 0;
458 	}
459 
460 	x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
461 			      ah->spi, IPPROTO_AH, AF_INET);
462 	if (!x)
463 		return 0;
464 
465 	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
466 		ipv4_update_pmtu(skb, net, info, 0, IPPROTO_AH);
467 	else
468 		ipv4_redirect(skb, net, 0, IPPROTO_AH);
469 	xfrm_state_put(x);
470 
471 	return 0;
472 }
473 
474 static int ah_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack)
475 {
476 	struct ah_data *ahp = NULL;
477 	struct xfrm_algo_desc *aalg_desc;
478 	struct crypto_ahash *ahash;
479 
480 	if (!x->aalg) {
481 		NL_SET_ERR_MSG(extack, "AH requires a state with an AUTH algorithm");
482 		goto error;
483 	}
484 
485 	if (x->encap) {
486 		NL_SET_ERR_MSG(extack, "AH is not compatible with encapsulation");
487 		goto error;
488 	}
489 
490 	ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
491 	if (!ahp)
492 		return -ENOMEM;
493 
494 	ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
495 	if (IS_ERR(ahash)) {
496 		NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
497 		goto error;
498 	}
499 
500 	ahp->ahash = ahash;
501 	if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
502 				(x->aalg->alg_key_len + 7) / 8)) {
503 		NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
504 		goto error;
505 	}
506 
507 	/*
508 	 * Lookup the algorithm description maintained by xfrm_algo,
509 	 * verify crypto transform properties, and store information
510 	 * we need for AH processing.  This lookup cannot fail here
511 	 * after a successful crypto_alloc_ahash().
512 	 */
513 	aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
514 	BUG_ON(!aalg_desc);
515 
516 	if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
517 	    crypto_ahash_digestsize(ahash)) {
518 		NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations");
519 		goto error;
520 	}
521 
522 	ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
523 	ahp->icv_trunc_len = x->aalg->alg_trunc_len/8;
524 
525 	if (x->props.flags & XFRM_STATE_ALIGN4)
526 		x->props.header_len = XFRM_ALIGN4(sizeof(struct ip_auth_hdr) +
527 						  ahp->icv_trunc_len);
528 	else
529 		x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
530 						  ahp->icv_trunc_len);
531 	if (x->props.mode == XFRM_MODE_TUNNEL)
532 		x->props.header_len += sizeof(struct iphdr);
533 	x->data = ahp;
534 
535 	return 0;
536 
537 error:
538 	if (ahp) {
539 		crypto_free_ahash(ahp->ahash);
540 		kfree(ahp);
541 	}
542 	return -EINVAL;
543 }
544 
545 static void ah_destroy(struct xfrm_state *x)
546 {
547 	struct ah_data *ahp = x->data;
548 
549 	if (!ahp)
550 		return;
551 
552 	crypto_free_ahash(ahp->ahash);
553 	kfree(ahp);
554 }
555 
556 static int ah4_rcv_cb(struct sk_buff *skb, int err)
557 {
558 	return 0;
559 }
560 
561 static const struct xfrm_type ah_type =
562 {
563 	.owner		= THIS_MODULE,
564 	.proto	     	= IPPROTO_AH,
565 	.flags		= XFRM_TYPE_REPLAY_PROT,
566 	.init_state	= ah_init_state,
567 	.destructor	= ah_destroy,
568 	.input		= ah_input,
569 	.output		= ah_output
570 };
571 
572 static struct xfrm4_protocol ah4_protocol = {
573 	.handler	=	xfrm4_rcv,
574 	.input_handler	=	xfrm_input,
575 	.cb_handler	=	ah4_rcv_cb,
576 	.err_handler	=	ah4_err,
577 	.priority	=	0,
578 };
579 
580 static int __init ah4_init(void)
581 {
582 	if (xfrm_register_type(&ah_type, AF_INET) < 0) {
583 		pr_info("%s: can't add xfrm type\n", __func__);
584 		return -EAGAIN;
585 	}
586 	if (xfrm4_protocol_register(&ah4_protocol, IPPROTO_AH) < 0) {
587 		pr_info("%s: can't add protocol\n", __func__);
588 		xfrm_unregister_type(&ah_type, AF_INET);
589 		return -EAGAIN;
590 	}
591 	return 0;
592 }
593 
594 static void __exit ah4_fini(void)
595 {
596 	if (xfrm4_protocol_deregister(&ah4_protocol, IPPROTO_AH) < 0)
597 		pr_info("%s: can't remove protocol\n", __func__);
598 	xfrm_unregister_type(&ah_type, AF_INET);
599 }
600 
601 module_init(ah4_init);
602 module_exit(ah4_fini);
603 MODULE_LICENSE("GPL");
604 MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH);
605