]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet6/ah_core.c
xnu-4903.270.47.tar.gz
[apple/xnu.git] / bsd / netinet6 / ah_core.c
index 97527725cdf97eecb246f5cc7ccb579ea0480fd6..cd503bea625c646a26a6a55be98cab8790643cab 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
 /*     $FreeBSD: src/sys/netinet6/ah_core.c,v 1.2.2.4 2001/07/03 11:01:49 ume Exp $    */
 /*     $KAME: ah_core.c,v 1.44 2001/03/12 11:24:39 itojun Exp $        */
 
 #include <netkey/keydb.h>
 #include <libkern/crypto/md5.h>
 #include <libkern/crypto/sha1.h>
-#include <crypto/sha2/sha2.h>
+#include <libkern/crypto/sha2.h>
 
 #include <net/net_osdep.h>
 
-#define        HMACSIZE        16
+#define HMACSIZE        16
 
 static int ah_sumsiz_1216(struct secasvar *);
 static int ah_sumsiz_zero(struct secasvar *);
 static int ah_none_mature(struct secasvar *);
 static int ah_none_init(struct ah_algorithm_state *, struct secasvar *);
 static void ah_none_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_none_result(struct ah_algorithm_state *, caddr_t);
+static void ah_none_result(struct ah_algorithm_state *, caddr_t, size_t);
 static int ah_keyed_md5_mature(struct secasvar *);
 static int ah_keyed_md5_init(struct ah_algorithm_state *, struct secasvar *);
 static void ah_keyed_md5_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_keyed_md5_result(struct ah_algorithm_state *, caddr_t);
+static void ah_keyed_md5_result(struct ah_algorithm_state *, caddr_t, size_t);
 static int ah_keyed_sha1_mature(struct secasvar *);
 static int ah_keyed_sha1_init(struct ah_algorithm_state *, struct secasvar *);
 static void ah_keyed_sha1_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_keyed_sha1_result(struct ah_algorithm_state *, caddr_t);
+static void ah_keyed_sha1_result(struct ah_algorithm_state *, caddr_t, size_t);
 static int ah_hmac_md5_mature(struct secasvar *);
 static int ah_hmac_md5_init(struct ah_algorithm_state *, struct secasvar *);
 static void ah_hmac_md5_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_hmac_md5_result(struct ah_algorithm_state *, caddr_t);
+static void ah_hmac_md5_result(struct ah_algorithm_state *, caddr_t, size_t);
 static int ah_hmac_sha1_mature(struct secasvar *);
 static int ah_hmac_sha1_init(struct ah_algorithm_state *, struct secasvar *);
 static void ah_hmac_sha1_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_hmac_sha1_result(struct ah_algorithm_state *, caddr_t);
-#if ALLCRYPTO
+static void ah_hmac_sha1_result(struct ah_algorithm_state *, caddr_t, size_t);
+#if AH_ALL_CRYPTO
+static int ah_sumsiz_sha2_256(struct secasvar *);
 static int ah_hmac_sha2_256_mature(struct secasvar *);
 static int ah_hmac_sha2_256_init(struct ah_algorithm_state *,
-       struct secasvar *);
+    struct secasvar *);
 static void ah_hmac_sha2_256_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_hmac_sha2_256_result(struct ah_algorithm_state *, caddr_t);
+static void ah_hmac_sha2_256_result(struct ah_algorithm_state *, caddr_t, size_t);
+static int ah_sumsiz_sha2_384(struct secasvar *);
 static int ah_hmac_sha2_384_mature(struct secasvar *);
 static int ah_hmac_sha2_384_init(struct ah_algorithm_state *,
-       struct secasvar *);
+    struct secasvar *);
 static void ah_hmac_sha2_384_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_hmac_sha2_384_result(struct ah_algorithm_state *, caddr_t);
+static void ah_hmac_sha2_384_result(struct ah_algorithm_state *, caddr_t, size_t);
+static int ah_sumsiz_sha2_512(struct secasvar *);
 static int ah_hmac_sha2_512_mature(struct secasvar *);
 static int ah_hmac_sha2_512_init(struct ah_algorithm_state *,
-       struct secasvar *);
+    struct secasvar *);
 static void ah_hmac_sha2_512_loop(struct ah_algorithm_state *, caddr_t, size_t);
-static void ah_hmac_sha2_512_result(struct ah_algorithm_state *, caddr_t);
-#endif /* ALLCRYPTO */
+static void ah_hmac_sha2_512_result(struct ah_algorithm_state *, caddr_t, size_t);
+#endif /* AH_ALL_CRYPTO */
 
 static void ah_update_mbuf(struct mbuf *, int, int,
-       const struct ah_algorithm *, struct ah_algorithm_state *);
+    const struct ah_algorithm *, struct ah_algorithm_state *);
 
 const struct ah_algorithm *
