From 116c6972827819bbff03a1bc32363f56bc8b9290 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 10 Nov 2015 17:26:59 +0100 Subject: [PATCH] util: rework timestamp fuzzing Use UTI_GetRandomBytes() instead of random() to generate random bits below precision. Save the result in NTP_int64 in the network order and allow precision in the full range from -32 to 32. With precision 32 the fuzzing now makes the timestamp completely random and can be used to hide the time. --- ntp_core.c | 17 +++++++++-------- util.c | 41 +++++++++++++++++++++++++---------------- util.h | 6 +++--- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/ntp_core.c b/ntp_core.c index a72a01c..92b52c4 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -286,8 +286,8 @@ do_time_checks(void) NTP_int64 ntv1, ntv2; int r; - UTI_TimevalToInt64(&tv1, &ntv1, 0); - UTI_TimevalToInt64(&tv2, &ntv2, 0); + UTI_TimevalToInt64(&tv1, &ntv1, NULL); + UTI_TimevalToInt64(&tv2, &ntv2, NULL); UTI_Int64ToTimeval(&ntv1, &tv1); UTI_Int64ToTimeval(&ntv2, &tv2); @@ -783,11 +783,12 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ NTP_Packet message; int leap, auth_len, length, ret; struct timeval local_receive, local_transmit; + NTP_int64 ts_fuzz; /* Parameters read from reference module */ int are_we_synchronised, our_stratum, smooth_time; NTP_Leap leap_status; - uint32_t our_ref_id, ts_fuzz; + uint32_t our_ref_id; struct timeval our_ref_time; double our_root_delay, our_root_dispersion, smooth_offset; @@ -855,7 +856,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ /* Now fill in timestamps */ - UTI_TimevalToInt64(&our_ref_time, &message.reference_ts, 0); + UTI_TimevalToInt64(&our_ref_time, &message.reference_ts, NULL); /* Originate - this comes from the last packet the source sent us */ message.originate_ts = *orig_ts; @@ -864,10 +865,10 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ This timestamp will have been adjusted so that it will now look to the source like we have been running on our latest estimate of frequency all along */ - UTI_TimevalToInt64(&local_receive, &message.receive_ts, 0); + UTI_TimevalToInt64(&local_receive, &message.receive_ts, NULL); /* Prepare random bits which will be added to the transmit timestamp. */ - ts_fuzz = UTI_GetNTPTsFuzz(message.precision); + UTI_GetInt64Fuzz(&ts_fuzz, message.precision); /* Transmit - this our local time right now! Also, we might need to store this for our own use later, next time we receive a message @@ -885,7 +886,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ take to generate the authentication data. */ local_transmit.tv_usec += KEY_GetAuthDelay(key_id); UTI_NormaliseTimeval(&local_transmit); - UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, ts_fuzz); + UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, &ts_fuzz); auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message, offsetof(NTP_Packet, auth_keyid), @@ -905,7 +906,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */ message.auth_keyid = 0; length += sizeof (message.auth_keyid); } - UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, ts_fuzz); + UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, &ts_fuzz); } ret = NIO_SendPacket(&message, where_to, from, length); diff --git a/util.c b/util.c index f6a7727..fc3a81c 100644 --- a/util.c +++ b/util.c @@ -566,16 +566,21 @@ UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval * /* ================================================== */ -uint32_t -UTI_GetNTPTsFuzz(int precision) +void +UTI_GetInt64Fuzz(NTP_int64 *ts, int precision) { - uint32_t fuzz; - int fuzz_bits; - - fuzz_bits = 32 - 1 + precision; - fuzz = random() % (1 << fuzz_bits); + int start, bits; - return fuzz; + assert(precision >= -32 && precision <= 32); + + start = sizeof (*ts) - (precision + 32 + 7) / 8; + ts->hi = ts->lo = 0; + + UTI_GetRandomBytes((unsigned char *)ts + start, sizeof (*ts) - start); + + bits = (precision + 32) % 8; + if (bits) + ((unsigned char *)ts)[start] %= 1U << bits; } /* ================================================== */ @@ -608,9 +613,9 @@ UTI_DoubleToInt32(double x) void UTI_TimevalToInt64(struct timeval *src, - NTP_int64 *dest, uint32_t fuzz) + NTP_int64 *dest, NTP_int64 *fuzz) { - uint32_t lo, sec, usec; + uint32_t hi, lo, sec, usec; sec = (uint32_t)src->tv_sec; usec = (uint32_t)src->tv_usec; @@ -618,18 +623,22 @@ UTI_TimevalToInt64(struct timeval *src, /* Recognize zero as a special case - it always signifies an 'unknown' value */ if (!usec && !sec) { - dest->hi = dest->lo = 0; + hi = lo = 0; } else { - dest->hi = htonl(sec + JAN_1970); + hi = htonl(sec + JAN_1970); /* This formula gives an error of about 0.1us worst case */ - lo = 4295 * usec - (usec>>5) - (usec>>9); + lo = htonl(4295 * usec - (usec >> 5) - (usec >> 9)); /* Add the fuzz */ - lo ^= fuzz; - - dest->lo = htonl(lo); + if (fuzz) { + hi ^= fuzz->hi; + lo ^= fuzz->lo; + } } + + dest->hi = hi; + dest->lo = lo; } /* ================================================== */ diff --git a/util.h b/util.h index 0a49fe6..f0cb610 100644 --- a/util.h +++ b/util.h @@ -96,13 +96,13 @@ extern char *UTI_TimeToLogForm(time_t t); /* Adjust time following a frequency/offset change */ extern void UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *new_tv, double *delta, double dfreq, double doffset); -/* Get a random value to fuzz an NTP timestamp in the given precision */ -extern uint32_t UTI_GetNTPTsFuzz(int precision); +/* Get zero NTP timestamp with random bits below precision */ +extern void UTI_GetInt64Fuzz(NTP_int64 *ts, int precision); extern double UTI_Int32ToDouble(NTP_int32 x); extern NTP_int32 UTI_DoubleToInt32(double x); -extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, uint32_t fuzz); +extern void UTI_TimevalToInt64(struct timeval *src, NTP_int64 *dest, NTP_int64 *fuzz); extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);