Esempio n. 1
0
/* This is the implementation from FreeBSD, with tweaks */
static uint16_t
Fhash(const struct inpcb_hdr *inp_hdr)
{
	MD5_CTX f_ctx;
	uint32_t Ff[4];
	uint32_t secret_f[4];
	uint32_t offset;
	uint16_t soffset[2];

	cprng_fast(secret_f, sizeof(secret_f));

	MD5Init(&f_ctx);
	switch (inp_hdr->inph_af) {
#ifdef INET
	case AF_INET: {
		const struct inpcb *inp =
		    (const struct inpcb *)(const void *)inp_hdr;
		MD5Update(&f_ctx, (const u_char *)&inp->inp_laddr,
		    sizeof(inp->inp_laddr));
		MD5Update(&f_ctx, (const u_char *)&inp->inp_faddr,
		    sizeof(inp->inp_faddr));
		MD5Update(&f_ctx, (const u_char *)&inp->inp_fport,
		    sizeof(inp->inp_fport));
		break;
	}
#endif
#ifdef INET6
	case AF_INET6: {
		const struct in6pcb *in6p =
		    (const struct in6pcb *)(const void *)inp_hdr;
		MD5Update(&f_ctx, (const u_char *)&in6p->in6p_laddr,
		    sizeof(in6p->in6p_laddr));
		MD5Update(&f_ctx, (const u_char *)&in6p->in6p_faddr,
		    sizeof(in6p->in6p_faddr));
		MD5Update(&f_ctx, (const u_char *)&in6p->in6p_fport,
		    sizeof(in6p->in6p_fport));
		break;
	}
#endif
	default:
		break;
	}
	MD5Update(&f_ctx, (const u_char *)secret_f, sizeof(secret_f));
	MD5Final((u_char *)&Ff, &f_ctx);

	offset = (Ff[0] ^ Ff[1]) ^ (Ff[2] ^ Ff[3]);

	memcpy(&soffset, &offset, sizeof(soffset));

	return soffset[0] ^ soffset[1];
}
Esempio n. 2
0
static void
uuid_generate(struct uuid *uuid)
{

	/* Randomly generate the content.  */
	cprng_fast(uuid, sizeof(*uuid));

	/* Set the version number to 4.  */
	uuid->time_hi_and_version &= ~(uint32_t)0xf000;
	uuid->time_hi_and_version |= 0x4000;

	/* Fix the reserved bits.  */
	uuid->clock_seq_hi_and_reserved &= ~(uint8_t)0x40;
	uuid->clock_seq_hi_and_reserved |= 0x80;
}
Esempio n. 3
0
int
aes_gmac_setkey(u_int8_t **sched, const u_int8_t *key, int len)
{
	struct aes_gmac_ctx *ctx;

	ctx = malloc(sizeof(struct aes_gmac_ctx), M_CRYPTO_DATA,
		     M_NOWAIT|M_ZERO);
	if (!ctx)
		return ENOMEM;

	/* random start value for simple counter */
	cprng_fast(&ctx->ivgenctx.lastiv, sizeof(ctx->ivgenctx.lastiv));
	*sched = (void *)ctx;
	return 0;
}
Esempio n. 4
0
void
ssp_init(void)
{
	int s;

	aprint_debug("Initializing SSP: ");
	/*
	 * We initialize ssp here carefully:
	 *	1. after we got some entropy
	 *	2. without calling a function
	 */
	size_t i;
	long guard[__arraycount(__stack_chk_guard)];

	cprng_fast(guard, sizeof(guard));
	s = splhigh();
	for (i = 0; i < __arraycount(guard); i++)
		__stack_chk_guard[i] = guard[i];
	splx(s);
	for (i = 0; i < __arraycount(guard); i++)
		aprint_debug("%lx ", guard[i]);
	aprint_debug("\n");
}
Esempio n. 5
0
/*
 * sysctl helper routine for kern.arandom node.  Fills the supplied
 * structure with random data for you.
 *
 * This node was originally declared as type "int" but its implementation
 * in OpenBSD, whence it came, would happily return up to 8K of data if
 * requested.  Evidently this was used to key RC4 in userspace.
 *
 * In NetBSD, the libc stack-smash-protection code reads 64 bytes
 * from here at every program startup.  So though it would be nice
 * to make this node return only 32 or 64 bits, we can't.  Too bad!
 */
