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