-ah_algorithm_lookup(idx)
-       int idx;
+ah_algorithm_lookup(int idx)
 {
        /* checksum algorithms */
        static struct ah_algorithm hmac_md5 =
-               { ah_sumsiz_1216, ah_hmac_md5_mature, 128, 128, "hmac-md5",
-                       ah_hmac_md5_init, ah_hmac_md5_loop,
-                       ah_hmac_md5_result, };
+       { ah_sumsiz_1216, ah_hmac_md5_mature, 128, 128, "hmac-md5",
+         ah_hmac_md5_init, ah_hmac_md5_loop,
+         ah_hmac_md5_result, };
        static struct ah_algorithm keyed_md5 =
-               { 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_keyed_md5_mature, 128, 128, "keyed-md5",
+         ah_keyed_md5_init, ah_keyed_md5_loop,
+         ah_keyed_md5_result, };
        static struct ah_algorithm hmac_sha1 =
-               { ah_sumsiz_1216, ah_hmac_sha1_mature, 160, 160, "hmac-sha1",
-                       ah_hmac_sha1_init, ah_hmac_sha1_loop,
-                       ah_hmac_sha1_result, };
+       { ah_sumsiz_1216, ah_hmac_sha1_mature, 160, 160, "hmac-sha1",
+         ah_hmac_sha1_init, ah_hmac_sha1_loop,
+         ah_hmac_sha1_result, };
        static struct ah_algorithm keyed_sha1 =
-               { ah_sumsiz_1216, ah_keyed_sha1_mature, 160, 160, "keyed-sha1",
-                       ah_keyed_sha1_init, ah_keyed_sha1_loop,
-                       ah_keyed_sha1_result, };
+       { ah_sumsiz_1216, ah_keyed_sha1_mature, 160, 160, "keyed-sha1",
+         ah_keyed_sha1_init, ah_keyed_sha1_loop,
+         ah_keyed_sha1_result, };
        static struct ah_algorithm ah_none =
-               { ah_sumsiz_zero, ah_none_mature, 0, 2048, "none",
-                       ah_none_init, ah_none_loop, ah_none_result, };
-#if ALLCRYPTO
+       { ah_sumsiz_zero, ah_none_mature, 0, 2048, "none",
+         ah_none_init, ah_none_loop, ah_none_result, };
+#if AH_ALL_CRYPTO
        static struct ah_algorithm hmac_sha2_256 =
-               { ah_sumsiz_1216, ah_hmac_sha2_256_mature, 256, 256,
-                       "hmac-sha2-256",
-                       ah_hmac_sha2_256_init, ah_hmac_sha2_256_loop,
-                       ah_hmac_sha2_256_result, };
+       { ah_sumsiz_sha2_256, ah_hmac_sha2_256_mature, 256, 256,
+         "hmac-sha2-256",
+         ah_hmac_sha2_256_init, ah_hmac_sha2_256_loop,
+         ah_hmac_sha2_256_result, };
        static struct ah_algorithm hmac_sha2_384 =
-               { ah_sumsiz_1216, ah_hmac_sha2_384_mature, 384, 384,
-                       "hmac-sha2-384",
-                       ah_hmac_sha2_384_init, ah_hmac_sha2_384_loop,
-                       ah_hmac_sha2_384_result, };
+       { ah_sumsiz_sha2_384, ah_hmac_sha2_384_mature, 384, 384,
+         "hmac-sha2-384",
+         ah_hmac_sha2_384_init, ah_hmac_sha2_384_loop,
+         ah_hmac_sha2_384_result, };
        static struct ah_algorithm hmac_sha2_512 =
-               { ah_sumsiz_1216, ah_hmac_sha2_512_mature, 512, 512,
-                       "hmac-sha2-512",
-                       ah_hmac_sha2_512_init, ah_hmac_sha2_512_loop,
-                       ah_hmac_sha2_512_result, };
-#endif /* ALLCRYPTO */
+       { ah_sumsiz_sha2_512, ah_hmac_sha2_512_mature, 512, 512,
+         "hmac-sha2-512",
+         ah_hmac_sha2_512_init, ah_hmac_sha2_512_loop,
+         ah_hmac_sha2_512_result, };
+#endif /* AH_ALL_CRYPTO */
 
        switch (idx) {
        case SADB_AALG_MD5HMAC:
@@ -182,14 +212,14 @@ ah_algorithm_lookup(idx)
                return &keyed_sha1;
        case SADB_X_AALG_NULL:
                return &ah_none;
-#if ALLCRYPTO
+#if AH_ALL_CRYPTO
        case SADB_X_AALG_SHA2_256:
                return &hmac_sha2_256;
        case SADB_X_AALG_SHA2_384:
                return &hmac_sha2_384;
        case SADB_X_AALG_SHA2_512:
                return &hmac_sha2_512;
-#endif /* ALLCRYPTO */
+#endif /* AH_ALL_CRYPTO */
        default:
                return NULL;
        }
@@ -197,29 +227,29 @@ ah_algorithm_lookup(idx)
 
 
 static int
-ah_sumsiz_1216(sav)
-       struct secasvar *sav;
+ah_sumsiz_1216(struct secasvar *sav)
 {
-       if (!sav)
+       if (!sav) {
                return -1;
-       if (sav->flags & SADB_X_EXT_OLD)
+       }
+       if (sav->flags & SADB_X_EXT_OLD) {
                return 16;
-       else
+       } else {
                return 12;
+       }
 }
 
 static int
-ah_sumsiz_zero(sav)
-       struct secasvar *sav;
+ah_sumsiz_zero(struct secasvar *sav)
 {
-       if (!sav)
+       if (!sav) {
                return -1;
+       }
        return 0;
 }
 
 static int
-ah_none_mature(sav)
-       struct secasvar *sav;
+ah_none_mature(struct secasvar *sav)
 {
        if (sav->sah->saidx.proto == IPPROTO_AH) {
                ipseclog((LOG_ERR,
@@ -249,7 +279,8 @@ ah_none_loop(
 static void
 ah_none_result(
        __unused struct ah_algorithm_state *state,
-       __unused caddr_t addr)
+       __unused caddr_t addr,
+       __unused size_t l)
 {
 }
 
@@ -262,37 +293,38 @@ ah_keyed_md5_mature(
 }
 
 static int
-ah_keyed_md5_init(state, sav)
-       struct ah_algorithm_state *state;
-       struct secasvar *sav;
+ah_keyed_md5_init(struct ah_algorithm_state *state, struct secasvar *sav)
 {
        size_t padlen;
        size_t keybitlen;
-       u_int8_t buf[32];
+       u_int8_t buf[32] __attribute__((aligned(4)));
 
-       if (!state)
+       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)
+       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));
+                   (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)
+               if (_KEYLEN(state->sav->key_auth) < 56) {
                        padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
-               else
+               } else {
                        padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
+               }
                keybitlen = _KEYLEN(state->sav->key_auth);
                keybitlen *= 8;
 
@@ -320,40 +352,36 @@ ah_keyed_md5_init(state, sav)
 }
 
 static void
-ah_keyed_md5_loop(state, addr, len)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
-       size_t len;
+ah_keyed_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
 {
-       if (!state)
+       if (!state) {
                panic("ah_keyed_md5_loop: what?");
+       }
 
        MD5Update((MD5_CTX *)state->foo, addr, len);
 }
 
 static void
-ah_keyed_md5_result(state, addr)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
+ah_keyed_md5_result(struct ah_algorithm_state *state, caddr_t addr, size_t l)
 {
-       u_char digest[16];
+       u_char digest[16] __attribute__((aligned(4)));
 
-       if (!state)
+       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));
+                   (u_int8_t *)_KEYBUF(state->sav->key_auth),
+                   (u_int)_KEYLEN(state->sav->key_auth));
        }
        MD5Final(&digest[0], (MD5_CTX *)state->foo);
        FREE(state->foo, M_TEMP);
