1 /*
2 * Copyright 2022-2023 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"
16 #include "internal/e_winsock.h" /* for struct timeval */
17 #include "internal/safe_math.h"
18
19 /*
20 * Internal type defining a time.
21 * This should be treated as an opaque structure.
22 *
23 * The time datum is Unix's 1970 and at nanosecond precision, this gives
24 * a range of 584 years roughly.
25 */
26 typedef struct {
27 uint64_t t; /* Ticks since the epoch */
28 } OSSL_TIME;
29
30 /* The precision of times allows this many values per second */
31 #define OSSL_TIME_SECOND ((uint64_t)1000000000)
32
33 /* One millisecond. */
34 #define OSSL_TIME_MS (OSSL_TIME_SECOND / 1000)
35
36 /* One microsecond. */
37 #define OSSL_TIME_US (OSSL_TIME_MS / 1000)
38
39 /* One nanosecond. */
40 #define OSSL_TIME_NS (OSSL_TIME_US / 1000)
41
42 #define ossl_seconds2time(s) ossl_ticks2time((s) * OSSL_TIME_SECOND)
43 #define ossl_time2seconds(t) (ossl_time2ticks(t) / OSSL_TIME_SECOND)
44 #define ossl_ms2time(ms) ossl_ticks2time((ms) * OSSL_TIME_MS)
45 #define ossl_time2ms(t) (ossl_time2ticks(t) / OSSL_TIME_MS)
46 #define ossl_us2time(us) ossl_ticks2time((us) * OSSL_TIME_US)
47 #define ossl_time2us(t) (ossl_time2ticks(t) / OSSL_TIME_US)
48
49 /*
50 * Arithmetic operations on times.
51 * These operations are saturating, in that an overflow or underflow returns
52 * the largest or smallest value respectively.
53 */
OSSL_SAFE_MATH_UNSIGNED(time,uint64_t)54 OSSL_SAFE_MATH_UNSIGNED(time, uint64_t)
55
56 /* Convert a tick count into a time */
57 static ossl_unused ossl_inline
58 OSSL_TIME
59 ossl_ticks2time(uint64_t ticks)
60 {
61 OSSL_TIME r;
62
63 r.t = ticks;
64 return r;
65 }
66
67 /* Convert a time to a tick count */
68 static ossl_unused ossl_inline
69 uint64_t
ossl_time2ticks(OSSL_TIME t)70 ossl_time2ticks(OSSL_TIME t)
71 {
72 return t.t;
73 }
74
75 /* Get current time */
76 OSSL_TIME ossl_time_now(void);
77
78 /* The beginning and end of the time range */
79 static ossl_unused ossl_inline
80 OSSL_TIME
ossl_time_zero(void)81 ossl_time_zero(void)
82 {
83 return ossl_ticks2time(0);
84 }
85
86 static ossl_unused ossl_inline
87 OSSL_TIME
ossl_time_infinite(void)88 ossl_time_infinite(void)
89 {
90 return ossl_ticks2time(~(uint64_t)0);
91 }
92
93 /* Convert time to timeval */
ossl_time_to_timeval(OSSL_TIME t)94 static ossl_unused ossl_inline struct timeval ossl_time_to_timeval(OSSL_TIME t)
95 {
96 struct timeval tv;
97 int err = 0;
98
99 /*
100 * Round up any nano secs which struct timeval doesn't support. Ensures that
101 * we never return a zero time if the input time is non zero
102 */
103 t.t = safe_add_time(t.t, OSSL_TIME_US - 1, &err);
104 if (err)
105 t = ossl_time_infinite();
106
107 #ifdef _WIN32
108 tv.tv_sec = (long int)(t.t / OSSL_TIME_SECOND);
109 #else
110 tv.tv_sec = (time_t)(t.t / OSSL_TIME_SECOND);
111 #endif
112 tv.tv_usec = (t.t % OSSL_TIME_SECOND) / OSSL_TIME_US;
113 return tv;
114 }
115
116 /* Convert timeval to time */
117 static ossl_unused ossl_inline
118 OSSL_TIME
ossl_time_from_timeval(struct timeval tv)119 ossl_time_from_timeval(struct timeval tv)
120 {
121 OSSL_TIME t;
122
123 #ifndef __DJGPP__ /* tv_sec is unsigned on djgpp. */
124 if (tv.tv_sec < 0)
125 return ossl_time_zero();
126 #endif
127 t.t = tv.tv_sec * OSSL_TIME_SECOND + tv.tv_usec * OSSL_TIME_US;
128 return t;
129 }
130
131 /* Convert OSSL_TIME to time_t */
132 static ossl_unused ossl_inline
133 time_t
ossl_time_to_time_t(OSSL_TIME t)134 ossl_time_to_time_t(OSSL_TIME t)
135 {
136 return (time_t)(t.t / OSSL_TIME_SECOND);
137 }
138
139 /* Convert time_t to OSSL_TIME */
140 static ossl_unused ossl_inline
141 OSSL_TIME
ossl_time_from_time_t(time_t t)142 ossl_time_from_time_t(time_t t)
143 {
144 OSSL_TIME ot;
145
146 ot.t = t;
147 ot.t *= OSSL_TIME_SECOND;
148 return ot;
149 }
150
151 /* Compare two time values, return -1 if less, 1 if greater and 0 if equal */
ossl_time_compare(OSSL_TIME a,OSSL_TIME b)152 static ossl_unused ossl_inline int ossl_time_compare(OSSL_TIME a, OSSL_TIME b)
153 {
154 if (a.t > b.t)
155 return 1;
156 if (a.t < b.t)
157 return -1;
158 return 0;
159 }
160
161 /* Returns true if an OSSL_TIME is ossl_time_zero(). */
ossl_time_is_zero(OSSL_TIME t)162 static ossl_unused ossl_inline int ossl_time_is_zero(OSSL_TIME t)
163 {
164 return ossl_time_compare(t, ossl_time_zero()) == 0;
165 }
166
167 /* Returns true if an OSSL_TIME is ossl_time_infinite(). */
ossl_time_is_infinite(OSSL_TIME t)168 static ossl_unused ossl_inline int ossl_time_is_infinite(OSSL_TIME t)
169 {
170 return ossl_time_compare(t, ossl_time_infinite()) == 0;
171 }
172
173 static ossl_unused ossl_inline
174 OSSL_TIME
ossl_time_add(OSSL_TIME a,OSSL_TIME b)175 ossl_time_add(OSSL_TIME a, OSSL_TIME b)
176 {
177 OSSL_TIME r;
178 int err = 0;
179
180 r.t = safe_add_time(a.t, b.t, &err);
181 return err ? ossl_time_infinite() : r;
182 }
183
184 static ossl_unused ossl_inline
185 OSSL_TIME
ossl_time_subtract(OSSL_TIME a,OSSL_TIME b)186 ossl_time_subtract(OSSL_TIME a, OSSL_TIME b)
187 {
188 OSSL_TIME r;
189 int err = 0;
190
191 r.t = safe_sub_time(a.t, b.t, &err);
192 return err ? ossl_time_zero() : r;
193 }
194
195 /* Returns |a - b|. */
196 static ossl_unused ossl_inline
197 OSSL_TIME
ossl_time_abs_difference(OSSL_TIME a,OSSL_TIME b)198 ossl_time_abs_difference(OSSL_TIME a, OSSL_TIME b)
199 {
200 return a.t > b.t ? ossl_time_subtract(a, b)
201 : ossl_time_subtract(b, a);
202 }
203
204 static ossl_unused ossl_inline
205 OSSL_TIME
ossl_time_multiply(OSSL_TIME a,uint64_t b)206 ossl_time_multiply(OSSL_TIME a, uint64_t b)
207 {
208 OSSL_TIME r;
209 int err = 0;
210
211 r.t = safe_mul_time(a.t, b, &err);
212 return err ? ossl_time_infinite() : r;
213 }
214
215 static ossl_unused ossl_inline
216 OSSL_TIME
ossl_time_divide(OSSL_TIME a,uint64_t b)217 ossl_time_divide(OSSL_TIME a, uint64_t b)
218 {
219 OSSL_TIME r;
220 int err = 0;
221
222 r.t = safe_div_time(a.t, b, &err);
223 return err ? ossl_time_zero() : r;
224 }
225
226 static ossl_unused ossl_inline
227 OSSL_TIME
ossl_time_muldiv(OSSL_TIME a,uint64_t b,uint64_t c)228 ossl_time_muldiv(OSSL_TIME a, uint64_t b, uint64_t c)
229 {
230 OSSL_TIME r;
231 int err = 0;
232
233 r.t = safe_muldiv_time(a.t, b, c, &err);
234 return err ? ossl_time_zero() : r;
235 }
236
237 /* Return higher of the two given time values. */
238 static ossl_unused ossl_inline
239 OSSL_TIME
ossl_time_max(OSSL_TIME a,OSSL_TIME b)240 ossl_time_max(OSSL_TIME a, OSSL_TIME b)
241 {
242 return a.t > b.t ? a : b;
243 }
244
245 /* Return the lower of the two given time values. */
246 static ossl_unused ossl_inline
247 OSSL_TIME
ossl_time_min(OSSL_TIME a,OSSL_TIME b)248 ossl_time_min(OSSL_TIME a, OSSL_TIME b)
249 {
250 return a.t < b.t ? a : b;
251 }
252
253 #endif
254