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