]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/esp_input.c
xnu-344.tar.gz
[apple/xnu.git] / bsd / netinet6 / esp_input.c
CommitLineData
9bccf70c
A
1/* $FreeBSD: src/sys/netinet6/esp_input.c,v 1.1.2.3 2001/07/03 11:01:50 ume Exp $ */
2/* $KAME: esp_input.c,v 1.55 2001/03/23 08:08:47 itojun Exp $ */
1c79356b
A
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * RFC1827/2406 Encapsulated Security Payload.
35 */
36
1c79356b
A
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/malloc.h>
40#include <sys/mbuf.h>
41#include <sys/domain.h>
42#include <sys/protosw.h>
43#include <sys/socket.h>
44#include <sys/errno.h>
45#include <sys/time.h>
46#include <sys/kernel.h>
47#include <sys/syslog.h>
48
49#include <net/if.h>
50#include <net/route.h>
51#include <net/netisr.h>
52#include <kern/cpu_number.h>
53
54#include <netinet/in.h>
55#include <netinet/in_systm.h>
56#include <netinet/ip.h>
57#include <netinet/ip_var.h>
58#include <netinet/in_var.h>
59#include <netinet/ip_ecn.h>
9bccf70c
A
60#include <netinet/in_pcb.h>
61#if INET6
62#include <netinet6/ip6_ecn.h>
63#endif
1c79356b
A
64
65#if INET6
66#include <netinet/ip6.h>
9bccf70c 67#include <netinet6/in6_pcb.h>
1c79356b
A
68#include <netinet6/ip6_var.h>
69#include <netinet/icmp6.h>
9bccf70c 70#include <netinet6/ip6protosw.h>
1c79356b
A
71#endif
72
73#include <netinet6/ipsec.h>
9bccf70c
A
74#if INET6
75#include <netinet6/ipsec6.h>
76#endif
1c79356b 77#include <netinet6/ah.h>
9bccf70c
A
78#if INET6
79#include <netinet6/ah6.h>
80#endif
1c79356b 81#include <netinet6/esp.h>
9bccf70c
A
82#if INET6
83#include <netinet6/esp6.h>
84#endif
1c79356b
A
85#include <netkey/key.h>
86#include <netkey/keydb.h>
87#include <netkey/key_debug.h>
88
89
90#include <net/net_osdep.h>
91
92#define IPLEN_FLIPPED
93
94#if INET
95extern struct protosw inetsw[];
1c79356b
A
96
97#define ESPMAXLEN \
98 (sizeof(struct esp) < sizeof(struct newesp) \
99 ? sizeof(struct newesp) : sizeof(struct esp))
100
101void
102esp4_input(m, off)
103 struct mbuf *m;
104 int off;
105{
106 struct ip *ip;
107 struct esp *esp;
108 struct esptail esptail;
109 u_int32_t spi;
110 struct secasvar *sav = NULL;
111 size_t taillen;
112 u_int16_t nxt;
9bccf70c 113 const struct esp_algorithm *algo;
1c79356b
A
114 int ivlen;
115 size_t hlen;
116 size_t esplen;
117 int s;
118
119 /* sanity check for alignment. */
120 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
121 ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
122 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
123 ipsecstat.in_inval++;
124 goto bad;
125 }
126
127 if (m->m_len < off + ESPMAXLEN) {
128 m = m_pullup(m, off + ESPMAXLEN);
129 if (!m) {
130 ipseclog((LOG_DEBUG,
131 "IPv4 ESP input: can't pullup in esp4_input\n"));
132 ipsecstat.in_inval++;
133 goto bad;
134 }
135 }
136
137 ip = mtod(m, struct ip *);
138 esp = (struct esp *)(((u_int8_t *)ip) + off);
139#ifdef _IP_VHL
140 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
141#else
142 hlen = ip->ip_hl << 2;
143#endif
144
145 /* find the sassoc. */
146 spi = esp->esp_spi;
147
148 if ((sav = key_allocsa(AF_INET,
149 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
150 IPPROTO_ESP, spi)) == 0) {
151 ipseclog((LOG_WARNING,
152 "IPv4 ESP input: no key association found for spi %u\n",
153 (u_int32_t)ntohl(spi)));
154 ipsecstat.in_nosa++;
155 goto bad;
156 }
157 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
158 printf("DP esp4_input called to allocate SA:%p\n", sav));
159 if (sav->state != SADB_SASTATE_MATURE
160 && sav->state != SADB_SASTATE_DYING) {
161 ipseclog((LOG_DEBUG,
162 "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
163 (u_int32_t)ntohl(spi)));
164 ipsecstat.in_badspi++;
165 goto bad;
166 }
9bccf70c
A
167 algo = esp_algorithm_lookup(sav->alg_enc);
168 if (!algo) {
1c79356b 169 ipseclog((LOG_DEBUG, "IPv4 ESP input: "
9bccf70c 170 "unsupported encryption algorithm for spi %u\n",
1c79356b
A
171 (u_int32_t)ntohl(spi)));
172 ipsecstat.in_badspi++;
173 goto bad;
174 }
175
1c79356b
A
176 /* check if we have proper ivlen information */
177 ivlen = sav->ivlen;
178 if (ivlen < 0) {
179 ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n",
180 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
181 ipsecstat.in_inval++;
182 goto bad;
183 }
184
185 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
186 && (sav->alg_auth && sav->key_auth)))
187 goto noreplaycheck;
188
9bccf70c
A
189 if (sav->alg_auth == SADB_X_AALG_NULL ||
190 sav->alg_auth == SADB_AALG_NONE)
1c79356b
A
191 goto noreplaycheck;
192
193 /*
194 * check for sequence number.
195 */
196 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
197 ; /*okey*/
198 else {
199 ipsecstat.in_espreplay++;
200 ipseclog((LOG_WARNING,
201 "replay packet in IPv4 ESP input: %s %s\n",
202 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
203 goto bad;
204 }
205
206 /* check ICV */
207 {
208 u_char sum0[AH_MAXSUMSIZE];
209 u_char sum[AH_MAXSUMSIZE];
9bccf70c 210 const struct ah_algorithm *sumalgo;
1c79356b
A
211 size_t siz;
212
9bccf70c
A
213 sumalgo = ah_algorithm_lookup(sav->alg_auth);
214 if (!sumalgo)
215 goto noreplaycheck;
1c79356b
A
216 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
217 if (AH_MAXSUMSIZE < siz) {
218 ipseclog((LOG_DEBUG,
219 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
220 (u_long)siz));
221 ipsecstat.in_inval++;
222 goto bad;
223 }
224
225 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
226
227 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
228 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
229 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
230 ipsecstat.in_espauthfail++;
231 goto bad;
232 }
233
234 if (bcmp(sum0, sum, siz) != 0) {
235 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
236 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
237 ipsecstat.in_espauthfail++;
238 goto bad;
239 }
240
241 /* strip off the authentication data */
242 m_adj(m, -siz);
243 ip = mtod(m, struct ip *);
244#ifdef IPLEN_FLIPPED
245 ip->ip_len = ip->ip_len - siz;
246#else
247 ip->ip_len = htons(ntohs(ip->ip_len) - siz);
248#endif
249 m->m_flags |= M_AUTHIPDGM;
250 ipsecstat.in_espauthsucc++;
251 }
252
253 /*
254 * update sequence number.
255 */
256 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
257 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
258 ipsecstat.in_espreplay++;
259 goto bad;
260 }
261 }
262
263noreplaycheck:
264
265 /* process main esp header. */
266 if (sav->flags & SADB_X_EXT_OLD) {
267 /* RFC 1827 */
268 esplen = sizeof(struct esp);
269 } else {
270 /* RFC 2406 */
271 if (sav->flags & SADB_X_EXT_DERIV)
272 esplen = sizeof(struct esp);
273 else
274 esplen = sizeof(struct newesp);
275 }
276
277 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
278 ipseclog((LOG_WARNING,
279 "IPv4 ESP input: packet too short\n"));
280 ipsecstat.in_inval++;
281 goto bad;
282 }
283
284 if (m->m_len < off + esplen + ivlen) {
285 m = m_pullup(m, off + esplen + ivlen);
286 if (!m) {
287 ipseclog((LOG_DEBUG,
288 "IPv4 ESP input: can't pullup in esp4_input\n"));
289 ipsecstat.in_inval++;
290 goto bad;
291 }
292 }
293
9bccf70c
A
294 /*
295 * pre-compute and cache intermediate key
296 */
297 if (esp_schedule(algo, sav) != 0) {
298 ipsecstat.in_inval++;
299 goto bad;
300 }
301
1c79356b
A
302 /*
303 * decrypt the packet.
304 */
305 if (!algo->decrypt)
306 panic("internal error: no decrypt function");
307 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
9bccf70c
A
308 /* m is already freed */
309 m = NULL;
310 ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n",
311 ipsec_logsastr(sav)));
1c79356b
A
312 ipsecstat.in_inval++;
313 goto bad;
314 }
315 ipsecstat.in_esphist[sav->alg_enc]++;
316
317 m->m_flags |= M_DECRYPTED;
1c79356b
A
318
319 /*
320 * find the trailer of the ESP.
321 */
322 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
323 (caddr_t)&esptail);
324 nxt = esptail.esp_nxt;
325 taillen = esptail.esp_padlen + sizeof(esptail);
326
327 if (m->m_pkthdr.len < taillen
328 || m->m_pkthdr.len - taillen < hlen) { /*?*/
329 ipseclog((LOG_WARNING,
330 "bad pad length in IPv4 ESP input: %s %s\n",
331 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
332 ipsecstat.in_inval++;
333 goto bad;
334 }
335
336 /* strip off the trailing pad area. */
337 m_adj(m, -taillen);
338
339#ifdef IPLEN_FLIPPED
340 ip->ip_len = ip->ip_len - taillen;
341#else
342 ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
343#endif
344
345 /* was it transmitted over the IPsec tunnel SA? */
9bccf70c 346 if (ipsec4_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
1c79356b
A
347 /*
348 * strip off all the headers that precedes ESP header.
349 * IP4 xx ESP IP4' payload -> IP4' payload
350 *
351 * XXX more sanity checks
352 * XXX relationship with gif?
353 */
354 u_int8_t tos;
355
356 tos = ip->ip_tos;
357 m_adj(m, off + esplen + ivlen);
358 if (m->m_len < sizeof(*ip)) {
359 m = m_pullup(m, sizeof(*ip));
360 if (!m) {
361 ipsecstat.in_inval++;
362 goto bad;
363 }
364 }
365 ip = mtod(m, struct ip *);
366 /* ECN consideration. */
367 ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
368 if (!key_checktunnelsanity(sav, AF_INET,
369 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
370 ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
371 "in IPv4 ESP input: %s %s\n",
372 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
373 ipsecstat.in_inval++;
374 goto bad;
375 }
376
377#if 0 /* XXX should call ipfw rather than ipsec_in_reject, shouldn't it ? */
378 /* drop it if it does not match the default policy */
379 if (ipsec4_in_reject(m, NULL)) {
380 ipsecstat.in_polvio++;
381 goto bad;
382 }
383#endif
384
385 key_sa_recordxfer(sav, m);
9bccf70c
A
386 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
387 ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) {
388 ipsecstat.in_nomem++;
389 goto bad;
390 }
1c79356b
A
391
392 s = splimp();
393 if (IF_QFULL(&ipintrq)) {
394 ipsecstat.in_inval++;
9bccf70c 395 splx(s);
1c79356b
A
396 goto bad;
397 }
398 IF_ENQUEUE(&ipintrq, m);
399 m = NULL;
400 schednetisr(NETISR_IP); /*can be skipped but to make sure*/
401 splx(s);
402 nxt = IPPROTO_DONE;
403 } else {
404 /*
405 * strip off ESP header and IV.
406 * even in m_pulldown case, we need to strip off ESP so that
407 * we can always compute checksum for AH correctly.
408 */
409 size_t stripsiz;
410
411 stripsiz = esplen + ivlen;
412
413 ip = mtod(m, struct ip *);
414 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
415 m->m_data += stripsiz;
416 m->m_len -= stripsiz;
417 m->m_pkthdr.len -= stripsiz;
418
419 ip = mtod(m, struct ip *);
420#ifdef IPLEN_FLIPPED
421 ip->ip_len = ip->ip_len - stripsiz;
422#else
423 ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
424#endif
425 ip->ip_p = nxt;
426
427 key_sa_recordxfer(sav, m);
9bccf70c
A
428 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
429 ipsecstat.in_nomem++;
430 goto bad;
431 }
1c79356b 432
9bccf70c
A
433 if (nxt != IPPROTO_DONE) {
434 if ((ip_protox[nxt]->pr_flags & PR_LASTHDR) != 0 &&
435 ipsec4_in_reject(m, NULL)) {
436 ipsecstat.in_polvio++;
437 goto bad;
438 }
1c79356b 439 (*ip_protox[nxt]->pr_input)(m, off);
9bccf70c 440 } else
1c79356b
A
441 m_freem(m);
442 m = NULL;
443 }
444
445 if (sav) {
446 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
447 printf("DP esp4_input call free SA:%p\n", sav));
448 key_freesav(sav);
449 }
450 ipsecstat.in_success++;
451 return;
452
453bad:
454 if (sav) {
455 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
456 printf("DP esp4_input call free SA:%p\n", sav));
457 key_freesav(sav);
458 }
459 if (m)
460 m_freem(m);
461 return;
462}
463#endif /* INET */
464
465#if INET6
466int
467esp6_input(mp, offp, proto)
468 struct mbuf **mp;
469 int *offp, proto;
470{
471 struct mbuf *m = *mp;
472 int off = *offp;
473 struct ip6_hdr *ip6;
474 struct esp *esp;
475 struct esptail esptail;
476 u_int32_t spi;
477 struct secasvar *sav = NULL;
478 size_t taillen;
479 u_int16_t nxt;
9bccf70c 480 const struct esp_algorithm *algo;
1c79356b
A
481 int ivlen;
482 size_t esplen;
483 int s;
484
485 /* sanity check for alignment. */
486 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
487 ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
488 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
489 ipsec6stat.in_inval++;
490 goto bad;
491 }
492
493#ifndef PULLDOWN_TEST
494 IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, IPPROTO_DONE);
495 esp = (struct esp *)(mtod(m, caddr_t) + off);
496#else
497 IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
498 if (esp == NULL) {
499 ipsec6stat.in_inval++;
500 return IPPROTO_DONE;
501 }
502#endif
503 ip6 = mtod(m, struct ip6_hdr *);
504
505 if (ntohs(ip6->ip6_plen) == 0) {
506 ipseclog((LOG_ERR, "IPv6 ESP input: "
507 "ESP with IPv6 jumbogram is not supported.\n"));
508 ipsec6stat.in_inval++;
509 goto bad;
510 }
511
512 /* find the sassoc. */
513 spi = esp->esp_spi;
514
515 if ((sav = key_allocsa(AF_INET6,
516 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
517 IPPROTO_ESP, spi)) == 0) {
518 ipseclog((LOG_WARNING,
519 "IPv6 ESP input: no key association found for spi %u\n",
520 (u_int32_t)ntohl(spi)));
521 ipsec6stat.in_nosa++;
522 goto bad;
523 }
524 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
525 printf("DP esp6_input called to allocate SA:%p\n", sav));
526 if (sav->state != SADB_SASTATE_MATURE
527 && sav->state != SADB_SASTATE_DYING) {
528 ipseclog((LOG_DEBUG,
529 "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
530 (u_int32_t)ntohl(spi)));
531 ipsec6stat.in_badspi++;
532 goto bad;
533 }
9bccf70c
A
534 algo = esp_algorithm_lookup(sav->alg_enc);
535 if (!algo) {
1c79356b 536 ipseclog((LOG_DEBUG, "IPv6 ESP input: "
9bccf70c 537 "unsupported encryption algorithm for spi %u\n",
1c79356b
A
538 (u_int32_t)ntohl(spi)));
539 ipsec6stat.in_badspi++;
540 goto bad;
541 }
542
1c79356b
A
543 /* check if we have proper ivlen information */
544 ivlen = sav->ivlen;
545 if (ivlen < 0) {
546 ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n",
547 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
548 ipsec6stat.in_badspi++;
549 goto bad;
550 }
551
552 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
553 && (sav->alg_auth && sav->key_auth)))
554 goto noreplaycheck;
555
9bccf70c
A
556 if (sav->alg_auth == SADB_X_AALG_NULL ||
557 sav->alg_auth == SADB_AALG_NONE)
1c79356b
A
558 goto noreplaycheck;
559
560 /*
561 * check for sequence number.
562 */
563 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
564 ; /*okey*/
565 else {
566 ipsec6stat.in_espreplay++;
567 ipseclog((LOG_WARNING,
568 "replay packet in IPv6 ESP input: %s %s\n",
569 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
570 goto bad;
571 }
572
573 /* check ICV */
574 {
575 u_char sum0[AH_MAXSUMSIZE];
576 u_char sum[AH_MAXSUMSIZE];
9bccf70c 577 const struct ah_algorithm *sumalgo;
1c79356b
A
578 size_t siz;
579
9bccf70c
A
580 sumalgo = ah_algorithm_lookup(sav->alg_auth);
581 if (!sumalgo)
582 goto noreplaycheck;
1c79356b
A
583 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
584 if (AH_MAXSUMSIZE < siz) {
585 ipseclog((LOG_DEBUG,
586 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
587 (u_long)siz));
588 ipsec6stat.in_inval++;
589 goto bad;
590 }
591
592 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
593
594 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
595 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
596 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
597 ipsec6stat.in_espauthfail++;
598 goto bad;
599 }
600
601 if (bcmp(sum0, sum, siz) != 0) {
602 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
603 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
604 ipsec6stat.in_espauthfail++;
605 goto bad;
606 }
607
608 /* strip off the authentication data */
609 m_adj(m, -siz);
610 ip6 = mtod(m, struct ip6_hdr *);
611 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
612
613 m->m_flags |= M_AUTHIPDGM;
614 ipsec6stat.in_espauthsucc++;
615 }
616
617 /*
618 * update sequence number.
619 */
620 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
621 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
622 ipsec6stat.in_espreplay++;
623 goto bad;
624 }
625 }
626
627noreplaycheck:
628
629 /* process main esp header. */
630 if (sav->flags & SADB_X_EXT_OLD) {
631 /* RFC 1827 */
632 esplen = sizeof(struct esp);
633 } else {
634 /* RFC 2406 */
635 if (sav->flags & SADB_X_EXT_DERIV)
636 esplen = sizeof(struct esp);
637 else
638 esplen = sizeof(struct newesp);
639 }
640
641 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
642 ipseclog((LOG_WARNING,
643 "IPv6 ESP input: packet too short\n"));
644 ipsec6stat.in_inval++;
645 goto bad;
646 }
647
648#ifndef PULLDOWN_TEST
649 IP6_EXTHDR_CHECK(m, off, esplen + ivlen, IPPROTO_DONE); /*XXX*/
650#else
651 IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
652 if (esp == NULL) {
653 ipsec6stat.in_inval++;
654 m = NULL;
655 goto bad;
656 }
657#endif
658 ip6 = mtod(m, struct ip6_hdr *); /*set it again just in case*/
659
9bccf70c
A
660 /*
661 * pre-compute and cache intermediate key
662 */
663 if (esp_schedule(algo, sav) != 0) {
664 ipsec6stat.in_inval++;
665 goto bad;
666 }
667
1c79356b
A
668 /*
669 * decrypt the packet.
670 */
671 if (!algo->decrypt)
672 panic("internal error: no decrypt function");
673 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
9bccf70c
A
674 /* m is already freed */
675 m = NULL;
676 ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n",
677 ipsec_logsastr(sav)));
1c79356b
A
678 ipsec6stat.in_inval++;
679 goto bad;
680 }
681 ipsec6stat.in_esphist[sav->alg_enc]++;
682
683 m->m_flags |= M_DECRYPTED;
684
685 /*
686 * find the trailer of the ESP.
687 */
688 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
689 (caddr_t)&esptail);
690 nxt = esptail.esp_nxt;
691 taillen = esptail.esp_padlen + sizeof(esptail);
692
693 if (m->m_pkthdr.len < taillen
694 || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) { /*?*/
695 ipseclog((LOG_WARNING,
696 "bad pad length in IPv6 ESP input: %s %s\n",
697 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
698 ipsec6stat.in_inval++;
699 goto bad;
700 }
701
702 /* strip off the trailing pad area. */
703 m_adj(m, -taillen);
704
705 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
706
707 /* was it transmitted over the IPsec tunnel SA? */
9bccf70c 708 if (ipsec6_tunnel_validate(m, off + esplen + ivlen, nxt, sav)) {
1c79356b
A
709 /*
710 * strip off all the headers that precedes ESP header.
711 * IP6 xx ESP IP6' payload -> IP6' payload
712 *
713 * XXX more sanity checks
714 * XXX relationship with gif?
715 */
716 u_int32_t flowinfo; /*net endian*/
717 flowinfo = ip6->ip6_flow;
718 m_adj(m, off + esplen + ivlen);
719 if (m->m_len < sizeof(*ip6)) {
720#ifndef PULLDOWN_TEST
721 /*
722 * m_pullup is prohibited in KAME IPv6 input processing
723 * but there's no other way!
724 */
725#else
726 /* okay to pullup in m_pulldown style */
727#endif
728 m = m_pullup(m, sizeof(*ip6));
729 if (!m) {
730 ipsec6stat.in_inval++;
731 goto bad;
732 }
733 }
734 ip6 = mtod(m, struct ip6_hdr *);
735 /* ECN consideration. */
736 ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
737 if (!key_checktunnelsanity(sav, AF_INET6,
738 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
739 ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
740 "in IPv6 ESP input: %s %s\n",
741 ipsec6_logpacketstr(ip6, spi),
742 ipsec_logsastr(sav)));
743 ipsec6stat.in_inval++;
744 goto bad;
745 }
746
747#if 0 /* XXX should call ipfw rather than ipsec_in_reject, shouldn't it ? */
748 /* drop it if it does not match the default policy */
749 if (ipsec6_in_reject(m, NULL)) {
750 ipsec6stat.in_polvio++;
751 goto bad;
752 }
753#endif
754
755 key_sa_recordxfer(sav, m);
9bccf70c
A
756 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 ||
757 ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) {
758 ipsec6stat.in_nomem++;
759 goto bad;
760 }
1c79356b
A
761
762 s = splimp();
763 if (IF_QFULL(&ip6intrq)) {
764 ipsec6stat.in_inval++;
9bccf70c 765 splx(s);
1c79356b
A
766 goto bad;
767 }
768 IF_ENQUEUE(&ip6intrq, m);
769 m = NULL;
770 schednetisr(NETISR_IPV6); /*can be skipped but to make sure*/
771 splx(s);
772 nxt = IPPROTO_DONE;
773 } else {
774 /*
775 * strip off ESP header and IV.
776 * even in m_pulldown case, we need to strip off ESP so that
777 * we can always compute checksum for AH correctly.
778 */
779 size_t stripsiz;
780 char *prvnxtp;
781
782 /*
783 * Set the next header field of the previous header correctly.
784 */
785 prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
786 *prvnxtp = nxt;
787
788 stripsiz = esplen + ivlen;
789
790 ip6 = mtod(m, struct ip6_hdr *);
791 if (m->m_len >= stripsiz + off) {
792 ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
793 m->m_data += stripsiz;
794 m->m_len -= stripsiz;
795 m->m_pkthdr.len -= stripsiz;
796 } else {
797 /*
798 * this comes with no copy if the boundary is on
799 * cluster
800 */
801 struct mbuf *n;
802
803 n = m_split(m, off, M_DONTWAIT);
804 if (n == NULL) {
805 /* m is retained by m_split */
806 goto bad;
807 }
808 m_adj(n, stripsiz);
809 m_cat(m, n);
810 /* m_cat does not update m_pkthdr.len */
811 m->m_pkthdr.len += n->m_pkthdr.len;
812 }
813
9bccf70c
A
814#ifndef PULLDOWN_TEST
815 /*
816 * KAME requires that the packet to be contiguous on the
817 * mbuf. We need to make that sure.
818 * this kind of code should be avoided.
819 * XXX other conditions to avoid running this part?
820 */
821 if (m->m_len != m->m_pkthdr.len) {
822 struct mbuf *n = NULL;
823 int maxlen;
824
825 MGETHDR(n, M_DONTWAIT, MT_HEADER);
826 maxlen = MHLEN;
827 if (n)
828 M_COPY_PKTHDR(n, m);
829 if (n && m->m_pkthdr.len > maxlen) {
830 MCLGET(n, M_DONTWAIT);
831 maxlen = MCLBYTES;
832 if ((n->m_flags & M_EXT) == 0) {
833 m_free(n);
834 n = NULL;
835 }
836 }
837 if (!n) {
838 printf("esp6_input: mbuf allocation failed\n");
839 goto bad;
840 }
841
842 if (m->m_pkthdr.len <= maxlen) {
843 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
844 n->m_len = m->m_pkthdr.len;
845 n->m_pkthdr.len = m->m_pkthdr.len;
846 n->m_next = NULL;
847 m_freem(m);
848 } else {
849 m_copydata(m, 0, maxlen, mtod(n, caddr_t));
850 m_adj(m, maxlen);
851 n->m_len = maxlen;
852 n->m_pkthdr.len = m->m_pkthdr.len;
853 n->m_next = m;
854 m->m_flags &= ~M_PKTHDR;
855 }
856 m = n;
857 }
858#endif
859
1c79356b
A
860 ip6 = mtod(m, struct ip6_hdr *);
861 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
862
863 key_sa_recordxfer(sav, m);
9bccf70c
A
864 if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) {
865 ipsec6stat.in_nomem++;
866 goto bad;
867 }
1c79356b
A
868 }
869
870 *offp = off;
871 *mp = m;
872
873 if (sav) {
874 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
875 printf("DP esp6_input call free SA:%p\n", sav));
876 key_freesav(sav);
877 }
878 ipsec6stat.in_success++;
879 return nxt;
880
881bad:
882 if (sav) {
883 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
884 printf("DP esp6_input call free SA:%p\n", sav));
885 key_freesav(sav);
886 }
887 if (m)
888 m_freem(m);
889 return IPPROTO_DONE;
890}
9bccf70c
A
891
892void
893esp6_ctlinput(cmd, sa, d)
894 int cmd;
895 struct sockaddr *sa;
896 void *d;
897{
898 const struct newesp *espp;
899 struct newesp esp;
900 struct ip6ctlparam *ip6cp = NULL, ip6cp1;
901 struct secasvar *sav;
902 struct ip6_hdr *ip6;
903 struct mbuf *m;
904 int off;
905 struct sockaddr_in6 sa6_src, sa6_dst;
906
907 if (sa->sa_family != AF_INET6 ||
908 sa->sa_len != sizeof(struct sockaddr_in6))
909 return;
910 if ((unsigned)cmd >= PRC_NCMDS)
911 return;
912
913 /* if the parameter is from icmp6, decode it. */
914 if (d != NULL) {
915 ip6cp = (struct ip6ctlparam *)d;
916 m = ip6cp->ip6c_m;
917 ip6 = ip6cp->ip6c_ip6;
918 off = ip6cp->ip6c_off;
919 } else {
920 m = NULL;
921 ip6 = NULL;
922 }
923
924 if (ip6) {
925 /*
926 * Notify the error to all possible sockets via pfctlinput2.
927 * Since the upper layer information (such as protocol type,
928 * source and destination ports) is embedded in the encrypted
929 * data and might have been cut, we can't directly call
930 * an upper layer ctlinput function. However, the pcbnotify
931 * function will consider source and destination addresses
932 * as well as the flow info value, and may be able to find
933 * some PCB that should be notified.
934 * Although pfctlinput2 will call esp6_ctlinput(), there is
935 * no possibility of an infinite loop of function calls,
936 * because we don't pass the inner IPv6 header.
937 */
938 bzero(&ip6cp1, sizeof(ip6cp1));
939 ip6cp1.ip6c_src = ip6cp->ip6c_src;
940 pfctlinput2(cmd, sa, (void *)&ip6cp1);
941
942 /*
943 * Then go to special cases that need ESP header information.
944 * XXX: We assume that when ip6 is non NULL,
945 * M and OFF are valid.
946 */
947
948 /* check if we can safely examine src and dst ports */
949 if (m->m_pkthdr.len < off + sizeof(esp))
950 return;
951
952 if (m->m_len < off + sizeof(esp)) {
953 /*
954 * this should be rare case,
955 * so we compromise on this copy...
956 */
957 m_copydata(m, off, sizeof(esp), (caddr_t)&esp);
958 espp = &esp;
959 } else
960 espp = (struct newesp*)(mtod(m, caddr_t) + off);
961
962 if (cmd == PRC_MSGSIZE) {
963 int valid = 0;
964
965 /*
966 * Check to see if we have a valid SA corresponding to
967 * the address in the ICMP message payload.
968 */
969 sav = key_allocsa(AF_INET6,
970 (caddr_t)&sa6_src.sin6_addr,
971 (caddr_t)&sa6_dst, IPPROTO_ESP,
972 espp->esp_spi);
973 if (sav) {
974 if (sav->state == SADB_SASTATE_MATURE ||
975 sav->state == SADB_SASTATE_DYING)
976 valid++;
977 key_freesav(sav);
978 }
979
980 /* XXX Further validation? */
981
982 /*
983 * Depending on the value of "valid" and routing table
984 * size (mtudisc_{hi,lo}wat), we will:
985 * - recalcurate the new MTU and create the
986 * corresponding routing entry, or
987 * - ignore the MTU change notification.
988 */
989 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
990 }
991 } else {
992 /* we normally notify any pcb here */
993 }
994}
1c79356b 995#endif /* INET6 */