Kernel part of bluetooth stack ported by Dmitry Komissaroff. Very much work
[dragonfly.git] / sys / netinet6 / ah_core.c
blob6976ea718411a8d3c7464f37fe31a6330d15e347
1 /* $FreeBSD: src/sys/netinet6/ah_core.c,v 1.2.2.5 2002/04/28 05:40:26 suz Exp $ */
2 /* $DragonFly: src/sys/netinet6/ah_core.c,v 1.10 2006/10/24 06:18:42 hsu Exp $ */
3 /* $KAME: ah_core.c,v 1.44 2001/03/12 11:24:39 itojun Exp $ */
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
35 * RFC1826/2402 authentication header.
38 /* TODO: have shared routines for hmac-* algorithms */
40 #include "opt_inet.h"
41 #include "opt_inet6.h"
42 #include "opt_ipsec.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/domain.h>
49 #include <sys/protosw.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/errno.h>
53 #include <sys/time.h>
54 #include <sys/syslog.h>
56 #include <net/if.h>
57 #include <net/route.h>
59 #include <netinet/in.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/ip.h>
62 #include <netinet/in_var.h>
64 #ifdef INET6
65 #include <netinet/ip6.h>
66 #include <netinet6/ip6_var.h>
67 #include <netinet/icmp6.h>
68 #endif
70 #include <netinet6/ipsec.h>
71 #ifdef INET6
72 #include <netinet6/ipsec6.h>
73 #endif
74 #include <netinet6/ah.h>
75 #ifdef INET6
76 #include <netinet6/ah6.h>
77 #endif
78 #ifdef IPSEC_ESP
79 #include <netinet6/esp.h>
80 #ifdef INET6
81 #include <netinet6/esp6.h>
82 #endif
83 #endif
84 #include <net/pfkeyv2.h>
85 #include <netproto/key/keydb.h>
86 #include <sys/md5.h>
87 #include <crypto/sha1.h>
88 #include <crypto/sha2/sha2.h>
90 #include <net/net_osdep.h>
92 #define HMACSIZE 16
94 static int ah_sumsiz_1216 (struct secasvar *);
95 static int ah_sumsiz_zero (struct secasvar *);
96 static int ah_none_mature (struct secasvar *);
97 static int ah_none_init (struct ah_algorithm_state *, struct secasvar *);
98 static void ah_none_loop (struct ah_algorithm_state *, caddr_t, size_t);
99 static void ah_none_result (struct ah_algorithm_state *, caddr_t);
100 static int ah_keyed_md5_mature (struct secasvar *);
101 static int ah_keyed_md5_init (struct ah_algorithm_state *,
102 struct secasvar *);
103 static void ah_keyed_md5_loop (struct ah_algorithm_state *, caddr_t,
104 size_t);
105 static void ah_keyed_md5_result (struct ah_algorithm_state *, caddr_t);
106 static int ah_keyed_sha1_mature (struct secasvar *);
107 static int ah_keyed_sha1_init (struct ah_algorithm_state *,
108 struct secasvar *);
109 static void ah_keyed_sha1_loop (struct ah_algorithm_state *, caddr_t,
110 size_t);
111 static void ah_keyed_sha1_result (struct ah_algorithm_state *, caddr_t);
112 static int ah_hmac_md5_mature (struct secasvar *);
113 static int ah_hmac_md5_init (struct ah_algorithm_state *,
114 struct secasvar *);
115 static void ah_hmac_md5_loop (struct ah_algorithm_state *, caddr_t,
116 size_t);
117 static void ah_hmac_md5_result (struct ah_algorithm_state *, caddr_t);
118 static int ah_hmac_sha1_mature (struct secasvar *);
119 static int ah_hmac_sha1_init (struct ah_algorithm_state *,
120 struct secasvar *);
121 static void ah_hmac_sha1_loop (struct ah_algorithm_state *, caddr_t,
122 size_t);
123 static void ah_hmac_sha1_result (struct ah_algorithm_state *, caddr_t);
124 static int ah_hmac_sha2_256_mature (struct secasvar *);
125 static int ah_hmac_sha2_256_init (struct ah_algorithm_state *,
126 struct secasvar *);
127 static void ah_hmac_sha2_256_loop (struct ah_algorithm_state *, caddr_t,
128 size_t);
129 static void ah_hmac_sha2_256_result (struct ah_algorithm_state *, caddr_t);
130 static int ah_hmac_sha2_384_mature (struct secasvar *);
131 static int ah_hmac_sha2_384_init (struct ah_algorithm_state *,
132 struct secasvar *);
133 static void ah_hmac_sha2_384_loop (struct ah_algorithm_state *, caddr_t,
134 size_t);
135 static void ah_hmac_sha2_384_result (struct ah_algorithm_state *, caddr_t);
136 static int ah_hmac_sha2_512_mature (struct secasvar *);
137 static int ah_hmac_sha2_512_init (struct ah_algorithm_state *,
138 struct secasvar *);
139 static void ah_hmac_sha2_512_loop (struct ah_algorithm_state *, caddr_t,
140 size_t);
141 static void ah_hmac_sha2_512_result (struct ah_algorithm_state *, caddr_t);
143 static void ah_update_mbuf (struct mbuf *, int, int,
144 const struct ah_algorithm *, struct ah_algorithm_state *);
146 const struct ah_algorithm *
147 ah_algorithm_lookup(int idx)
149 /* checksum algorithms */
150 static struct ah_algorithm ah_algorithms[] = {
151 { ah_sumsiz_1216, ah_hmac_md5_mature, 128, 128, "hmac-md5",
152 ah_hmac_md5_init, ah_hmac_md5_loop,
153 ah_hmac_md5_result, },
154 { ah_sumsiz_1216, ah_hmac_sha1_mature, 160, 160, "hmac-sha1",
155 ah_hmac_sha1_init, ah_hmac_sha1_loop,
156 ah_hmac_sha1_result, },
157 { ah_sumsiz_1216, ah_keyed_md5_mature, 128, 128, "keyed-md5",
158 ah_keyed_md5_init, ah_keyed_md5_loop,
159 ah_keyed_md5_result, },
160 { ah_sumsiz_1216, ah_keyed_sha1_mature, 160, 160, "keyed-sha1",
161 ah_keyed_sha1_init, ah_keyed_sha1_loop,
162 ah_keyed_sha1_result, },
163 { ah_sumsiz_zero, ah_none_mature, 0, 2048, "none",
164 ah_none_init, ah_none_loop, ah_none_result, },
165 { ah_sumsiz_1216, ah_hmac_sha2_256_mature, 256, 256,
166 "hmac-sha2-256",
167 ah_hmac_sha2_256_init, ah_hmac_sha2_256_loop,
168 ah_hmac_sha2_256_result, },
169 { ah_sumsiz_1216, ah_hmac_sha2_384_mature, 384, 384,
170 "hmac-sha2-384",
171 ah_hmac_sha2_384_init, ah_hmac_sha2_384_loop,
172 ah_hmac_sha2_384_result, },
173 { ah_sumsiz_1216, ah_hmac_sha2_512_mature, 512, 512,
174 "hmac-sha2-512",
175 ah_hmac_sha2_512_init, ah_hmac_sha2_512_loop,
176 ah_hmac_sha2_512_result, },
179 switch (idx) {
180 case SADB_AALG_MD5HMAC:
181 return &ah_algorithms[0];
182 case SADB_AALG_SHA1HMAC:
183 return &ah_algorithms[1];
184 case SADB_X_AALG_MD5:
185 return &ah_algorithms[2];
186 case SADB_X_AALG_SHA:
187 return &ah_algorithms[3];
188 case SADB_X_AALG_NULL:
189 return &ah_algorithms[4];
190 case SADB_X_AALG_SHA2_256:
191 return &ah_algorithms[5];
192 case SADB_X_AALG_SHA2_384:
193 return &ah_algorithms[6];
194 case SADB_X_AALG_SHA2_512:
195 return &ah_algorithms[7];
196 default:
197 return NULL;
202 static int
203 ah_sumsiz_1216(struct secasvar *sav)
205 if (!sav)
206 return -1;
207 if (sav->flags & SADB_X_EXT_OLD)
208 return 16;
209 else
210 return 12;
213 static int
214 ah_sumsiz_zero(struct secasvar *sav)
216 if (!sav)
217 return -1;
218 return 0;
221 static int
222 ah_none_mature(struct secasvar *sav)
224 if (sav->sah->saidx.proto == IPPROTO_AH) {
225 ipseclog((LOG_ERR,
226 "ah_none_mature: protocol and algorithm mismatch.\n"));
227 return 1;
229 return 0;
232 static int
233 ah_none_init(struct ah_algorithm_state *state, struct secasvar *sav)
235 state->foo = NULL;
236 return 0;
239 static void
240 ah_none_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
244 static void
245 ah_none_result(struct ah_algorithm_state *state, caddr_t addr)
249 static int
250 ah_keyed_md5_mature(struct secasvar *sav)
252 /* anything is okay */
253 return 0;
256 static int
257 ah_keyed_md5_init(struct ah_algorithm_state *state, struct secasvar *sav)
259 size_t padlen;
260 size_t keybitlen;
261 u_int8_t buf[32];
263 if (!state)
264 panic("ah_keyed_md5_init: what?");
266 state->sav = sav;
267 state->foo = (void *)kmalloc(sizeof(MD5_CTX), M_TEMP, M_NOWAIT);
268 if (state->foo == NULL)
269 return ENOBUFS;
271 MD5Init((MD5_CTX *)state->foo);
272 if (state->sav) {
273 MD5Update((MD5_CTX *)state->foo,
274 (u_int8_t *)_KEYBUF(state->sav->key_auth),
275 (u_int)_KEYLEN(state->sav->key_auth));
278 * Pad after the key.
279 * We cannot simply use md5_pad() since the function
280 * won't update the total length.
282 if (_KEYLEN(state->sav->key_auth) < 56)
283 padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
284 else
285 padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
286 keybitlen = _KEYLEN(state->sav->key_auth);
287 keybitlen *= 8;
289 buf[0] = 0x80;
290 MD5Update((MD5_CTX *)state->foo, &buf[0], 1);
291 padlen--;
293 bzero(buf, sizeof(buf));
294 while (sizeof(buf) < padlen) {
295 MD5Update((MD5_CTX *)state->foo, &buf[0], sizeof(buf));
296 padlen -= sizeof(buf);
298 if (padlen) {
299 MD5Update((MD5_CTX *)state->foo, &buf[0], padlen);
302 buf[0] = (keybitlen >> 0) & 0xff;
303 buf[1] = (keybitlen >> 8) & 0xff;
304 buf[2] = (keybitlen >> 16) & 0xff;
305 buf[3] = (keybitlen >> 24) & 0xff;
306 MD5Update((MD5_CTX *)state->foo, buf, 8);
309 return 0;
312 static void
313 ah_keyed_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
315 if (!state)
316 panic("ah_keyed_md5_loop: what?");
318 MD5Update((MD5_CTX *)state->foo, addr, len);
321 static void
322 ah_keyed_md5_result(struct ah_algorithm_state *state, caddr_t addr)
324 u_char digest[16];
326 if (!state)
327 panic("ah_keyed_md5_result: what?");
329 if (state->sav) {
330 MD5Update((MD5_CTX *)state->foo,
331 (u_int8_t *)_KEYBUF(state->sav->key_auth),
332 (u_int)_KEYLEN(state->sav->key_auth));
334 MD5Final(&digest[0], (MD5_CTX *)state->foo);
335 kfree(state->foo, M_TEMP);
336 bcopy(&digest[0], (void *)addr, sizeof(digest));
339 static int
340 ah_keyed_sha1_mature(struct secasvar *sav)
342 const struct ah_algorithm *algo;
344 if (!sav->key_auth) {
345 ipseclog((LOG_ERR, "ah_keyed_sha1_mature: no key is given.\n"));
346 return 1;
349 algo = ah_algorithm_lookup(sav->alg_auth);
350 if (!algo) {
351 ipseclog((LOG_ERR, "ah_keyed_sha1_mature: unsupported algorithm.\n"));
352 return 1;
355 if (sav->key_auth->sadb_key_bits < algo->keymin
356 || algo->keymax < sav->key_auth->sadb_key_bits) {
357 ipseclog((LOG_ERR,
358 "ah_keyed_sha1_mature: invalid key length %d.\n",
359 sav->key_auth->sadb_key_bits));
360 return 1;
363 return 0;
366 static int
367 ah_keyed_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav)
369 SHA1_CTX *ctxt;
370 size_t padlen;
371 size_t keybitlen;
372 u_int8_t buf[32];
374 if (!state)
375 panic("ah_keyed_sha1_init: what?");
377 state->sav = sav;
378 state->foo = (void *)kmalloc(sizeof(SHA1_CTX), M_TEMP, M_NOWAIT);
379 if (!state->foo)
380 return ENOBUFS;
382 ctxt = (SHA1_CTX *)state->foo;
383 SHA1Init(ctxt);
385 if (state->sav) {
386 SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
387 (u_int)_KEYLEN(state->sav->key_auth));
390 * Pad after the key.
392 if (_KEYLEN(state->sav->key_auth) < 56)
393 padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
394 else
395 padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
396 keybitlen = _KEYLEN(state->sav->key_auth);
397 keybitlen *= 8;
399 buf[0] = 0x80;
400 SHA1Update(ctxt, &buf[0], 1);
401 padlen--;
403 bzero(buf, sizeof(buf));
404 while (sizeof(buf) < padlen) {
405 SHA1Update(ctxt, &buf[0], sizeof(buf));
406 padlen -= sizeof(buf);
408 if (padlen) {
409 SHA1Update(ctxt, &buf[0], padlen);
412 buf[0] = (keybitlen >> 0) & 0xff;
413 buf[1] = (keybitlen >> 8) & 0xff;
414 buf[2] = (keybitlen >> 16) & 0xff;
415 buf[3] = (keybitlen >> 24) & 0xff;
416 SHA1Update(ctxt, buf, 8);
419 return 0;
422 static void
423 ah_keyed_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
425 SHA1_CTX *ctxt;
427 if (!state || !state->foo)
428 panic("ah_keyed_sha1_loop: what?");
429 ctxt = (SHA1_CTX *)state->foo;
431 SHA1Update(ctxt, (caddr_t)addr, (size_t)len);
434 static void
435 ah_keyed_sha1_result(struct ah_algorithm_state *state, caddr_t addr)
437 u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
438 SHA1_CTX *ctxt;
440 if (!state || !state->foo)
441 panic("ah_keyed_sha1_result: what?");
442 ctxt = (SHA1_CTX *)state->foo;
444 if (state->sav) {
445 SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
446 (u_int)_KEYLEN(state->sav->key_auth));
448 SHA1Final((caddr_t)&digest[0], ctxt);
449 bcopy(&digest[0], (void *)addr, HMACSIZE);
451 kfree(state->foo, M_TEMP);
454 static int
455 ah_hmac_md5_mature(struct secasvar *sav)
457 const struct ah_algorithm *algo;
459 if (!sav->key_auth) {
460 ipseclog((LOG_ERR, "ah_hmac_md5_mature: no key is given.\n"));
461 return 1;
464 algo = ah_algorithm_lookup(sav->alg_auth);
465 if (!algo) {
466 ipseclog((LOG_ERR, "ah_hmac_md5_mature: unsupported algorithm.\n"));
467 return 1;
470 if (sav->key_auth->sadb_key_bits < algo->keymin
471 || algo->keymax < sav->key_auth->sadb_key_bits) {
472 ipseclog((LOG_ERR,
473 "ah_hmac_md5_mature: invalid key length %d.\n",
474 sav->key_auth->sadb_key_bits));
475 return 1;
478 return 0;
481 static int
482 ah_hmac_md5_init(struct ah_algorithm_state *state, struct secasvar *sav)
484 u_char *ipad;
485 u_char *opad;
486 u_char tk[16];
487 u_char *key;
488 size_t keylen;
489 size_t i;
490 MD5_CTX *ctxt;
492 if (!state)
493 panic("ah_hmac_md5_init: what?");
495 state->sav = sav;
496 state->foo = (void *)kmalloc(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_NOWAIT);
497 if (!state->foo)
498 return ENOBUFS;
500 ipad = (u_char *)state->foo;
501 opad = (u_char *)(ipad + 64);
502 ctxt = (MD5_CTX *)(opad + 64);
504 /* compress the key if necessery */
505 if (64 < _KEYLEN(state->sav->key_auth)) {
506 MD5Init(ctxt);
507 MD5Update(ctxt, _KEYBUF(state->sav->key_auth),
508 _KEYLEN(state->sav->key_auth));
509 MD5Final(&tk[0], ctxt);
510 key = &tk[0];
511 keylen = 16;
512 } else {
513 key = _KEYBUF(state->sav->key_auth);
514 keylen = _KEYLEN(state->sav->key_auth);
517 bzero(ipad, 64);
518 bzero(opad, 64);
519 bcopy(key, ipad, keylen);
520 bcopy(key, opad, keylen);
521 for (i = 0; i < 64; i++) {
522 ipad[i] ^= 0x36;
523 opad[i] ^= 0x5c;
526 MD5Init(ctxt);
527 MD5Update(ctxt, ipad, 64);
529 return 0;
532 static void
533 ah_hmac_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
535 MD5_CTX *ctxt;
537 if (!state || !state->foo)
538 panic("ah_hmac_md5_loop: what?");
539 ctxt = (MD5_CTX *)(((caddr_t)state->foo) + 128);
540 MD5Update(ctxt, addr, len);
543 static void
544 ah_hmac_md5_result(struct ah_algorithm_state *state, caddr_t addr)
546 u_char digest[16];
547 u_char *ipad;
548 u_char *opad;
549 MD5_CTX *ctxt;
551 if (!state || !state->foo)
552 panic("ah_hmac_md5_result: what?");
554 ipad = (u_char *)state->foo;
555 opad = (u_char *)(ipad + 64);
556 ctxt = (MD5_CTX *)(opad + 64);
558 MD5Final(&digest[0], ctxt);
560 MD5Init(ctxt);
561 MD5Update(ctxt, opad, 64);
562 MD5Update(ctxt, &digest[0], sizeof(digest));
563 MD5Final(&digest[0], ctxt);
565 bcopy(&digest[0], (void *)addr, HMACSIZE);
567 kfree(state->foo, M_TEMP);
570 static int
571 ah_hmac_sha1_mature(struct secasvar *sav)
573 const struct ah_algorithm *algo;
575 if (!sav->key_auth) {
576 ipseclog((LOG_ERR, "ah_hmac_sha1_mature: no key is given.\n"));
577 return 1;
580 algo = ah_algorithm_lookup(sav->alg_auth);
581 if (!algo) {
582 ipseclog((LOG_ERR, "ah_hmac_sha1_mature: unsupported algorithm.\n"));
583 return 1;
586 if (sav->key_auth->sadb_key_bits < algo->keymin
587 || algo->keymax < sav->key_auth->sadb_key_bits) {
588 ipseclog((LOG_ERR,
589 "ah_hmac_sha1_mature: invalid key length %d.\n",
590 sav->key_auth->sadb_key_bits));
591 return 1;
594 return 0;
597 static int
598 ah_hmac_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav)
600 u_char *ipad;
601 u_char *opad;
602 SHA1_CTX *ctxt;
603 u_char tk[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
604 u_char *key;
605 size_t keylen;
606 size_t i;
608 if (!state)
609 panic("ah_hmac_sha1_init: what?");
611 state->sav = sav;
612 state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA1_CTX),
613 M_TEMP, M_NOWAIT);
614 if (!state->foo)
615 return ENOBUFS;
617 ipad = (u_char *)state->foo;
618 opad = (u_char *)(ipad + 64);
619 ctxt = (SHA1_CTX *)(opad + 64);
621 /* compress the key if necessery */
622 if (64 < _KEYLEN(state->sav->key_auth)) {
623 SHA1Init(ctxt);
624 SHA1Update(ctxt, _KEYBUF(state->sav->key_auth),
625 _KEYLEN(state->sav->key_auth));
626 SHA1Final(&tk[0], ctxt);
627 key = &tk[0];
628 keylen = SHA1_RESULTLEN;
629 } else {
630 key = _KEYBUF(state->sav->key_auth);
631 keylen = _KEYLEN(state->sav->key_auth);
634 bzero(ipad, 64);
635 bzero(opad, 64);
636 bcopy(key, ipad, keylen);
637 bcopy(key, opad, keylen);
638 for (i = 0; i < 64; i++) {
639 ipad[i] ^= 0x36;
640 opad[i] ^= 0x5c;
643 SHA1Init(ctxt);
644 SHA1Update(ctxt, ipad, 64);
646 return 0;
649 static void
650 ah_hmac_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
652 SHA1_CTX *ctxt;
654 if (!state || !state->foo)
655 panic("ah_hmac_sha1_loop: what?");
657 ctxt = (SHA1_CTX *)(((u_char *)state->foo) + 128);
658 SHA1Update(ctxt, (caddr_t)addr, (size_t)len);
661 static void
662 ah_hmac_sha1_result(struct ah_algorithm_state *state, caddr_t addr)
664 u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
665 u_char *ipad;
666 u_char *opad;
667 SHA1_CTX *ctxt;
669 if (!state || !state->foo)
670 panic("ah_hmac_sha1_result: what?");
672 ipad = (u_char *)state->foo;
673 opad = (u_char *)(ipad + 64);
674 ctxt = (SHA1_CTX *)(opad + 64);
676 SHA1Final((caddr_t)&digest[0], ctxt);
678 SHA1Init(ctxt);
679 SHA1Update(ctxt, opad, 64);
680 SHA1Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
681 SHA1Final((caddr_t)&digest[0], ctxt);
683 bcopy(&digest[0], (void *)addr, HMACSIZE);
685 kfree(state->foo, M_TEMP);
688 static int
689 ah_hmac_sha2_256_mature(struct secasvar *sav)
691 const struct ah_algorithm *algo;
693 if (!sav->key_auth) {
694 ipseclog((LOG_ERR,
695 "ah_hmac_sha2_256_mature: no key is given.\n"));
696 return 1;
699 algo = ah_algorithm_lookup(sav->alg_auth);
700 if (!algo) {
701 ipseclog((LOG_ERR,
702 "ah_hmac_sha2_256_mature: unsupported algorithm.\n"));
703 return 1;
706 if (sav->key_auth->sadb_key_bits < algo->keymin ||
707 algo->keymax < sav->key_auth->sadb_key_bits) {
708 ipseclog((LOG_ERR,
709 "ah_hmac_sha2_256_mature: invalid key length %d.\n",
710 sav->key_auth->sadb_key_bits));
711 return 1;
714 return 0;
717 static int
718 ah_hmac_sha2_256_init(struct ah_algorithm_state *state, struct secasvar *sav)
720 u_char *ipad;
721 u_char *opad;
722 SHA256_CTX *ctxt;
723 u_char tk[SHA256_DIGEST_LENGTH];
724 u_char *key;
725 size_t keylen;
726 size_t i;
728 if (!state)
729 panic("ah_hmac_sha2_256_init: what?");
731 state->sav = sav;
732 state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA256_CTX),
733 M_TEMP, M_NOWAIT);
734 if (!state->foo)
735 return ENOBUFS;
737 ipad = (u_char *)state->foo;
738 opad = (u_char *)(ipad + 64);
739 ctxt = (SHA256_CTX *)(opad + 64);
741 /* compress the key if necessery */
742 if (64 < _KEYLEN(state->sav->key_auth)) {
743 bzero(tk, sizeof(tk));
744 bzero(ctxt, sizeof(*ctxt));
745 SHA256_Init(ctxt);
746 SHA256_Update(ctxt, _KEYBUF(state->sav->key_auth),
747 _KEYLEN(state->sav->key_auth));
748 SHA256_Final(&tk[0], ctxt);
749 key = &tk[0];
750 keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
751 } else {
752 key = _KEYBUF(state->sav->key_auth);
753 keylen = _KEYLEN(state->sav->key_auth);
756 bzero(ipad, 64);
757 bzero(opad, 64);
758 bcopy(key, ipad, keylen);
759 bcopy(key, opad, keylen);
760 for (i = 0; i < 64; i++) {
761 ipad[i] ^= 0x36;
762 opad[i] ^= 0x5c;
765 bzero(ctxt, sizeof(*ctxt));
766 SHA256_Init(ctxt);
767 SHA256_Update(ctxt, ipad, 64);
769 return 0;
772 static void
773 ah_hmac_sha2_256_loop(struct ah_algorithm_state *state, caddr_t addr, size_t
774 len)
776 SHA256_CTX *ctxt;
778 if (!state || !state->foo)
779 panic("ah_hmac_sha2_256_loop: what?");
781 ctxt = (SHA256_CTX *)(((u_char *)state->foo) + 128);
782 SHA256_Update(ctxt, (caddr_t)addr, (size_t)len);
785 static void
786 ah_hmac_sha2_256_result(struct ah_algorithm_state *state, caddr_t addr)
788 u_char digest[SHA256_DIGEST_LENGTH];
789 u_char *ipad;
790 u_char *opad;
791 SHA256_CTX *ctxt;
793 if (!state || !state->foo)
794 panic("ah_hmac_sha2_256_result: what?");
796 ipad = (u_char *)state->foo;
797 opad = (u_char *)(ipad + 64);
798 ctxt = (SHA256_CTX *)(opad + 64);
800 SHA256_Final((caddr_t)&digest[0], ctxt);
802 bzero(ctxt, sizeof(*ctxt));
803 SHA256_Init(ctxt);
804 SHA256_Update(ctxt, opad, 64);
805 SHA256_Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
806 SHA256_Final((caddr_t)&digest[0], ctxt);
808 bcopy(&digest[0], (void *)addr, HMACSIZE);
810 kfree(state->foo, M_TEMP);
813 static int
814 ah_hmac_sha2_384_mature(struct secasvar *sav)
816 const struct ah_algorithm *algo;
818 if (!sav->key_auth) {
819 ipseclog((LOG_ERR,
820 "ah_hmac_sha2_384_mature: no key is given.\n"));
821 return 1;
824 algo = ah_algorithm_lookup(sav->alg_auth);
825 if (!algo) {
826 ipseclog((LOG_ERR,
827 "ah_hmac_sha2_384_mature: unsupported algorithm.\n"));
828 return 1;
831 if (sav->key_auth->sadb_key_bits < algo->keymin ||
832 algo->keymax < sav->key_auth->sadb_key_bits) {
833 ipseclog((LOG_ERR,
834 "ah_hmac_sha2_384_mature: invalid key length %d.\n",
835 sav->key_auth->sadb_key_bits));
836 return 1;
839 return 0;
842 static int
843 ah_hmac_sha2_384_init(struct ah_algorithm_state *state, struct secasvar *sav)
845 u_char *ipad;
846 u_char *opad;
847 SHA384_CTX *ctxt;
848 u_char tk[SHA384_DIGEST_LENGTH];
849 u_char *key;
850 size_t keylen;
851 size_t i;
853 if (!state)
854 panic("ah_hmac_sha2_384_init: what?");
856 state->sav = sav;
857 state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA384_CTX),
858 M_TEMP, M_NOWAIT);
859 if (!state->foo)
860 return ENOBUFS;
861 bzero(state->foo, 64 + 64 + sizeof(SHA384_CTX));
863 ipad = (u_char *)state->foo;
864 opad = (u_char *)(ipad + 64);
865 ctxt = (SHA384_CTX *)(opad + 64);
867 /* compress the key if necessery */
868 if (64 < _KEYLEN(state->sav->key_auth)) {
869 bzero(tk, sizeof(tk));
870 bzero(ctxt, sizeof(*ctxt));
871 SHA384_Init(ctxt);
872 SHA384_Update(ctxt, _KEYBUF(state->sav->key_auth),
873 _KEYLEN(state->sav->key_auth));
874 SHA384_Final(&tk[0], ctxt);
875 key = &tk[0];
876 keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
877 } else {
878 key = _KEYBUF(state->sav->key_auth);
879 keylen = _KEYLEN(state->sav->key_auth);
882 bzero(ipad, 64);
883 bzero(opad, 64);
884 bcopy(key, ipad, keylen);
885 bcopy(key, opad, keylen);
886 for (i = 0; i < 64; i++) {
887 ipad[i] ^= 0x36;
888 opad[i] ^= 0x5c;
891 bzero(ctxt, sizeof(*ctxt));
892 SHA384_Init(ctxt);
893 SHA384_Update(ctxt, ipad, 64);
895 return 0;
898 static void
899 ah_hmac_sha2_384_loop(struct ah_algorithm_state *state, caddr_t addr,
900 size_t len)
902 SHA384_CTX *ctxt;
904 if (!state || !state->foo)
905 panic("ah_hmac_sha2_384_loop: what?");
907 ctxt = (SHA384_CTX *)(((u_char *)state->foo) + 128);
908 SHA384_Update(ctxt, (caddr_t)addr, (size_t)len);
911 static void
912 ah_hmac_sha2_384_result(struct ah_algorithm_state *state, caddr_t addr)
914 u_char digest[SHA384_DIGEST_LENGTH];
915 u_char *ipad;
916 u_char *opad;
917 SHA384_CTX *ctxt;
919 if (!state || !state->foo)
920 panic("ah_hmac_sha2_384_result: what?");
922 ipad = (u_char *)state->foo;
923 opad = (u_char *)(ipad + 64);
924 ctxt = (SHA384_CTX *)(opad + 64);
926 SHA384_Final((caddr_t)&digest[0], ctxt);
928 bzero(ctxt, sizeof(*ctxt));
929 SHA384_Init(ctxt);
930 SHA384_Update(ctxt, opad, 64);
931 SHA384_Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
932 SHA384_Final((caddr_t)&digest[0], ctxt);
934 bcopy(&digest[0], (void *)addr, HMACSIZE);
936 kfree(state->foo, M_TEMP);
939 static int
940 ah_hmac_sha2_512_mature(struct secasvar *sav)
942 const struct ah_algorithm *algo;
944 if (!sav->key_auth) {
945 ipseclog((LOG_ERR,
946 "ah_hmac_sha2_512_mature: no key is given.\n"));
947 return 1;
950 algo = ah_algorithm_lookup(sav->alg_auth);
951 if (!algo) {
952 ipseclog((LOG_ERR,
953 "ah_hmac_sha2_512_mature: unsupported algorithm.\n"));
954 return 1;
957 if (sav->key_auth->sadb_key_bits < algo->keymin ||
958 algo->keymax < sav->key_auth->sadb_key_bits) {
959 ipseclog((LOG_ERR,
960 "ah_hmac_sha2_512_mature: invalid key length %d.\n",
961 sav->key_auth->sadb_key_bits));
962 return 1;
965 return 0;
968 static int
969 ah_hmac_sha2_512_init(struct ah_algorithm_state *state, struct secasvar *sav)
971 u_char *ipad;
972 u_char *opad;
973 SHA512_CTX *ctxt;
974 u_char tk[SHA512_DIGEST_LENGTH];
975 u_char *key;
976 size_t keylen;
977 size_t i;
979 if (!state)
980 panic("ah_hmac_sha2_512_init: what?");
982 state->sav = sav;
983 state->foo = (void *)kmalloc(64 + 64 + sizeof(SHA512_CTX),
984 M_TEMP, M_NOWAIT);
985 if (!state->foo)
986 return ENOBUFS;
987 bzero(state->foo, 64 + 64 + sizeof(SHA512_CTX));
989 ipad = (u_char *)state->foo;
990 opad = (u_char *)(ipad + 64);
991 ctxt = (SHA512_CTX *)(opad + 64);
993 /* compress the key if necessery */
994 if (64 < _KEYLEN(state->sav->key_auth)) {
995 bzero(tk, sizeof(tk));
996 bzero(ctxt, sizeof(*ctxt));
997 SHA512_Init(ctxt);
998 SHA512_Update(ctxt, _KEYBUF(state->sav->key_auth),
999 _KEYLEN(state->sav->key_auth));
1000 SHA512_Final(&tk[0], ctxt);
1001 key = &tk[0];
1002 keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
1003 } else {
1004 key = _KEYBUF(state->sav->key_auth);
1005 keylen = _KEYLEN(state->sav->key_auth);
1008 bzero(ipad, 64);
1009 bzero(opad, 64);
1010 bcopy(key, ipad, keylen);
1011 bcopy(key, opad, keylen);
1012 for (i = 0; i < 64; i++) {
1013 ipad[i] ^= 0x36;
1014 opad[i] ^= 0x5c;
1017 bzero(ctxt, sizeof(*ctxt));
1018 SHA512_Init(ctxt);
1019 SHA512_Update(ctxt, ipad, 64);
1021 return 0;
1024 static void
1025 ah_hmac_sha2_512_loop(struct ah_algorithm_state *state, caddr_t addr,
1026 size_t len)
1028 SHA512_CTX *ctxt;
1030 if (!state || !state->foo)
1031 panic("ah_hmac_sha2_512_loop: what?");
1033 ctxt = (SHA512_CTX *)(((u_char *)state->foo) + 128);
1034 SHA512_Update(ctxt, (caddr_t)addr, (size_t)len);
1037 static void
1038 ah_hmac_sha2_512_result(struct ah_algorithm_state *state, caddr_t addr)
1040 u_char digest[SHA512_DIGEST_LENGTH];
1041 u_char *ipad;
1042 u_char *opad;
1043 SHA512_CTX *ctxt;
1045 if (!state || !state->foo)
1046 panic("ah_hmac_sha2_512_result: what?");
1048 ipad = (u_char *)state->foo;
1049 opad = (u_char *)(ipad + 64);
1050 ctxt = (SHA512_CTX *)(opad + 64);
1052 SHA512_Final((caddr_t)&digest[0], ctxt);
1054 bzero(ctxt, sizeof(*ctxt));
1055 SHA512_Init(ctxt);
1056 SHA512_Update(ctxt, opad, 64);
1057 SHA512_Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
1058 SHA512_Final((caddr_t)&digest[0], ctxt);
1060 bcopy(&digest[0], (void *)addr, HMACSIZE);
1062 kfree(state->foo, M_TEMP);
1065 /*------------------------------------------------------------*/
1068 * go generate the checksum.
1070 static void
1071 ah_update_mbuf(struct mbuf *m, int off, int len,
1072 const struct ah_algorithm *algo,
1073 struct ah_algorithm_state *algos)
1075 struct mbuf *n;
1076 int tlen;
1078 /* easy case first */
1079 if (off + len <= m->m_len) {
1080 (algo->update)(algos, mtod(m, caddr_t) + off, len);
1081 return;
1084 for (n = m; n; n = n->m_next) {
1085 if (off < n->m_len)
1086 break;
1088 off -= n->m_len;
1091 if (!n)
1092 panic("ah_update_mbuf: wrong offset specified");
1094 for (/* nothing */; n && len > 0; n = n->m_next) {
1095 if (n->m_len == 0)
1096 continue;
1097 if (n->m_len - off < len)
1098 tlen = n->m_len - off;
1099 else
1100 tlen = len;
1102 (algo->update)(algos, mtod(n, caddr_t) + off, tlen);
1104 len -= tlen;
1105 off = 0;
1109 #ifdef INET
1111 * Go generate the checksum. This function won't modify the mbuf chain
1112 * except AH itself.
1114 * NOTE: the function does not free mbuf on failure.
1115 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
1118 ah4_calccksum(struct mbuf *m, caddr_t ahdat, size_t len,
1119 const struct ah_algorithm *algo, struct secasvar *sav)
1121 int off;
1122 int hdrtype;
1123 size_t advancewidth;
1124 struct ah_algorithm_state algos;
1125 u_char sumbuf[AH_MAXSUMSIZE];
1126 int error = 0;
1127 int ahseen;
1128 struct mbuf *n = NULL;
1130 if ((m->m_flags & M_PKTHDR) == 0)
1131 return EINVAL;
1133 ahseen = 0;
1134 hdrtype = -1; /* dummy, it is called IPPROTO_IP */
1136 off = 0;
1138 error = (algo->init)(&algos, sav);
1139 if (error)
1140 return error;
1142 advancewidth = 0; /* safety */
1144 again:
1145 /* gory. */
1146 switch (hdrtype) {
1147 case -1: /* first one only */
1150 * copy ip hdr, modify to fit the AH checksum rule,
1151 * then take a checksum.
1153 struct ip iphdr;
1154 size_t hlen;
1156 m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr);
1157 #ifdef _IP_VHL
1158 hlen = IP_VHL_HL(iphdr.ip_vhl) << 2;
1159 #else
1160 hlen = iphdr.ip_hl << 2;
1161 #endif
1162 iphdr.ip_ttl = 0;
1163 iphdr.ip_sum = htons(0);
1164 if (ip4_ah_cleartos)
1165 iphdr.ip_tos = 0;
1166 iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
1167 (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip));
1169 if (hlen != sizeof(struct ip)) {
1170 u_char *p;
1171 int i, l, skip;
1173 if (hlen > MCLBYTES) {
1174 error = EMSGSIZE;
1175 goto fail;
1177 n = m_getb(hlen, MB_DONTWAIT, MT_DATA, 0);
1178 if (n == NULL) {
1179 error = ENOBUFS;
1180 goto fail;
1182 m_copydata(m, off, hlen, mtod(n, caddr_t));
1185 * IP options processing.
1186 * See RFC2402 appendix A.
1188 p = mtod(n, u_char *);
1189 i = sizeof(struct ip);
1190 while (i < hlen) {
1191 if (i + IPOPT_OPTVAL >= hlen) {
1192 ipseclog((LOG_ERR, "ah4_calccksum: "
1193 "invalid IP option\n"));
1194 error = EINVAL;
1195 goto fail;
1197 if (p[i + IPOPT_OPTVAL] == IPOPT_EOL ||
1198 p[i + IPOPT_OPTVAL] == IPOPT_NOP ||
1199 i + IPOPT_OLEN < hlen)
1201 else {
1202 ipseclog((LOG_ERR,
1203 "ah4_calccksum: invalid IP option "
1204 "(type=%02x)\n",
1205 p[i + IPOPT_OPTVAL]));
1206 error = EINVAL;
1207 goto fail;
1210 skip = 1;
1211 switch (p[i + IPOPT_OPTVAL]) {
1212 case IPOPT_EOL:
1213 case IPOPT_NOP:
1214 l = 1;
1215 skip = 0;
1216 break;
1217 case IPOPT_SECURITY: /* 0x82 */
1218 case 0x85: /* Extended security */
1219 case 0x86: /* Commercial security */
1220 case 0x94: /* Router alert */
1221 case 0x95: /* RFC1770 */
1222 l = p[i + IPOPT_OLEN];
1223 if (l < 2)
1224 goto invalopt;
1225 skip = 0;
1226 break;
1227 default:
1228 l = p[i + IPOPT_OLEN];
1229 if (l < 2)
1230 goto invalopt;
1231 skip = 1;
1232 break;
1234 if (l < 1 || hlen - i < l) {
1235 invalopt:
1236 ipseclog((LOG_ERR,
1237 "ah4_calccksum: invalid IP option "
1238 "(type=%02x len=%02x)\n",
1239 p[i + IPOPT_OPTVAL],
1240 p[i + IPOPT_OLEN]));
1241 error = EINVAL;
1242 goto fail;
1244 if (skip)
1245 bzero(p + i, l);
1246 if (p[i + IPOPT_OPTVAL] == IPOPT_EOL)
1247 break;
1248 i += l;
1250 p = mtod(n, u_char *) + sizeof(struct ip);
1251 (algo->update)(&algos, p, hlen - sizeof(struct ip));
1253 m_free(n);
1254 n = NULL;
1257 hdrtype = (iphdr.ip_p) & 0xff;
1258 advancewidth = hlen;
1259 break;
1262 case IPPROTO_AH:
1264 struct ah ah;
1265 int siz;
1266 int hdrsiz;
1267 int totlen;
1269 m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
1270 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
1271 ? sizeof(struct ah)
1272 : sizeof(struct newah);
1273 siz = (*algo->sumsiz)(sav);
1274 totlen = (ah.ah_len + 2) << 2;
1277 * special treatment is necessary for the first one, not others
1279 if (!ahseen) {
1280 if (totlen > m->m_pkthdr.len - off ||
1281 totlen > MCLBYTES) {
1282 error = EMSGSIZE;
1283 goto fail;
1285 n = m_getb(totlen, MB_DONTWAIT, MT_DATA, 0);
1286 if (n == NULL) {
1287 error = ENOBUFS;
1288 goto fail;
1290 m_copydata(m, off, totlen, mtod(n, caddr_t));
1291 n->m_len = totlen;
1292 bzero(mtod(n, caddr_t) + hdrsiz, siz);
1293 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
1294 m_free(n);
1295 n = NULL;
1296 } else
1297 ah_update_mbuf(m, off, totlen, algo, &algos);
1298 ahseen++;
1300 hdrtype = ah.ah_nxt;
1301 advancewidth = totlen;
1302 break;
1305 default:
1306 ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, &algos);
1307 advancewidth = m->m_pkthdr.len - off;
1308 break;
1311 off += advancewidth;
1312 if (off < m->m_pkthdr.len)
1313 goto again;
1315 if (len < (*algo->sumsiz)(sav)) {
1316 error = EINVAL;
1317 goto fail;
1320 (algo->result)(&algos, &sumbuf[0]);
1321 bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
1323 if (n)
1324 m_free(n);
1325 return error;
1327 fail:
1328 if (n)
1329 m_free(n);
1330 return error;
1332 #endif
1334 #ifdef INET6
1336 * Go generate the checksum. This function won't modify the mbuf chain
1337 * except AH itself.
1339 * NOTE: the function does not free mbuf on failure.
1340 * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
1343 ah6_calccksum(struct mbuf *m, caddr_t ahdat, size_t len,
1344 const struct ah_algorithm *algo, struct secasvar *sav)
1346 int newoff, off;
1347 int proto, nxt;
1348 struct mbuf *n = NULL;
1349 int error;
1350 int ahseen;
1351 struct ah_algorithm_state algos;
1352 u_char sumbuf[AH_MAXSUMSIZE];
1354 if ((m->m_flags & M_PKTHDR) == 0)
1355 return EINVAL;
1357 error = (algo->init)(&algos, sav);
1358 if (error)
1359 return error;
1361 off = 0;
1362 proto = IPPROTO_IPV6;
1363 nxt = -1;
1364 ahseen = 0;
1366 again:
1367 newoff = ip6_nexthdr(m, off, proto, &nxt);
1368 if (newoff < 0)
1369 newoff = m->m_pkthdr.len;
1370 else if (newoff <= off) {
1371 error = EINVAL;
1372 goto fail;
1375 switch (proto) {
1376 case IPPROTO_IPV6:
1378 * special treatment is necessary for the first one, not others
1380 if (off == 0) {
1381 struct ip6_hdr ip6copy;
1383 if (newoff - off != sizeof(struct ip6_hdr)) {
1384 error = EINVAL;
1385 goto fail;
1388 m_copydata(m, off, newoff - off, (caddr_t)&ip6copy);
1389 /* RFC2402 */
1390 ip6copy.ip6_flow = 0;
1391 ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
1392 ip6copy.ip6_vfc |= IPV6_VERSION;
1393 ip6copy.ip6_hlim = 0;
1394 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src))
1395 ip6copy.ip6_src.s6_addr16[1] = 0x0000;
1396 if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst))
1397 ip6copy.ip6_dst.s6_addr16[1] = 0x0000;
1398 (algo->update)(&algos, (caddr_t)&ip6copy,
1399 sizeof(struct ip6_hdr));
1400 } else {
1401 newoff = m->m_pkthdr.len;
1402 ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo,
1403 &algos);
1405 break;
1407 case IPPROTO_AH:
1409 int siz;
1410 int hdrsiz;
1412 hdrsiz = (sav->flags & SADB_X_EXT_OLD)
1413 ? sizeof(struct ah)
1414 : sizeof(struct newah);
1415 siz = (*algo->sumsiz)(sav);
1418 * special treatment is necessary for the first one, not others
1420 if (!ahseen) {
1421 if (newoff - off > MCLBYTES) {
1422 error = EMSGSIZE;
1423 goto fail;
1425 n = m_getb(newoff - off, MB_DONTWAIT, MT_DATA, 0);
1426 if (n == NULL) {
1427 error = ENOBUFS;
1428 goto fail;
1430 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
1431 n->m_len = newoff - off;
1432 bzero(mtod(n, caddr_t) + hdrsiz, siz);
1433 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
1434 m_free(n);
1435 n = NULL;
1436 } else
1437 ah_update_mbuf(m, off, newoff - off, algo, &algos);
1438 ahseen++;
1439 break;
1442 case IPPROTO_HOPOPTS:
1443 case IPPROTO_DSTOPTS:
1445 struct ip6_ext *ip6e;
1446 int hdrlen, optlen;
1447 u_int8_t *p, *optend, *optp;
1449 if (newoff - off > MCLBYTES) {
1450 error = EMSGSIZE;
1451 goto fail;
1453 n = m_getb(newoff - off, MB_DONTWAIT, MT_DATA, 0);
1454 if (n == NULL) {
1455 error = ENOBUFS;
1456 goto fail;
1458 m_copydata(m, off, newoff - off, mtod(n, caddr_t));
1459 n->m_len = newoff - off;
1461 ip6e = mtod(n, struct ip6_ext *);
1462 hdrlen = (ip6e->ip6e_len + 1) << 3;
1463 if (newoff - off < hdrlen) {
1464 error = EINVAL;
1465 m_free(n);
1466 n = NULL;
1467 goto fail;
1469 p = mtod(n, u_int8_t *);
1470 optend = p + hdrlen;
1473 * ICV calculation for the options header including all
1474 * options. This part is a little tricky since there are
1475 * two type of options; mutable and immutable. We try to
1476 * null-out mutable ones here.
1478 optp = p + 2;
1479 while (optp < optend) {
1480 if (optp[0] == IP6OPT_PAD1)
1481 optlen = 1;
1482 else {
1483 if (optp + 2 > optend) {
1484 error = EINVAL;
1485 m_free(n);
1486 n = NULL;
1487 goto fail;
1489 optlen = optp[1] + 2;
1491 if (optp[0] & IP6OPT_MUTABLE)
1492 bzero(optp + 2, optlen - 2);
1495 optp += optlen;
1498 (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
1499 m_free(n);
1500 n = NULL;
1501 break;
1504 case IPPROTO_ROUTING:
1506 * For an input packet, we can just calculate `as is'.
1507 * For an output packet, we assume ip6_output have already
1508 * made packet how it will be received at the final
1509 * destination.
1511 /* FALLTHROUGH */
1513 default:
1514 ah_update_mbuf(m, off, newoff - off, algo, &algos);
1515 break;
1518 if (newoff < m->m_pkthdr.len) {
1519 proto = nxt;
1520 off = newoff;
1521 goto again;
1524 if (len < (*algo->sumsiz)(sav)) {
1525 error = EINVAL;
1526 goto fail;
1529 (algo->result)(&algos, &sumbuf[0]);
1530 bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
1532 /* just in case */
1533 if (n)
1534 m_free(n);
1535 return 0;
1536 fail:
1537 /* just in case */
1538 if (n)
1539 m_free(n);
1540 return error;
1542 #endif