Make OSSL_TIME a structure
authorPauli <pauli@openssl.org>
Wed, 27 Jul 2022 01:52:17 +0000 (11:52 +1000)
committerMatt Caswell <matt@openssl.org>
Fri, 12 Aug 2022 14:44:01 +0000 (15:44 +0100)
This prevents misuses creeping in.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18882)

doc/internal/man3/OSSL_TIME.pod
include/internal/time.h
ssl/event_queue.c
ssl/quic/quic_wire.c
ssl/time.c
test/event_queue_test.c
test/quic_wire_test.c

index c7091d083287e9903747e7b49d1d80979e78f5e6..81dad2e0d9803fa323077ad1ac98bb2c97f8f038 100644 (file)
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-OSSL_TIME, OSSL_TIME_SECOND, OSSL_TIME_INFINITY,
+OSSL_TIME, OSSL_TIME_SECOND, ossl_time_infinite, ossl_time_zero,
+ossl_ticks2time, ossl_time2ticks,
 ossl_time_now, ossl_time_time_to_timeval, ossl_time_compare,
 ossl_time_add, ossl_time_subtract
 - times and durations
@@ -11,12 +12,17 @@ ossl_time_add, ossl_time_subtract
 
  #include "internal/time.h"
 
- typedef uint64_t OSSL_TIME;
+ typedef struct OSSL_TIME;
 
- #define OSSL_TIME_SECOND
- #define OSSL_TIME_INFINITY
+ #define OSSL_TIME_SECOND   /* Ticks per second */
 
+ OSSL_TIME ossl_ticks2time(uint64_t);
+ uint64_t ossl_time2ticks(OSSL_TIME t);
+
+ OSSL_TIME ossl_time_zero(void);
+ OSSL_TIME ossl_time_infinite(void);
  OSSL_TIME ossl_time_now(void);
+
  void ossl_time_time_to_timeval(OSSL_TIME t, struct timeval *out);
 
  int ossl_time_compare(OSSL_TIME a, OSSL_TIME b);
@@ -40,8 +46,16 @@ B<OSSL_TIME>.  Specifically, it is the number of counts per second that
 a time can represent.  The accuracy is independent of this and is system
 dependent.
 
-B<OSSL_TIME_INFINITY> is the largest representable B<OSSL_TIME>.  This value
-is returned when an overflow would otherwise occur.
+B<ossl_ticks2time> converts an integral number of counts to a time.
+
+B<ossl_time2ticks> converts a time to an integral number of counts.
+
+B<ossl_time_zero> returns the smallest representable B<OSSL_TIME>.
+This value represents the time Epoch and it is returned when an underflow
+would otherwise occur.
+
+B<ossl_time_infinite> returns the largest representable B<OSSL_TIME>.
+This value is returned when an overflow would otherwise occur.
 
 B<ossl_time_now> returns the current time relative to an Epoch which
 is undefined but unchanging for at least the duration of program
@@ -70,15 +84,23 @@ The largest representable duration is guaranteed to be at least 500 years.
 
 =head1 RETURN VALUES
 
-B<ossl_time_now> returns the current time, or 0 on error.
+B<ossl_time_now> returns the current time, or the time of the Epoch on error.
+
+B<ossl_time_zero> returns the time of the Epoch.
+
+B<ossl_time_infinite> returns the last representable time.
+
+B<ossl_ticks2time> return the duration specified.
+
+B<ossl_time2ticks> returns the ticks since Epoch.
 
 B<ossl_time_compare> returns -1, 0 or 1 depending on the comparison.
 
 B<ossl_time_add> returns the summation of the two times or
-B<OSSL_TIME_INFINITY> on overflow.
+the last representable time on overflow.
 
 B<ossl_time_subtract> returns the difference of the two times or the
-0 on underflow.
+time of the Epoch on underflow.
 
 =head1 HISTORY
 
index b4a67fb998e5c8f606cb41abf84722f5ee44f17b..50f50822a882bffbb80046185587444577bbeadc 100644 (file)
 # include "internal/e_os.h"     /* for struct timeval */
 # include "internal/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 microsecond. */
 # define OSSL_TIME_US     (OSSL_TIME_MS     / 1000)
 
-/* Macro representing the most distant future time */
-# define OSSL_TIME_INFINITY (~(OSSL_TIME)0)
-
-/* Macro that's guaranteed to be now or before */
-# define OSSL_TIME_IMMEDIATE    0
+/* Convert a tick count into a time */
+static ossl_unused ossl_inline OSSL_TIME ossl_ticks2time(uint64_t ticks)
+{
+    OSSL_TIME r;
 
-/* Macro representing the zero value */
-# define OSSL_TIME_ZERO         0
+    r.t = ticks;
+    return r;
+}
 
