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 + -
显示快捷键?