-       bcopy(&digest[0], (void *)addr, sizeof(digest));
+       bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest));
 }
 
 static int
-ah_keyed_sha1_mature(sav)
-       struct secasvar *sav;
+ah_keyed_sha1_mature(struct secasvar *sav)
 {
        const struct ah_algorithm *algo;
 
@@ -369,7 +397,7 @@ ah_keyed_sha1_mature(sav)
        }
 
        if (sav->key_auth->sadb_key_bits < algo->keymin
-        || algo->keymax < sav->key_auth->sadb_key_bits) {
+           || algo->keymax < sav->key_auth->sadb_key_bits) {
                ipseclog((LOG_ERR,
                    "ah_keyed_sha1_mature: invalid key length %d.\n",
                    sav->key_auth->sadb_key_bits));
@@ -380,37 +408,38 @@ ah_keyed_sha1_mature(sav)
 }
 
 static int
-ah_keyed_sha1_init(state, sav)
-       struct ah_algorithm_state *state;
-       struct secasvar *sav;
+ah_keyed_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav)
 {
        SHA1_CTX *ctxt;
        size_t padlen;
        size_t keybitlen;
-       u_int8_t buf[32];
+       u_int8_t buf[32] __attribute__((aligned(4)));
 
-       if (!state)
+       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)
+       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));
+                   (u_int)_KEYLEN(state->sav->key_auth));
 
                /*
                 * Pad after the key.
                 */
-               if (_KEYLEN(state->sav->key_auth) < 56)
+               if (_KEYLEN(state->sav->key_auth) < 56) {
                        padlen = 64 - 8 - _KEYLEN(state->sav->key_auth);
-               else
+               } else {
                        padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth);
+               }
                keybitlen = _KEYLEN(state->sav->key_auth);
                keybitlen *= 8;
 
@@ -438,45 +467,41 @@ ah_keyed_sha1_init(state, sav)
 }
 
 static void
-ah_keyed_sha1_loop(state, addr, len)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
-       size_t len;
+ah_keyed_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
 {
        SHA1_CTX *ctxt;
 
-       if (!state || !state->foo)
+       if (!state || !state->foo) {
                panic("ah_keyed_sha1_loop: what?");
+       }
        ctxt = (SHA1_CTX *)state->foo;
 
        SHA1Update(ctxt, (caddr_t)addr, (size_t)len);
 }
 
 static void
-ah_keyed_sha1_result(state, addr)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
+ah_keyed_sha1_result(struct ah_algorithm_state *state, caddr_t addr, size_t l)
 {
-       u_char digest[SHA1_RESULTLEN];  /* SHA-1 generates 160 bits */
+       u_char digest[SHA1_RESULTLEN] __attribute__((aligned(4)));      /* SHA-1 generates 160 bits */
        SHA1_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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));
+                   (u_int)_KEYLEN(state->sav->key_auth));
        }
        SHA1Final((caddr_t)&digest[0], ctxt);
-       bcopy(&digest[0], (void *)addr, HMACSIZE);
+       bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest));
 
        FREE(state->foo, M_TEMP);
 }
 
 static int
-ah_hmac_md5_mature(sav)
-       struct secasvar *sav;
+ah_hmac_md5_mature(struct secasvar *sav)
 {
        const struct ah_algorithm *algo;
 
@@ -492,7 +517,7 @@ ah_hmac_md5_mature(sav)
        }
 
        if (sav->key_auth->sadb_key_bits < algo->keymin
-        || algo->keymax < sav->key_auth->sadb_key_bits) {
+           || algo->keymax < sav->key_auth->sadb_key_bits) {
                ipseclog((LOG_ERR,
                    "ah_hmac_md5_mature: invalid key length %d.\n",
                    sav->key_auth->sadb_key_bits));
@@ -503,40 +528,40 @@ ah_hmac_md5_mature(sav)
 }
 
 static int
-ah_hmac_md5_init(state, sav)
-       struct ah_algorithm_state *state;
-       struct secasvar *sav;
+ah_hmac_md5_init(struct ah_algorithm_state *state, struct secasvar *sav)
 {
        u_char *ipad;
        u_char *opad;
-       u_char tk[16];
+       u_char tk[16] __attribute__((aligned(4)));
        u_char *key;
        size_t keylen;
        size_t i;
        MD5_CTX *ctxt;
 
-       if (!state)
+       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)
+       if (!state->foo) {
                return ENOBUFS;
+       }
 
        ipad = (u_char *)state->foo;
        opad = (u_char *)(ipad + 64);
