/* 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]; }
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; }
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; }
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"); }
/* * 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; } }
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; }
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); }
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; }