--- /dev/null
+/*
+ * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PERFLIB_SAFE_MATH_H
+# define OSSL_PERFLIB_SAFE_MATH_H
+# pragma once
+
+# include <stddef.h>
+# include <openssl/e_os2.h> /* For 'ossl_inline' */
+
+# ifndef OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING
+# ifdef __has_builtin
+# define has(func) __has_builtin(func)
+# elif __GNUC__ > 5
+# define has(func) 1
+# endif
+# endif /* OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING */
+
+# ifndef has
+# define has(func) 0
+# endif
+
+/*
+ * Safe addition helpers
+ */
+# if has(__builtin_add_overflow)
+# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ type r; \
+ \
+ if (!__builtin_add_overflow(a, b, &r)) \
+ return r; \
+ *err |= 1; \
+ return a < 0 ? min : max; \
+ }
+
+# define OSSL_SAFE_MATH_ADDU(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ type r; \
+ \
+ if (!__builtin_add_overflow(a, b, &r)) \
+ return r; \
+ *err |= 1; \
+ return a + b; \
+ }
+
+# else /* has(__builtin_add_overflow) */
+# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if ((a < 0) ^ (b < 0) \
+ || (a > 0 && b <= max - a) \
+ || (a < 0 && b >= min - a) \
+ || a == 0) \
+ return a + b; \
+ *err |= 1; \
+ return a < 0 ? min : max; \
+ }
+
+# define OSSL_SAFE_MATH_ADDU(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (b > max - a) \
+ *err |= 1; \
+ return a + b; \
+ }
+# endif /* has(__builtin_add_overflow) */
+
+/*
+ * Safe subtraction helpers
+ */
+# if has(__builtin_sub_overflow)
+# define OSSL_SAFE_MATH_SUBS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ type r; \
+ \
+ if (!__builtin_sub_overflow(a, b, &r)) \
+ return r; \
+ *err |= 1; \
+ return a < 0 ? min : max; \
+ }
+
+# else /* has(__builtin_sub_overflow) */
+# define OSSL_SAFE_MATH_SUBS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (!((a < 0) ^ (b < 0)) \
+ || (b > 0 && a >= min + b) \
+ || (b < 0 && a <= max + b) \
+ || b == 0) \
+ return a - b; \
+ *err |= 1; \
+ return a < 0 ? min : max; \
+ }
+
+# endif /* has(__builtin_sub_overflow) */
+
+# define OSSL_SAFE_MATH_SUBU(type_name, type) \
+ static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (b > a) \
+ *err |= 1; \
+ return a - b; \
+ }
+
+/*
+ * Safe multiplication helpers
+ */
+# if has(__builtin_mul_overflow)
+# define OSSL_SAFE_MATH_MULS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ type r; \
+ \
+ if (!__builtin_mul_overflow(a, b, &r)) \
+ return r; \
+ *err |= 1; \
+ return (a < 0) ^ (b < 0) ? min : max; \
+ }
+
+# define OSSL_SAFE_MATH_MULU(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ type r; \
+ \
+ if (!__builtin_mul_overflow(a, b, &r)) \
+ return r; \
+ *err |= 1; \
+ return a * b; \
+ }
+
+# else /* has(__builtin_mul_overflow) */
+# define OSSL_SAFE_MATH_MULS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (a == 0 || b == 0) \
+ return 0; \
+ if (a == 1) \
+ return b; \
+ if (b == 1) \
+ return a; \
+ if (a != min && b != min) { \
+ const type x = a < 0 ? -a : a; \
+ const type y = b < 0 ? -b : b; \
+ \
+ if (x <= max / y) \
+ return a * b; \
+ } \
+ *err |= 1; \
+ return (a < 0) ^ (b < 0) ? min : max; \
+ }
+
+# define OSSL_SAFE_MATH_MULU(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (b != 0 && a > max / b) \
+ *err |= 1; \
+ return a * b; \
+ }
+# endif /* has(__builtin_mul_overflow) */
+
+/*
+ * Safe division helpers
+ */
+# define OSSL_SAFE_MATH_DIVS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_div_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (b == 0) { \
+ *err |= 1; \
+ return a < 0 ? min : max; \
+ } \
+ if (b == -1 && a == min) { \
+ *err |= 1; \
+ return max; \
+ } \
+ return a / b; \
+ }
+
+# define OSSL_SAFE_MATH_DIVU(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_div_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (b != 0) \
+ return a / b; \
+ *err |= 1; \
+ return max; \
+ }
+
+/*
+ * Safe modulus helpers
+ */
+# define OSSL_SAFE_MATH_MODS(type_name, type, min, max) \
+ static ossl_inline ossl_unused type safe_mod_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (b == 0) { \
+ *err |= 1; \
+ return 0; \
+ } \
+ if (b == -1 && a == min) { \
+ *err |= 1; \
+ return max; \
+ } \
+ return a % b; \
+ }
+
+# define OSSL_SAFE_MATH_MODU(type_name, type) \
+ static ossl_inline ossl_unused type safe_mod_ ## type_name(type a, \
+ type b, \
+ int *err) \
+ { \
+ if (b != 0) \
+ return a % b; \
+ *err |= 1; \
+ return 0; \
+ }
+
+/*
+ * Safe negation helpers
+ */
+# define OSSL_SAFE_MATH_NEGS(type_name, type, min) \
+ static ossl_inline ossl_unused type safe_neg_ ## type_name(type a, \
+ int *err) \
+ { \
+ if (a != min) \
+ return -a; \
+ *err |= 1; \
+ return min; \
+ }
+
+# define OSSL_SAFE_MATH_NEGU(type_name, type) \
+ static ossl_inline ossl_unused type safe_neg_ ## type_name(type a, \
+ int *err) \
+ { \
+ if (a == 0) \
+ return a; \
+ *err |= 1; \
+ return 1 + ~a; \
+ }
+
+/*
+ * Safe absolute value helpers
+ */
+# define OSSL_SAFE_MATH_ABSS(type_name, type, min) \
+ static ossl_inline ossl_unused type safe_abs_ ## type_name(type a, \
+ int *err) \
+ { \
+ if (a != min) \
+ return a < 0 ? -a : a; \
+ *err |= 1; \
+ return min; \
+ }
+
+# define OSSL_SAFE_MATH_ABSU(type_name, type) \
+ static ossl_inline ossl_unused type safe_abs_ ## type_name(type a, \
+ int *err) \
+ { \
+ return a; \
+ }
+
+/*
+ * Safe fused multiply divide helpers
+ *
+ * These are a bit obscure:
+ * . They begin by checking the denominator for zero and getting rid of this
+ * corner case.
+ *
+ * . Second is an attempt to do the multiplication directly, if it doesn't
+ * overflow, the quotient is returned (for signed values there is a
+ * potential problem here which isn't present for unsigned).
+ *
+ * . Finally, the multiplication/division is transformed so that the larger
+ * of the numerators is divided first. This requires a remainder
+ * correction:
+ *
+ * a b / c = (a / c) b + (a mod c) b / c, where a > b
+ *
+ * The individual operations need to be overflow checked (again signed
+ * being more problematic).
+ *
+ * The algorithm used is not perfect but it should be "good enough".
+ */
+# define OSSL_SAFE_MATH_MULDIVS(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_muldiv_ ## type_name(type a, \
+ type b, \
+ type c, \
+ int *err) \
+ { \
+ int e2 = 0; \
+ type q, r, x, y; \
+ \
+ if (c == 0) { \
+ *err |= 1; \
+ return a == 0 || b == 0 ? 0 : max; \
+ } \
+ x = safe_mul_ ## type_name(a, b, &e2); \
+ if (!e2) \
+ return safe_div_ ## type_name(x, c, err); \
+ if (b > a) { \
+ x = b; \
+ b = a; \
+ a = x; \
+ } \
+ q = safe_div_ ## type_name(a, c, err); \
+ r = safe_mod_ ## type_name(a, c, err); \
+ x = safe_mul_ ## type_name(r, b, err); \
+ y = safe_mul_ ## type_name(q, b, err); \
+ q = safe_div_ ## type_name(x, c, err); \
+ return safe_add_ ## type_name(y, q, err); \
+ }
+
+# define OSSL_SAFE_MATH_MULDIVU(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_muldiv_ ## type_name(type a, \
+ type b, \
+ type c, \
+ int *err) \
+ { \
+ int e2 = 0; \
+ type x, y; \
+ \
+ if (c == 0) { \
+ *err |= 1; \
+ return a == 0 || b == 0 ? 0 : max; \
+ } \
+ x = safe_mul_ ## type_name(a, b, &e2); \
+ if (!e2) \
+ return x / c; \
+ if (b > a) { \
+ x = b; \
+ b = a; \
+ a = x; \
+ } \
+ x = safe_mul_ ## type_name(a % c, b, err); \
+ y = safe_mul_ ## type_name(a / c, b, err); \
+ return safe_add_ ## type_name(y, x / c, err); \
+ }
+
+/*
+ * Calculate a / b rounding up:
+ * i.e. a / b + (a % b != 0)
+ * Which is usually (less safely) converted to (a + b - 1) / b
+ * If you *know* that b != 0, then it's safe to ignore err.
+ */
+#define OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, max) \
+ static ossl_inline ossl_unused type safe_div_round_up_ ## type_name \
+ (type a, type b, int *errp) \
+ { \
+ type x; \
+ int *err, err_local = 0; \
+ \
+ /* Allow errors to be ignored by callers */ \
+ err = errp != NULL ? errp : &err_local; \
+ /* Fast path, both positive */ \
+ if (b > 0 && a > 0) { \
+ /* Faster path: no overflow concerns */ \
+ if (a < max - b) \
+ return (a + b - 1) / b; \
+ return a / b + (a % b != 0); \
+ } \
+ if (b == 0) { \
+ *err |= 1; \
+ return a == 0 ? 0 : max; \
+ } \
+ if (a == 0) \
+ return 0; \
+ /* Rather slow path because there are negatives involved */ \
+ x = safe_mod_ ## type_name(a, b, err); \
+ return safe_add_ ## type_name(safe_div_ ## type_name(a, b, err), \
+ x != 0, err); \
+ }
+
+/* Calculate ranges of types */
+# define OSSL_SAFE_MATH_MINS(type) ((type)1 << (sizeof(type) * 8 - 1))
+# define OSSL_SAFE_MATH_MAXS(type) (~OSSL_SAFE_MATH_MINS(type))
+# define OSSL_SAFE_MATH_MAXU(type) (~(type)0)
+
+/*
+ * Wrapper macros to create all the functions of a given type
+ */
+# define OSSL_SAFE_MATH_SIGNED(type_name, type) \
+ OSSL_SAFE_MATH_ADDS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
+ OSSL_SAFE_MATH_MAXS(type)) \
+ OSSL_SAFE_MATH_SUBS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
+ OSSL_SAFE_MATH_MAXS(type)) \
+ OSSL_SAFE_MATH_MULS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
+ OSSL_SAFE_MATH_MAXS(type)) \
+ OSSL_SAFE_MATH_DIVS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
+ OSSL_SAFE_MATH_MAXS(type)) \
+ OSSL_SAFE_MATH_MODS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
+ OSSL_SAFE_MATH_MAXS(type)) \
+ OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, \
+ OSSL_SAFE_MATH_MAXS(type)) \
+ OSSL_SAFE_MATH_MULDIVS(type_name, type, OSSL_SAFE_MATH_MAXS(type)) \
+ OSSL_SAFE_MATH_NEGS(type_name, type, OSSL_SAFE_MATH_MINS(type)) \
+ OSSL_SAFE_MATH_ABSS(type_name, type, OSSL_SAFE_MATH_MINS(type))
+
+# define OSSL_SAFE_MATH_UNSIGNED(type_name, type) \
+ OSSL_SAFE_MATH_ADDU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
+ OSSL_SAFE_MATH_SUBU(type_name, type) \
+ OSSL_SAFE_MATH_MULU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
+ OSSL_SAFE_MATH_DIVU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
+ OSSL_SAFE_MATH_MODU(type_name, type) \
+ OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, \
+ OSSL_SAFE_MATH_MAXU(type)) \
+ OSSL_SAFE_MATH_MULDIVU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
+ OSSL_SAFE_MATH_NEGU(type_name, type) \
+ OSSL_SAFE_MATH_ABSU(type_name, type)
+
+#endif /* OSSL_INTERNAL_SAFE_MATH_H */
--- /dev/null
+/*
+ * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PERFLIB_TIME_H
+# define OSSL_PERFLIB_TIME_H
+# pragma once
+
+# include <openssl/e_os2.h> /* uint64_t */
+# include "sys/time.h" /* TODO: Probably needs something else on Windows */
+# include "safe_math.h"
+
+/*
+ * Internal type defining a time.
+ * This should be treated as an opaque structure.
+ *
+ * The time datum is Unix's 1970 and at nanosecond precision, this gives
+ * a range of 584 years roughly.
+ */
+typedef struct {
+ uint64_t t; /* Ticks since the epoch */
+} OSSL_TIME;
+
+/* The precision of times allows this many values per second */
+# define OSSL_TIME_SECOND ((uint64_t)1000000000)
+
+/* One millisecond. */
+# define OSSL_TIME_MS (OSSL_TIME_SECOND / 1000)
+
+/* One microsecond. */
+# define OSSL_TIME_US (OSSL_TIME_MS / 1000)
+
+/* One nanosecond. */
+# define OSSL_TIME_NS (OSSL_TIME_US / 1000)
+
+#define ossl_seconds2time(s) ossl_ticks2time((s) * OSSL_TIME_SECOND)
+#define ossl_time2seconds(t) (ossl_time2ticks(t) / OSSL_TIME_SECOND)
+#define ossl_ms2time(ms) ossl_ticks2time((ms) * OSSL_TIME_MS)
+#define ossl_time2ms(t) (ossl_time2ticks(t) / OSSL_TIME_MS)
+#define ossl_us2time(us) ossl_ticks2time((us) * OSSL_TIME_US)
+#define ossl_time2us(t) (ossl_time2ticks(t) / OSSL_TIME_US)
+
+/* Convert a tick count into a time */
+static ossl_unused ossl_inline
+OSSL_TIME ossl_ticks2time(uint64_t ticks)
+{
+ OSSL_TIME r;
+
+ r.t = ticks;
+ return r;
+}
+
+/* Convert a time to a tick count */
+static ossl_unused ossl_inline
+uint64_t ossl_time2ticks(OSSL_TIME t)
+{
+ return t.t;
+}
+
+/* Get current time */
+OSSL_TIME ossl_time_now(void);
+
+/* The beginning and end of the time range */
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_zero(void)
+{
+ return ossl_ticks2time(0);
+}
+
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_infinite(void)
+{
+ return ossl_ticks2time(~(uint64_t)0);
+}
+
+
+/* Convert time to timeval */
+static ossl_unused ossl_inline
+struct timeval ossl_time_to_timeval(OSSL_TIME t)
+{
+ struct timeval tv;
+
+#ifdef _WIN32
+ tv.tv_sec = (long int)(t.t / OSSL_TIME_SECOND);
+#else
+ tv.tv_sec = (time_t)(t.t / OSSL_TIME_SECOND);
+#endif
+ tv.tv_usec = (t.t % OSSL_TIME_SECOND) / OSSL_TIME_US;
+ return tv;
+}
+
+/* Convert timeval to time */
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_from_timeval(struct timeval tv)
+{
+ OSSL_TIME t;
+
+#ifndef __DJGPP__ /* tv_sec is unsigned on djgpp. */
+ if (tv.tv_sec < 0)
+ return ossl_time_zero();
+#endif
+ t.t = tv.tv_sec * OSSL_TIME_SECOND + tv.tv_usec * OSSL_TIME_US;
+ return t;
+}
+
+/* Convert OSSL_TIME to time_t */
+static ossl_unused ossl_inline
+time_t ossl_time_to_time_t(OSSL_TIME t)
+{
+ return (time_t)(t.t / OSSL_TIME_SECOND);
+}
+
+/* Convert time_t to OSSL_TIME */
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_from_time_t(time_t t)
+{
+ OSSL_TIME ot;
+
+ ot.t = t;
+ ot.t *= OSSL_TIME_SECOND;
+ return ot;
+}
+
+/* Compare two time values, return -1 if less, 1 if greater and 0 if equal */
+static ossl_unused ossl_inline
+int ossl_time_compare(OSSL_TIME a, OSSL_TIME b)
+{
+ if (a.t > b.t)
+ return 1;
+ if (a.t < b.t)
+ return -1;
+ return 0;
+}
+
+/* Returns true if an OSSL_TIME is ossl_time_zero(). */
+static ossl_unused ossl_inline
+int ossl_time_is_zero(OSSL_TIME t)
+{
+ return ossl_time_compare(t, ossl_time_zero()) == 0;
+}
+
+/* Returns true if an OSSL_TIME is ossl_time_infinite(). */
+static ossl_unused ossl_inline
+int ossl_time_is_infinite(OSSL_TIME t)
+{
+ return ossl_time_compare(t, ossl_time_infinite()) == 0;
+}
+
+/*
+ * Arithmetic operations on times.
+ * These operations are saturating, in that an overflow or underflow returns
+ * the largest or smallest value respectively.
+ */
+OSSL_SAFE_MATH_UNSIGNED(time, uint64_t)
+
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b)
+{
+ OSSL_TIME r;
+ int err = 0;
+
+ r.t = safe_add_time(a.t, b.t, &err);
+ return err ? ossl_time_infinite() : r;
+}
+
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_subtract(OSSL_TIME a, OSSL_TIME b)
+{
+ OSSL_TIME r;
+ int err = 0;
+
+ r.t = safe_sub_time(a.t, b.t, &err);
+ return err ? ossl_time_zero() : r;
+}
+
+/* Returns |a - b|. */
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_abs_difference(OSSL_TIME a, OSSL_TIME b)
+{
+ return a.t > b.t ? ossl_time_subtract(a, b)
+ : ossl_time_subtract(b, a);
+}
+
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_multiply(OSSL_TIME a, uint64_t b)
+{
+ OSSL_TIME r;
+ int err = 0;
+
+ r.t = safe_mul_time(a.t, b, &err);
+ return err ? ossl_time_infinite() : r;
+}
+
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_divide(OSSL_TIME a, uint64_t b)
+{
+ OSSL_TIME r;
+ int err = 0;
+
+ r.t = safe_div_time(a.t, b, &err);
+ return err ? ossl_time_zero() : r;
+}
+
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_muldiv(OSSL_TIME a, uint64_t b, uint64_t c)
+{
+ OSSL_TIME r;
+ int err = 0;
+
+ r.t = safe_muldiv_time(a.t, b, c, &err);
+ return err ? ossl_time_zero() : r;
+}
+
+/* Return higher of the two given time values. */
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_max(OSSL_TIME a, OSSL_TIME b)
+{
+ return a.t > b.t ? a : b;
+}
+
+/* Return the lower of the two given time values. */
+static ossl_unused ossl_inline
+OSSL_TIME ossl_time_min(OSSL_TIME a, OSSL_TIME b)
+{
+ return a.t < b.t ? a : b;
+}
+
+#endif