1 /*
2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #ifndef OSSL_INTERNAL_TIME_H
11 # define OSSL_INTERNAL_TIME_H
12 # pragma once
13
14 # include <openssl/e_os2.h> /* uint64_t */
15 # include "internal/e_os.h" /* for struct timeval */
16 # include "internal/safe_math.h"
17
18 /*
19 * Internal type defining a time.
20 * This should be treated as an opaque structure.
21 *
22 * The time datum is Unix's 1970 and at nanosecond precision, this gives
23 * a range of 584 years roughly.
24 */
25 typedef struct {
26 uint64_t t; /* Ticks since the epoch */
27 } OSSL_TIME;
28
29 /* The precision of times allows this many values per second */
30 # define OSSL_TIME_SECOND ((uint64_t)1000000000)
31
32 /* One millisecond. */
33 # define OSSL_TIME_MS (OSSL_TIME_SECOND / 1000)
34
35 /* One microsecond. */
36 # define OSSL_TIME_US (OSSL_TIME_MS / 1000)
37
38 /* Convert a tick count into a time */
ossl_ticks2time(uint64_t ticks)39 static ossl_unused ossl_inline OSSL_TIME ossl_ticks2time(uint64_t ticks)
40 {
41 OSSL_TIME r;
42
43 r.t = ticks;
44 return r;
45 }
46
47 /* Convert a time to a tick count */
ossl_time2ticks(OSSL_TIME t)48 static ossl_unused ossl_inline uint64_t ossl_time2ticks(OSSL_TIME t)
49 {
50 return t.t;
51 }
52
53 /* Get current time */
54 OSSL_TIME ossl_time_now(void);
55
56 /* The beginning and end of the time range */
ossl_time_zero(void)57 static ossl_unused ossl_inline OSSL_TIME ossl_time_zero(void)
58 {
59 return ossl_ticks2time(0);
60 }
61
ossl_time_infinite(void)62 static ossl_unused ossl_inline OSSL_TIME ossl_time_infinite(void)
63 {
64 return ossl_ticks2time(~(uint64_t)0);
65 }
66
67
68 /* Convert time to timeval */
69 static ossl_unused ossl_inline
ossl_time_time_to_timeval(OSSL_TIME t,struct timeval * out)70 void ossl_time_time_to_timeval(OSSL_TIME t, struct timeval *out)
71 {
72 #ifdef _WIN32
73 out->tv_sec = (long int)(t.t / OSSL_TIME_SECOND);
74 #else
75 out->tv_sec = (time_t)(t.t / OSSL_TIME_SECOND);
76 #endif
77 out->tv_usec = (t.t % OSSL_TIME_SECOND) / (OSSL_TIME_SECOND / 1000000);
78 }
79
80 /* Convert time_t to OSSL_TIME */
ossl_time_from_time_t(time_t t)81 static ossl_inline OSSL_TIME ossl_time_from_time_t(time_t t)
82 {
83 OSSL_TIME ot;
84
85 ot.t = t;
86 ot.t *= OSSL_TIME_SECOND;
87 return ot;
88 }
89
90 /* Compare two time values, return -1 if less, 1 if greater and 0 if equal */
91 static ossl_unused ossl_inline
ossl_time_compare(OSSL_TIME a,OSSL_TIME b)92 int ossl_time_compare(OSSL_TIME a, OSSL_TIME b)
93 {
94 if (a.t > b.t)
95 return 1;
96 if (a.t < b.t)
97 return -1;
98 return 0;
99 }
100
101 /* Returns true if an OSSL_TIME is ossl_time_zero(). */
102 static ossl_unused ossl_inline
ossl_time_is_zero(OSSL_TIME t)103 int ossl_time_is_zero(OSSL_TIME t)
104 {
105 return ossl_time_compare(t, ossl_time_zero()) == 0;
106 }
107
108 /* Returns true if an OSSL_TIME is ossl_time_infinite(). */
109 static ossl_unused ossl_inline
ossl_time_is_infinite(OSSL_TIME t)110 int ossl_time_is_infinite(OSSL_TIME t)
111 {
112 return ossl_time_compare(t, ossl_time_infinite()) == 0;
113 }
114
115 /*
116 * Arithmetic operations on times.
117 * These operations are saturating, in that an overflow or underflow returns
118 * the largest or smallest value respectively.
119 */
OSSL_SAFE_MATH_UNSIGNED(time,uint64_t)120 OSSL_SAFE_MATH_UNSIGNED(time, uint64_t)
121
122 static ossl_unused ossl_inline
123 OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b)
124 {
125 OSSL_TIME r;
126 int err = 0;
127
128 r.t = safe_add_time(a.t, b.t, &err);
129 return err ? ossl_time_infinite() : r;
130 }
131
132 static ossl_unused ossl_inline
ossl_time_subtract(OSSL_TIME a,OSSL_TIME b)133 OSSL_TIME ossl_time_subtract(OSSL_TIME a, OSSL_TIME b)
134 {
135 OSSL_TIME r;
136 int err = 0;
137
138 r.t = safe_sub_time(a.t, b.t, &err);
139 return err ? ossl_time_zero() : r;
140 }
141
142 /* Returns |a - b|. */
143 static ossl_unused ossl_inline
ossl_time_abs_difference(OSSL_TIME a,OSSL_TIME b)144 OSSL_TIME ossl_time_abs_difference(OSSL_TIME a, OSSL_TIME b)
145 {
146 return a.t > b.t ? ossl_time_subtract(a, b)
147 : ossl_time_subtract(b, a);
148 }
149
150 static ossl_unused ossl_inline
ossl_time_multiply(OSSL_TIME a,uint64_t b)151 OSSL_TIME ossl_time_multiply(OSSL_TIME a, uint64_t b)
152 {
153 OSSL_TIME r;
154 int err = 0;
155
156 r.t = safe_mul_time(a.t, b, &err);
157 return err ? ossl_time_infinite() : r;
158 }
159
160 static ossl_unused ossl_inline
ossl_time_divide(OSSL_TIME a,uint64_t b)161 OSSL_TIME ossl_time_divide(OSSL_TIME a, uint64_t b)
162 {
163 OSSL_TIME r;
164 int err = 0;
165
166 r.t = safe_div_time(a.t, b, &err);
167 return err ? ossl_time_zero() : r;
168 }
169
170 /* Return higher of the two given time values. */
171 static ossl_unused ossl_inline
ossl_time_max(OSSL_TIME a,OSSL_TIME b)172 OSSL_TIME ossl_time_max(OSSL_TIME a, OSSL_TIME b)
173 {
174 return a.t > b.t ? a : b;
175 }
176
177 /* Return the lower of the two given time values. */
178 static ossl_unused ossl_inline
ossl_time_min(OSSL_TIME a,OSSL_TIME b)179 OSSL_TIME ossl_time_min(OSSL_TIME a, OSSL_TIME b)
180 {
181 return a.t < b.t ? a : b;
182 }
183
184 #endif
185