xref: /openbsd-src/lib/libfido2/src/time.c (revision ab19a69ebe1d1275c01611de862453c36b3d15b9)
1*ab19a69eSdjm /*
2*ab19a69eSdjm  * Copyright (c) 2021 Yubico AB. All rights reserved.
3*ab19a69eSdjm  * Use of this source code is governed by a BSD-style
4*ab19a69eSdjm  * license that can be found in the LICENSE file.
5*ab19a69eSdjm  */
6*ab19a69eSdjm 
7*ab19a69eSdjm #include <errno.h>
8*ab19a69eSdjm #include "fido.h"
9*ab19a69eSdjm 
10*ab19a69eSdjm static int
timespec_to_ms(const struct timespec * ts)11*ab19a69eSdjm timespec_to_ms(const struct timespec *ts)
12*ab19a69eSdjm {
13*ab19a69eSdjm 	int64_t x, y;
14*ab19a69eSdjm 
15*ab19a69eSdjm 	if (ts->tv_sec < 0 || ts->tv_nsec < 0 ||
16*ab19a69eSdjm 	    ts->tv_nsec >= 1000000000LL)
17*ab19a69eSdjm 		return -1;
18*ab19a69eSdjm 
19*ab19a69eSdjm 	if ((uint64_t)ts->tv_sec >= INT64_MAX / 1000LL)
20*ab19a69eSdjm 		return -1;
21*ab19a69eSdjm 
22*ab19a69eSdjm 	x = ts->tv_sec * 1000LL;
23*ab19a69eSdjm 	y = ts->tv_nsec / 1000000LL;
24*ab19a69eSdjm 
25*ab19a69eSdjm 	if (INT64_MAX - x < y || x + y > INT_MAX)
26*ab19a69eSdjm 		return -1;
27*ab19a69eSdjm 
28*ab19a69eSdjm 	return (int)(x + y);
29*ab19a69eSdjm }
30*ab19a69eSdjm 
31*ab19a69eSdjm int
fido_time_now(struct timespec * ts_now)32*ab19a69eSdjm fido_time_now(struct timespec *ts_now)
33*ab19a69eSdjm {
34*ab19a69eSdjm 	if (clock_gettime(CLOCK_MONOTONIC, ts_now) != 0) {
35*ab19a69eSdjm 		fido_log_error(errno, "%s: clock_gettime", __func__);
36*ab19a69eSdjm 		return -1;
37*ab19a69eSdjm 	}
38*ab19a69eSdjm 
39*ab19a69eSdjm 	return 0;
40*ab19a69eSdjm }
41*ab19a69eSdjm 
42*ab19a69eSdjm int
fido_time_delta(const struct timespec * ts_start,int * ms_remain)43*ab19a69eSdjm fido_time_delta(const struct timespec *ts_start, int *ms_remain)
44*ab19a69eSdjm {
45*ab19a69eSdjm 	struct timespec ts_end, ts_delta;
46*ab19a69eSdjm 	int ms;
47*ab19a69eSdjm 
48*ab19a69eSdjm 	if (*ms_remain < 0)
49*ab19a69eSdjm 		return 0;
50*ab19a69eSdjm 
51*ab19a69eSdjm 	if (clock_gettime(CLOCK_MONOTONIC, &ts_end) != 0) {
52*ab19a69eSdjm 		fido_log_error(errno, "%s: clock_gettime", __func__);
53*ab19a69eSdjm 		return -1;
54*ab19a69eSdjm 	}
55*ab19a69eSdjm 
56*ab19a69eSdjm 	if (timespeccmp(&ts_end, ts_start, <)) {
57*ab19a69eSdjm 		fido_log_debug("%s: timespeccmp", __func__);
58*ab19a69eSdjm 		return -1;
59*ab19a69eSdjm 	}
60*ab19a69eSdjm 
61*ab19a69eSdjm 	timespecsub(&ts_end, ts_start, &ts_delta);
62*ab19a69eSdjm 
63*ab19a69eSdjm 	if ((ms = timespec_to_ms(&ts_delta)) < 0) {
64*ab19a69eSdjm 		fido_log_debug("%s: timespec_to_ms", __func__);
65*ab19a69eSdjm 		return -1;
66*ab19a69eSdjm 	}
67*ab19a69eSdjm 
68*ab19a69eSdjm 	if (ms > *ms_remain)
69*ab19a69eSdjm 		ms = *ms_remain;
70*ab19a69eSdjm 
71*ab19a69eSdjm 	*ms_remain -= ms;
72*ab19a69eSdjm 
73*ab19a69eSdjm 	return 0;
74*ab19a69eSdjm }
75