summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ah_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/ah_core.c')
-rw-r--r--sys/netinet6/ah_core.c1644
1 files changed, 0 insertions, 1644 deletions
diff --git a/sys/netinet6/ah_core.c b/sys/netinet6/ah_core.c
deleted file mode 100644
index c36a777..0000000
--- a/sys/netinet6/ah_core.c
+++ /dev/null
@@ -1,1644 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: ah_core.c,v 1.59 2003/07/25 10:17:14 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * RFC1826/2402 authentication header.
- */
-
-/* TODO: have shared routines for hmac-* algorithms */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-#include "opt_ipsec.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_var.h>
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/ip6_var.h>
-#include <netinet6/scope6_var.h>
-#include <netinet/icmp6.h>
-#endif
-
-#include <netinet6/ipsec.h>
-#ifdef INET6
-#include <netinet6/ipsec6.h>
-#endif
-#include <netinet6/ah.h>
-#ifdef INET6
-#include <netinet6/ah6.h>
-#endif
-#include <netinet6/ah_aesxcbcmac.h>
-#ifdef IPSEC_ESP
-#include <netinet6/esp.h>
-#ifdef INET6
-#include <netinet6/esp6.h>
-#endif
-#endif
-#include <net/pfkeyv2.h>
-#include <netkey/keydb.h>
-#include <sys/md5.h>
-#define MD5_RESULTLEN 16
-#include <crypto/sha1.h>
-#include <crypto/sha2/sha2.h>
-#include <opencrypto/rmd160.h>
-#define RIPEMD160_RESULTLEN 20
-
-static int ah_sumsiz_1216 __P((struct secasvar *));
-static int ah_sumsiz_zero __P((struct secasvar *));
-static int ah_common_mature __P((struct secasvar *));
-static int ah_none_mature __P((struct secasvar *));
-static int ah_none_init __P((struct ah_algorithm_state *, struct secasvar *));
-static void ah_none_loop __P((struct ah_algorithm_state *, u_int8_t *, size_t));
-static void ah_none_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_keyed_md5_mature __P((struct secasvar *));
-static int ah_keyed_md5_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_keyed_md5_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_keyed_md5_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_keyed_sha1_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_keyed_sha1_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_keyed_sha1_result __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static int ah_hmac_md5_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_md5_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_md5_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha1_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha1_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha1_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha2_256_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha2_256_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha2_256_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha2_384_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha2_384_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha2_384_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_sha2_512_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_sha2_512_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_sha2_512_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-static int ah_hmac_ripemd160_init __P((struct ah_algorithm_state *,
- struct secasvar *));
-static void ah_hmac_ripemd160_loop __P((struct ah_algorithm_state *, u_int8_t *,
- size_t));
-static void ah_hmac_ripemd160_result __P((struct ah_algorithm_state *,
- u_int8_t *, size_t));
-
-static void ah_update_mbuf __P((struct mbuf *, int, int,
- const struct ah_algorithm *, struct ah_algorithm_state *));
-
-/* checksum algorithms */
-static const struct ah_algorithm ah_algorithms[] = {
- { ah_sumsiz_1216, ah_common_mature, 128, 128, "hmac-md5",
- ah_hmac_md5_init, ah_hmac_md5_loop,
- ah_hmac_md5_result, },
- { ah_sumsiz_1216, ah_common_mature, 160, 160, "hmac-sha1",
- ah_hmac_sha1_init, ah_hmac_sha1_loop,
- ah_hmac_sha1_result, },
- { ah_sumsiz_1216, ah_keyed_md5_mature, 128, 128, "keyed-md5",
- ah_keyed_md5_init, ah_keyed_md5_loop,
- ah_keyed_md5_result, },
- { ah_sumsiz_1216, ah_common_mature, 160, 160, "keyed-sha1",
- ah_keyed_sha1_init, ah_keyed_sha1_loop,
- ah_keyed_sha1_result, },
- { ah_sumsiz_zero, ah_none_mature, 0, 2048, "none",
- ah_none_init, ah_none_loop, ah_none_result, },
- { ah_sumsiz_1216, ah_common_mature, 256, 256,
- "hmac-sha2-256",
- ah_hmac_sha2_256_init, ah_hmac_sha2_256_loop,
- ah_hmac_sha2_256_result, },
- { ah_sumsiz_1216, ah_common_mature, 384, 384,
- "hmac-sha2-384",
- ah_hmac_sha2_384_init, ah_hmac_sha2_384_loop,
- ah_hmac_sha2_384_result, },
- { ah_sumsiz_1216, ah_common_mature, 512, 512,
- "hmac-sha2-512",
- ah_hmac_sha2_512_init, ah_hmac_sha2_512_loop,
- ah_hmac_sha2_512_result, },
- { ah_sumsiz_1216, ah_common_mature, 160, 160,
- "hmac-ripemd160",
- ah_hmac_ripemd160_init, ah_hmac_ripemd160_loop,
- ah_hmac_ripemd160_result, },
- { ah_sumsiz_1216, ah_common_mature, 128, 128,
- "aes-xcbc-mac",
- ah_aes_xcbc_mac_init, ah_aes_xcbc_mac_loop,
- ah_aes_xcbc_mac_result, },
- { ah_sumsiz_1216, ah_none_mature, 8, 640, /* bits (RFC 2385) */
- "TCP-MD5",
- ah_none_init, ah_none_loop,
- ah_none_result, },
-};
-
-const struct ah_algorithm *
-ah_algorithm_lookup(idx)
- int idx;
-{
-
- switch (idx) {
- case SADB_AALG_MD5HMAC:
- return &ah_algorithms[0];
- case SADB_AALG_SHA1HMAC:
- return &ah_algorithms[1];
- case SADB_X_AALG_MD5:
- return &ah_algorithms[2];
- case SADB_X_AALG_SHA:
- return &ah_algorithms[3];
- case SADB_X_AALG_NULL:
- return &ah_algorithms[4];
- case SADB_X_AALG_SHA2_256:
- return &ah_algorithms[5];
- case SADB_X_AALG_SHA2_384:
- return &ah_algorithms[6];
- case SADB_X_AALG_SHA2_512:
- return &ah_algorithms[7];
- case SADB_X_AALG_RIPEMD160HMAC:
- return &ah_algorithms[8];
- case SADB_X_AALG_AES_XCBC_MAC:
- return &ah_algorithms[9];
- case SADB_X_AALG_TCP_MD5:
- return &ah_algorithms[10];
- default:
- return NULL;
- }
-}
-
-
-static int
-ah_sumsiz_1216(sav)
- struct secasvar *sav;
-{
- if (!sav)
- panic("ah_sumsiz_1216: null pointer is passed");
- if (sav->flags & SADB_X_EXT_OLD)
- return 16;
- else
- return 12;
-}
-
-static int
-ah_sumsiz_zero(sav)
- struct secasvar *sav;
-{
- if (!sav)
- panic("ah_sumsiz_zero: null pointer is passed");
- return 0;
-}
-
-static int
-ah_common_mature(sav)
- struct secasvar *sav;
-{
- const struct ah_algorithm *algo;
-
- if (!sav->key_auth) {
- ipseclog((LOG_ERR, "ah_common_mature: no key is given.\n"));
- return 1;
- }
-
- algo = ah_algorithm_lookup(sav->alg_auth);
- if (!algo) {
- ipseclog((LOG_ERR, "ah_common_mature: unsupported algorithm.\n"));
- return 1;
- }
-
- if (sav->key_auth->sadb_key_bits < algo->keymin ||
- algo->keymax < sav->key_auth->sadb_key_bits) {
- ipseclog((LOG_ERR,
- "ah_common_mature: invalid key length %d for %s.\n",
- sav->key_auth->sadb_key_bits, algo->name));
- return 1;
- }
-
- return 0;
-}
-
-static int
-ah_none_mature(sav)
- struct secasvar *sav;
-{
- if (sav->sah->saidx.proto == IPPROTO_AH) {
- ipseclog((LOG_ERR,
- "ah_none_mature: protocol and algorithm mismatch.\n"));
- return 1;
- }
- return 0;
-}
-
-static int
-ah_none_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- state->foo = NULL;
- return 0;
-}
-
-static void
-ah_none_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
-}
-
-static void
-ah_none_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
-}
-
-static int
-ah_keyed_md5_mature(sav)
- struct secasvar *sav;
-{
- /* anything is okay */
- return 0;
-}
-
-static int
-ah_keyed_md5_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- size_t padlen;
- size_t keybitlen;
- u_int8_t buf[32];
-
- if (!state)
- panic("ah_keyed_md5_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(sizeof(MD5_CTX), M_TEMP, M_NOWAIT);
- if (state->foo == NULL)
- return ENOBUFS;
-
- MD5Init((MD5_CTX *)state->foo);
- if (state->sav) {
- MD5Update((MD5_CTX *)state->foo,
- (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
-
- /*
- * Pad after the key.
- * We cannot simply use md5_pad() since the function
- * won't update the total length.
- */
- if (_KEYLEN(state->sav->key_auth) < 56)
- padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
- else
- padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
- keybitlen = _KEYLEN(state->sav->key_auth);
- keybitlen *= 8;
-
- buf[0] = 0x80;
- MD5Update((MD5_CTX *)state->foo, &buf[0], 1);
- padlen--;
-
- bzero(buf, sizeof(buf));
- while (sizeof(buf) < padlen) {
- MD5Update((MD5_CTX *)state->foo, &buf[0], sizeof(buf));
- padlen -= sizeof(buf);
- }
- if (padlen) {
- MD5Update((MD5_CTX *)state->foo, &buf[0], padlen);
- }
-
- buf[0] = (keybitlen >> 0) & 0xff;
- buf[1] = (keybitlen >> 8) & 0xff;
- buf[2] = (keybitlen >> 16) & 0xff;
- buf[3] = (keybitlen >> 24) & 0xff;
- MD5Update((MD5_CTX *)state->foo, buf, 8);
- }
-
- return 0;
-}
-
-static void
-ah_keyed_md5_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- if (!state)
- panic("ah_keyed_md5_loop: what?");
-
- MD5Update((MD5_CTX *)state->foo, addr, len);
-}
-
-static void
-ah_keyed_md5_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[MD5_RESULTLEN];
-
- if (!state)
- panic("ah_keyed_md5_result: what?");
-
- if (state->sav) {
- MD5Update((MD5_CTX *)state->foo,
- (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
- }
- MD5Final(digest, (MD5_CTX *)state->foo);
- free(state->foo, M_TEMP);
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-}
-
-static int
-ah_keyed_sha1_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- SHA1_CTX *ctxt;
- size_t padlen;
- size_t keybitlen;
- u_int8_t buf[32];
-
- if (!state)
- panic("ah_keyed_sha1_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(sizeof(SHA1_CTX), M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ctxt = (SHA1_CTX *)state->foo;
- SHA1Init(ctxt);
-
- if (state->sav) {
- SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
-
- /*
- * Pad after the key.
- */
- if (_KEYLEN(state->sav->key_auth) < 56)
- padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
- else
- padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
- keybitlen = _KEYLEN(state->sav->key_auth);
- keybitlen *= 8;
-
- buf[0] = 0x80;
- SHA1Update(ctxt, &buf[0], 1);
- padlen--;
-
- bzero(buf, sizeof(buf));
- while (sizeof(buf) < padlen) {
- SHA1Update(ctxt, &buf[0], sizeof(buf));
- padlen -= sizeof(buf);
- }
- if (padlen) {
- SHA1Update(ctxt, &buf[0], padlen);
- }
-
- buf[0] = (keybitlen >> 0) & 0xff;
- buf[1] = (keybitlen >> 8) & 0xff;
- buf[2] = (keybitlen >> 16) & 0xff;
- buf[3] = (keybitlen >> 24) & 0xff;
- SHA1Update(ctxt, buf, 8);
- }
-
- return 0;
-}
-
-static void
-ah_keyed_sha1_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_keyed_sha1_loop: what?");
- ctxt = (SHA1_CTX *)state->foo;
-
- SHA1Update(ctxt, (u_int8_t *)addr, (size_t)len);
-}
-
-static void
-ah_keyed_sha1_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_keyed_sha1_result: what?");
- ctxt = (SHA1_CTX *)state->foo;
-
- if (state->sav) {
- SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth),
- (u_int)_KEYLEN(state->sav->key_auth));
- }
- SHA1Final((u_int8_t *)digest, ctxt);
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_md5_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- u_char tk[MD5_RESULTLEN];
- u_char *key;
- size_t keylen;
- size_t i;
- MD5_CTX *ctxt;
-
- if (!state)
- panic("ah_hmac_md5_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (MD5_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- MD5Init(ctxt);
- MD5Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- MD5Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = 16;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- MD5Init(ctxt);
- MD5Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_md5_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- MD5_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_md5_loop: what?");
- ctxt = (MD5_CTX *)(((u_int8_t *)state->foo) + 128);
- MD5Update(ctxt, addr, len);
-}
-
-static void
-ah_hmac_md5_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[MD5_RESULTLEN];
- u_char *ipad;
- u_char *opad;
- MD5_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_md5_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (MD5_CTX *)(opad + 64);
-
- MD5Final(digest, ctxt);
-
- MD5Init(ctxt);
- MD5Update(ctxt, opad, 64);
- MD5Update(ctxt, digest, sizeof(digest));
- MD5Final(digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha1_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA1_CTX *ctxt;
- u_char tk[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha1_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA1_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA1_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- SHA1Init(ctxt);
- SHA1Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA1Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = SHA1_RESULTLEN;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- SHA1Init(ctxt);
- SHA1Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha1_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t * addr;
- size_t len;
-{
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha1_loop: what?");
-
- ctxt = (SHA1_CTX *)(((u_char *)state->foo) + 128);
- SHA1Update(ctxt, (u_int8_t *)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha1_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA1_RESULTLEN]; /* SHA-1 generates 160 bits */
- u_char *ipad;
- u_char *opad;
- SHA1_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha1_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA1_CTX *)(opad + 64);
-
- SHA1Final((u_int8_t *)digest, ctxt);
-
- SHA1Init(ctxt);
- SHA1Update(ctxt, opad, 64);
- SHA1Update(ctxt, (u_int8_t *)digest, sizeof(digest));
- SHA1Final((u_int8_t *)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha2_256_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA256_CTX *ctxt;
- u_char tk[SHA256_DIGEST_LENGTH];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha2_256_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA256_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA256_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- SHA256_Init(ctxt);
- SHA256_Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA256_Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- SHA256_Init(ctxt);
- SHA256_Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha2_256_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- SHA256_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_256_loop: what?");
-
- ctxt = (SHA256_CTX *)(((u_char *)state->foo) + 128);
- SHA256_Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha2_256_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA256_DIGEST_LENGTH];
- u_char *ipad;
- u_char *opad;
- SHA256_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_256_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA256_CTX *)(opad + 64);
-
- SHA256_Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- SHA256_Init(ctxt);
- SHA256_Update(ctxt, opad, 64);
- SHA256_Update(ctxt, (caddr_t)digest, sizeof(digest));
- SHA256_Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha2_384_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA384_CTX *ctxt;
- u_char tk[SHA384_DIGEST_LENGTH];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha2_384_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA384_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
- bzero(state->foo, 64 + 64 + sizeof(SHA384_CTX));
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA384_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- SHA384_Init(ctxt);
- SHA384_Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA384_Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- SHA384_Init(ctxt);
- SHA384_Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha2_384_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- SHA384_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_384_loop: what?");
-
- ctxt = (SHA384_CTX *)(((u_char *)state->foo) + 128);
- SHA384_Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha2_384_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA384_DIGEST_LENGTH];
- u_char *ipad;
- u_char *opad;
- SHA384_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_384_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA384_CTX *)(opad + 64);
-
- SHA384_Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- SHA384_Init(ctxt);
- SHA384_Update(ctxt, opad, 64);
- SHA384_Update(ctxt, (caddr_t)digest, sizeof(digest));
- SHA384_Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_sha2_512_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- SHA512_CTX *ctxt;
- u_char tk[SHA512_DIGEST_LENGTH];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_sha2_512_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(SHA512_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
- bzero(state->foo, 64 + 64 + sizeof(SHA512_CTX));
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA512_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- SHA512_Init(ctxt);
- SHA512_Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- SHA512_Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- SHA512_Init(ctxt);
- SHA512_Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_sha2_512_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- SHA512_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_512_loop: what?");
-
- ctxt = (SHA512_CTX *)(((u_char *)state->foo) + 128);
- SHA512_Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_sha2_512_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[SHA512_DIGEST_LENGTH];
- u_char *ipad;
- u_char *opad;
- SHA512_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_sha2_512_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (SHA512_CTX *)(opad + 64);
-
- SHA512_Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- SHA512_Init(ctxt);
- SHA512_Update(ctxt, opad, 64);
- SHA512_Update(ctxt, (caddr_t)digest, sizeof(digest));
- SHA512_Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-static int
-ah_hmac_ripemd160_init(state, sav)
- struct ah_algorithm_state *state;
- struct secasvar *sav;
-{
- u_char *ipad;
- u_char *opad;
- RMD160_CTX *ctxt;
- u_char tk[RIPEMD160_RESULTLEN];
- u_char *key;
- size_t keylen;
- size_t i;
-
- if (!state)
- panic("ah_hmac_ripemd160_init: what?");
-
- state->sav = sav;
- state->foo = (void *)malloc(64 + 64 + sizeof(RMD160_CTX),
- M_TEMP, M_NOWAIT);
- if (!state->foo)
- return ENOBUFS;
- bzero(state->foo, 64 + 64 + sizeof(RMD160_CTX));
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (RMD160_CTX *)(opad + 64);
-
- /* compress the key if necessery */
- if (64 < _KEYLEN(state->sav->key_auth)) {
- bzero(tk, sizeof(tk));
- bzero(ctxt, sizeof(*ctxt));
- RMD160Init(ctxt);
- RMD160Update(ctxt, _KEYBUF(state->sav->key_auth),
- _KEYLEN(state->sav->key_auth));
- RMD160Final(&tk[0], ctxt);
- key = &tk[0];
- keylen = sizeof(tk) < 64 ? sizeof(tk) : 64;
- } else {
- key = _KEYBUF(state->sav->key_auth);
- keylen = _KEYLEN(state->sav->key_auth);
- }
-
- bzero(ipad, 64);
- bzero(opad, 64);
- bcopy(key, ipad, keylen);
- bcopy(key, opad, keylen);
- for (i = 0; i < 64; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- bzero(ctxt, sizeof(*ctxt));
- RMD160Init(ctxt);
- RMD160Update(ctxt, ipad, 64);
-
- return 0;
-}
-
-static void
-ah_hmac_ripemd160_loop(state, addr, len)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t len;
-{
- RMD160_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_ripemd160_loop: what?");
-
- ctxt = (RMD160_CTX *)(((u_char *)state->foo) + 128);
- RMD160Update(ctxt, (caddr_t)addr, (size_t)len);
-}
-
-static void
-ah_hmac_ripemd160_result(state, addr, l)
- struct ah_algorithm_state *state;
- u_int8_t *addr;
- size_t l;
-{
- u_char digest[RIPEMD160_RESULTLEN];
- u_char *ipad;
- u_char *opad;
- RMD160_CTX *ctxt;
-
- if (!state || !state->foo)
- panic("ah_hmac_ripemd160_result: what?");
-
- ipad = (u_char *)state->foo;
- opad = (u_char *)(ipad + 64);
- ctxt = (RMD160_CTX *)(opad + 64);
-
- RMD160Final((caddr_t)digest, ctxt);
-
- bzero(ctxt, sizeof(*ctxt));
- RMD160Init(ctxt);
- RMD160Update(ctxt, opad, 64);
- RMD160Update(ctxt, (caddr_t)digest, sizeof(digest));
- RMD160Final((caddr_t)digest, ctxt);
-
- bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
-
- free(state->foo, M_TEMP);
-}
-
-/*------------------------------------------------------------*/
-
-/*
- * go generate the checksum.
- */
-static void
-ah_update_mbuf(m, off, len, algo, algos)
- struct mbuf *m;
- int off;
- int len;
- const struct ah_algorithm *algo;
- struct ah_algorithm_state *algos;
-{
- struct mbuf *n;
- int tlen;
-
- /* easy case first */
- if (off + len <= m->m_len) {
- (algo->update)(algos, mtod(m, u_int8_t *) + off, len);
- return;
- }
-
- for (n = m; n; n = n->m_next) {
- if (off < n->m_len)
- break;
-
- off -= n->m_len;
- }
-
- if (!n)
- panic("ah_update_mbuf: wrong offset specified");
-
- for (/* nothing */; n && len > 0; n = n->m_next) {
- if (n->m_len == 0)
- continue;
- if (n->m_len - off < len)
- tlen = n->m_len - off;
- else
- tlen = len;
-
- (algo->update)(algos, mtod(n, u_int8_t *) + off, tlen);
-
- len -= tlen;
- off = 0;
- }
-}
-
-#ifdef INET
-/*
- * Go generate the checksum. This function won't modify the mbuf chain
- * except AH itself.
- *
- * NOTE: the function does not free mbuf on failure.
- * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
- */
-int
-ah4_calccksum(m, ahdat, len, algo, sav)
- struct mbuf *m;
- u_int8_t * ahdat;
- size_t len;
- const struct ah_algorithm *algo;
- struct secasvar *sav;
-{
- int off;
- int hdrtype;
- size_t advancewidth;
- struct ah_algorithm_state algos;
- u_char sumbuf[AH_MAXSUMSIZE];
- int error = 0;
- int ahseen;
- struct mbuf *n = NULL;
-
- if ((m->m_flags & M_PKTHDR) == 0)
- return EINVAL;
-
- ahseen = 0;
- hdrtype = -1; /* dummy, it is called IPPROTO_IP */
-
- off = 0;
-
- error = (algo->init)(&algos, sav);
- if (error)
- return error;
-
- advancewidth = 0; /* safety */
-
-again:
- /* gory. */
- switch (hdrtype) {
- case -1: /* first one only */
- {
- /*
- * copy ip hdr, modify to fit the AH checksum rule,
- * then take a checksum.
- */
- struct ip iphdr;
- size_t hlen;
-
- m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr);
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(iphdr.ip_vhl) << 2;
-#else
- hlen = iphdr.ip_hl << 2;
-#endif
- iphdr.ip_ttl = 0;
- iphdr.ip_sum = htons(0);
- if (ip4_ah_cleartos)
- iphdr.ip_tos = 0;
- iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
- (algo->update)(&algos, (u_int8_t *)&iphdr, sizeof(struct ip));
-
- if (hlen != sizeof(struct ip)) {
- u_char *p;
- int i, l, skip;
-
- if (hlen > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && hlen > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, hlen, mtod(n, caddr_t));
-
- /*
- * IP options processing.
- * See RFC2402 appendix A.
- */
- p = mtod(n, u_char *);
- i = sizeof(struct ip);
- while (i < hlen) {
- if (i + IPOPT_OPTVAL >= hlen) {
- ipseclog((LOG_ERR, "ah4_calccksum: "
- "invalid IP option\n"));
- error = EINVAL;
- goto fail;
- }
- if (p[i + IPOPT_OPTVAL] == IPOPT_EOL ||
- p[i + IPOPT_OPTVAL] == IPOPT_NOP ||
- i + IPOPT_OLEN < hlen)
- ;
- else {
- ipseclog((LOG_ERR,
- "ah4_calccksum: invalid IP option "
- "(type=%02x)\n",
- p[i + IPOPT_OPTVAL]));
- error = EINVAL;
- goto fail;
- }
-
- skip = 1;
- switch (p[i + IPOPT_OPTVAL]) {
- case IPOPT_EOL:
- case IPOPT_NOP:
- l = 1;
- skip = 0;
- break;
- case IPOPT_SECURITY: /* 0x82 */
- case 0x85: /* Extended security */
- case 0x86: /* Commercial security */
- case 0x94: /* Router alert */
- case 0x95: /* RFC1770 */
- l = p[i + IPOPT_OLEN];
- if (l < 2)
- goto invalopt;
- skip = 0;
- break;
- default:
- l = p[i + IPOPT_OLEN];
- if (l < 2)
- goto invalopt;
- skip = 1;
- break;
- }
- if (l < 1 || hlen - i < l) {
- invalopt:
- ipseclog((LOG_ERR,
- "ah4_calccksum: invalid IP option "
- "(type=%02x len=%02x)\n",
- p[i + IPOPT_OPTVAL],
- p[i + IPOPT_OLEN]));
- error = EINVAL;
- goto fail;
- }
- if (skip)
- bzero(p + i, l);
- if (p[i + IPOPT_OPTVAL] == IPOPT_EOL)
- break;
- i += l;
- }
- p = mtod(n, u_char *) + sizeof(struct ip);
- (algo->update)(&algos, p, hlen - sizeof(struct ip));
-
- m_free(n);
- n = NULL;
- }
-
- hdrtype = (iphdr.ip_p) & 0xff;
- advancewidth = hlen;
- break;
- }
-
- case IPPROTO_AH:
- {
- struct ah ah;
- int siz;
- int hdrsiz;
- int totlen;
-
- m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
- hdrsiz = (sav->flags & SADB_X_EXT_OLD)
- ? sizeof(struct ah)
- : sizeof(struct newah);
- siz = (*algo->sumsiz)(sav);
- totlen = (ah.ah_len + 2) << 2;
-
- /*
- * special treatment is necessary for the first one, not others
- */
- if (!ahseen) {
- if (totlen > m->m_pkthdr.len - off ||
- totlen > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && totlen > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, totlen, mtod(n, caddr_t));
- n->m_len = totlen;
- bzero(mtod(n, u_int8_t *) + hdrsiz, siz);
- (algo->update)(&algos, mtod(n, u_int8_t *), n->m_len);
- m_free(n);
- n = NULL;
- } else
- ah_update_mbuf(m, off, totlen, algo, &algos);
- ahseen++;
-
- hdrtype = ah.ah_nxt;
- advancewidth = totlen;
- break;
- }
-
- default:
- ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, &algos);
- advancewidth = m->m_pkthdr.len - off;
- break;
- }
-
- off += advancewidth;
- if (off < m->m_pkthdr.len)
- goto again;
-
- if (len < (*algo->sumsiz)(sav)) {
- error = EINVAL;
- goto fail;
- }
-
- (algo->result)(&algos, sumbuf, sizeof(sumbuf));
- bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
-
- if (n)
- m_free(n);
- return error;
-
-fail:
- if (n)
- m_free(n);
- return error;
-}
-#endif
-
-#ifdef INET6
-/*
- * Go generate the checksum. This function won't modify the mbuf chain
- * except AH itself.
- *
- * NOTE: the function does not free mbuf on failure.
- * Don't use m_copy(), it will try to share cluster mbuf by using refcnt.
- */
-int
-ah6_calccksum(m, ahdat, len, algo, sav)
- struct mbuf *m;
- u_int8_t * ahdat;
- size_t len;
- const struct ah_algorithm *algo;
- struct secasvar *sav;
-{
- int newoff, off;
- int proto, nxt;
- struct mbuf *n = NULL;
- int error;
- int ahseen;
- struct ah_algorithm_state algos;
- u_char sumbuf[AH_MAXSUMSIZE];
-
- if ((m->m_flags & M_PKTHDR) == 0)
- return EINVAL;
-
- error = (algo->init)(&algos, sav);
- if (error)
- return error;
-
- off = 0;
- proto = IPPROTO_IPV6;
- nxt = -1;
- ahseen = 0;
-
- again:
- newoff = ip6_nexthdr(m, off, proto, &nxt);
- if (newoff < 0)
- newoff = m->m_pkthdr.len;
- else if (newoff <= off) {
- error = EINVAL;
- goto fail;
- }
-
- switch (proto) {
- case IPPROTO_IPV6:
- /*
- * special treatment is necessary for the first one, not others
- */
- if (off == 0) {
- struct ip6_hdr ip6copy;
-
- if (newoff - off != sizeof(struct ip6_hdr)) {
- error = EINVAL;
- goto fail;
- }
-
- m_copydata(m, off, newoff - off, (caddr_t)&ip6copy);
- /* RFC2402 */
- ip6copy.ip6_flow = 0;
- ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
- ip6copy.ip6_vfc |= IPV6_VERSION;
- ip6copy.ip6_hlim = 0;
- in6_clearscope(&ip6copy.ip6_src); /* XXX */
- in6_clearscope(&ip6copy.ip6_dst); /* XXX */
- (algo->update)(&algos, (u_int8_t *)&ip6copy,
- sizeof(struct ip6_hdr));
- } else {
- newoff = m->m_pkthdr.len;
- ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo,
- &algos);
- }
- break;
-
- case IPPROTO_AH:
- {
- int siz;
- int hdrsiz;
-
- hdrsiz = (sav->flags & SADB_X_EXT_OLD)
- ? sizeof(struct ah)
- : sizeof(struct newah);
- siz = (*algo->sumsiz)(sav);
-
- /*
- * special treatment is necessary for the first one, not others
- */
- if (!ahseen) {
- if (newoff - off > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && newoff - off > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, newoff - off, mtod(n, caddr_t));
- n->m_len = newoff - off;
- bzero(mtod(n, u_int8_t *) + hdrsiz, siz);
- (algo->update)(&algos, mtod(n, u_int8_t *), n->m_len);
- m_free(n);
- n = NULL;
- } else
- ah_update_mbuf(m, off, newoff - off, algo, &algos);
- ahseen++;
- break;
- }
-
- case IPPROTO_HOPOPTS:
- case IPPROTO_DSTOPTS:
- {
- struct ip6_ext *ip6e;
- int hdrlen, optlen;
- u_int8_t *p, *optend, *optp;
-
- if (newoff - off > MCLBYTES) {
- error = EMSGSIZE;
- goto fail;
- }
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n && newoff - off > MLEN) {
- MCLGET(n, M_DONTWAIT);
- if ((n->m_flags & M_EXT) == 0) {
- m_free(n);
- n = NULL;
- }
- }
- if (n == NULL) {
- error = ENOBUFS;
- goto fail;
- }
- m_copydata(m, off, newoff - off, mtod(n, caddr_t));
- n->m_len = newoff - off;
-
- ip6e = mtod(n, struct ip6_ext *);
- hdrlen = (ip6e->ip6e_len + 1) << 3;
- if (newoff - off < hdrlen) {
- error = EINVAL;
- m_free(n);
- n = NULL;
- goto fail;
- }
- p = mtod(n, u_int8_t *);
- optend = p + hdrlen;
-
- /*
- * ICV calculation for the options header including all
- * options. This part is a little tricky since there are
- * two type of options; mutable and immutable. We try to
- * null-out mutable ones here.
- */
- optp = p + 2;
- while (optp < optend) {
- if (optp[0] == IP6OPT_PAD1)
- optlen = 1;
- else {
- if (optp + 2 > optend) {
- error = EINVAL;
- m_free(n);
- n = NULL;
- goto fail;
- }
- optlen = optp[1] + 2;
- }
-
- if (optp + optlen > optend) {
- error = EINVAL;
- m_free(n);
- n = NULL;
- goto fail;
- }
-
- if (optp[0] & IP6OPT_MUTABLE)
- bzero(optp + 2, optlen - 2);
-
- optp += optlen;
- }
-
- (algo->update)(&algos, mtod(n, u_int8_t *), n->m_len);
- m_free(n);
- n = NULL;
- break;
- }
-
- case IPPROTO_ROUTING:
- /*
- * For an input packet, we can just calculate `as is'.
- * For an output packet, we assume ip6_output have already
- * made packet how it will be received at the final
- * destination.
- */
- /* FALLTHROUGH */
-
- default:
- ah_update_mbuf(m, off, newoff - off, algo, &algos);
- break;
- }
-
- if (newoff < m->m_pkthdr.len) {
- proto = nxt;
- off = newoff;
- goto again;
- }
-
- if (len < (*algo->sumsiz)(sav)) {
- error = EINVAL;
- goto fail;
- }
-
- (algo->result)(&algos, sumbuf, sizeof(sumbuf));
- bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
-
- /* just in case */
- if (n)
- m_free(n);
- return 0;
-fail:
- /* just in case */
- if (n)
- m_free(n);
- return error;
-}
-#endif
OpenPOWER on IntegriCloud