ah_core.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,667 行 · 第 1/3 页
C
1,667 行
//==========================================================================//// src/sys/netinet6/ah_core.c////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD, // FreeBSD or other sources, and are covered by the appropriate// copyright disclaimers included herein.//// Portions created by Red Hat are// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================/* $KAME: ah_core.c,v 1.47 2001/10/29 04:43:08 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 <sys/param.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>#if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)#include <sys/kernel.h>#endif#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 <netinet/icmp6.h>#endif#include <netinet6/ipsec.h>#include <netinet6/ah.h>#ifdef IPSEC_ESP#include <netinet6/esp.h>#endif#include <net/pfkeyv2.h>#include <netkey/keydb.h>#ifdef HAVE_MD5#include <sys/md5.h>#else#include <crypto/md5.h>#endif#ifdef HAVE_SHA1#include <sys/sha1.h>#define SHA1_RESULTLEN 20#else#include <crypto/sha1.h>#endif#include <crypto/sha2/sha2.h>#define HMACSIZE 16static int ah_sumsiz_1216 __P((struct secasvar *));static int ah_sumsiz_zero __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 *, caddr_t, size_t));static void ah_none_result __P((struct ah_algorithm_state *, caddr_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 *, caddr_t, size_t));static void ah_keyed_md5_result __P((struct ah_algorithm_state *, caddr_t));static int ah_keyed_sha1_mature __P((struct secasvar *));static int ah_keyed_sha1_init __P((struct ah_algorithm_state *, struct secasvar *));static void ah_keyed_sha1_loop __P((struct ah_algorithm_state *, caddr_t, size_t));static void ah_keyed_sha1_result __P((struct ah_algorithm_state *, caddr_t));static int ah_hmac_md5_mature __P((struct secasvar *));static int ah_hmac_md5_init __P((struct ah_algorithm_state *, struct secasvar *));static void ah_hmac_md5_loop __P((struct ah_algorithm_state *, caddr_t, size_t));static void ah_hmac_md5_result __P((struct ah_algorithm_state *, caddr_t));static int ah_hmac_sha1_mature __P((struct secasvar *));static int ah_hmac_sha1_init __P((struct ah_algorithm_state *, struct secasvar *));static void ah_hmac_sha1_loop __P((struct ah_algorithm_state *, caddr_t, size_t));static void ah_hmac_sha1_result __P((struct ah_algorithm_state *, caddr_t));static int ah_hmac_sha2_256_mature __P((struct secasvar *));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 *, caddr_t, size_t));static void ah_hmac_sha2_256_result __P((struct ah_algorithm_state *, caddr_t));static int ah_hmac_sha2_384_mature __P((struct secasvar *));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 *, caddr_t, size_t));static void ah_hmac_sha2_384_result __P((struct ah_algorithm_state *, caddr_t));static int ah_hmac_sha2_512_mature __P((struct secasvar *));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 *, caddr_t, size_t));static void ah_hmac_sha2_512_result __P((struct ah_algorithm_state *, caddr_t));static void ah_update_mbuf __P((struct mbuf *, int, int, const struct ah_algorithm *, struct ah_algorithm_state *));const struct ah_algorithm *ah_algorithm_lookup(idx) int idx;{ /* checksum algorithms */ static struct ah_algorithm ah_algorithms[] = { { 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_sha1_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_keyed_sha1_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_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_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_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, }, }; 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]; default: return NULL; }}static intah_sumsiz_1216(sav) struct secasvar *sav;{ if (!sav) return -1; if (sav->flags & SADB_X_EXT_OLD) return 16; else return 12;}static intah_sumsiz_zero(sav) struct secasvar *sav;{ if (!sav) return -1; return 0;}static intah_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 intah_none_init(state, sav) struct ah_algorithm_state *state; struct secasvar *sav;{ state->foo = NULL; return 0;}static voidah_none_loop(state, addr, len) struct ah_algorithm_state *state; caddr_t addr; size_t len;{}static voidah_none_result(state, addr) struct ah_algorithm_state *state; caddr_t addr;{}static intah_keyed_md5_mature(sav) struct secasvar *sav;{ /* anything is okay */ return 0;}static intah_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 voidah_keyed_md5_loop(state, addr, len) struct ah_algorithm_state *state; caddr_t addr; size_t len;{ if (!state) panic("ah_keyed_md5_loop: what?"); MD5Update((MD5_CTX *)state->foo, addr, len);}static voidah_keyed_md5_result(state, addr) struct ah_algorithm_state *state; caddr_t addr;{ u_char digest[16]; 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[0], (MD5_CTX *)state->foo); free(state->foo, M_TEMP); bcopy(&digest[0], (void *)addr, sizeof(digest));}static intah_keyed_sha1_mature(sav) struct secasvar *sav;{ const struct ah_algorithm *algo; if (!sav->key_auth) { ipseclog((LOG_ERR, "ah_keyed_sha1_mature: no key is given.\n")); return 1; } algo = ah_algorithm_lookup(sav->alg_auth); if (!algo) { ipseclog((LOG_ERR, "ah_keyed_sha1_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_keyed_sha1_mature: invalid key length %d.\n", sav->key_auth->sadb_key_bits)); return 1; } return 0;}static intah_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 voidah_keyed_sha1_loop(state, addr, len) struct ah_algorithm_state *state; caddr_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, (caddr_t)addr, (size_t)len);}static voidah_keyed_sha1_result(state, addr) struct ah_algorithm_state *state; caddr_t addr;{ 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((caddr_t)&digest[0], ctxt); bcopy(&digest[0], (void *)addr, HMACSIZE); free(state->foo, M_TEMP);}static intah_hmac_md5_mature(sav) struct secasvar *sav;{ const struct ah_algorithm *algo; if (!sav->key_auth) { ipseclog((LOG_ERR, "ah_hmac_md5_mature: no key is given.\n")); return 1; } algo = ah_algorithm_lookup(sav->alg_auth); if (!algo) { ipseclog((LOG_ERR, "ah_hmac_md5_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_hmac_md5_mature: invalid key length %d.\n", sav->key_auth->sadb_key_bits)); return 1; } return 0;}static intah_hmac_md5_init(state, sav) struct ah_algorithm_state *state; struct secasvar *sav;{ u_char *ipad; u_char *opad; u_char tk[16]; 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 {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?