Let me add utility functions to wait, so that those can be used in an application which wants to hide timing information.
Description
Description
Event Timeline
Comment Actions
I mean, something like this (for GNU/Linux):
diff --git a/src/misc.c b/src/misc.c index 4db2d9a4..74864334 100644 --- a/src/misc.c +++ b/src/misc.c @@ -577,3 +577,80 @@ _gcry_divide_by_zero (void) gpg_err_set_errno (EDOM); _gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero"); } + +#ifdef HAVE_CLOCK_GETTIME +#include <time.h> +# if defined(CLOCK_THREAD_CPUTIME_ID) && defined(CLOCK_TAI) +struct gcry_timedwait +{ + struct timespec ts; +}; + +typedef struct gcry_timedwait *gcry_timedwait_t; + +gcry_err_code_t +_gcry_timedwait_new (gcry_timedwait_t *r_tw, unsigned int flags) +{ + gcry_err_code_t err; + gcry_timedwait_t tw; + + *r_tw = NULL; + + /* Possibly, it would be good to be able to select the wall clock. + * For now, it's CPU time by the thread. */ + if (flags != 0) + return GPG_ERR_INV_ARG; + + tw = xtrymalloc (sizeof (gcry_timedwait_t)); + if (!tw) + return gpg_err_code_from_syserror (); + + if (clock_gettime (CLOCK_THREAD_CPUTIME_ID, &tw->ts) < 0) + { + err = gpg_err_code_from_syserror (); + xfree (tw); + return err; + } + + *r_tw = tw; + return 0; +} + +gcry_err_code_t +_gcry_timedwait_release (gcry_timedwait_t tw, struct timespec ts_r) +{ + gcry_err_code_t err; + struct timespec ts; + u32 negative; + + if (clock_gettime (CLOCK_THREAD_CPUTIME_ID, &ts) < 0) + { + err = gpg_err_code_from_syserror (); + xfree (tw); + return err; + } + + ts.tv_sec -= tw->ts.tv_sec; + ts.tv_nsec -= tw->ts.tv_nsec; + negative = ((u32)ts.tv_nsec) >> 31; + ts.tv_sec -= negative; + ts.tv_nsec += (1000000000 * negative); + + xfree (tw); + + ts_r.tv_sec -= ts.tv_sec; + ts_r.tv_nsec -= ts.tv_nsec; + negative = ((u32)ts_r.tv_nsec) >> 31; + ts_r.tv_sec -= negative; + ts_r.tv_nsec += (1000000000 * negative); + + if (ts_r.tv_sec < 0) + return GPG_ERR_TIME_CONFLICT; + + if (clock_nanosleep (CLOCK_TAI, 0, &ts_r, &ts_r)) + return gpg_err_code_from_syserror (); + + return 0; +} +# endif +#endif
Intended scenario is:
- gcry_timedwait_new
- some non-constant time computation
- gcry_timedwait_release specifying relative timespec
Comment Actions
API which does not require allocation internally would be better. In this case, it is allocated on stack by the caller.
Comment Actions
Here is current version:
diff --git a/src/misc.c b/src/misc.c index 4db2d9a4..bf50b00b 100644 --- a/src/misc.c +++ b/src/misc.c @@ -577,3 +577,61 @@ _gcry_divide_by_zero (void) gpg_err_set_errno (EDOM); _gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero"); } + +#ifdef HAVE_CLOCK_GETTIME +#include <time.h> +# if defined(CLOCK_THREAD_CPUTIME_ID) && defined(CLOCK_TAI) +struct gcry_timedwait +{ + clockid_t id; + struct timespec ts; +}; + +typedef struct gcry_timedwait *gcry_timedwait_t; + +gcry_err_code_t +_gcry_timedwait_init (gcry_timedwait_t tw, unsigned int flags) +{ + /* Possibly, it would be good to be able to select the wall clock. + * For now, it's CPU time by the thread. */ + if (flags != 0) + return GPG_ERR_INV_ARG; + + tw->id = CLOCK_THREAD_CPUTIME_ID; + if (clock_gettime (tw->id, &tw->ts) < 0) + return gpg_err_code_from_syserror (); + + return 0; +} + +gcry_err_code_t +_gcry_timedwait_finish (gcry_timedwait_t tw, struct timespec ts_r) +{ + struct timespec ts; + u32 negative; + + if (clock_gettime (tw->id, &ts) < 0) + return gpg_err_code_from_syserror (); + + ts.tv_sec -= tw->ts.tv_sec; + ts.tv_nsec -= tw->ts.tv_nsec; + negative = ((u32)ts.tv_nsec) >> 31; + ts.tv_sec -= negative; + ts.tv_nsec += (1000000000 * negative); + + ts_r.tv_sec -= ts.tv_sec; + ts_r.tv_nsec -= ts.tv_nsec; + negative = ((u32)ts_r.tv_nsec) >> 31; + ts_r.tv_sec -= negative; + ts_r.tv_nsec += (1000000000 * negative); + + if (ts_r.tv_sec < 0) + return GPG_ERR_TIME_CONFLICT; + + if (clock_nanosleep (CLOCK_TAI, 0, &ts_r, &ts_r)) + return gpg_err_code_from_syserror (); + + return 0; +} +# endif +#endif