-       ctxt = (MD5_CTX *)(opad + 64);
+       ctxt = (MD5_CTX *)(void *)(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));
+                   _KEYLEN(state->sav->key_auth));
                MD5Final(&tk[0], ctxt);
                key = &tk[0];
                keylen = 16;
        } else {
-               key = _KEYBUF(state->sav->key_auth);
+               key = (u_char *) _KEYBUF(state->sav->key_auth);
                keylen = _KEYLEN(state->sav->key_auth);
        }
 
@@ -556,35 +581,32 @@ ah_hmac_md5_init(state, sav)
 }
 
 static void
-ah_hmac_md5_loop(state, addr, len)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
-       size_t len;
+ah_hmac_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
 {
        MD5_CTX *ctxt;
 
-       if (!state || !state->foo)
+       if (!state || !state->foo) {
                panic("ah_hmac_md5_loop: what?");
-       ctxt = (MD5_CTX *)(((caddr_t)state->foo) + 128);
+       }
+       ctxt = (MD5_CTX *)(void *)(((caddr_t)state->foo) + 128);
        MD5Update(ctxt, addr, len);
 }
 
 static void
-ah_hmac_md5_result(state, addr)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
+ah_hmac_md5_result(struct ah_algorithm_state *state, caddr_t addr, size_t l)
 {
-       u_char digest[16];
+       u_char digest[16] __attribute__((aligned(4)));
        u_char *ipad;
        u_char *opad;
        MD5_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       ctxt = (MD5_CTX *)(void *)(opad + 64);
 
        MD5Final(&digest[0], ctxt);
 
@@ -593,14 +615,13 @@ ah_hmac_md5_result(state, addr)
        MD5Update(ctxt, &digest[0], sizeof(digest));
        MD5Final(&digest[0], ctxt);
 
-       bcopy(&digest[0], (void *)addr, HMACSIZE);
+       bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest));
 
        FREE(state->foo, M_TEMP);
 }
 
 static int
-ah_hmac_sha1_mature(sav)
-       struct secasvar *sav;
+ah_hmac_sha1_mature(struct secasvar *sav)
 {
        const struct ah_algorithm *algo;
 
@@ -616,7 +637,7 @@ ah_hmac_sha1_mature(sav)
        }
 
        if (sav->key_auth->sadb_key_bits < algo->keymin
-        || algo->keymax < sav->key_auth->sadb_key_bits) {
+           || algo->keymax < sav->key_auth->sadb_key_bits) {
                ipseclog((LOG_ERR,
                    "ah_hmac_sha1_mature: invalid key length %d.\n",
                    sav->key_auth->sadb_key_bits));
@@ -627,41 +648,41 @@ ah_hmac_sha1_mature(sav)
 }
 
 static int
-ah_hmac_sha1_init(state, sav)
-       struct ah_algorithm_state *state;
-       struct secasvar *sav;
+ah_hmac_sha1_init(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 tk[SHA1_RESULTLEN] __attribute__((aligned(4)));  /* SHA-1 generates 160 bits */
        u_char *key;
        size_t keylen;
        size_t i;
 
-       if (!state)
+       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)
+           M_TEMP, M_NOWAIT);
+       if (!state->foo) {
                return ENOBUFS;
+       }
 
        ipad = (u_char *)state->foo;
        opad = (u_char *)(ipad + 64);
-       ctxt = (SHA1_CTX *)(opad + 64);
+       ctxt = (SHA1_CTX *)(void *)(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));
+                   _KEYLEN(state->sav->key_auth));
                SHA1Final(&tk[0], ctxt);
                key = &tk[0];
                keylen = SHA1_RESULTLEN;
        } else {
-               key = _KEYBUF(state->sav->key_auth);
+               key = (u_char *) _KEYBUF(state->sav->key_auth);
                keylen = _KEYLEN(state->sav->key_auth);
        }
 
@@ -681,36 +702,33 @@ ah_hmac_sha1_init(state, sav)
 }
 
 static void
-ah_hmac_sha1_loop(state, addr, len)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
-       size_t len;
+ah_hmac_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len)
 {
        SHA1_CTX *ctxt;
 
-       if (!state || !state->foo)
+       if (!state || !state->foo) {
                panic("ah_hmac_sha1_loop: what?");
+       }
 
-       ctxt = (SHA1_CTX *)(((u_char *)state->foo) + 128);
+       ctxt = (SHA1_CTX *)(void *)(((u_char *)state->foo) + 128);
        SHA1Update(ctxt, (caddr_t)addr, (size_t)len);
 }
 
 static void
-ah_hmac_sha1_result(state, addr)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
+ah_hmac_sha1_result(struct ah_algorithm_state *state, caddr_t addr, size_t l)
 {
-       u_char digest[SHA1_RESULTLEN];  /* SHA-1 generates 160 bits */
+       u_char digest[SHA1_RESULTLEN] __attribute__((aligned(4)));      /* SHA-1 generates 160 bits */
        u_char *ipad;
        u_char *opad;
        SHA1_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       ctxt = (SHA1_CTX *)(void *)(opad + 64);
 
        SHA1Final((caddr_t)&digest[0], ctxt);
 
@@ -719,15 +737,24 @@ ah_hmac_sha1_result(state, addr)
        SHA1Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
        SHA1Final((caddr_t)&digest[0], ctxt);
 
-       bcopy(&digest[0], (void *)addr, HMACSIZE);
+       bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest));
 
        FREE(state->foo, M_TEMP);
 }
 
-#if ALLCRYPTO
+#if AH_ALL_CRYPTO
+static int
+ah_sumsiz_sha2_256(struct secasvar *sav)
+{
+       if (!sav) {
+               return -1;
+       }
+       // return half the output size (in bytes), as per rfc 4868
+       return 16; // 256/(8*2)
+}
+
 static int
