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 11static int 12timespec_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 32int 33fido_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 43int 44fido_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