-/*
- * Internal type defining a time.
- * The time datum is Unix's 1970 and at nanosecond precision, this gives
- * a range of 584 years roughly.
- */
-typedef uint64_t OSSL_TIME;
+/* 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
 void ossl_time_time_to_timeval(OSSL_TIME t, struct timeval *out)
 {
 #ifdef _WIN32
-    out->tv_sec = (long int)(t / OSSL_TIME_SECOND);
+    out->tv_sec = (long int)(t.t / OSSL_TIME_SECOND);
 #else
-    out->tv_sec = (time_t)(t / OSSL_TIME_SECOND);
+    out->tv_sec = (time_t)(t.t / OSSL_TIME_SECOND);
 #endif
-    out->tv_usec = (t % OSSL_TIME_SECOND) / (OSSL_TIME_SECOND / 1000000);
+    out->tv_usec = (t.t % OSSL_TIME_SECOND) / (OSSL_TIME_SECOND / 1000000);
 }
 
 /* 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 > b)
+    if (a.t > b.t)
         return 1;
-    if (a < b)
+    if (a.t < b.t)
         return -1;
     return 0;
 }
@@ -71,7 +93,7 @@ int ossl_time_compare(OSSL_TIME a, OSSL_TIME b)
  * These operations are saturating, in that an overflow or underflow returns
  * the largest or smallest value respectively.
  */
-OSSL_SAFE_MATH_UNSIGNED(time, OSSL_TIME)
+OSSL_SAFE_MATH_UNSIGNED(time, uint64_t)
 
 static ossl_unused ossl_inline
 OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b)
@@ -79,8 +101,8 @@ OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b)
     OSSL_TIME r;
     int err = 0;
 
-    r = safe_add_time(a, b, &err);
-    return err ? OSSL_TIME_INFINITY : r;
+    r.t = safe_add_time(a.t, b.t, &err);
+    return err ? ossl_time_infinite() : r;
 }
 
 static ossl_unused ossl_inline
@@ -89,15 +111,16 @@ OSSL_TIME ossl_time_subtract(OSSL_TIME a, OSSL_TIME b)
     OSSL_TIME r;
     int err = 0;
 
-    r = safe_sub_time(a, b, &err);
-    return err ? 0 : r;
+    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 > b ? ossl_time_subtract(a, b) : ossl_time_subtract(b, a);
+    return a.t > b.t ? ossl_time_subtract(a, b)
+                     : ossl_time_subtract(b, a);
 }
 
 static ossl_unused ossl_inline
@@ -106,8 +129,8 @@ OSSL_TIME ossl_time_multiply(OSSL_TIME a, uint64_t b)
     OSSL_TIME r;
     int err = 0;
 
-    r = safe_mul_time(a, b, &err);
-    return err ? OSSL_TIME_INFINITY : r;
+    r.t = safe_mul_time(a.t, b, &err);
+    return err ? ossl_time_infinite() : r;
 }
 
 static ossl_unused ossl_inline
@@ -116,22 +139,22 @@ OSSL_TIME ossl_time_divide(OSSL_TIME a, uint64_t b)
     OSSL_TIME r;
     int err = 0;
 
-    r = safe_div_time(a, b, &err);
-    return err ? 0 : r;
+    r.t = safe_div_time(a.t, b, &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 > b ? a : 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 < b ? a : b;
+    return a.t < b.t ? a : b;
 }
 
 #endif
index f828d5280fba916caee57c2d383f13b77e118f82..ed3c7909047cf2318af89440777930ef3f6c4e36 100644 (file)
@@ -145,16 +145,16 @@ int ossl_event_queue_remove(OSSL_EVENT_QUEUE *queue, OSSL_EVENT *event)
 OSSL_TIME ossl_event_time_until(const OSSL_EVENT *event)
 {
     if (event == NULL)
-        return OSSL_TIME_INFINITY;
+        return ossl_time_infinite();
     return ossl_time_subtract(event->when, ossl_time_now());
 }
 
 OSSL_TIME ossl_event_queue_time_until_next(const OSSL_EVENT_QUEUE *queue)
 {
     if (queue == NULL)
-        return OSSL_TIME_INFINITY;
+        return ossl_time_infinite();
     if (ossl_pqueue_OSSL_EVENT_num(queue->now_events) > 0)
-        return OSSL_TIME_IMMEDIATE;
+        return ossl_time_zero();
     return ossl_event_time_until(ossl_pqueue_OSSL_EVENT_peek(queue->timed_events));
 }
 
