]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
util: rework timestamp fuzzing
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 10 Nov 2015 16:26:59 +0000 (17:26 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 16 Nov 2015 09:26:14 +0000 (10:26 +0100)
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
util.c
util.h

index a72a01cae83d6756430c31b6f6c334a63046b0cd..92b52c461ae2f2f0320122348dc301677c9f4e1b 100644 (file)
@@ -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 f6a77275ff834149909be4f23bed1e76ebacd0c7..fc3a81c30306ab650686303ce3d3be9cb0e4bfb6 100644 (file)
--- 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;
+
+  assert(precision >= -32 && precision <= 32);
+
+  start = sizeof (*ts) - (precision + 32 + 7) / 8;
+  ts->hi = ts->lo = 0;
 
-  return fuzz;
+  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 0a49fe6fd28aae43736372b2c7b6d9b09f15ac86..f0cb61058938c3337c694190ec7ac2f938389ce5 100644 (file)
--- 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);