Example #1
0
static void natd_hash(const struct hash_desc *hasher, unsigned char *hash,
		const u_int8_t *icookie, const u_int8_t *rcookie,
		const ip_address *ip,
		u_int16_t port /* host order */)
{
	union hash_ctx ctx;

	if (is_zero_cookie(icookie))
		DBG(DBG_NATT, DBG_log("natd_hash: Warning, icookie is zero !!"));
	if (is_zero_cookie(rcookie))
		DBG(DBG_NATT, DBG_log("natd_hash: Warning, rcookie is zero !!"));

	/*
	 * RFC 3947
	 *
	 *   HASH = HASH(CKY-I | CKY-R | IP | Port)
	 *
	 * All values in network order
	 */
	hasher->hash_init(&ctx);
	hasher->hash_update(&ctx, icookie, COOKIE_SIZE);
	hasher->hash_update(&ctx, rcookie, COOKIE_SIZE);
	switch (addrtypeof(ip)) {
	case AF_INET:
		hasher->hash_update(&ctx,
				(const u_char *)&ip->u.v4.sin_addr.s_addr,
				sizeof(ip->u.v4.sin_addr.s_addr));
		break;
	case AF_INET6:
		hasher->hash_update(&ctx,
				(const u_char *)&ip->u.v6.sin6_addr.s6_addr,
				sizeof(ip->u.v6.sin6_addr.s6_addr));
		break;
	}
	{
		u_int16_t netorder_port = htons(port);

		hasher->hash_update(&ctx, (const u_char *)&netorder_port, sizeof(netorder_port));
	}
	hasher->hash_final(hash, &ctx);
	DBG(DBG_NATT, {
			DBG_log("natd_hash: hasher=%p(%d)", hasher,
				(int)hasher->hash_digest_len);
			DBG_dump("natd_hash: icookie=", icookie, COOKIE_SIZE);
			DBG_dump("natd_hash: rcookie=", rcookie, COOKIE_SIZE);
			switch (addrtypeof(ip)) {
			case AF_INET:
				DBG_dump("natd_hash: ip=",
					&ip->u.v4.sin_addr.s_addr,
					sizeof(ip->u.v4.sin_addr.s_addr));
				break;
			}
			DBG_log("natd_hash: port=%d", port);
			DBG_dump("natd_hash: hash=", hash,
				hasher->hash_digest_len);
		});
Example #2
0
static void natd_hash(const struct hash_desc *hasher, unsigned char *hash,
		const u_int8_t *icookie, const u_int8_t *rcookie,
		const ip_address *ip,
		u_int16_t port /* host order */)
{
	if (is_zero_cookie(icookie))
		DBG(DBG_NATT, DBG_log("natd_hash: Warning, icookie is zero !!"));
	if (is_zero_cookie(rcookie))
		DBG(DBG_NATT, DBG_log("natd_hash: Warning, rcookie is zero !!"));

	/*
	 * RFC 3947
	 *
	 *   HASH = HASH(CKY-I | CKY-R | IP | Port)
	 *
	 * All values in network order
	 */
	struct crypt_hash *ctx = crypt_hash_init(hasher, "NATD", DBG_CRYPT);
	crypt_hash_digest_bytes(ctx, "ICOOKIE", icookie, COOKIE_SIZE);
	crypt_hash_digest_bytes(ctx, "RCOOKIE", rcookie, COOKIE_SIZE);
	switch (addrtypeof(ip)) {
	case AF_INET:
		crypt_hash_digest_bytes(ctx, "SIN_ADDR",
					(const u_char *)&ip->u.v4.sin_addr.s_addr,
					sizeof(ip->u.v4.sin_addr.s_addr));
		break;
	case AF_INET6:
		crypt_hash_digest_bytes(ctx, "SIN6_ADDR",
					(const u_char *)&ip->u.v6.sin6_addr.s6_addr,
					sizeof(ip->u.v6.sin6_addr.s6_addr));
		break;
	}
	{
		u_int16_t netorder_port = htons(port);
		crypt_hash_digest_bytes(ctx, "PORT",
					&netorder_port, sizeof(netorder_port));
	}
	crypt_hash_final_bytes(&ctx, hash, hasher->hash_digest_len);
	DBG(DBG_NATT, {
			DBG_log("natd_hash: hasher=%p(%d)", hasher,
				(int)hasher->hash_digest_len);
			DBG_dump("natd_hash: icookie=", icookie, COOKIE_SIZE);
			DBG_dump("natd_hash: rcookie=", rcookie, COOKIE_SIZE);
			switch (addrtypeof(ip)) {
			case AF_INET:
				DBG_dump("natd_hash: ip=",
					&ip->u.v4.sin_addr.s_addr,
					sizeof(ip->u.v4.sin_addr.s_addr));
				break;
			}
			DBG_log("natd_hash: port=%d", port);
			DBG_dump("natd_hash: hash=", hash,
				hasher->hash_digest_len);
		});
Example #3
0
static void _natd_hash(const struct hash_desc *hasher, unsigned char *hash
		       , u_int8_t *icookie, u_int8_t *rcookie
		       , const ip_address *ip, u_int16_t port)
{
	union hash_ctx ctx;

	if (is_zero_cookie(icookie))
		DBG_log("_natd_hash: Warning, icookie is zero !!");
	if (is_zero_cookie(rcookie))
		DBG_log("_natd_hash: Warning, rcookie is zero !!");

	/**
	 * draft-ietf-ipsec-nat-t-ike-01.txt
	 *
	 *   HASH = HASH(CKY-I | CKY-R | IP | Port)
	 *
	 * All values in network order
	 */
	hasher->hash_init(&ctx);
	hasher->hash_update(&ctx, icookie, COOKIE_SIZE);
	hasher->hash_update(&ctx, rcookie, COOKIE_SIZE);
	switch (addrtypeof(ip)) {
		case AF_INET:
			hasher->hash_update(&ctx,
				(const u_char *)&ip->u.v4.sin_addr.s_addr,
				sizeof(ip->u.v4.sin_addr.s_addr));
			break;
		case AF_INET6:
			hasher->hash_update(&ctx,
				(const u_char *)&ip->u.v6.sin6_addr.s6_addr,
				sizeof(ip->u.v6.sin6_addr.s6_addr));
			break;
	}
	hasher->hash_update(&ctx, (const u_char *)&port, sizeof(u_int16_t));
	hasher->hash_final(hash, &ctx);
#ifdef NAT_D_DEBUG
	DBG(DBG_NATT,
		DBG_log("_natd_hash: hasher=%p(%d)", hasher, (int)hasher->hash_digest_len);
		DBG_dump("_natd_hash: icookie=", icookie, COOKIE_SIZE);
		DBG_dump("_natd_hash: rcookie=", rcookie, COOKIE_SIZE);
		switch (addrtypeof(ip)) {
			case AF_INET:
				DBG_dump("_natd_hash: ip=", &ip->u.v4.sin_addr.s_addr,
					sizeof(ip->u.v4.sin_addr.s_addr));
				break;
		}
		DBG_log("_natd_hash: port=%d", ntohs(port));
		DBG_dump("_natd_hash: hash=", hash, hasher->hash_digest_len);
	);
Example #4
0
/*
 * Generate a cookie (aka SPI)
 * First argument is true if we're to create an Initiator cookie.
 * Length SHOULD be a multiple of sizeof(u_int32_t).
 *
 * As responder, we use a hashing method to get a pseudo random
 * value instead of using our own random pool. It will prevent
 * an attacker from gaining raw data from our random pool and
 * it will prevent an attacker from depleting our random pool
 * or entropy.
 */
void get_cookie(bool initiator, u_int8_t cookie[COOKIE_SIZE],
		const ip_address *addr)
{

	do {
		if (initiator) {
			get_rnd_bytes(cookie, COOKIE_SIZE);
		} else {
			static u_int32_t counter = 0; /* STATIC */
			unsigned char addr_buff[
				sizeof(union { struct in_addr A;
					       struct in6_addr B;
				       })];
			u_char buffer[SHA2_256_DIGEST_SIZE];
			sha256_context ctx;

			size_t addr_length =
				addrbytesof(addr, addr_buff,
					    sizeof(addr_buff));
			sha256_init(&ctx);
			sha256_write(&ctx, addr_buff, addr_length);
			sha256_write(&ctx, secret_of_the_day,
				   sizeof(secret_of_the_day));
			counter++;
			sha256_write(&ctx, (const void *) &counter,
				   sizeof(counter));
			sha256_final(buffer, &ctx);
			/* cookie size is smaller than any hash output sizes */
			memcpy(cookie, buffer, COOKIE_SIZE);
		}
	} while (is_zero_cookie(cookie)); /* probably never loops */
}
/* Generate a cookie.
 * First argument is true if we're to create an Initiator cookie.
 * Length SHOULD be a multiple of sizeof(u_int32_t).
 */
void
get_cookie(bool initiator, u_int8_t *cookie, int length, const ip_address *addr)
{
    u_char buffer[SHA1_DIGEST_SIZE];
    SHA1_CTX ctx;

    do {
	if (initiator)
	{
	    get_rnd_bytes(cookie, length);
	}
	else  /* Responder cookie */
	{
	    /* This looks as good as any way */
	    size_t addr_length;
	    static u_int32_t counter = 0;
	    unsigned char addr_buff[
		sizeof(union {struct in_addr; struct in6_addr;})];

	    addr_length = addrbytesof(addr, addr_buff, sizeof(addr_buff));
	    SHA1Init(&ctx);
	    SHA1Update(&ctx, addr_buff, addr_length);
	    SHA1Update(&ctx, secret_of_the_day, sizeof(secret_of_the_day));
	    counter++;
	    SHA1Update(&ctx, (const void *) &counter, sizeof(counter));
	    SHA1Final(buffer, &ctx);
	    memcpy(cookie, buffer, length);
	}
    } while (is_zero_cookie(cookie));	/* probably never loops */
}
Example #6
0
bool nat_traversal_add_natd(u_int8_t np, pb_stream *outs,
	struct msg_digest *md)
{
	char hash[MAX_DIGEST_LEN];
	struct state *st = md->st;

	if (!out_modify_previous_np(ISAKMP_NEXT_NATD, outs))
		return FALSE;

	if (!st || !st->st_oakley.hasher) {
		loglog(RC_LOG_SERIOUS, "NAT-Traversal: assert failed %s:%d",
			__FILE__, __LINE__);
		return FALSE;
	}

	/**
	 * First one with sender IP & port
	 */
	_natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
		is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
		&(md->sender),
#ifdef FORCE_NAT_TRAVERSAL
		0
#else
		ntohs(md->sender_port)
#endif
	);
	if (!out_generic_raw(ISAKMP_NEXT_NATD, &isakmp_nat_d, outs,
		hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"))
		return FALSE;

	/**
	 * Second one with my IP & port
	 */
	_natd_hash(st->st_oakley.hasher, hash, st->st_icookie,
		is_zero_cookie(st->st_rcookie) ? md->hdr.isa_rcookie : st->st_rcookie,
		&(md->iface->addr),
#ifdef FORCE_NAT_TRAVERSAL
		0
#else
		ntohs(st->st_connection->this.host_port)
#endif
	);
	return (out_generic_raw(np, &isakmp_nat_d, outs,
		hash, st->st_oakley.hasher->hash_digest_len, "NAT-D"));
}
Example #7
0
/* Generate a cookie.
 * First argument is true if we're to create an Initiator cookie.
 * Length SHOULD be a multiple of sizeof(u_int32_t).
 */
void get_cookie(bool initiator, u_int8_t *cookie, int length, ip_address *addr)
{
	hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
	u_char buffer[HASH_SIZE_SHA1];

	do {
		if (initiator)
		{
			rng_t *rng;

			rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
			rng->get_bytes(rng, length, cookie);
			rng->destroy(rng);
		}
		else  /* Responder cookie */
		{
			chunk_t addr_chunk, secret_chunk, counter_chunk;
			size_t addr_len;
			static u_int32_t counter = 0;
			unsigned char addr_buf[
				sizeof(union {struct in_addr A; struct in6_addr B;})];

			addr_len = addrbytesof(addr, addr_buf, sizeof(addr_buf));
			addr_chunk = chunk_create(addr_buf, addr_len);
			secret_chunk = chunk_create(secret_of_the_day, HASH_SIZE_SHA1);
			counter++;
			counter_chunk = chunk_create((void *) &counter, sizeof(counter));
			hasher->get_hash(hasher, addr_chunk, NULL);
			hasher->get_hash(hasher, secret_chunk, NULL);
			hasher->get_hash(hasher, counter_chunk, buffer);
			memcpy(cookie, buffer, length);
		}
	} while (is_zero_cookie(cookie));   /* probably never loops */

	hasher->destroy(hasher);
}