index 0adb41ef590ecdf0054edcffa9973e15297e0016..a3a9b252faa0928852b73a7056ccffeae9653e10 100644 (file)
@@ -48,13 +48,15 @@ int ossl_quic_wire_encode_frame_ack(WPACKET *pkt,
 
     uint64_t largest_ackd, first_ack_range, ack_delay_enc;
     size_t i, num_ack_ranges = ack->num_ack_ranges;
+    OSSL_TIME delay;
 
     if (num_ack_ranges == 0)
         return 0;
 
-    ack_delay_enc   = ossl_time_divide(ossl_time_divide(ack->delay_time,
-                                                        OSSL_TIME_US),
-                                       1UL << ack_delay_exponent);
+    delay = ossl_time_divide(ossl_time_divide(ack->delay_time, OSSL_TIME_US),
+                             1UL << ack_delay_exponent);
+    ack_delay_enc   = ossl_time2ticks(delay);
+
     largest_ackd    = ack->ack_ranges[0].end;
     first_ack_range = ack->ack_ranges[0].end - ack->ack_ranges[0].start;
 
@@ -443,12 +445,12 @@ int ossl_quic_wire_decode_frame_ack(PACKET *pkt,
     if (ack != NULL) {
         int err = 0;
         ack->delay_time
-            = ossl_time_multiply(OSSL_TIME_US,
+            = ossl_time_multiply(ossl_ticks2time(OSSL_TIME_US),
                                  safe_mul_uint64_t(ack_delay_raw,
                                                    1UL << ack_delay_exponent,
                                                    &err));
         if (err)
-            ack->delay_time = OSSL_TIME_INFINITY;
+            ack->delay_time = ossl_time_infinite();
 
         if (ack->num_ack_ranges > 0) {
             ack->ack_ranges[0].end   = largest_ackd;
index ecdd6ea8cb0c4a41b769322139cc3fd3e5bde230..a1b9dc7534d1216ae24022f65bd1cb855e9d4dc4 100644 (file)
@@ -13,6 +13,8 @@
 
 OSSL_TIME ossl_time_now(void)
 {
+    OSSL_TIME r;
+
 #if defined(_WIN32)
     SYSTEMTIME st;
     union {
@@ -28,19 +30,20 @@ OSSL_TIME ossl_time_now(void)
 # else
     now.ul -= 116444736000000000UI64;
 # endif
-    return ((uint64_t)now.ul) * (OSSL_TIME_SECOND / 10000000);
+    r.t = ((uint64_t)now.ul) * (OSSL_TIME_SECOND / 10000000);
 #else
     struct timeval t;
 
     if (gettimeofday(&t, NULL) < 0) {
         ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
                        "calling gettimeofday()");
-        return 0;
+        return ossl_time_zero();
     }
     if (t.tv_sec <= 0)
-        return t.tv_usec <= 0 ? 0 : t.tv_usec * (OSSL_TIME_SECOND / 1000000);
-    return ((uint64_t)t.tv_sec * 1000000 + t.tv_usec)
-           * (OSSL_TIME_SECOND / 1000000);
+        r.t = t.tv_usec <= 0 ? 0 : t.tv_usec * (OSSL_TIME_SECOND / 1000000);
+    else
+        r.t = ((uint64_t)t.tv_sec * 1000000 + t.tv_usec)
+              * (OSSL_TIME_SECOND / 1000000);
 #endif
+    return r;
 }
-
index 76765c5ba177c8215b6bfb29d96bd0e1bdc81e0f..686233c930b27bcc085a081af9b0aaf89c59d1a0 100644 (file)
@@ -11,7 +11,7 @@
 #include "internal/nelem.h"
 #include "testutil.h"
 
-static OSSL_TIME cur_time = 100;
+static OSSL_TIME cur_time = { 100 };
 
 OSSL_TIME ossl_time_now(void)
 {
@@ -31,38 +31,49 @@ static int event_test(void)
 
     /* Create an event queue and add some events */
     if (!TEST_ptr(q = ossl_event_queue_new())
-            || !TEST_ptr(e1 = ossl_event_queue_add_new(q, 1, 10, 1100, "ctx 1",
+            || !TEST_ptr(e1 = ossl_event_queue_add_new(q, 1, 10,
+                                                       ossl_ticks2time(1100),
+                                                       "ctx 1",
                                                        PAYLOAD(payload)))
-            || !TEST_ptr(e2 = ossl_event_queue_add_new(q, 2, 5, 1100, "ctx 2",
+            || !TEST_ptr(e2 = ossl_event_queue_add_new(q, 2, 5,
+                                                       ossl_ticks2time(1100),
+                                                       "ctx 2",
                                                        PAYLOAD("data")))
-            || !TEST_true(ossl_event_queue_add(q, &e3, 3, 20, 1200, "ctx 3",
+            || !TEST_true(ossl_event_queue_add(q, &e3, 3, 20,
+                                               ossl_ticks2time(1200), "ctx 3",
                                                PAYLOAD("more data")))
-            || !TEST_ptr(e4 = ossl_event_queue_add_new(q, 2, 5, 1150, "ctx 2",
+            || !TEST_ptr(e4 = ossl_event_queue_add_new(q, 2, 5,
+                                                       ossl_ticks2time(1150),
+                                                       "ctx 2",
                                                        PAYLOAD("data")))
 
             /* Verify some event details */
             || !TEST_uint_eq(ossl_event_get_type(e1), 1)
             || !TEST_uint_eq(ossl_event_get_priority(e1), 10)
-            || !TEST_uint64_t_eq(ossl_event_get_when(e1), 1100)
+            || !TEST_uint64_t_eq(ossl_time2ticks(ossl_event_get_when(e1))
+                                 , 1100)
             || !TEST_str_eq(ossl_event_get0_ctx(e1), "ctx 1")
             || !TEST_ptr(p = ossl_event_get0_payload(e1, &len))
             || !TEST_str_eq((char *)p, payload)
-            || !TEST_uint64_t_eq(ossl_event_time_until(&e3), 1100)
-            || !TEST_uint64_t_eq(ossl_event_queue_time_until_next(q), 1000)
+            || !TEST_uint64_t_eq(ossl_time2ticks(ossl_event_time_until(&e3)),
+                                 1100)
+            || !TEST_uint64_t_eq(ossl_time2ticks(ossl_event_queue_time_until_next(q)),
+                                 1000)
 
             /* Modify an event's time */
-            || !TEST_true(ossl_event_queue_postpone_until(q, e1, 1200))
-            || !TEST_uint64_t_eq(ossl_event_get_when(e1), 1200)
+            || !TEST_true(ossl_event_queue_postpone_until(q, e1,
+                                                          ossl_ticks2time(1200)))
+            || !TEST_uint64_t_eq(ossl_time2ticks(ossl_event_get_when(e1)), 1200)
             || !TEST_true(ossl_event_queue_remove(q, e4)))
         goto err;
     ossl_event_free(e4);
 
     /* Execute the queue */
-    cur_time = 1000;
+    cur_time = ossl_ticks2time(1000);
     if (!TEST_true(ossl_event_queue_get1_next_event(q, &ep))
             || !TEST_ptr_null(ep))
         goto err;
-    cur_time = 1100;
+    cur_time = ossl_ticks2time(1100);
     if (!TEST_true(ossl_event_queue_get1_next_event(q, &ep))
             || !TEST_ptr_eq(ep, e2))
         goto err;
@@ -72,7 +83,7 @@ static int event_test(void)
             || !TEST_ptr_null(ep))
         goto err;
 
-    cur_time = 1250;
+    cur_time = ossl_ticks2time(1250);
     if (!TEST_true(ossl_event_queue_get1_next_event(q, &ep))
             || !TEST_ptr_eq(ep, &e3))
         goto err;
index 55d18aa27cc7b1aaf26ee3deca3eaaea7f774b37..10c7835e0cf1982f7f37ba73216de0bfa609e45a 100644 (file)
@@ -80,7 +80,7 @@ static const OSSL_QUIC_ACK_RANGE encode_case_3_ranges[] = {
 static const OSSL_QUIC_FRAME_ACK encode_case_3_f = {
     (OSSL_QUIC_ACK_RANGE *)encode_case_3_ranges,
     OSSL_NELEM(encode_case_3_ranges),
-    OSSL_TIME_MS,
+    { OSSL_TIME_MS },
     60, 70, 80, 1
 };
 
@@ -123,7 +123,8 @@ static int encode_case_3_dec(PACKET *pkt, ossl_ssize_t fail)
                      encode_case_3_f.num_ack_ranges * sizeof(OSSL_QUIC_ACK_RANGE)))
         return 0;
 
-    if (!TEST_uint64_t_eq(f.delay_time, encode_case_3_f.delay_time))
+    if (!TEST_uint64_t_eq(ossl_time2ticks(f.delay_time),
+                          ossl_time2ticks(encode_case_3_f.delay_time)))
         return 0;
 
     if (!TEST_true(f.ecn_present))