/** * Hash key. * * This is the trapping function we're installing for our hash set, which will * dereference the pointer field of the user's key within the value and hash it. */ static uint hikset_key_hash(const void *value, void *data) { hikset_t *hik = data; const void * const *key = value; hikset_check(hik); return NULL == hik->ihash ? binary_hash(*key, hik->uik.keysize) : (*hik->ihash)(*key); }
/** * Hashing of host_addr_t. */ unsigned host_addr_hash(host_addr_t ha) { switch (ha.net) { case NET_TYPE_IPV6: { host_addr_t ha_ipv4; if (!host_addr_convert(ha, &ha_ipv4, NET_TYPE_IPV4)) return binary_hash(&ha.addr.ipv6[0], sizeof ha.addr.ipv6); ha = ha_ipv4; } /* FALL THROUGH */ case NET_TYPE_IPV4: return ha.net ^ integer_hash(host_addr_ipv4(ha)); case NET_TYPE_LOCAL: case NET_TYPE_NONE: return ha.net; } g_assert_not_reached(); return (unsigned) -1; }
/** * Create a security token from host address and port using specified key. * * Optionally, extra contextual data may be given (i.e. the token is not * only based on the address and port) to make the token more unique to * a specific context. * * @param stg the security token generator * @param n key index to use * @param tok where security token is written * @param addr address of the host for which we're generating a token * @param port port of the host for which we're generating a token * @param data optional contextual data * @param len length of contextual data */ static void sectoken_generate_n(sectoken_gen_t *stg, size_t n, sectoken_t *tok, host_addr_t addr, uint16 port, const void *data, size_t len) { char block[8]; char enc[8]; char *p = block; sectoken_gen_check(stg); g_assert(tok != NULL); g_assert(size_is_non_negative(n)); g_assert(n < stg->keycnt); g_assert((NULL != data) == (len != 0)); switch (host_addr_net(addr)) { case NET_TYPE_IPV4: p = poke_be32(p, host_addr_ipv4(addr)); break; case NET_TYPE_IPV6: { uint val; val = binary_hash(host_addr_ipv6(&addr), 16); p = poke_be32(p, val); } break; case NET_TYPE_LOCAL: case NET_TYPE_NONE: g_error("unexpected address for security token generation: %s", host_addr_to_string(addr)); } p = poke_be16(p, port); p = poke_be16(p, 0); /* Filler */ g_assert(p == &block[8]); STATIC_ASSERT(sizeof(tok->v) == sizeof(uint32)); STATIC_ASSERT(sizeof(block) == sizeof(enc)); tea_encrypt(&stg->keys[n], enc, block, sizeof block); /* * If they gave contextual data, encrypt them by block of 8 bytes, * filling the last partial block with zeroes if needed. */ if (data != NULL) { const void *q = data; size_t remain = len; char denc[8]; STATIC_ASSERT(sizeof(denc) == sizeof(enc)); while (remain != 0) { size_t fill = MIN(remain, 8U); unsigned i; if (fill != 8U) ZERO(&block); memcpy(block, q, fill); remain -= fill; q = const_ptr_add_offset(q, fill); /* * Encrypt block of contextual data (possibly filled with trailing * zeroes) and merge back the result into the main encryption * output with XOR. */ tea_encrypt(&stg->keys[n], denc, block, sizeof block); for (i = 0; i < sizeof denc; i++) enc[i] ^= denc[i]; } } poke_be32(tok->v, tea_squeeze(enc, sizeof enc)); }
/** * Hash a KUID. */ unsigned kuid_hash(const void *key) { return binary_hash(key, KUID_RAW_SIZE); }