summaryrefslogtreecommitdiff
path: root/usr.sbin/unbound/util
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2023-09-05 11:07:50 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2023-09-05 11:07:50 +0000
commit65023e51352b4beeaa4af0238ec090b306289d66 (patch)
treed3f6a24b3382284c9bf89a5f93f5ff76d6666e02 /usr.sbin/unbound/util
parentc1b43d4e7957a063ae5ffed673d4ba1ecf2dbb6d (diff)
import unbound 1.18.0, ok florian
Diffstat (limited to 'usr.sbin/unbound/util')
-rw-r--r--usr.sbin/unbound/util/data/msgencode.h42
-rw-r--r--usr.sbin/unbound/util/edns.c59
-rw-r--r--usr.sbin/unbound/util/edns.h59
-rw-r--r--usr.sbin/unbound/util/regional.c2
-rw-r--r--usr.sbin/unbound/util/rfc_1982.c74
-rw-r--r--usr.sbin/unbound/util/rfc_1982.h63
-rw-r--r--usr.sbin/unbound/util/siphash.c187
-rw-r--r--usr.sbin/unbound/util/siphash.h43
-rw-r--r--usr.sbin/unbound/util/timeval_func.c113
-rw-r--r--usr.sbin/unbound/util/timeval_func.h53
10 files changed, 692 insertions, 3 deletions
diff --git a/usr.sbin/unbound/util/data/msgencode.h b/usr.sbin/unbound/util/data/msgencode.h
index 30dc515cbe5..6aff06099ee 100644
--- a/usr.sbin/unbound/util/data/msgencode.h
+++ b/usr.sbin/unbound/util/data/msgencode.h
@@ -109,6 +109,27 @@ void qinfo_query_encode(struct sldns_buffer* pkt, struct query_info* qinfo);
uint16_t calc_edns_field_size(struct edns_data* edns);
/**
+ * Calculate the size of a specific EDNS option in packet.
+ * @param edns: edns data or NULL.
+ * @param code: the opt code to get the size of.
+ * @return octets the option will take up.
+ */
+uint16_t calc_edns_option_size(struct edns_data* edns, uint16_t code);
+
+/**
+ * Calculate the size of the EDE option(s) in packet. Also calculate seperately
+ * the size of the EXTRA-TEXT field(s) in case we can trim them to fit.
+ * In this case include any LDNS_EDE_OTHER options in their entirety since they
+ * are useless without extra text.
+ * @param edns: edns data or NULL.
+ * @param txt_size: the size of the EXTRA-TEXT field(s); this includes
+ * LDNS_EDE_OTHER in their entirety since they are useless without
+ * extra text.
+ * @return octets the option will take up.
+ */
+uint16_t calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size);
+
+/**
* Attach EDNS record to buffer. Buffer has complete packet. There must
* be enough room left for the EDNS record.
* @param pkt: packet added to.
@@ -116,11 +137,11 @@ uint16_t calc_edns_field_size(struct edns_data* edns);
*/
void attach_edns_record(struct sldns_buffer* pkt, struct edns_data* edns);
-/**
+/**
* Encode an error. With QR and RA set.
*
* @param pkt: where to store the packet.
- * @param r: RCODE value to encode.
+ * @param r: RCODE value to encode (may contain extra flags).
* @param qinfo: if not NULL, the query is included.
* @param qid: query ID to set in packet. network order.
* @param qflags: original query flags (to copy RD and CD bits). host order.
@@ -130,4 +151,21 @@ void attach_edns_record(struct sldns_buffer* pkt, struct edns_data* edns);
void error_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
uint16_t qid, uint16_t qflags, struct edns_data* edns);
+/**
+ * Encode an extended error. With QR and RA set.
+ *
+ * @param pkt: where to store the packet.
+ * @param rcode: Extended RCODE value to encode.
+ * @param qinfo: if not NULL, the query is included.
+ * @param qid: query ID to set in packet. network order.
+ * @param qflags: original query flags (to copy RD and CD bits). host order.
+ * @param xflags: extra flags to set (such as for example BIT_AA and/or BIT_TC)
+ * @param edns: if not NULL, this is the query edns info,
+ * and an edns reply is attached. Only attached if EDNS record fits reply.
+ * Without edns extended errors (i.e. > 15) will not be conveyed.
+ */
+void extended_error_encode(struct sldns_buffer* pkt, uint16_t rcode,
+ struct query_info* qinfo, uint16_t qid, uint16_t qflags,
+ uint16_t xflags, struct edns_data* edns);
+
#endif /* UTIL_DATA_MSGENCODE_H */
diff --git a/usr.sbin/unbound/util/edns.c b/usr.sbin/unbound/util/edns.c
index f55dcb97e75..2b4047f0b60 100644
--- a/usr.sbin/unbound/util/edns.c
+++ b/usr.sbin/unbound/util/edns.c
@@ -45,8 +45,11 @@
#include "util/netevent.h"
#include "util/net_help.h"
#include "util/regional.h"
+#include "util/rfc_1982.h"
+#include "util/siphash.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
+#include "sldns/sbuffer.h"
struct edns_strings* edns_strings_create(void)
{
@@ -128,3 +131,59 @@ edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen);
}
+uint8_t*
+edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret, int v4,
+ uint8_t* hash)
+{
+ v4?siphash(in, 20, secret, hash, 8):siphash(in, 32, secret, hash, 8);
+ return hash;
+}
+
+void
+edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4,
+ uint32_t timestamp)
+{
+ uint8_t hash[8];
+ buf[ 8] = 1; /* Version */
+ buf[ 9] = 0; /* Reserved */
+ buf[10] = 0; /* Reserved */
+ buf[11] = 0; /* Reserved */
+ sldns_write_uint32(buf + 12, timestamp);
+ (void)edns_cookie_server_hash(buf, secret, v4, hash);
+ memcpy(buf + 16, hash, 8);
+}
+
+enum edns_cookie_val_status
+edns_cookie_server_validate(const uint8_t* cookie, size_t cookie_len,
+ const uint8_t* secret, size_t secret_len, int v4,
+ const uint8_t* hash_input, uint32_t now)
+{
+ uint8_t hash[8];
+ uint32_t timestamp;
+ uint32_t subt_1982 = 0; /* Initialize for the compiler; unused value */
+ int comp_1982;
+ if(cookie_len != 24)
+ /* RFC9018 cookies are 24 bytes long */
+ return COOKIE_STATUS_CLIENT_ONLY;
+ if(secret_len != 16 || /* RFC9018 cookies have 16 byte secrets */
+ cookie[8] != 1) /* RFC9018 cookies are cookie version 1 */
+ return COOKIE_STATUS_INVALID;
+ timestamp = sldns_read_uint32(cookie + 12);
+ if((comp_1982 = compare_1982(now, timestamp)) > 0
+ && (subt_1982 = subtract_1982(timestamp, now)) > 3600)
+ /* Cookie is older than 1 hour (see RFC9018 Section 4.3.) */
+ return COOKIE_STATUS_EXPIRED;
+ if(comp_1982 <= 0 && subtract_1982(now, timestamp) > 300)
+ /* Cookie time is more than 5 minutes in the future.
+ * (see RFC9018 Section 4.3.) */
+ return COOKIE_STATUS_FUTURE;
+ if(memcmp(edns_cookie_server_hash(hash_input, secret, v4, hash),
+ cookie + 16, 8) != 0)
+ /* Hashes do not match */
+ return COOKIE_STATUS_INVALID;
+ if(comp_1982 > 0 && subt_1982 > 1800)
+ /* Valid cookie but older than 30 minutes, so create a new one
+ * anyway */
+ return COOKIE_STATUS_VALID_RENEW;
+ return COOKIE_STATUS_VALID;
+}
diff --git a/usr.sbin/unbound/util/edns.h b/usr.sbin/unbound/util/edns.h
index d9ded0b84dc..5da0ecb290a 100644
--- a/usr.sbin/unbound/util/edns.h
+++ b/usr.sbin/unbound/util/edns.h
@@ -75,6 +75,15 @@ struct edns_string_addr {
size_t string_len;
};
+enum edns_cookie_val_status {
+ COOKIE_STATUS_CLIENT_ONLY = -3,
+ COOKIE_STATUS_FUTURE = -2,
+ COOKIE_STATUS_EXPIRED = -1,
+ COOKIE_STATUS_INVALID = 0,
+ COOKIE_STATUS_VALID = 1,
+ COOKIE_STATUS_VALID_RENEW = 2,
+};
+
/**
* Create structure to hold EDNS strings
* @return: newly created edns_strings, NULL on alloc failure.
@@ -106,4 +115,54 @@ struct edns_string_addr*
edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
socklen_t addrlen);
+/**
+ * Compute the interoperable DNS cookie (RFC9018) hash.
+ * @param in: buffer input for the hash generation. It needs to be:
+ * Client Cookie | Version | Reserved | Timestamp | Client-IP
+ * @param secret: the server secret; implicit length of 16 octets.
+ * @param v4: if the client IP is v4 or v6.
+ * @param hash: buffer to write the hash to.
+ * return a pointer to the hash.
+ */
+uint8_t* edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret,
+ int v4, uint8_t* hash);
+
+/**
+ * Write an interoperable DNS server cookie (RFC9018).
+ * @param buf: buffer to write to. It should have a size of at least 32 octets
+ * as it doubles as the output buffer and the hash input buffer.
+ * The first 8 octets are expected to be the Client Cookie and will be
+ * left untouched.
+ * The next 8 octets will be written with Version | Reserved | Timestamp.
+ * The next 4 or 16 octets are expected to be the IPv4 or the IPv6 address
+ * based on the v4 flag.
+ * Thus the first 20 or 32 octets, based on the v4 flag, will be used as
+ * the hash input.
+ * The server hash (8 octets) will be written after the first 16 octets;
+ * overwriting the address information.
+ * The caller expects a complete, 24 octet long cookie in the buffer.
+ * @param secret: the server secret; implicit length of 16 octets.
+ * @param v4: if the client IP is v4 or v6.
+ * @param timestamp: the timestamp to use.
+ */
+void edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4,
+ uint32_t timestamp);
+
+/**
+ * Validate an interoperable DNS cookie (RFC9018).
+ * @param cookie: pointer to the cookie data.
+ * @param cookie_len: the length of the cookie data.
+ * @param secret: pointer to the server secret.
+ * @param secret_len: the length of the secret.
+ * @param v4: if the client IP is v4 or v6.
+ * @param hash_input: pointer to the hash input for validation. It needs to be:
+ * Client Cookie | Version | Reserved | Timestamp | Client-IP
+ * @param now: the current time.
+ * return edns_cookie_val_status with the cookie validation status i.e.,
+ * <=0 for invalid, else valid.
+ */
+enum edns_cookie_val_status edns_cookie_server_validate(const uint8_t* cookie,
+ size_t cookie_len, const uint8_t* secret, size_t secret_len, int v4,
+ const uint8_t* hash_input, uint32_t now);
+
#endif
diff --git a/usr.sbin/unbound/util/regional.c b/usr.sbin/unbound/util/regional.c
index 93e911c5ec1..44aee68b202 100644
--- a/usr.sbin/unbound/util/regional.c
+++ b/usr.sbin/unbound/util/regional.c
@@ -186,7 +186,7 @@ regional_alloc_init(struct regional* r, const void *init, size_t size)
{
void *s = regional_alloc(r, size);
if(!s) return NULL;
- memcpy(s, init, size);
+ memmove(s, init, size);
return s;
}
diff --git a/usr.sbin/unbound/util/rfc_1982.c b/usr.sbin/unbound/util/rfc_1982.c
new file mode 100644
index 00000000000..c28deded606
--- /dev/null
+++ b/usr.sbin/unbound/util/rfc_1982.c
@@ -0,0 +1,74 @@
+/*
+ * util/rfc_1982.c - RFC 1982 Serial Number Arithmetic
+ *
+ * Copyright (c) 2023, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions for RFC 1982 serial number arithmetic.
+ */
+#include "config.h"
+
+int
+compare_1982(uint32_t a, uint32_t b)
+{
+ /* for 32 bit values */
+ const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
+
+ if (a == b) {
+ return 0;
+ } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+uint32_t
+subtract_1982(uint32_t a, uint32_t b)
+{
+ /* for 32 bit values */
+ const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
+
+ if(a == b)
+ return 0;
+ if(a < b && b - a < cutoff) {
+ return b-a;
+ }
+ if(a > b && a - b > cutoff) {
+ return ((uint32_t)0xffffffff) - (a-b-1);
+ }
+ /* wrong case, b smaller than a */
+ return 0;
+}
diff --git a/usr.sbin/unbound/util/rfc_1982.h b/usr.sbin/unbound/util/rfc_1982.h
new file mode 100644
index 00000000000..bae383d0e01
--- /dev/null
+++ b/usr.sbin/unbound/util/rfc_1982.h
@@ -0,0 +1,63 @@
+/*
+ * util/rfc_1982.h - RFC 1982 Serial Number Arithmetic
+ *
+ * Copyright (c) 2023, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions for RFC 1982 serial number arithmetic.
+ */
+#ifndef RFC_1982_H
+#define RFC_1982_H
+
+/**
+ * RFC 1982 comparison, uses unsigned integers, and tries to avoid
+ * compiler optimization (eg. by avoiding a-b<0 comparisons).
+ * @param a: value to compare.
+ * @param b: value to compare.
+ * @return 0 if equal, 1 if a > b, else -1.
+ */
+int compare_1982(uint32_t a, uint32_t b);
+
+/**
+ * RFC 1982 subtraction, uses unsigned integers, and tries to avoid
+ * compiler optimization (eg. by avoiding a-b<0 comparisons).
+ * @param a: value to subtract from.
+ * @param b: value to subtract.
+ * @return the difference between them if we know that b is larger than a,
+ * that is the distance between them in serial number arithmetic.
+ */
+uint32_t subtract_1982(uint32_t a, uint32_t b);
+
+#endif /* RFC_1982_H */
diff --git a/usr.sbin/unbound/util/siphash.c b/usr.sbin/unbound/util/siphash.c
new file mode 100644
index 00000000000..0e1b597d052
--- /dev/null
+++ b/usr.sbin/unbound/util/siphash.c
@@ -0,0 +1,187 @@
+/*
+ SipHash reference C implementation
+
+ Copyright (c) 2012-2016 Jean-Philippe Aumasson
+ <jeanphilippe.aumasson@gmail.com>
+ Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ You should have received a copy of the CC0 Public Domain Dedication along
+ with
+ this software. If not, see
+ <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+/**
+ * Edited slightly for integration in Unbound. Edits are noted with 'EDIT'.
+ */
+/** EDIT
+ * \#include <assert.h>
+ * \#include <stdint.h>
+ * \#include <stdio.h>
+ * \#include <string.h>
+ * Replaced the above includes with Unbound's config.h
+ */
+#include "config.h"
+
+/* default: SipHash-2-4 */
+#define cROUNDS 2
+#define dROUNDS 4
+
+#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+
+#define U32TO8_LE(p, v) \
+ (p)[0] = (uint8_t)((v)); \
+ (p)[1] = (uint8_t)((v) >> 8); \
+ (p)[2] = (uint8_t)((v) >> 16); \
+ (p)[3] = (uint8_t)((v) >> 24);
+
+#define U64TO8_LE(p, v) \
+ U32TO8_LE((p), (uint32_t)((v))); \
+ U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+
+#define U8TO64_LE(p) \
+ (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
+ ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
+ ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
+ ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
+
+#define SIPROUND \
+ do { \
+ v0 += v1; \
+ v1 = ROTL(v1, 13); \
+ v1 ^= v0; \
+ v0 = ROTL(v0, 32); \
+ v2 += v3; \
+ v3 = ROTL(v3, 16); \
+ v3 ^= v2; \
+ v0 += v3; \
+ v3 = ROTL(v3, 21); \
+ v3 ^= v0; \
+ v2 += v1; \
+ v1 = ROTL(v1, 17); \
+ v1 ^= v2; \
+ v2 = ROTL(v2, 32); \
+ } while (0)
+
+#ifdef DEBUG
+#define TRACE \
+ do { \
+ printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32), \
+ (uint32_t)v0); \
+ printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32), \
+ (uint32_t)v1); \
+ printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32), \
+ (uint32_t)v2); \
+ printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32), \
+ (uint32_t)v3); \
+ } while (0)
+#else
+#define TRACE
+#endif
+
+int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
+ uint8_t *out, const size_t outlen) {
+
+ uint64_t v0 = 0x736f6d6570736575ULL;
+ uint64_t v1 = 0x646f72616e646f6dULL;
+ uint64_t v2 = 0x6c7967656e657261ULL;
+ uint64_t v3 = 0x7465646279746573ULL;
+ uint64_t k0 = U8TO64_LE(k);
+ uint64_t k1 = U8TO64_LE(k + 8);
+ uint64_t m;
+ int i;
+ const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
+ const int left = inlen & 7;
+ uint64_t b = ((uint64_t)inlen) << 56;
+ /** EDIT
+ * The following assert moved here from the top for C90 compliance.
+ */
+ assert((outlen == 8) || (outlen == 16));
+ v3 ^= k1;
+ v2 ^= k0;
+ v1 ^= k1;
+ v0 ^= k0;
+
+ if (outlen == 16)
+ v1 ^= 0xee;
+
+ for (; in != end; in += 8) {
+ m = U8TO64_LE(in);
+ v3 ^= m;
+
+ TRACE;
+ for (i = 0; i < cROUNDS; ++i)
+ SIPROUND;
+
+ v0 ^= m;
+ }
+
+ switch (left) {
+ case 7:
+ b |= ((uint64_t)in[6]) << 48;
+ /** EDIT annotate case statement fallthrough for gcc */
+ /* fallthrough */
+ case 6:
+ b |= ((uint64_t)in[5]) << 40;
+ /** EDIT annotate case statement fallthrough for gcc */
+ /* fallthrough */
+ case 5:
+ b |= ((uint64_t)in[4]) << 32;
+ /** EDIT annotate case statement fallthrough for gcc */
+ /* fallthrough */
+ case 4:
+ b |= ((uint64_t)in[3]) << 24;
+ /** EDIT annotate case statement fallthrough for gcc */
+ /* fallthrough */
+ case 3:
+ b |= ((uint64_t)in[2]) << 16;
+ /** EDIT annotate case statement fallthrough for gcc */
+ /* fallthrough */
+ case 2:
+ b |= ((uint64_t)in[1]) << 8;
+ /** EDIT annotate case statement fallthrough for gcc */
+ /* fallthrough */
+ case 1:
+ b |= ((uint64_t)in[0]);
+ break;
+ case 0:
+ break;
+ }
+
+ v3 ^= b;
+
+ TRACE;
+ for (i = 0; i < cROUNDS; ++i)
+ SIPROUND;
+
+ v0 ^= b;
+
+ if (outlen == 16)
+ v2 ^= 0xee;
+ else
+ v2 ^= 0xff;
+
+ TRACE;
+ for (i = 0; i < dROUNDS; ++i)
+ SIPROUND;
+
+ b = v0 ^ v1 ^ v2 ^ v3;
+ U64TO8_LE(out, b);
+
+ if (outlen == 8)
+ return 0;
+
+ v1 ^= 0xdd;
+
+ TRACE;
+ for (i = 0; i < dROUNDS; ++i)
+ SIPROUND;
+
+ b = v0 ^ v1 ^ v2 ^ v3;
+ U64TO8_LE(out + 8, b);
+
+ return 0;
+}
diff --git a/usr.sbin/unbound/util/siphash.h b/usr.sbin/unbound/util/siphash.h
new file mode 100644
index 00000000000..63da2175cab
--- /dev/null
+++ b/usr.sbin/unbound/util/siphash.h
@@ -0,0 +1,43 @@
+/*
+ * util/siphash.h - header for SipHash reference C implementation.
+ *
+ * Copyright (c) 2023, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * \file
+ * Contains the SipHash reference C implementation.
+ */
+#ifndef UTIL_SIPHASH_H
+#define UTIL_SIPHASH_H
+int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
+ uint8_t *out, const size_t outlen);
+#endif /* UTIL_SIPHASH_H */
diff --git a/usr.sbin/unbound/util/timeval_func.c b/usr.sbin/unbound/util/timeval_func.c
new file mode 100644
index 00000000000..90250e153d9
--- /dev/null
+++ b/usr.sbin/unbound/util/timeval_func.c
@@ -0,0 +1,113 @@
+/*
+ * util/timeval_func.c - helpers to work with struct timeval values.
+ *
+ * Copyright (c) 2023, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains helpers to manipulate struct timeval values.
+ */
+
+#include "config.h"
+#include "timeval_func.h"
+
+/** subtract timers and the values do not overflow or become negative */
+void
+timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start)
+{
+#ifndef S_SPLINT_S
+ time_t end_usec = end->tv_usec;
+ d->tv_sec = end->tv_sec - start->tv_sec;
+ if(end_usec < start->tv_usec) {
+ end_usec += 1000000;
+ d->tv_sec--;
+ }
+ d->tv_usec = end_usec - start->tv_usec;
+#endif
+}
+
+/** add timers and the values do not overflow or become negative */
+void
+timeval_add(struct timeval* d, const struct timeval* add)
+{
+#ifndef S_SPLINT_S
+ d->tv_sec += add->tv_sec;
+ d->tv_usec += add->tv_usec;
+ if(d->tv_usec >= 1000000 ) {
+ d->tv_usec -= 1000000;
+ d->tv_sec++;
+ }
+#endif
+}
+
+/** divide sum of timers to get average */
+void
+timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
+{
+#ifndef S_SPLINT_S
+ long long leftover;
+ if(d <= 0) {
+ avg->tv_sec = 0;
+ avg->tv_usec = 0;
+ return;
+ }
+ avg->tv_sec = sum->tv_sec / d;
+ avg->tv_usec = sum->tv_usec / d;
+ /* handle fraction from seconds divide */
+ leftover = sum->tv_sec - avg->tv_sec*d;
+ if(leftover <= 0)
+ leftover = 0;
+ avg->tv_usec += (((long long)leftover)*((long long)1000000))/d;
+ if(avg->tv_sec < 0)
+ avg->tv_sec = 0;
+ if(avg->tv_usec < 0)
+ avg->tv_usec = 0;
+#endif
+}
+
+/** histogram compare of time values */
+int
+timeval_smaller(const struct timeval* x, const struct timeval* y)
+{
+#ifndef S_SPLINT_S
+ if(x->tv_sec < y->tv_sec)
+ return 1;
+ else if(x->tv_sec == y->tv_sec) {
+ if(x->tv_usec <= y->tv_usec)
+ return 1;
+ else return 0;
+ }
+ else return 0;
+#endif
+}
diff --git a/usr.sbin/unbound/util/timeval_func.h b/usr.sbin/unbound/util/timeval_func.h
new file mode 100644
index 00000000000..819d1dd80fb
--- /dev/null
+++ b/usr.sbin/unbound/util/timeval_func.h
@@ -0,0 +1,53 @@
+/*
+ * util/timeval_func.h - definitions of helpers for struct timeval values.
+ *
+ * Copyright (c) 2023, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains definitions of helpers to manipulate struct timeval
+ * values, implemented in the corresponding C file.
+ */
+#include <sys/time.h>
+
+#ifndef timeval_isset
+#define timeval_isset(tv) ((tv)->tv_sec || (tv)->tv_usec)
+#endif
+#ifndef timeval_clear
+#define timeval_clear(tv) ((tv)->tv_sec = (tv)->tv_usec = 0)
+#endif
+void timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start);
+void timeval_add(struct timeval* d, const struct timeval* add);
+void timeval_divide(struct timeval* avg, const struct timeval* sum, long long d);
+int timeval_smaller(const struct timeval* x, const struct timeval* y);