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