]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/ah_core.c
f218998284fa713ed2b95ec831c0a271b474b294
[apple/xnu.git] / bsd / netinet6 / ah_core.c
1 /*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * RFC1826/2402 authentication header.
32 */
33 #define _IP_VHL
34 #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
35 #include "opt_inet.h"
36 #if __NetBSD__ /*XXX*/
37 #include "opt_ipsec.h"
38 #endif
39 #endif
40
41 /* Some of operating systems have standard crypto checksum library */
42 #if __NetBSD__
43 #define HAVE_MD5
44 #define HAVE_SHA1
45 #endif
46 #if defined(__FreeBSD__) || defined(__APPLE__)
47 #define HAVE_MD5 1
48 #endif
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/malloc.h>
53 #include <sys/mbuf.h>
54 #include <sys/domain.h>
55 #include <sys/protosw.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/errno.h>
59 #include <sys/time.h>
60 #include <sys/kernel.h>
61 #include <sys/syslog.h>
62
63 #include <net/if.h>
64 #include <net/route.h>
65
66 #include <netinet/in.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/ip.h>
69 #include <netinet/in_var.h>
70
71 #if INET6
72 #include <netinet/ip6.h>
73 #include <netinet6/ip6_var.h>
74 #include <netinet/icmp6.h>
75 #endif
76
77 #include <netinet6/ipsec.h>
78 #include <netinet6/ah.h>
79 #if IPSEC_ESP
80 #include <netinet6/esp.h>
81 #endif
82 #include <net/pfkeyv2.h>
83 #include <netkey/keydb.h>
84 #if HAVE_MD5
85 #include <sys/md5.h>
86 #else
87 #include <crypto/md5.h>
88 #endif
89 #if HAVE_SHA1
90 #include <sys/sha1.h>
91 #define SHA1_RESULTLEN 20
92 #else
93 #include <crypto/sha1.h>
94 #endif
95
96 #include <net/net_osdep.h>
97
98 #define HMACSIZE 16
99
100 static int ah_sumsiz_1216 __P((struct secasvar *));
101 static int ah_sumsiz_zero __P((struct secasvar *));
102 static int ah_none_mature __P((struct secasvar *));
103 static void ah_none_init __P((struct ah_algorithm_state *,
104 struct secasvar *));
105 static void ah_none_loop __P((struct ah_algorithm_state *, caddr_t, size_t));
106 static void ah_none_result __P((struct ah_algorithm_state *, caddr_t));
107 static int ah_keyed_md5_mature __P((struct secasvar *));
108 static void ah_keyed_md5_init __P((struct ah_algorithm_state *,
109 struct secasvar *));
110 static void ah_keyed_md5_loop __P((struct ah_algorithm_state *, caddr_t,
111 size_t));
112 static void ah_keyed_md5_result __P((struct ah_algorithm_state *, caddr_t));
113 static int ah_keyed_sha1_mature __P((struct secasvar *));
114 static void ah_keyed_sha1_init __P((struct ah_algorithm_state *,
115 struct secasvar *));
116 static void ah_keyed_sha1_loop __P((struct ah_algorithm_state *, caddr_t,
117 size_t));
118 static void ah_keyed_sha1_result __P((struct ah_algorithm_state *, caddr_t));
119 static int ah_hmac_md5_mature __P((struct secasvar *));
120 static void ah_hmac_md5_init __P((struct ah_algorithm_state *,
121 struct secasvar *));
122 static void ah_hmac_md5_loop __P((struct ah_algorithm_state *, caddr_t,
123 size_t));
124 static void ah_hmac_md5_result __P((struct ah_algorithm_state *, caddr_t));
125 static int ah_hmac_sha1_mature __P((struct secasvar *));
126 static void ah_hmac_sha1_init __P((struct ah_algorithm_state *,
127 struct secasvar *));
128 static void ah_hmac_sha1_loop __P((struct ah_algorithm_state *, caddr_t,
129 size_t));
130 static void ah_hmac_sha1_result __P((struct ah_algorithm_state *, caddr_t));
131
132 static void ah_update_mbuf __P((struct mbuf *, int, int, struct ah_algorithm *,
133 struct ah_algorithm_state *));
134
135 /* checksum algorithms */
136 /* NOTE: The order depends on SADB_AALG_x in net/pfkeyv2.h */
137 struct ah_algorithm ah_algorithms[] = {
138 { 0, 0, 0, 0, 0, 0, },
139 { ah_sumsiz_1216, ah_hmac_md5_mature, 128, 128,
140 ah_hmac_md5_init, ah_hmac_md5_loop, ah_hmac_md5_result, },
141 { ah_sumsiz_1216, ah_hmac_sha1_mature, 160, 160,
142 ah_hmac_sha1_init, ah_hmac_sha1_loop, ah_hmac_sha1_result, },
143 { ah_sumsiz_1216, ah_keyed_md5_mature, 128, 128,
144 ah_keyed_md5_init, ah_keyed_md5_loop, ah_keyed_md5_result, },
145 { ah_sumsiz_1216, ah_keyed_sha1_mature, 160, 160,
146 ah_keyed_sha1_init, ah_keyed_sha1_loop, ah_keyed_sha1_result, },
147 { ah_sumsiz_zero, ah_none_mature, 0, 2048,
148 ah_none_init, ah_none_loop, ah_none_result, },
149 };
150
151 static int
152 ah_sumsiz_1216(sav)
153 struct secasvar *sav;
154 {
155 if (!sav)
156 return -1;
157 if (sav->flags & SADB_X_EXT_OLD)
158 return 16;
159 else
160 return 12;
161 }
162
163 static int
164 ah_sumsiz_zero(sav)
165 struct secasvar *sav;
166 {
167 if (!sav)
168 return -1;
169 return 0;
170 }
171
172 static int
173 ah_none_mature(sav)
174 struct secasvar *sav;
175 {
176 if (sav->sah->saidx.proto == IPPROTO_AH) {
177 ipseclog((LOG_ERR,
178 "ah_none_mature: protocol and algorithm mismatch.\n"));
179 return 1;
180 }
181 return 0;
182 }
183
184 static void
185 ah_none_init(state, sav)
186 struct ah_algorithm_state *state;
187 struct secasvar *sav;
188 {
189 state->foo = NULL;
190 }
191
192 static void
193 ah_none_loop(state, addr, len)
194 struct ah_algorithm_state *state;
195 caddr_t addr;
196 size_t len;
197 {
198 }
199
200 static void
201 ah_none_result(state, addr)
202 struct ah_algorithm_state *state;
203 caddr_t addr;
204 {
205 }
206
207 static int
208 ah_keyed_md5_mature(sav)
209 struct secasvar *sav;
210 {
211 /* anything is okay */
212 return 0;
213 }
214
215 static void
216 ah_keyed_md5_init(state, sav)
217 struct ah_algorithm_state *state;
218 struct secasvar *sav;
219 {
220 if (!state)
221 panic("ah_keyed_md5_init: what?");
222
223 state->sav = sav;
224 state->foo = (void *)_MALLOC(sizeof(MD5_CTX), M_TEMP, M_WAITOK);
225 if (state->foo == NULL)
226 panic("ah_keyed_md5_init: what?");
227 MD5Init((MD5_CTX *)state->foo);
228 if (state->sav) {
229 MD5Update((MD5_CTX *)state->foo,
230 (u_int8_t *)_KEYBUF(state->sav->key_auth),
231 (u_int)_KEYLEN(state->sav->key_auth));
232
233 {
234 /*
235 * Pad after the key.
236 * We cannot simply use md5_pad() since the function
237 * won't update the total length.
238 */
239 size_t padlen;
240 size_t keybitlen;
241 u_int8_t buf[32];
242
243 if (_KEYLEN(state->sav->key_auth) < 56)
244 padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
245 else
246 padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
247 keybitlen = _KEYLEN(state->sav->key_auth);
248 keybitlen *= 8;
249
250 buf[0] = 0x80;
251 MD5Update((MD5_CTX *)state->foo, &buf[0], 1);
252 padlen--;
253
254 bzero(buf, sizeof(buf));
255 while (sizeof(buf) < padlen) {
256 MD5Update((MD5_CTX *)state->foo, &buf[0], sizeof(buf));
257 padlen -= sizeof(buf);
258 }
259 if (padlen) {
260 MD5Update((MD5_CTX *)state->foo, &buf[0], padlen);
261 }
262
263 buf[0] = (keybitlen >> 0) & 0xff;
264 buf[1] = (keybitlen >> 8) & 0xff;
265 buf[2] = (keybitlen >> 16) & 0xff;
266 buf[3] = (keybitlen >> 24) & 0xff;
267 MD5Update((MD5_CTX *)state->foo, buf, 8);
268 }
269 }
270 }
271
272 static void
273 ah_keyed_md5_loop(state, addr, len)
274 struct ah_algorithm_state *state;
275 caddr_t addr;
276 size_t len;
277 {
278 if (!state)
279 panic("ah_keyed_md5_loop: what?");
280
281 MD5Update((MD5_CTX *)state->foo, addr, len);
282 }
283
284 static void
285 ah_keyed_md5_result(state, addr)
286 struct ah_algorithm_state *state;
287 caddr_t addr;
288 {
289 u_char digest[16];
290
291 if (!state)
292 panic("ah_keyed_md5_result: what?");
293
294 if (state->sav) {
295 MD5Update((MD5_CTX *)state->foo,
296 (u_int8_t *)_KEYBUF(state->sav->key_auth),
297 (u_int)_KEYLEN(state->sav->key_auth));
298 }
299 MD5Final(&digest[0], (MD5_CTX *)state->foo);
300 _FREE(state->foo, M_TEMP);
301 bcopy(&digest[0], (void *)addr, sizeof(digest));
302 }
303
304 static int
305 ah_keyed_sha1_mature(sav)
306 struct secasvar *sav;
307 {
308 struct ah_algorithm *algo;
309
310 if (!sav->key_auth) {
311 ipseclog((LOG_ERR, "ah_keyed_sha1_mature: no key is given.\n"));
312 return 1;
313 }
314 algo = &ah_algorithms[sav->alg_auth];
315 if (sav->key_auth->sadb_key_bits < algo->keymin
316 || algo->keymax < sav->key_auth->sadb_key_bits) {
317 ipseclog((LOG_ERR,
318 "ah_keyed_sha1_mature: invalid key length %d.\n",
319 sav->key_auth->sadb_key_bits));
320 return 1;
321 }
322
323 return 0;
324 }
325
326 static void
327 ah_keyed_sha1_init(state, sav)
328 struct ah_algorithm_state *state;
329 struct secasvar *sav;
330 {
331 SHA1_CTX *ctxt;
332
333 if (!state)
334 panic("ah_keyed_sha1_init: what?");
335
336 state->sav = sav;
337 state->foo = (void *)_MALLOC(sizeof(SHA1_CTX), M_TEMP, M_WAITOK);
338 if (!state->foo)
339 panic("ah_keyed_sha1_init: what?");
340
341 ctxt = (SHA1_CTX *)state->foo;
342 SHA1Init(ctxt);
343
344 if (state->sav) {
345 SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
346 (u_int)_KEYLEN(state->sav->key_auth));
347
348 {
349 /*
350 * Pad after the key.
351 */
352 size_t padlen;
353 size_t keybitlen;
354 u_int8_t buf[32];
355
356 if (_KEYLEN(state->sav->key_auth) < 56)
357 padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
358 else
359 padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
360 keybitlen = _KEYLEN(state->sav->key_auth);
361 keybitlen *= 8;
362
363 buf[0] = 0x80;
364 SHA1Update(ctxt, &buf[0], 1);
365 padlen--;
366
367 bzero(buf, sizeof(buf));
368 while (sizeof(buf) < padlen) {
369 SHA1Update(ctxt, &buf[0], sizeof(buf));
370 padlen -= sizeof(buf);
371 }
372 if (padlen) {
373 SHA1Update(ctxt, &buf[0], padlen);
374 }
375
376 buf[0] = (keybitlen >> 0) & 0xff;
377 buf[1] = (keybitlen >> 8) & 0xff;
378 buf[2] = (keybitlen >> 16) & 0xff;
379 buf[3] = (keybitlen >> 24) & 0xff;
380 SHA1Update(ctxt, buf, 8);
381 }
382 }
383 }
384
385 static void
386 ah_keyed_sha1_loop(state, addr, len)
387 struct ah_algorithm_state *state;
388 caddr_t addr;
389 size_t len;
390 {
391 SHA1_CTX *ctxt;
392
393 if (!state || !state->foo)
394 panic("ah_keyed_sha1_loop: what?");
395 ctxt = (SHA1_CTX *)state->foo;
396
397 SHA1Update(ctxt, (caddr_t)addr, (size_t)len);
398 }
399
400 static void
401 ah_keyed_sha1_result(state, addr)
402 struct ah_algorithm_state *state;
403 caddr_t addr;
404 {
405 u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
406 SHA1_CTX *ctxt;
407
408 if (!state || !state->foo)
409 panic("ah_keyed_sha1_result: what?");
410 ctxt = (SHA1_CTX *)state->foo;
411
412 if (state->sav) {
413 SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
414 (u_int)_KEYLEN(state->sav->key_auth));
415 }
416 SHA1Final((caddr_t)&digest[0], ctxt);
417 bcopy(&digest[0], (void *)addr, HMACSIZE);
418
419 _FREE(state->foo, M_TEMP);
420 }
421
422 static int
423 ah_hmac_md5_mature(sav)
424 struct secasvar *sav;
425 {
426 struct ah_algorithm *algo;
427
428 if (!sav->key_auth) {
429 ipseclog((LOG_ERR, "ah_hmac_md5_mature: no key is given.\n"));
430 return 1;
431 }
432 algo = &ah_algorithms[sav->alg_auth];
433 if (sav->key_auth->sadb_key_bits < algo->keymin
434 || algo->keymax < sav->key_auth->sadb_key_bits) {
435 ipseclog((LOG_ERR,
436 "ah_hmac_md5_mature: invalid key length %d.\n",
437 sav->key_auth->sadb_key_bits));
438 return 1;
439 }
440
441 return 0;
442 }
443
444 static void
445 ah_hmac_md5_init(state, sav)
446 struct ah_algorithm_state *state;
447 struct secasvar *sav;
448 {
449 u_char *ipad;
450 u_char *opad;
451 u_char tk[16];
452 u_char *key;
453 size_t keylen;
454 size_t i;
455 MD5_CTX *ctxt;
456
457 if (!state)
458 panic("ah_hmac_md5_init: what?");
459
460 state->sav = sav;
461 state->foo = (void *)_MALLOC(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_WAITOK);
462 if (!state->foo)
463 panic("ah_hmac_md5_init: what?");
464
465 ipad = (u_char *)state->foo;
466 opad = (u_char *)(ipad + 64);
467 ctxt = (MD5_CTX *)(opad + 64);
468
469 /* compress the key if necessery */
470 if (64 < _KEYLEN(state->sav->key_auth)) {
471 MD5Init(ctxt);
472 MD5Update(ctxt, _KEYBUF(state->sav->key_auth),
473 _KEYLEN(state->sav->key_auth));
474 MD5Final(&tk[0], ctxt);
475 key = &tk[0];
476 keylen = 16;
477 } else {
478 key = _KEYBUF(state->sav->key_auth);
479 keylen = _KEYLEN(state->sav->key_auth);
480 }
481
482 bzero(ipad, 64);
483 bzero(opad, 64);
484 bcopy(key, ipad, keylen);
485 bcopy(key, opad, keylen);
486 for (i = 0; i < 64; i++) {
487 ipad[i] ^= 0x36;
488 opad[i] ^= 0x5c;
489 }
490
491 MD5Init(ctxt);
492 MD5Update(ctxt, ipad, 64);
493 }
494
495 static void
496 ah_hmac_md5_loop(state, addr, len)
497 struct ah_algorithm_state *state;
498 caddr_t addr;
499 size_t len;
500 {
501 MD5_CTX *ctxt;
502
503 if (!state || !state->foo)
504 panic("ah_hmac_md5_loop: what?");
505 ctxt = (MD5_CTX *)(((caddr_t)state->foo) + 128);
506 MD5Update(ctxt, addr, len);
507 }
508
509 static void
510 ah_hmac_md5_result(state, addr)
511 struct ah_algorithm_state *state;
512 caddr_t addr;
513 {
514 u_char digest[16];
515 u_char *ipad;
516 u_char *opad;
517 MD5_CTX *ctxt;
518
519 if (!state || !state->foo)
520 panic("ah_hmac_md5_result: what?");
521
522 ipad = (u_char *)state->foo;
523 opad = (u_char *)(ipad + 64);
524 ctxt = (MD5_CTX *)(opad + 64);
525
526 MD5Final(&digest[0], ctxt);
527
528 MD5Init(ctxt);
529 MD5Update(ctxt, opad, 64);
530 MD5Update(ctxt, &digest[0], sizeof(digest));
531 MD5Final(&digest[0], ctxt);
532
533 bcopy(&digest[0], (void *)addr, HMACSIZE);
534
535 _FREE(state->foo, M_TEMP);
536 }
537
538 static int
539 ah_hmac_sha1_mature(sav)
540 struct secasvar *sav;
541 {
542 struct ah_algorithm *algo;
543
544 if (!sav->key_auth) {
545 ipseclog((LOG_ERR, "ah_hmac_sha1_mature: no key is given.\n"));
546 return 1;
547 }
548 algo = &ah_algorithms[sav->alg_auth];
549 if (sav->key_auth->sadb_key_bits < algo->keymin
550 || algo->keymax < sav->key_auth->sadb_key_bits) {
551 ipseclog((LOG_ERR,
552 "ah_hmac_sha1_mature: invalid key length %d.\n",
553 sav->key_auth->sadb_key_bits));
554 return 1;
555 }
556
557 return 0;
558 }
559
560 static void
561 ah_hmac_sha1_init(state, sav)
562 struct ah_algorithm_state *state;
563 struct secasvar *sav;
564 {
565 u_char *ipad;
566 u_char *opad;
567 SHA1_CTX *ctxt;
568 u_char tk[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
569 u_char *key;
570 size_t keylen;
571 size_t i;
572
573 if (!state)
574 panic("ah_hmac_sha1_init: what?");
575
576 state->sav = sav;
577 state->foo = (void *)_MALLOC(64 + 64 + sizeof(SHA1_CTX),
578 M_TEMP, M_WAITOK);
579 if (!state->foo)
580 panic("ah_hmac_sha1_init: what?");
581
582 ipad = (u_char *)state->foo;
583 opad = (u_char *)(ipad + 64);
584 ctxt = (SHA1_CTX *)(opad + 64);
585
586 /* compress the key if necessery */
587 if (64 < _KEYLEN(state->sav->key_auth)) {
588 SHA1Init(ctxt);
589 SHA1Update(ctxt, _KEYBUF(state->sav->key_auth),
590 _KEYLEN(state->sav->key_auth));
591 SHA1Final(&tk[0], ctxt);
592 key = &tk[0];
593 keylen = SHA1_RESULTLEN;
594 } else {
595 key = _KEYBUF(state->sav->key_auth);
596 keylen = _KEYLEN(state->sav->key_auth);
597 }
598
599 bzero(ipad, 64);
600 bzero(opad, 64);
601 bcopy(key, ipad, keylen);
602 bcopy(key, opad, keylen);
603 for (i = 0; i < 64; i++) {
604 ipad[i] ^= 0x36;
605 opad[i] ^= 0x5c;
606 }
607
608 SHA1Init(ctxt);
609 SHA1Update(ctxt, ipad, 64);
610 }
611
612 static void
613 ah_hmac_sha1_loop(state, addr, len)
614 struct ah_algorithm_state *state;
615 caddr_t addr;
616 size_t len;
617 {
618 SHA1_CTX *ctxt;
619
620 if (!state || !state->foo)
621 panic("ah_hmac_sha1_loop: what?");
622
623 ctxt = (SHA1_CTX *)(((u_char *)state->foo) + 128);
624 SHA1Update(ctxt, (caddr_t)addr, (size_t)len);
625 }
626
627 static void
628 ah_hmac_sha1_result(state, addr)
629 struct ah_algorithm_state *state;
630 caddr_t addr;
631 {
632 u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
633 u_char *ipad;
634 u_char *opad;
635 SHA1_CTX *ctxt;
636
637 if (!state || !state->foo)
638 panic("ah_hmac_sha1_result: what?");
639
640 ipad = (u_char *)state->foo;
641 opad = (u_char *)(ipad + 64);
642 ctxt = (SHA1_CTX *)(opad + 64);
643
644 SHA1Final((caddr_t)&digest[0], ctxt);
645
646 SHA1Init(ctxt);
647 SHA1Update(ctxt, opad, 64);
648 SHA1Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
649 SHA1Final((caddr_t)&digest[0], ctxt);
650
651 bcopy(&digest[0], (void *)addr, HMACSIZE);
652
653 _FREE(state->foo, M_TEMP);
654 }
655
656 /*------------------------------------------------------------*/
657
658 /*
659 * go generate the checksum.
660 */
661 static void
662 ah_update_mbuf(m, off, len, algo, algos)
663 struct mbuf *m;
664 int off;
665 int len;
666 struct ah_algorithm *algo;
667 struct ah_algorithm_state *algos;
668 {
669 struct mbuf *n;
670 int tlen;
671
672 /* easy case first */
673 if (off + len <= m->m_len) {
674 (algo->update)(algos, mtod(m, caddr_t) + off, len);
675 return;
676 }
677
678 for (n = m; n; n = n->m_next) {
679 if (off < n->m_len)
680 break;
681
682 off -= n->m_len;
683 }
684
685 if (!n)
686 panic("ah_update_mbuf: wrong offset specified");
687
688 for (/*nothing*/; n && len > 0; n = n->m_next) {
689 if (n->m_len == 0)
690 continue;
691 if (n->m_len - off < len)
692 tlen = n->m_len - off;
693 else
694 tlen = len;
695
696 (algo->update)(algos, mtod(n, caddr_t) + off, tlen);
697
698 len -= tlen;
699 off = 0;
700 }
701 }
702
703 /*
704 * Go generate the checksum. This function won't modify the mbuf chain
705 * except AH itself.
706 *
707 * NOTE: the function does not free mbuf on failure.
708 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
709 */
710 int
711 ah4_calccksum(m, ahdat, algo, sav)
712 struct mbuf *m;
713 caddr_t ahdat;
714 struct ah_algorithm *algo;
715 struct secasvar *sav;
716 {
717 int off;
718 int hdrtype;
719 size_t advancewidth;
720 struct ah_algorithm_state algos;
721 u_char sumbuf[AH_MAXSUMSIZE];
722 int error = 0;
723 int ahseen;
724 struct mbuf *n = NULL;
725
726 if ((m->m_flags & M_PKTHDR) == 0)
727 return EINVAL;
728
729 ahseen = 0;
730 hdrtype = -1; /*dummy, it is called IPPROTO_IP*/
731
732 off = 0;
733
734 (algo->init)(&algos, sav);
735
736 advancewidth = 0; /*safety*/
737
738 again:
739 /* gory. */
740 switch (hdrtype) {
741 case -1: /*first one only*/
742 {
743 /*
744 * copy ip hdr, modify to fit the AH checksum rule,
745 * then take a checksum.
746 */
747 struct ip iphdr;
748 size_t hlen;
749
750 m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr);
751 #ifdef _IP_VHL
752 hlen = IP_VHL_HL(iphdr.ip_vhl) << 2;
753 #else
754 hlen = iphdr.ip_hl << 2;
755 #endif
756 iphdr.ip_ttl = 0;
757 iphdr.ip_sum = htons(0);
758 if (ip4_ah_cleartos)
759 iphdr.ip_tos = 0;
760 iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
761 (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip));
762
763 if (hlen != sizeof(struct ip)) {
764 u_char *p;
765 int i, l, skip;
766
767 if (hlen > MCLBYTES) {
768 error = EMSGSIZE;
769 goto fail;
770 }
771 MGET(n, M_DONTWAIT, MT_DATA);
772 if (n && hlen > MLEN) {
773 MCLGET(n, M_DONTWAIT);
774 if ((n->m_flags & M_EXT) == 0) {
775 m_free(n);
776 n = NULL;
777 }
778 }
779 if (n == NULL) {
780 error = ENOBUFS;
781 goto fail;
782 }
783 m_copydata(m, off, hlen, mtod(n, caddr_t));
784
785 /*
786 * IP options processing.
787 * See RFC2402 appendix A.
788 */
789 p = mtod(n, u_char *);
790 i = sizeof(struct ip);
791 while (i < hlen) {
792 skip = 1;
793 switch (p[i + IPOPT_OPTVAL]) {
794 case IPOPT_EOL:
795 case IPOPT_NOP:
796 l = 1;
797 skip = 0;
798 break;
799 case IPOPT_SECURITY: /* 0x82 */
800 case 0x85: /* Extended security */
801 case 0x86: /* Commercial security */
802 case 0x94: /* Router alert */
803 case 0x95: /* RFC1770 */
804 l = p[i + IPOPT_OLEN];
805 skip = 0;
806 break;
807 default:
808 l = p[i + IPOPT_OLEN];
809 skip = 1;
810 break;
811 }
812 if (l <= 0 || hlen - i < l) {
813 ipseclog((LOG_ERR,
814 "ah4_calccksum: invalid IP option "
815 "(type=%02x len=%02x)\n",
816 p[i + IPOPT_OPTVAL],
817 p[i + IPOPT_OLEN]));
818 m_free(n);
819 n = NULL;
820 error = EINVAL;
821 goto fail;
822 }
823 if (skip)
824 bzero(p + i, l);
825 if (p[i + IPOPT_OPTVAL] == IPOPT_EOL)
826 break;
827 i += l;
828 }
829 p = mtod(n, u_char *) + sizeof(struct ip);
830 (algo->update)(&algos, p, hlen - sizeof(struct ip));
831
832 m_free(n);
833 n = NULL;
834 }
835
836 hdrtype = (iphdr.ip_p) & 0xff;
837 advancewidth = hlen;
838 break;
839 }
840
841 case IPPROTO_AH:
842 {
843 struct ah ah;
844 int siz;
845 int hdrsiz;
846 int totlen;
847
848 m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
849 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
850 ? sizeof(struct ah)
851 : sizeof(struct newah);
852 siz = (*algo->sumsiz)(sav);
853 totlen = (ah.ah_len + 2) << 2;
854
855 /*
856 * special treatment is necessary for the first one, not others
857 */
858 if (!ahseen) {
859 if (totlen > m->m_pkthdr.len - off ||
860 totlen > MCLBYTES) {
861 error = EMSGSIZE;
862 goto fail;
863 }
864 MGET(n, M_DONTWAIT, MT_DATA);
865 if (n && totlen > MLEN) {
866 MCLGET(n, M_DONTWAIT);
867 if ((n->m_flags & M_EXT) == 0) {
868 m_free(n);
869 n = NULL;
870 }
871 }
872 if (n == NULL) {
873 error = ENOBUFS;
874 goto fail;
875 }
876 m_copydata(m, off, totlen, mtod(n, caddr_t));
877 n->m_len = totlen;
878 bzero(mtod(n, caddr_t) + hdrsiz, siz);
879 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
880 m_free(n);
881 n = NULL;
882 } else
883 ah_update_mbuf(m, off, totlen, algo, &algos);
884 ahseen++;
885
886 hdrtype = ah.ah_nxt;
887 advancewidth = totlen;
888 break;
889 }
890
891 default:
892 ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, &algos);
893 advancewidth = m->m_pkthdr.len - off;
894 break;
895 }
896
897 off += advancewidth;
898 if (off < m->m_pkthdr.len)
899 goto again;
900
901 (algo->result)(&algos, &sumbuf[0]);
902 bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
903
904 if (n)
905 m_free(n);
906 return error;
907
908 fail:
909 if (n)
910 m_free(n);
911 return error;
912 }
913
914 #if INET6
915 /*
916 * Go generate the checksum. This function won't modify the mbuf chain
917 * except AH itself.
918 *
919 * NOTE: the function does not free mbuf on failure.
920 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
921 */
922 int
923 ah6_calccksum(m, ahdat, algo, sav)
924 struct mbuf *m;
925 caddr_t ahdat;
926 struct ah_algorithm *algo;
927 struct secasvar *sav;
928 {
929 int newoff, off;
930 int proto, nxt;
931 struct mbuf *n = NULL;
932 int error;
933 int ahseen;
934 struct ah_algorithm_state algos;
935 u_char sumbuf[AH_MAXSUMSIZE];
936
937 if ((m->m_flags & M_PKTHDR) == 0)
938 return EINVAL;
939
940 (algo->init)(&algos, sav);
941
942 off = 0;
943 proto = IPPROTO_IPV6;
944 nxt = -1;
945 ahseen = 0;
946
947 again:
948 newoff = ip6_nexthdr(m, off, proto, &nxt);
949 if (newoff < 0)
950 newoff = m->m_pkthdr.len;
951 else if (newoff <= off) {
952 error = EINVAL;
953 goto fail;
954 }
955
956 switch (proto) {
957 case IPPROTO_IPV6:
958 /*
959 * special treatment is necessary for the first one, not others
960 */
961 if (off == 0) {
962 struct ip6_hdr ip6copy;
963
964 if (newoff - off != sizeof(struct ip6_hdr)) {
965 error = EINVAL;
966 goto fail;
967 }
968
969 m_copydata(m, off, newoff - off, (caddr_t)&ip6copy);
970 /* RFC2402 */
971 ip6copy.ip6_flow = 0;
972 ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
973 ip6copy.ip6_vfc |= IPV6_VERSION;
974 ip6copy.ip6_hlim = 0;
975 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src))
976 ip6copy.ip6_src.s6_addr16[1] = 0x0000;
977 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst))
978 ip6copy.ip6_dst.s6_addr16[1] = 0x0000;
979 (algo->update)(&algos, (caddr_t)&ip6copy,
980 sizeof(struct ip6_hdr));
981 } else {
982 newoff = m->m_pkthdr.len;
983 ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo,
984 &algos);
985 }
986 break;
987
988 case IPPROTO_AH:
989 {
990 int siz;
991 int hdrsiz;
992
993 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
994 ? sizeof(struct ah)
995 : sizeof(struct newah);
996 siz = (*algo->sumsiz)(sav);
997
998 /*
999 * special treatment is necessary for the first one, not others
1000 */
1001 if (!ahseen) {
1002 if (newoff - off > MCLBYTES) {
1003 error = EMSGSIZE;
1004 goto fail;
1005 }
1006 MGET(n, M_DONTWAIT, MT_DATA);
1007 if (n && newoff - off > MLEN) {
1008 MCLGET(n, M_DONTWAIT);
1009 if ((n->m_flags & M_EXT) == 0) {
1010 m_free(n);
1011 n = NULL;
1012 }
1013 }
1014 if (n == NULL) {
1015 error = ENOBUFS;
1016 goto fail;
1017 }
1018 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
1019 n->m_len = newoff - off;
1020 bzero(mtod(n, caddr_t) + hdrsiz, siz);
1021 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
1022 m_free(n);
1023 n = NULL;
1024 } else
1025 ah_update_mbuf(m, off, newoff - off, algo, &algos);
1026 ahseen++;
1027 break;
1028 }
1029
1030 case IPPROTO_HOPOPTS:
1031 case IPPROTO_DSTOPTS:
1032 {
1033 struct ip6_ext *ip6e;
1034 int hdrlen, optlen;
1035 u_int8_t *p, *optend, *optp;
1036
1037 if (newoff - off > MCLBYTES) {
1038 error = EMSGSIZE;
1039 goto fail;
1040 }
1041 MGET(n, M_DONTWAIT, MT_DATA);
1042 if (n && newoff - off > MLEN) {
1043 MCLGET(n, M_DONTWAIT);
1044 if ((n->m_flags & M_EXT) == 0) {
1045 m_free(n);
1046 n = NULL;
1047 }
1048 }
1049 if (n == NULL) {
1050 error = ENOBUFS;
1051 goto fail;
1052 }
1053 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
1054 n->m_len = newoff - off;
1055
1056 ip6e = mtod(n, struct ip6_ext *);
1057 hdrlen = (ip6e->ip6e_len + 1) << 3;
1058 if (newoff - off < hdrlen) {
1059 error = EINVAL;
1060 m_free(n);
1061 n = NULL;
1062 goto fail;
1063 }
1064 p = mtod(n, u_int8_t *);
1065 optend = p + hdrlen;
1066
1067 /*
1068 * ICV calculation for the options header including all
1069 * options. This part is a little tricky since there are
1070 * two type of options; mutable and immutable. We try to
1071 * null-out mutable ones here.
1072 */
1073 optp = p + 2;
1074 while (optp < optend) {
1075 if (optp[0] == IP6OPT_PAD1)
1076 optlen = 1;
1077 else {
1078 if (optp + 2 > optend) {
1079 error = EINVAL;
1080 m_free(n);
1081 n = NULL;
1082 goto fail;
1083 }
1084 optlen = optp[1] + 2;
1085
1086 if (optp[0] & IP6OPT_MUTABLE)
1087 bzero(optp + 2, optlen - 2);
1088 }
1089
1090 optp += optlen;
1091 }
1092
1093 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
1094 m_free(n);
1095 n = NULL;
1096 break;
1097 }
1098
1099 case IPPROTO_ROUTING:
1100 /*
1101 * For an input packet, we can just calculate `as is'.
1102 * For an output packet, we assume ip6_output have already
1103 * made packet how it will be received at the final
1104 * destination.
1105 */
1106 /* FALLTHROUGH */
1107
1108 default:
1109 ah_update_mbuf(m, off, newoff - off, algo, &algos);
1110 break;
1111 }
1112
1113 if (newoff < m->m_pkthdr.len) {
1114 proto = nxt;
1115 off = newoff;
1116 goto again;
1117 }
1118
1119 (algo->result)(&algos, &sumbuf[0]);
1120 bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
1121
1122 /* just in case */
1123 if (n)
1124 m_free(n);
1125 return 0;
1126 fail:
1127 /* just in case */
1128 if (n)
1129 m_free(n);
1130 return error;
1131 }
1132 #endif