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 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8 #include <errno.h> 9 #include "fido.h" 10 11 static int 12 timespec_to_ms(const struct timespec *ts) 13 { 14 int64_t x, y; 15 16 if (ts->tv_sec < 0 || ts->tv_nsec < 0 || 17 ts->tv_nsec >= 1000000000LL) 18 return -1; 19 20 if ((uint64_t)ts->tv_sec >= INT64_MAX / 1000LL) 21 return -1; 22 23 x = ts->tv_sec * 1000LL; 24 y = ts->tv_nsec / 1000000LL; 25 26 if (INT64_MAX - x < y || x + y > INT_MAX) 27 return -1; 28 29 return (int)(x + y); 30 } 31 32 int 33 fido_time_now(struct timespec *ts_now) 34 { 35 if (clock_gettime(CLOCK_MONOTONIC, ts_now) != 0) { 36 fido_log_error(errno, "%s: clock_gettime", __func__); 37 return -1; 38 } 39 40 return 0; 41 } 42 43 int 44 fido_time_delta(const struct timespec *ts_start, int *ms_remain) 45 { 46 struct timespec ts_end, ts_delta; 47 int ms; 48 49 if (*ms_remain < 0) 50 return 0; 51 52 if (clock_gettime(CLOCK_MONOTONIC, &ts_end) != 0) { 53 fido_log_error(errno, "%s: clock_gettime", __func__); 54 return -1; 55 } 56 57 if (timespeccmp(&ts_end, ts_start, <)) { 58 fido_log_debug("%s: timespeccmp", __func__); 59 return -1; 60 } 61 62 timespecsub(&ts_end, ts_start, &ts_delta); 63 64 if ((ms = timespec_to_ms(&ts_delta)) < 0) { 65 fido_log_debug("%s: timespec_to_ms", __func__); 66 return -1; 67 } 68 69 if (ms > *ms_remain) 70 ms = *ms_remain; 71 72 *ms_remain -= ms; 73 74 return 0; 75 } 76