-ah_hmac_sha2_256_mature(sav)
-       struct secasvar *sav;
+ah_hmac_sha2_256_mature(struct secasvar *sav)
 {
        const struct ah_algorithm *algo;
 
@@ -756,43 +783,43 @@ ah_hmac_sha2_256_mature(sav)
 }
 
 static int
-ah_hmac_sha2_256_init(state, sav)
-       struct ah_algorithm_state *state;
-       struct secasvar *sav;
+ah_hmac_sha2_256_init(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 tk[SHA256_DIGEST_LENGTH] __attribute__((aligned(4)));
        u_char *key;
        size_t keylen;
        size_t i;
 
-       if (!state)
+       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)
+       if (!state->foo) {
                return ENOBUFS;
+       }
 
        ipad = (u_char *)state->foo;
        opad = (u_char *)(ipad + 64);
-       ctxt = (SHA256_CTX *)(opad + 64);
+       ctxt = (SHA256_CTX *)(void *)(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),
+               SHA256_Update(ctxt, (const u_int8_t *) _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);
+               key = (u_char *) _KEYBUF(state->sav->key_auth);
                keylen = _KEYLEN(state->sav->key_auth);
        }
 
@@ -813,53 +840,62 @@ ah_hmac_sha2_256_init(state, sav)
 }
 
 static void
-ah_hmac_sha2_256_loop(state, addr, len)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
-       size_t len;
+ah_hmac_sha2_256_loop(struct ah_algorithm_state *state,
+    caddr_t addr,
+    size_t len)
 {
        SHA256_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       ctxt = (SHA256_CTX *)(void *)(((u_char *)state->foo) + 128);
+       SHA256_Update(ctxt, (const u_int8_t *)addr, (size_t)len);
 }
 
 static void
-ah_hmac_sha2_256_result(state, addr)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
+ah_hmac_sha2_256_result(struct ah_algorithm_state *state,
+    caddr_t addr,
+    size_t l)
 {
-       u_char digest[SHA256_DIGEST_LENGTH];
+       u_char digest[SHA256_DIGEST_LENGTH] __attribute__((aligned(4)));
        u_char *ipad;
        u_char *opad;
        SHA256_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       ctxt = (SHA256_CTX *)(void *)(opad + 64);
 
-       SHA256_Final((caddr_t)&digest[0], ctxt);
+       SHA256_Final((u_int8_t *)digest, ctxt);
 
-       bzero(ctxt, sizeof(*ctxt));
        SHA256_Init(ctxt);
        SHA256_Update(ctxt, opad, 64);
-       SHA256_Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
-       SHA256_Final((caddr_t)&digest[0], ctxt);
+       SHA256_Update(ctxt, (const u_int8_t *)digest, sizeof(digest));
+       SHA256_Final((u_int8_t *)digest, ctxt);
 
-       bcopy(&digest[0], (void *)addr, HMACSIZE);
+       bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest));
 
        FREE(state->foo, M_TEMP);
 }
 
 static int
-ah_hmac_sha2_384_mature(sav)
-       struct secasvar *sav;
+ah_sumsiz_sha2_384(struct secasvar *sav)
+{
+       if (!sav) {
+               return -1;
+       }
+       // return half the output size (in bytes), as per rfc 4868
+       return 24; // 384/(8*2)
+}
+
+static int
+ah_hmac_sha2_384_mature(struct secasvar *sav)
 {
        const struct ah_algorithm *algo;
 
@@ -888,111 +924,119 @@ ah_hmac_sha2_384_mature(sav)
 }
 
 static int
-ah_hmac_sha2_384_init(state, sav)
-       struct ah_algorithm_state *state;
-       struct secasvar *sav;
+ah_hmac_sha2_384_init(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 tk[SHA384_DIGEST_LENGTH] __attribute__((aligned(4)));
        u_char *key;
        size_t keylen;
        size_t i;
 
-       if (!state)
+       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)
+       state->foo = (void *)_MALLOC(128 + 128 + sizeof(SHA384_CTX),
+           M_TEMP, M_NOWAIT | M_ZERO);
+       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);
+       opad = (u_char *)(ipad + 128);
+       ctxt = (SHA384_CTX *)(void *)(opad + 128);
 
        /* compress the key if necessery */
