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.
This commit is contained in:
Miroslav Lichvar 2015-11-10 17:26:59 +01:00
parent 6199a89170
commit 116c697282
3 changed files with 37 additions and 27 deletions

View file

@ -286,8 +286,8 @@ do_time_checks(void)
NTP_int64 ntv1, ntv2; NTP_int64 ntv1, ntv2;
int r; int r;
UTI_TimevalToInt64(&tv1, &ntv1, 0); UTI_TimevalToInt64(&tv1, &ntv1, NULL);
UTI_TimevalToInt64(&tv2, &ntv2, 0); UTI_TimevalToInt64(&tv2, &ntv2, NULL);
UTI_Int64ToTimeval(&ntv1, &tv1); UTI_Int64ToTimeval(&ntv1, &tv1);
UTI_Int64ToTimeval(&ntv2, &tv2); UTI_Int64ToTimeval(&ntv2, &tv2);
@ -783,11 +783,12 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
NTP_Packet message; NTP_Packet message;
int leap, auth_len, length, ret; int leap, auth_len, length, ret;
struct timeval local_receive, local_transmit; struct timeval local_receive, local_transmit;
NTP_int64 ts_fuzz;
/* Parameters read from reference module */ /* Parameters read from reference module */
int are_we_synchronised, our_stratum, smooth_time; int are_we_synchronised, our_stratum, smooth_time;
NTP_Leap leap_status; NTP_Leap leap_status;
uint32_t our_ref_id, ts_fuzz; uint32_t our_ref_id;
struct timeval our_ref_time; struct timeval our_ref_time;
double our_root_delay, our_root_dispersion, smooth_offset; 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 */ /* 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 */ /* Originate - this comes from the last packet the source sent us */
message.originate_ts = *orig_ts; 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 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 the source like we have been running on our latest estimate of
frequency all along */ 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. */ /* 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 /* 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 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. */ take to generate the authentication data. */
local_transmit.tv_usec += KEY_GetAuthDelay(key_id); local_transmit.tv_usec += KEY_GetAuthDelay(key_id);
UTI_NormaliseTimeval(&local_transmit); 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, auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
offsetof(NTP_Packet, auth_keyid), 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; message.auth_keyid = 0;
length += sizeof (message.auth_keyid); 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); ret = NIO_SendPacket(&message, where_to, from, length);

39
util.c
View file

@ -566,16 +566,21 @@ UTI_AdjustTimeval(struct timeval *old_tv, struct timeval *when, struct timeval *
/* ================================================== */ /* ================================================== */
uint32_t void
UTI_GetNTPTsFuzz(int precision) UTI_GetInt64Fuzz(NTP_int64 *ts, int precision)
{ {
uint32_t fuzz; int start, bits;
int fuzz_bits;
fuzz_bits = 32 - 1 + precision; assert(precision >= -32 && precision <= 32);
fuzz = random() % (1 << fuzz_bits);
return fuzz; 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 void
UTI_TimevalToInt64(struct timeval *src, 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; sec = (uint32_t)src->tv_sec;
usec = (uint32_t)src->tv_usec; usec = (uint32_t)src->tv_usec;
@ -618,18 +623,22 @@ UTI_TimevalToInt64(struct timeval *src,
/* Recognize zero as a special case - it always signifies /* Recognize zero as a special case - it always signifies
an 'unknown' value */ an 'unknown' value */
if (!usec && !sec) { if (!usec && !sec) {
dest->hi = dest->lo = 0; hi = lo = 0;
} else { } else {
dest->hi = htonl(sec + JAN_1970); hi = htonl(sec + JAN_1970);
/* This formula gives an error of about 0.1us worst case */ /* 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 */ /* Add the fuzz */
lo ^= fuzz; if (fuzz) {
hi ^= fuzz->hi;
dest->lo = htonl(lo); lo ^= fuzz->lo;
}
} }
dest->hi = hi;
dest->lo = lo;
} }
/* ================================================== */ /* ================================================== */

6
util.h
View file

@ -96,13 +96,13 @@ extern char *UTI_TimeToLogForm(time_t t);
/* Adjust time following a frequency/offset change */ /* 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); 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 */ /* Get zero NTP timestamp with random bits below precision */
extern uint32_t UTI_GetNTPTsFuzz(int precision); extern void UTI_GetInt64Fuzz(NTP_int64 *ts, int precision);
extern double UTI_Int32ToDouble(NTP_int32 x); extern double UTI_Int32ToDouble(NTP_int32 x);
extern NTP_int32 UTI_DoubleToInt32(double 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); extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);