xref: /freebsd/crypto/openssl/include/internal/time.h (revision dafba19e42e78cd3d7c9264ece49ddd3d7d70da5)
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  */
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
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
81     ossl_time_zero(void)
82 {
83     return ossl_ticks2time(0);
84 }
85 
86 static ossl_unused ossl_inline
87     OSSL_TIME
88     ossl_time_infinite(void)
89 {
90     return ossl_ticks2time(~(uint64_t)0);
91 }
92 
93 /* Convert time to timeval */
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
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
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
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 */
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(). */
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(). */
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
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
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
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
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
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
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
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
248     ossl_time_min(OSSL_TIME a, OSSL_TIME b)
249 {
250     return a.t < b.t ? a : b;
251 }
252 
253 #endif
254