⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ah_core.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================
//
//      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	16

static 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 int
ah_sumsiz_1216(sav)
	struct secasvar *sav;
{
	if (!sav)
		return -1;
	if (sav->flags & SADB_X_EXT_OLD)
		return 16;
	else
		return 12;
}

static int
ah_sumsiz_zero(sav)
	struct secasvar *sav;
{
	if (!sav)
		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;
	caddr_t addr;
	size_t len;
{
}

static void
ah_none_result(state, addr)
	struct ah_algorithm_state *state;
	caddr_t addr;
{
}

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;
	caddr_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)
	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 int
ah_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 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;
	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 void
ah_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 int
ah_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 int
ah_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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -