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