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