2 /* $KAME: esp_input.c,v 1.25 2000/05/08 08:04:30 itojun Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
34 * RFC1827/2406 Encapsulated Security Payload.
38 #include "opt_inet6.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
43 #include <sys/domain.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/errno.h>
48 #include <sys/syslog.h>
51 #include <net/route.h>
52 #include <net/netisr.h>
53 #include <machine/cpu.h>
55 #include <netinet/in.h>
56 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #include <netinet/ip_var.h>
59 #include <netinet/in_var.h>
60 #include <netinet/ip_ecn.h>
62 #include <netinet6/ip6_ecn.h>
66 #include <netinet/ip6.h>
67 #include <netinet6/ip6_var.h>
68 #include <netinet/icmp6.h>
71 #include <netinet6/ipsec.h>
73 #include <netinet6/ipsec6.h>
75 #include <netinet6/ah.h>
77 #include <netinet6/ah6.h>
79 #include <netinet6/esp.h>
81 #include <netinet6/esp6.h>
83 #include <netkey/key.h>
84 #include <netkey/keydb.h>
86 #include <netkey/key_debug.h>
88 #define KEYDEBUG(lev,arg)
91 #include <machine/stdarg.h>
93 #include <net/net_osdep.h>
98 #include <netinet/ipprotosw.h>
99 extern struct ipprotosw inetsw[];
102 (sizeof(struct esp) < sizeof(struct newesp) \
103 ? sizeof(struct newesp) : sizeof(struct esp))
107 esp4_input(struct mbuf *m, ...)
109 esp4_input(m, va_alist)
116 struct esptail esptail;
118 struct secasvar *sav = NULL;
121 struct esp_algorithm *algo;
129 off = va_arg(ap, int);
130 proto = va_arg(ap, int);
133 /* sanity check for alignment. */
134 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
135 ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem "
136 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
137 ipsecstat.in_inval++;
141 if (m->m_len < off + ESPMAXLEN) {
142 m = m_pullup(m, off + ESPMAXLEN);
145 "IPv4 ESP input: can't pullup in esp4_input\n"));
146 ipsecstat.in_inval++;
151 ip = mtod(m, struct ip *);
152 esp = (struct esp *)(((u_int8_t *)ip) + off);
154 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
156 hlen = ip->ip_hl << 2;
159 /* find the sassoc. */
162 if ((sav = key_allocsa(AF_INET,
163 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
164 IPPROTO_ESP, spi)) == 0) {
165 ipseclog((LOG_WARNING,
166 "IPv4 ESP input: no key association found for spi %u\n",
167 (u_int32_t)ntohl(spi)));
171 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
172 printf("DP esp4_input called to allocate SA:%p\n", sav));
173 if (sav->state != SADB_SASTATE_MATURE
174 && sav->state != SADB_SASTATE_DYING) {
176 "IPv4 ESP input: non-mature/dying SA found for spi %u\n",
177 (u_int32_t)ntohl(spi)));
178 ipsecstat.in_badspi++;
181 if (sav->alg_enc == SADB_EALG_NONE) {
182 ipseclog((LOG_DEBUG, "IPv4 ESP input: "
183 "unspecified encryption algorithm for spi %u\n",
184 (u_int32_t)ntohl(spi)));
185 ipsecstat.in_badspi++;
189 algo = &esp_algorithms[sav->alg_enc]; /*XXX*/
191 /* check if we have proper ivlen information */
194 ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n",
195 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
196 ipsecstat.in_inval++;
200 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
201 && (sav->alg_auth && sav->key_auth)))
204 if (sav->alg_auth == SADB_AALG_NULL)
208 * check for sequence number.
210 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
213 ipsecstat.in_espreplay++;
214 ipseclog((LOG_WARNING,
215 "replay packet in IPv4 ESP input: %s %s\n",
216 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
222 u_char sum0[AH_MAXSUMSIZE];
223 u_char sum[AH_MAXSUMSIZE];
224 struct ah_algorithm *sumalgo;
227 sumalgo = &ah_algorithms[sav->alg_auth];
228 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
229 if (AH_MAXSUMSIZE < siz) {
231 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
233 ipsecstat.in_inval++;
237 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
239 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
240 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
241 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
242 ipsecstat.in_espauthfail++;
246 if (bcmp(sum0, sum, siz) != 0) {
247 ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n",
248 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
249 ipsecstat.in_espauthfail++;
253 /* strip off the authentication data */
255 ip = mtod(m, struct ip *);
257 ip->ip_len = ip->ip_len - siz;
259 ip->ip_len = htons(ntohs(ip->ip_len) - siz);
261 m->m_flags |= M_AUTHIPDGM;
262 ipsecstat.in_espauthsucc++;
266 * update sequence number.
268 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
269 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
270 ipsecstat.in_espreplay++;
277 /* process main esp header. */
278 if (sav->flags & SADB_X_EXT_OLD) {
280 esplen = sizeof(struct esp);
283 if (sav->flags & SADB_X_EXT_DERIV)
284 esplen = sizeof(struct esp);
286 esplen = sizeof(struct newesp);
289 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
290 ipseclog((LOG_WARNING,
291 "IPv4 ESP input: packet too short\n"));
292 ipsecstat.in_inval++;
296 if (m->m_len < off + esplen + ivlen) {
297 m = m_pullup(m, off + esplen + ivlen);
300 "IPv4 ESP input: can't pullup in esp4_input\n"));
301 ipsecstat.in_inval++;
308 * decrypt the packet.
311 panic("internal error: no decrypt function");
312 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
313 ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s %s\n",
314 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
315 ipsecstat.in_inval++;
318 ipsecstat.in_esphist[sav->alg_enc]++;
320 m->m_flags |= M_DECRYPTED;
324 * find the trailer of the ESP.
326 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
328 nxt = esptail.esp_nxt;
329 taillen = esptail.esp_padlen + sizeof(esptail);
331 if (m->m_pkthdr.len < taillen
332 || m->m_pkthdr.len - taillen < hlen) { /*?*/
333 ipseclog((LOG_WARNING,
334 "bad pad length in IPv4 ESP input: %s %s\n",
335 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
336 ipsecstat.in_inval++;
340 /* strip off the trailing pad area. */
344 ip->ip_len = ip->ip_len - taillen;
346 ip->ip_len = htons(ntohs(ip->ip_len) - taillen);
349 /* was it transmitted over the IPsec tunnel SA? */
350 if (ipsec4_tunnel_validate(ip, nxt, sav)) {
352 * strip off all the headers that precedes ESP header.
353 * IP4 xx ESP IP4' payload -> IP4' payload
355 * XXX more sanity checks
356 * XXX relationship with gif?
361 m_adj(m, off + esplen + ivlen);
362 if (m->m_len < sizeof(*ip)) {
363 m = m_pullup(m, sizeof(*ip));
365 ipsecstat.in_inval++;
369 ip = mtod(m, struct ip *);
370 /* ECN consideration. */
371 ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos);
372 if (!key_checktunnelsanity(sav, AF_INET,
373 (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) {
374 ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
375 "in IPv4 ESP input: %s %s\n",
376 ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav)));
377 ipsecstat.in_inval++;
381 #if 0 /* XXX should call ipfw rather than ipsec_in_reject, shouldn't it ? */
382 /* drop it if it does not match the default policy */
383 if (ipsec4_in_reject(m, NULL)) {
384 ipsecstat.in_polvio++;
389 key_sa_recordxfer(sav, m);
391 if (! IF_HANDOFF(&ipintrq, m, NULL)) {
392 ipsecstat.in_inval++;
397 schednetisr(NETISR_IP); /*can be skipped but to make sure*/
401 * strip off ESP header and IV.
402 * even in m_pulldown case, we need to strip off ESP so that
403 * we can always compute checksum for AH correctly.
407 stripsiz = esplen + ivlen;
409 ip = mtod(m, struct ip *);
410 ovbcopy((caddr_t)ip, (caddr_t)(((u_char *)ip) + stripsiz), off);
411 m->m_data += stripsiz;
412 m->m_len -= stripsiz;
413 m->m_pkthdr.len -= stripsiz;
415 ip = mtod(m, struct ip *);
417 ip->ip_len = ip->ip_len - stripsiz;
419 ip->ip_len = htons(ntohs(ip->ip_len) - stripsiz);
423 key_sa_recordxfer(sav, m);
425 if (nxt != IPPROTO_DONE)
426 (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt);
433 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
434 printf("DP esp4_input call free SA:%p\n", sav));
437 ipsecstat.in_success++;
442 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
443 printf("DP esp4_input call free SA:%p\n", sav));
454 esp6_input(mp, offp, proto)
458 struct mbuf *m = *mp;
462 struct esptail esptail;
464 struct secasvar *sav = NULL;
467 struct esp_algorithm *algo;
472 /* sanity check for alignment. */
473 if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) {
474 ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem "
475 "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len));
476 ipsec6stat.in_inval++;
480 #ifndef PULLDOWN_TEST
481 IP6_EXTHDR_CHECK(m, off, ESPMAXLEN, IPPROTO_DONE);
482 esp = (struct esp *)(mtod(m, caddr_t) + off);
484 IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN);
486 ipsec6stat.in_inval++;
490 ip6 = mtod(m, struct ip6_hdr *);
492 if (ntohs(ip6->ip6_plen) == 0) {
493 ipseclog((LOG_ERR, "IPv6 ESP input: "
494 "ESP with IPv6 jumbogram is not supported.\n"));
495 ipsec6stat.in_inval++;
499 /* find the sassoc. */
502 if ((sav = key_allocsa(AF_INET6,
503 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
504 IPPROTO_ESP, spi)) == 0) {
505 ipseclog((LOG_WARNING,
506 "IPv6 ESP input: no key association found for spi %u\n",
507 (u_int32_t)ntohl(spi)));
508 ipsec6stat.in_nosa++;
511 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
512 printf("DP esp6_input called to allocate SA:%p\n", sav));
513 if (sav->state != SADB_SASTATE_MATURE
514 && sav->state != SADB_SASTATE_DYING) {
516 "IPv6 ESP input: non-mature/dying SA found for spi %u\n",
517 (u_int32_t)ntohl(spi)));
518 ipsec6stat.in_badspi++;
521 if (sav->alg_enc == SADB_EALG_NONE) {
522 ipseclog((LOG_DEBUG, "IPv6 ESP input: "
523 "unspecified encryption algorithm for spi %u\n",
524 (u_int32_t)ntohl(spi)));
525 ipsec6stat.in_badspi++;
529 algo = &esp_algorithms[sav->alg_enc]; /*XXX*/
531 /* check if we have proper ivlen information */
534 ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n",
535 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
536 ipsec6stat.in_badspi++;
540 if (!((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay
541 && (sav->alg_auth && sav->key_auth)))
544 if (sav->alg_auth == SADB_AALG_NULL)
548 * check for sequence number.
550 if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav))
553 ipsec6stat.in_espreplay++;
554 ipseclog((LOG_WARNING,
555 "replay packet in IPv6 ESP input: %s %s\n",
556 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
562 u_char sum0[AH_MAXSUMSIZE];
563 u_char sum[AH_MAXSUMSIZE];
564 struct ah_algorithm *sumalgo;
567 sumalgo = &ah_algorithms[sav->alg_auth];
568 siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1));
569 if (AH_MAXSUMSIZE < siz) {
571 "internal error: AH_MAXSUMSIZE must be larger than %lu\n",
573 ipsec6stat.in_inval++;
577 m_copydata(m, m->m_pkthdr.len - siz, siz, &sum0[0]);
579 if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) {
580 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
581 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
582 ipsec6stat.in_espauthfail++;
586 if (bcmp(sum0, sum, siz) != 0) {
587 ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n",
588 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
589 ipsec6stat.in_espauthfail++;
593 /* strip off the authentication data */
595 ip6 = mtod(m, struct ip6_hdr *);
596 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz);
598 m->m_flags |= M_AUTHIPDGM;
599 ipsec6stat.in_espauthsucc++;
603 * update sequence number.
605 if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) {
606 if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) {
607 ipsec6stat.in_espreplay++;
614 /* process main esp header. */
615 if (sav->flags & SADB_X_EXT_OLD) {
617 esplen = sizeof(struct esp);
620 if (sav->flags & SADB_X_EXT_DERIV)
621 esplen = sizeof(struct esp);
623 esplen = sizeof(struct newesp);
626 if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) {
627 ipseclog((LOG_WARNING,
628 "IPv6 ESP input: packet too short\n"));
629 ipsec6stat.in_inval++;
633 #ifndef PULLDOWN_TEST
634 IP6_EXTHDR_CHECK(m, off, esplen + ivlen, IPPROTO_DONE); /*XXX*/
636 IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen);
638 ipsec6stat.in_inval++;
643 ip6 = mtod(m, struct ip6_hdr *); /*set it again just in case*/
646 * decrypt the packet.
649 panic("internal error: no decrypt function");
650 if ((*algo->decrypt)(m, off, sav, algo, ivlen)) {
651 ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s %s\n",
652 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
653 ipsec6stat.in_inval++;
656 ipsec6stat.in_esphist[sav->alg_enc]++;
658 m->m_flags |= M_DECRYPTED;
661 * find the trailer of the ESP.
663 m_copydata(m, m->m_pkthdr.len - sizeof(esptail), sizeof(esptail),
665 nxt = esptail.esp_nxt;
666 taillen = esptail.esp_padlen + sizeof(esptail);
668 if (m->m_pkthdr.len < taillen
669 || m->m_pkthdr.len - taillen < sizeof(struct ip6_hdr)) { /*?*/
670 ipseclog((LOG_WARNING,
671 "bad pad length in IPv6 ESP input: %s %s\n",
672 ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav)));
673 ipsec6stat.in_inval++;
677 /* strip off the trailing pad area. */
680 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - taillen);
682 /* was it transmitted over the IPsec tunnel SA? */
683 if (ipsec6_tunnel_validate(ip6, nxt, sav)) {
685 * strip off all the headers that precedes ESP header.
686 * IP6 xx ESP IP6' payload -> IP6' payload
688 * XXX more sanity checks
689 * XXX relationship with gif?
691 u_int32_t flowinfo; /*net endian*/
692 flowinfo = ip6->ip6_flow;
693 m_adj(m, off + esplen + ivlen);
694 if (m->m_len < sizeof(*ip6)) {
695 #ifndef PULLDOWN_TEST
697 * m_pullup is prohibited in KAME IPv6 input processing
698 * but there's no other way!
701 /* okay to pullup in m_pulldown style */
703 m = m_pullup(m, sizeof(*ip6));
705 ipsec6stat.in_inval++;
709 ip6 = mtod(m, struct ip6_hdr *);
710 /* ECN consideration. */
711 ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow);
712 if (!key_checktunnelsanity(sav, AF_INET6,
713 (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) {
714 ipseclog((LOG_ERR, "ipsec tunnel address mismatch "
715 "in IPv6 ESP input: %s %s\n",
716 ipsec6_logpacketstr(ip6, spi),
717 ipsec_logsastr(sav)));
718 ipsec6stat.in_inval++;
722 #if 0 /* XXX should call ipfw rather than ipsec_in_reject, shouldn't it ? */
723 /* drop it if it does not match the default policy */
724 if (ipsec6_in_reject(m, NULL)) {
725 ipsec6stat.in_polvio++;
730 key_sa_recordxfer(sav, m);
732 if (! IF_HANDOFF(&ip6intrq, m, NULL)) {
733 ipsec6stat.in_inval++;
738 schednetisr(NETISR_IPV6); /*can be skipped but to make sure*/
742 * strip off ESP header and IV.
743 * even in m_pulldown case, we need to strip off ESP so that
744 * we can always compute checksum for AH correctly.
750 * Set the next header field of the previous header correctly.
752 prvnxtp = ip6_get_prevhdr(m, off); /* XXX */
755 stripsiz = esplen + ivlen;
757 ip6 = mtod(m, struct ip6_hdr *);
758 if (m->m_len >= stripsiz + off) {
759 ovbcopy((caddr_t)ip6, ((caddr_t)ip6) + stripsiz, off);
760 m->m_data += stripsiz;
761 m->m_len -= stripsiz;
762 m->m_pkthdr.len -= stripsiz;
765 * this comes with no copy if the boundary is on
770 n = m_split(m, off, M_DONTWAIT);
772 /* m is retained by m_split */
777 /* m_cat does not update m_pkthdr.len */
778 m->m_pkthdr.len += n->m_pkthdr.len;
781 ip6 = mtod(m, struct ip6_hdr *);
782 ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - stripsiz);
784 key_sa_recordxfer(sav, m);
791 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
792 printf("DP esp6_input call free SA:%p\n", sav));
795 ipsec6stat.in_success++;
800 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
801 printf("DP esp6_input call free SA:%p\n", sav));