-       if (64 < _KEYLEN(state->sav->key_auth)) {
+       if (128 < _KEYLEN(state->sav->key_auth)) {
                bzero(tk, sizeof(tk));
                bzero(ctxt, sizeof(*ctxt));
                SHA384_Init(ctxt);
-               SHA384_Update(ctxt, _KEYBUF(state->sav->key_auth),
+               SHA384_Update(ctxt, (const u_int8_t *) _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;
+               keylen = sizeof(tk) < 128 ? sizeof(tk) : 128;
        } else {
-               key = _KEYBUF(state->sav->key_auth);
+               key = (u_char *) _KEYBUF(state->sav->key_auth);
                keylen = _KEYLEN(state->sav->key_auth);
        }
 
-       bzero(ipad, 64);
-       bzero(opad, 64);
+       bzero(ipad, 128);
+       bzero(opad, 128);
        bcopy(key, ipad, keylen);
        bcopy(key, opad, keylen);
-       for (i = 0; i < 64; i++) {
+       for (i = 0; i < 128; i++) {
                ipad[i] ^= 0x36;
                opad[i] ^= 0x5c;
        }
 
        bzero(ctxt, sizeof(*ctxt));
        SHA384_Init(ctxt);
-       SHA384_Update(ctxt, ipad, 64);
+       SHA384_Update(ctxt, ipad, 128);
 
        return 0;
 }
 
 static void
-ah_hmac_sha2_384_loop(state, addr, len)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
-       size_t len;
+ah_hmac_sha2_384_loop(struct ah_algorithm_state *state,
+    caddr_t addr,
+    size_t len)
 {
        SHA384_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       ctxt = (SHA384_CTX *)(void *)(((u_char *)state->foo) + 256);
+       SHA384_Update(ctxt, (const u_int8_t *)addr, (size_t)len);
 }
 
 static void
-ah_hmac_sha2_384_result(state, addr)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
+ah_hmac_sha2_384_result(struct ah_algorithm_state *state,
+    caddr_t addr,
+    size_t l)
 {
        u_char digest[SHA384_DIGEST_LENGTH];
        u_char *ipad;
        u_char *opad;
        SHA384_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       opad = (u_char *)(ipad + 128);
+       ctxt = (SHA384_CTX *)(void *)(opad + 128);
 
-       SHA384_Final((caddr_t)&digest[0], ctxt);
+       SHA384_Final((u_int8_t *)digest, ctxt);
 
-       bzero(ctxt, sizeof(*ctxt));
        SHA384_Init(ctxt);
-       SHA384_Update(ctxt, opad, 64);
-       SHA384_Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
-       SHA384_Final((caddr_t)&digest[0], ctxt);
+       SHA384_Update(ctxt, opad, 128);
+       SHA384_Update(ctxt, (const u_int8_t *)digest, sizeof(digest));
+       SHA384_Final((u_int8_t *)digest, ctxt);
 
-       bcopy(&digest[0], (void *)addr, HMACSIZE);
+       bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest));
 
        FREE(state->foo, M_TEMP);
 }
 
 static int
-ah_hmac_sha2_512_mature(sav)
-       struct secasvar *sav;
+ah_sumsiz_sha2_512(struct secasvar *sav)
+{
+       if (!sav) {
+               return -1;
+       }
+       // return half the output size (in bytes), as per rfc 4868
+       return 32; // 512/(8*2)
+}
+
+static int
+ah_hmac_sha2_512_mature(struct secasvar *sav)
 {
        const struct ah_algorithm *algo;
 
@@ -1021,108 +1065,107 @@ ah_hmac_sha2_512_mature(sav)
 }
 
 static int
-ah_hmac_sha2_512_init(state, sav)
-       struct ah_algorithm_state *state;
-       struct secasvar *sav;
+ah_hmac_sha2_512_init(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 tk[SHA512_DIGEST_LENGTH] __attribute__((aligned(4)));
        u_char *key;
        size_t keylen;
        size_t i;
 
-       if (!state)
+       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)
+       state->foo = (void *)_MALLOC(128 + 128 + sizeof(SHA512_CTX),
+           M_TEMP, M_NOWAIT | M_ZERO);
+       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);
+       opad = (u_char *)(ipad + 128);
+       ctxt = (SHA512_CTX *)(void *)(opad + 128);
 
        /* compress the key if necessery */
-       if (64 < _KEYLEN(state->sav->key_auth)) {
+       if (128 < _KEYLEN(state->sav->key_auth)) {
                bzero(tk, sizeof(tk));
                bzero(ctxt, sizeof(*ctxt));
                SHA512_Init(ctxt);
-               SHA512_Update(ctxt, _KEYBUF(state->sav->key_auth),
+               SHA512_Update(ctxt, (const u_int8_t *) _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;
+               keylen = sizeof(tk) < 128 ? sizeof(tk) : 128;
        } else {
-               key = _KEYBUF(state->sav->key_auth);
+               key = (u_char *) _KEYBUF(state->sav->key_auth);
                keylen = _KEYLEN(state->sav->key_auth);
        }
 
-       bzero(ipad, 64);
-       bzero(opad, 64);
+       bzero(ipad, 128);
+       bzero(opad, 128);
        bcopy(key, ipad, keylen);
        bcopy(key, opad, keylen);
-       for (i = 0; i < 64; i++) {
+       for (i = 0; i < 128; i++) {
                ipad[i] ^= 0x36;
                opad[i] ^= 0x5c;
        }
 
        bzero(ctxt, sizeof(*ctxt));
        SHA512_Init(ctxt);
-       SHA512_Update(ctxt, ipad, 64);
+       SHA512_Update(ctxt, ipad, 128);
 
        return 0;
 }
 
 static void
-ah_hmac_sha2_512_loop(state, addr, len)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
-       size_t len;
+ah_hmac_sha2_512_loop(struct ah_algorithm_state *state,
+    caddr_t addr,
+    size_t len)
 {
        SHA512_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       ctxt = (SHA512_CTX *)(void *)(((u_char *)state->foo) + 256);
+       SHA512_Update(ctxt, (const u_int8_t *) addr, (size_t)len);
 }
 
 static void
-ah_hmac_sha2_512_result(state, addr)
-       struct ah_algorithm_state *state;
-       caddr_t addr;
+ah_hmac_sha2_512_result(struct ah_algorithm_state *state,
+    caddr_t addr,
+    size_t l)
 {
-       u_char digest[SHA512_DIGEST_LENGTH];
+       u_char digest[SHA512_DIGEST_LENGTH] __attribute__((aligned(4)));
        u_char *ipad;
        u_char *opad;
        SHA512_CTX *ctxt;
 
-       if (!state || !state->foo)
+       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);
+       opad = (u_char *)(ipad + 128);
+       ctxt = (SHA512_CTX *)(void *)(opad + 128);
 
-       SHA512_Final((caddr_t)&digest[0], ctxt);
+       SHA512_Final((u_int8_t *)digest, ctxt);
 
-       bzero(ctxt, sizeof(*ctxt));
        SHA512_Init(ctxt);
-       SHA512_Update(ctxt, opad, 64);
-       SHA512_Update(ctxt, (caddr_t)&digest[0], sizeof(digest));
-       SHA512_Final((caddr_t)&digest[0], ctxt);
+       SHA512_Update(ctxt, opad, 128);
+       SHA512_Update(ctxt, (const u_int8_t *)digest, sizeof(digest));
+       SHA512_Final((u_int8_t *)digest, ctxt);
 
-       bcopy(&digest[0], (void *)addr, HMACSIZE);
+       bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest));
 
        FREE(state->foo, M_TEMP);
 }
