/*
* Allocate and initialize a digest context. As a speed optimization,
* take an idea from ntpsec and cache the context to avoid malloc/free
* overhead in time-critical paths. ntpsec also caches the algorithms
* with each key.
* This is not thread-safe, but that is
* not a problem at present.
*/
static EVP_MD_CTX *
get_md_ctx(
int nid
)
{
#ifndef OPENSSL
static MD5_CTX md5_ctx;
static size_t
make_mac(
const rwbuffT * digest,
int ktype,
const robuffT * key,
const robuffT * msg
)
{
/*
* Compute digest of key concatenated with packet. Note: the
* key type and digest type have been verified when the key
* was created.
*/
size_t retlen = 0;
#ifdef OPENSSL
INIT_SSL();
/* Check if CMAC key type specific code required */
# ifdef ENABLE_CMAC
if (ktype == NID_cmac) {
CMAC_CTX * ctx = NULL;
void const * keyptr = key->buf;
u_char keybuf[AES_128_KEY_SIZE];
/*
* Calculate the reference id from the address. If it is an IPv4
* address, use it as is. If it is an IPv6 address, do a md5 on
* it and use the bottom 4 bytes.
* The result is in network byte order for IPv4 addreseses. For
* IPv6, ntpd long differed in the hash calculated on big-endian
* vs. little-endian because the first four bytes of the MD5 hash
* were used as a u_int32 without any byte swapping. This broke
* the refid-based loop detection between mixed-endian systems.
* In order to preserve behavior on the more-common little-endian
* systems, the hash is now byte-swapped on big-endian systems to
* match the little-endian hash. This is ugly but it seems better
* than changing the IPv6 refid calculation on the more-common
* systems.
* This is not thread safe, not a problem so far.
*/
u_int32
addr2refid(sockaddr_u *addr)
{
static MD5_CTX md5_ctx;
union u_tag {
u_char digest[MD5_DIGEST_LENGTH];
u_int32 addr_refid;
} u;
if (IS_IPV4(addr)) {
return (NSRCADR(addr));
}
/* MD5 is not used for authentication here. */
MD5Init(&md5_ctx);
MD5Update(&md5_ctx, (void *)&SOCK_ADDR6(addr), sizeof(SOCK_ADDR6(addr)));
MD5Final(u.digest, &md5_ctx);
#ifdef WORDS_BIGENDIAN
u.addr_refid = BYTESWAP32(u.addr_refid);
#endif
return u.addr_refid;
}