static int
sysctl_kern_arnd(SYSCTLFN_ARGS)
{
	int error;
	void *v;
	struct sysctlnode node = *rnode;

	switch (*oldlenp) {
	    case 0:
		return 0;
	    default:
		if (*oldlenp > 256) {
			return E2BIG;
		}
		v = kmem_alloc(*oldlenp, KM_SLEEP);
		cprng_fast(v, *oldlenp);
		node.sysctl_data = v;
		node.sysctl_size = *oldlenp;
		error = sysctl_lookup(SYSCTLFN_CALL(&node));
		kmem_free(v, *oldlenp);
		return error;
	}
}
Esempio n. 6
0
int
aes_ctr_setkey(u_int8_t **sched, const u_int8_t *key, int len)
{
	struct aes_ctr_ctx *ctx;

	if (len < AESCTR_NONCESIZE)
		return EINVAL;

	ctx = malloc(sizeof(struct aes_ctr_ctx), M_CRYPTO_DATA,
		     M_NOWAIT|M_ZERO);
	if (!ctx)
		return ENOMEM;
	ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (const u_char *)key,
			(len - AESCTR_NONCESIZE) * 8);
	if (!ctx->ac_nr) { /* wrong key len */
		aes_ctr_zerokey((u_int8_t **)&ctx);
		return EINVAL;
	}
	memcpy(ctx->ac_block, key + len - AESCTR_NONCESIZE, AESCTR_NONCESIZE);
	/* random start value for simple counter */
	cprng_fast(&ctx->ivgenctx.lastiv, sizeof(ctx->ivgenctx.lastiv));
	*sched = (void *)ctx;
	return 0;
}
Esempio n. 7
0
void
tap_attach(device_t parent, device_t self, void *aux)
{
	struct tap_softc *sc = device_private(self);
	struct ifnet *ifp;
	const struct sysctlnode *node;
	int error;
	uint8_t enaddr[ETHER_ADDR_LEN] =
	    { 0xf2, 0x0b, 0xa4, 0xff, 0xff, 0xff };
	char enaddrstr[3 * ETHER_ADDR_LEN];

	sc->sc_dev = self;
	sc->sc_sih = NULL;
	getnanotime(&sc->sc_btime);
	sc->sc_atime = sc->sc_mtime = sc->sc_btime;
	sc->sc_flags = 0;
	selinit(&sc->sc_rsel);

	/*
	 * Initialize the two locks for the device.
	 *
	 * We need a lock here because even though the tap device can be
	 * opened only once, the file descriptor might be passed to another
	 * process, say a fork(2)ed child.
	 *
	 * The Giant saves us from most of the hassle, but since the read
	 * operation can sleep, we don't want two processes to wake up at
	 * the same moment and both try and dequeue a single packet.
	 *
	 * The queue for event listeners (used by kqueue(9), see below) has
	 * to be protected too, so use a spin lock.
	 */
	mutex_init(&sc->sc_rdlock, MUTEX_DEFAULT, IPL_NONE);
	mutex_init(&sc->sc_kqlock, MUTEX_DEFAULT, IPL_VM);

	if (!pmf_device_register(self, NULL, NULL))
		aprint_error_dev(self, "couldn't establish power handler\n");

	/*
	 * In order to obtain unique initial Ethernet address on a host,
	 * do some randomisation.  It's not meant for anything but avoiding
	 * hard-coding an address.
	 */
	cprng_fast(&enaddr[3], 3);

	aprint_verbose_dev(self, "Ethernet address %s\n",
	    ether_snprintf(enaddrstr, sizeof(enaddrstr), enaddr));

	/*
	 * Why 1000baseT? Why not? You can add more.
	 *
	 * Note that there are 3 steps: init, one or several additions to
	 * list of supported media, and in the end, the selection of one
	 * of them.
	 */
	ifmedia_init(&sc->sc_im, 0, tap_mediachange, tap_mediastatus);
	ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T, 0, NULL);
	ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T|IFM_FDX, 0, NULL);
	ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX, 0, NULL);
	ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
	ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T, 0, NULL);
	ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
	ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_AUTO, 0, NULL);
	ifmedia_set(&sc->sc_im, IFM_ETHER|IFM_AUTO);

	/*
	 * One should note that an interface must do multicast in order
	 * to support IPv6.
	 */
	ifp = &sc->sc_ec.ec_if;
	strcpy(ifp->if_xname, device_xname(self));
	ifp->if_softc	= sc;
	ifp->if_flags	= IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
	ifp->if_ioctl	= tap_ioctl;
	ifp->if_start	= tap_start;
	ifp->if_stop	= tap_stop;
	ifp->if_init	= tap_init;
	IFQ_SET_READY(&ifp->if_snd);

	sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU;

	/* Those steps are mandatory for an Ethernet driver. */
	if_initialize(ifp);
	ether_ifattach(ifp, enaddr);
	if_register(ifp);

	/*
	 * Add a sysctl node for that interface.
	 *
	 * The pointer transmitted is not a string, but instead a pointer to
	 * the softc structure, which we can use to build the string value on
	 * the fly in the helper function of the node.  See the comments for
	 * tap_sysctl_handler for details.
	 *
	 * Usually sysctl_createv is called with CTL_CREATE as the before-last
	 * component.  However, we can allocate a number ourselves, as we are
	 * the only consumer of the net.link.<iface> node.  In this case, the
	 * unit number is conveniently used to number the node.  CTL_CREATE
	 * would just work, too.
	 */
	if ((error = sysctl_createv(NULL, 0, NULL,
	    &node, CTLFLAG_READWRITE,
	    CTLTYPE_STRING, device_xname(self), NULL,
	    tap_sysctl_handler, 0, (void *)sc, 18,
	    CTL_NET, AF_LINK, tap_node, device_unit(sc->sc_dev),
	    CTL_EOL)) != 0)
		aprint_error_dev(self, "sysctl_createv returned %d, ignoring\n",
		    error);
}
Esempio n. 8
0
static int
generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
{
	MD5_CTX ctxt;
	u_int8_t seed[16], digest[16], nullbuf[8];
	/*
	 * interface ID for subnet anycast addresses.
	 * XXX: we assume the unicast address range that requires IDs
	 * in EUI-64 format.
	 */
	static const uint8_t anycast_id[8] = { 0xfd, 0xff, 0xff, 0xff,
	    0xff, 0xff, 0xff, 0x80 };
	static const uint8_t isatap_id[4] = { 0x00, 0x00, 0x5e, 0xfe };
	int badid, retry = 0;

	/* If there's no hisotry, start with a random seed. */
	memset(nullbuf, 0, sizeof(nullbuf));
	if (memcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
		cprng_fast(seed, sizeof(seed));
	} else
		memcpy(seed, seed0, 8);

	/* copy the right-most 64-bits of the given address */
	/* XXX assumption on the size of IFID */
	memcpy(&seed[8], seed1, 8);

  again:
	/* for debugging purposes only */
#if 0
	{
		int i;

		printf("generate_tmp_ifid: new randomized ID from: ");
		for (i = 0; i < 16; i++)
			printf("%02x", seed[i]);
		printf(" ");
	}
#endif

	/* generate 16 bytes of pseudo-random value. */
	memset(&ctxt, 0, sizeof(ctxt));
	MD5Init(&ctxt);
	MD5Update(&ctxt, seed, sizeof(seed));
	MD5Final(digest, &ctxt);

	/*
	 * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (3)
	 * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
	 * left-most bit is numbered 0) to zero.
	 */
	memcpy(ret, digest, 8);
	ret[0] &= ~EUI64_UBIT;

	/*
	 * Reject inappropriate identifiers according to
	 * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (4)
	 * At this moment, we reject following cases:
	 * - all 0 identifier
	 * - identifiers that conflict with reserved subnet anycast addresses,
	 *   which are defined in RFC 2526.
	 * - identifiers that conflict with ISATAP addresses
	 * - identifiers used in our own addresses
	 */
	badid = 0;
	if (memcmp(nullbuf, ret, sizeof(nullbuf)) == 0)
		badid = 1;
	else if (memcmp(anycast_id, ret, 7) == 0 &&
	    (anycast_id[7] & ret[7]) == anycast_id[7]) {
		badid = 1;
	} else if (memcmp(isatap_id, ret, sizeof(isatap_id)) == 0)
		badid = 1;
	else {
		struct in6_ifaddr *ia;

		for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
			if (!memcmp(&ia->ia_addr.sin6_addr.s6_addr[8], 
			    ret, 8)) {
				badid = 1;
				break;
			}
		}
	}

	/*
	 * In the event that an unacceptable identifier has been generated,
	 * restart the process, using the right-most 64 bits of the MD5 digest
	 * obtained in place of the history value.
	 */
	if (badid) {
		/* for debugging purposes only */
#if 0
		{
			int i;

			printf("unacceptable random ID: ");
			for (i = 0; i < 16; i++)
				printf("%02x", digest[i]);
			printf("\n");
		}
#endif

		if (++retry < GEN_TEMPID_RETRY_MAX) {
			memcpy(seed, &digest[8], 8);
			goto again;
		} else {
			/*
			 * We're so unlucky.  Give up for now, and return
			 * all 0 IDs to tell the caller not to make a
			 * temporary address.
			 */
			nd6log((LOG_NOTICE,
			    "generate_tmp_ifid: never found a good ID\n"));
			memset(ret, 0, 8);
		}
	}

	/*
	 * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.2.1. (6)
	 * Take the rightmost 64-bits of the MD5 digest and save them in
	 * stable storage as the history value to be used in the next
	 * iteration of the algorithm.
	 */
	memcpy(seed0, &digest[8], 8);

	/* for debugging purposes only */
#if 0
	{
		int i;

		printf("to: ");
		for (i = 0; i < 16; i++)
			printf("%02x", digest[i]);
		printf("\n");
	}
#endif

	return 0;
}