-#endif /* ALLCRYPTO */
+#endif /* AH_ALL_CRYPTO */
 
 /*------------------------------------------------------------*/
 
@@ -1130,12 +1173,9 @@ ah_hmac_sha2_512_result(state, addr)
  * 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;
+ah_update_mbuf(struct mbuf *m, int off, int len,
+    const struct ah_algorithm *algo,
+    struct ah_algorithm_state *algos)
 {
        struct mbuf *n;
        int tlen;
@@ -1147,22 +1187,26 @@ ah_update_mbuf(m, off, len, algo, algos)
        }
 
        for (n = m; n; n = n->m_next) {
-               if (off < n->m_len)
+               if (off < n->m_len) {
                        break;
+               }
 
                off -= n->m_len;
        }
 
-       if (!n)
+       if (!n) {
                panic("ah_update_mbuf: wrong offset specified");
+       }
 
        for (/*nothing*/; n && len > 0; n = n->m_next) {
-               if (n->m_len == 0)
+               if (n->m_len == 0) {
                        continue;
-               if (n->m_len - off < len)
+               }
+               if (n->m_len - off < len) {
                        tlen = n->m_len - off;
-               else
+               } else {
                        tlen = len;
+               }
 
                (algo->update)(algos, mtod(n, caddr_t) + off, tlen);
 
@@ -1180,41 +1224,39 @@ ah_update_mbuf(m, off, len, algo, algos)
  * 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;
-       caddr_t ahdat;
-       size_t len;
-       const struct ah_algorithm *algo;
-       struct secasvar *sav;
+ah4_calccksum(struct mbuf *m, caddr_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];
+       u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
        int error = 0;
        int ahseen;
        struct mbuf *n = NULL;
 
-       if ((m->m_flags & M_PKTHDR) == 0)
+       if ((m->m_flags & M_PKTHDR) == 0) {
                return EINVAL;
+       }
 
        ahseen = 0;
-       hdrtype = -1;   /*dummy, it is called IPPROTO_IP*/
+       hdrtype = -1;   /*dummy, it is called IPPROTO_IP*/
 
        off = 0;
 
        error = (algo->init)(&algos, sav);
-       if (error)
+       if (error) {
                return error;
+       }
 
-       advancewidth = 0;       /*safety*/
+       advancewidth = 0;       /*safety*/
 
 again:
        /* gory. */
        switch (hdrtype) {
-       case -1:        /*first one only*/
-           {
+       case -1:        /*first one only*/
+       {
                /*
                 * copy ip hdr, modify to fit the AH checksum rule,
                 * then take a checksum.
@@ -1230,8 +1272,9 @@ again:
 #endif
                iphdr.ip_ttl = 0;
                iphdr.ip_sum = htons(0);
-               if (ip4_ah_cleartos)
+               if (ip4_ah_cleartos) {
                        iphdr.ip_tos = 0;
+               }
                iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask);
                (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip));
 
@@ -1272,9 +1315,9 @@ again:
                                }
                                if (p[i + IPOPT_OPTVAL] == IPOPT_EOL ||
                                    p[i + IPOPT_OPTVAL] == IPOPT_NOP ||
-                                   i + IPOPT_OLEN < hlen)
+                                   i + IPOPT_OLEN < hlen) {
                                        ;
-                               else {
+                               else {
                                        ipseclog((LOG_ERR,
                                            "ah4_calccksum: invalid IP option "
                                            "(type=%02x)\n",
@@ -1290,25 +1333,27 @@ again:
                                        l = 1;
                                        skip = 0;
                                        break;
-                               case IPOPT_SECURITY:    /* 0x82 */
-                               case 0x85:      /* Extended security */
-                               case 0x86:      /* Commercial security */
-                               case 0x94:      /* Router alert */
-                               case 0x95:      /* RFC1770 */
+                               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)
+                                       if (l < 2) {
                                                goto invalopt;
+                                       }
                                        skip = 0;
                                        break;
                                default:
                                        l = p[i + IPOPT_OLEN];
-                                       if (l < 2)
+                                       if (l < 2) {
                                                goto invalopt;
+                                       }
                                        skip = 1;
                                        break;
                                }
                                if (l < 1 || hlen - i < l) {
-                       invalopt:
+invalopt:
                                        ipseclog((LOG_ERR,
                                            "ah4_calccksum: invalid IP option "
                                            "(type=%02x len=%02x)\n",
@@ -1317,14 +1362,17 @@ again:
                                        error = EINVAL;
                                        goto fail;
                                }
-                               if (skip)
+                               if (skip) {
                                        bzero(p + i, l);
-                               if (p[i + IPOPT_OPTVAL] == IPOPT_EOL)
+                               }
+                               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));
+                       (algo->update)(&algos, (caddr_t)p, hlen - sizeof(struct ip));
 
                        m_free(n);
                        n = NULL;
@@ -1333,10 +1381,10 @@ again:
                hdrtype = (iphdr.ip_p) & 0xff;
                advancewidth = hlen;
                break;
-           }
+       }
 
        case IPPROTO_AH:
-           {
+       {
                struct ah ah;
                int siz;
                int hdrsiz;
@@ -1344,8 +1392,8 @@ again:
 
                m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
                hdrsiz = (sav->flags & SADB_X_EXT_OLD)
-                               ? sizeof(struct ah)
-                               : sizeof(struct newah);
+                   ? sizeof(struct ah)
+                   : sizeof(struct newah);
                siz = (*algo->sumsiz)(sav);
                totlen = (ah.ah_len + 2) << 2;
 
@@ -1376,14 +1424,15 @@ again:
                        (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
                        m_free(n);
                        n = NULL;
-               } else
+               } 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);
@@ -1392,24 +1441,27 @@ again:
        }
 
        off += advancewidth;
-       if (off < m->m_pkthdr.len)
+       if (off < m->m_pkthdr.len) {
                goto again;
+       }
 
        if (len < (*algo->sumsiz)(sav)) {
                error = EINVAL;
                goto fail;
        }
 
-       (algo->result)(&algos, &sumbuf[0]);
+       (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf));
        bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
 
-       if (n)
+       if (n) {
                m_free(n);
+       }
        return error;
 
 fail:
-       if (n)
+       if (n) {
                m_free(n);
+       }
        return error;
 }
 #endif
@@ -1423,12 +1475,8 @@ fail:
  * 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;
-       caddr_t ahdat;
-       size_t len;
-       const struct ah_algorithm *algo;
-       struct secasvar *sav;
+ah6_calccksum(struct mbuf *m, caddr_t ahdat, size_t len,
+    const struct ah_algorithm *algo, struct secasvar *sav)
 {
        int newoff, off;
        int proto, nxt;
@@ -1436,25 +1484,30 @@ ah6_calccksum(m, ahdat, len, algo, sav)
        int error;
        int ahseen;
        struct ah_algorithm_state algos;
-       u_char sumbuf[AH_MAXSUMSIZE];
+       u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
 
-       if ((m->m_flags & M_PKTHDR) == 0)
+       if ((m->m_flags & M_PKTHDR) == 0) {
                return EINVAL;
+       }
 
        error = (algo->init)(&algos, sav);
-       if (error)
+       if (error) {
                return error;
+       }
 
        off = 0;
        proto = IPPROTO_IPV6;
        nxt = -1;
        ahseen = 0;
 
- again:
+again:
        newoff = ip6_nexthdr(m, off, proto, &nxt);
-       if (newoff < 0)
+       if (newoff < 0) {
                newoff = m->m_pkthdr.len;
-       else if (newoff <= off) {
+       } else if (newoff <= off) {
+               error = EINVAL;
+               goto fail;
+       } else if (m->m_pkthdr.len < newoff) {
                error = EINVAL;
                goto fail;
        }
@@ -1478,12 +1531,14 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                        ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK;
                        ip6copy.ip6_vfc |= IPV6_VERSION;
                        ip6copy.ip6_hlim = 0;
-                       if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src))
+                       if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src)) {
                                ip6copy.ip6_src.s6_addr16[1] = 0x0000;
-                       if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst))
+                       }
+                       if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst)) {
                                ip6copy.ip6_dst.s6_addr16[1] = 0x0000;
+                       }
                        (algo->update)(&algos, (caddr_t)&ip6copy,
-                                      sizeof(struct ip6_hdr));
+                           sizeof(struct ip6_hdr));
                } else {
                        newoff = m->m_pkthdr.len;
                        ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo,
@@ -1492,13 +1547,13 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                break;
 
        case IPPROTO_AH:
-           {
+       {
                int siz;
                int hdrsiz;
 
                hdrsiz = (sav->flags & SADB_X_EXT_OLD)
-                               ? sizeof(struct ah)
-                               : sizeof(struct newah);
+                   ? sizeof(struct ah)
+                   : sizeof(struct newah);
                siz = (*algo->sumsiz)(sav);
 
                /*
@@ -1527,15 +1582,16 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                        (algo->update)(&algos, mtod(n, caddr_t), n->m_len);
                        m_free(n);
                        n = NULL;
-               } else
+               } else {
                        ah_update_mbuf(m, off, newoff - off, algo, &algos);
+               }
                ahseen++;
                break;
-           }
+       }
 
-        case IPPROTO_HOPOPTS:
-        case IPPROTO_DSTOPTS:
-        {
+       case IPPROTO_HOPOPTS:
+       case IPPROTO_DSTOPTS:
+       {
                struct ip6_ext *ip6e;
                int hdrlen, optlen;
                u_int8_t *p, *optend, *optp;
@@ -1562,10 +1618,10 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                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;
+                       error = EINVAL;
+                       m_free(n);
+                       n = NULL;
+                       goto fail;
                }
                p = mtod(n, u_int8_t *);
                optend = p + hdrlen;
@@ -1578,9 +1634,9 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                 */
                optp = p + 2;
                while (optp < optend) {
-                       if (optp[0] == IP6OPT_PAD1)
+                       if (optp[0] == IP6OPT_PAD1) {
                                optlen = 1;
-                       else {
+                       else {
                                if (optp + 2 > optend) {
                                        error = EINVAL;
                                        m_free(n);
@@ -1588,9 +1644,16 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                                        goto fail;
                                }
                                optlen = optp[1] + 2;
+                               if (optp + optlen > optend) {
+                                       error = EINVAL;
+                                       m_free(n);
+                                       n = NULL;
+                                       goto fail;
+                               }
 
-                               if (optp[0] & IP6OPT_MUTABLE)
+                               if (optp[0] & IP6OPT_MUTABLE) {
                                        bzero(optp + 2, optlen - 2);
+                               }
                        }
 
                        optp += optlen;
@@ -1600,16 +1663,16 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                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 */
+       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);
@@ -1627,17 +1690,19 @@ ah6_calccksum(m, ahdat, len, algo, sav)
                goto fail;
        }
 
-       (algo->result)(&algos, &sumbuf[0]);
+       (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf));
        bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav));
 
        /* just in case */
-       if (n)
+       if (n) {
                m_free(n);
+       }
        return 0;
 fail:
        /* just in case */
-       if (n)
+       if (n) {
                m_free(n);
+       }
        return error;
 }
 #endif