ntp: drop precompensation of TX timestamp

The daemon transmit timestamps are precompensated for the time it takes
to generate a MAC using a symmetric key (as measured on chronyd start)
and also an average round-trip time of the Samba signing of MS-SNTP
responses. This improves accuracy of the transmit timestamp, but it
has some issues.

The correction has a random error which is changing over time due to
variable CPU frequency, system load, migration to a different machine,
etc. If the measured delay is too large, the correction may cause the
transmit timestamp to be later than the actual transmission. Also, the
delay is measured for a packet of a minimal length with no extension
fields, and there is no support for NTS.

Drop the precompensation in favor of the interleaved mode, which now
avoids the authentication delay even when no kernel/hardware timestamps
are available.
This commit is contained in:
Miroslav Lichvar 2020-07-02 15:34:22 +02:00
parent ff03b813b0
commit eae4b2abe5
9 changed files with 0 additions and 132 deletions

51
keys.c
View file

@ -60,7 +60,6 @@ typedef struct {
} ntp_mac; } ntp_mac;
CMC_Instance cmac; CMC_Instance cmac;
} data; } data;
int auth_delay;
} Key; } Key;
static ARR_Instance keys; static ARR_Instance keys;
@ -122,38 +121,6 @@ get_key(unsigned int index)
return ((Key *)ARR_GetElements(keys)) + index; return ((Key *)ARR_GetElements(keys)) + index;
} }
/* ================================================== */
static int
determine_hash_delay(uint32_t key_id)
{
NTP_Packet pkt;
struct timespec before, after;
double diff, min_diff;
int i, nsecs;
memset(&pkt, 0, sizeof (pkt));
for (i = 0; i < 10; i++) {
LCL_ReadRawTime(&before);
KEY_GenerateAuth(key_id, (unsigned char *)&pkt, NTP_HEADER_LENGTH,
(unsigned char *)&pkt + NTP_HEADER_LENGTH,
sizeof (pkt) - NTP_HEADER_LENGTH);
LCL_ReadRawTime(&after);
diff = UTI_DiffTimespecsToDouble(&after, &before);
if (i == 0 || min_diff > diff)
min_diff = diff;
}
nsecs = 1.0e9 * min_diff;
DEBUG_LOG("authentication delay for key %"PRIu32": %d nsecs", key_id, nsecs);
return nsecs;
}
/* ================================================== */ /* ================================================== */
/* Decode key encoded in ASCII or HEX */ /* Decode key encoded in ASCII or HEX */
@ -296,9 +263,6 @@ KEY_Reload(void)
/* Erase any passwords from stack */ /* Erase any passwords from stack */
memset(line, 0, sizeof (line)); memset(line, 0, sizeof (line));
for (i = 0; i < ARR_GetSize(keys); i++)
get_key(i)->auth_delay = determine_hash_delay(get_key(i)->id);
} }
/* ================================================== */ /* ================================================== */
@ -354,21 +318,6 @@ KEY_KeyKnown(uint32_t key_id)
/* ================================================== */ /* ================================================== */
int
KEY_GetAuthDelay(uint32_t key_id)
{
Key *key;
key = get_key_by_id(key_id);
if (!key)
return 0;
return key->auth_delay;
}
/* ================================================== */
int int
KEY_GetAuthLength(uint32_t key_id) KEY_GetAuthLength(uint32_t key_id)
{ {

1
keys.h
View file

@ -35,7 +35,6 @@ extern void KEY_Finalise(void);
extern void KEY_Reload(void); extern void KEY_Reload(void);
extern int KEY_KeyKnown(uint32_t key_id); extern int KEY_KeyKnown(uint32_t key_id);
extern int KEY_GetAuthDelay(uint32_t key_id);
extern int KEY_GetAuthLength(uint32_t key_id); extern int KEY_GetAuthLength(uint32_t key_id);
extern int KEY_CheckKeyLength(uint32_t key_id); extern int KEY_CheckKeyLength(uint32_t key_id);
extern int KEY_GetKeyInfo(uint32_t key_id, int *type, int *bits); extern int KEY_GetKeyInfo(uint32_t key_id, int *type, int *bits);

View file

@ -96,24 +96,6 @@ check_symmetric_auth(NTP_Packet *packet, NTP_PacketInfo *info)
/* ================================================== */ /* ================================================== */
static void
adjust_timestamp(NTP_AuthMode mode, uint32_t key_id, struct timespec *ts)
{
switch (mode) {
case NTP_AUTH_SYMMETRIC:
ts->tv_nsec += KEY_GetAuthDelay(key_id);
UTI_NormaliseTimespec(ts);
break;
case NTP_AUTH_MSSNTP:
ts->tv_nsec += NSD_GetAuthDelay(key_id);
UTI_NormaliseTimespec(ts);
default:
break;
}
}
/* ================================================== */
static int static int
is_zero_data(unsigned char *data, int length) is_zero_data(unsigned char *data, int length)
{ {
@ -230,14 +212,6 @@ NAU_PrepareRequestAuth(NAU_Instance instance)
/* ================================================== */ /* ================================================== */
void
NAU_AdjustRequestTimestamp(NAU_Instance instance, struct timespec *ts)
{
adjust_timestamp(instance->mode, instance->key_id, ts);
}
/* ================================================== */
int int
NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request, NTP_PacketInfo *info) NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request, NTP_PacketInfo *info)
{ {
@ -397,14 +371,6 @@ NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info, uint32_t *kod)
/* ================================================== */ /* ================================================== */
void
NAU_AdjustResponseTimestamp(NTP_Packet *request, NTP_PacketInfo *info, struct timespec *ts)
{
adjust_timestamp(info->auth.mode, info->auth.mac.key_id, ts);
}
/* ================================================== */
int int
NAU_GenerateResponseAuth(NTP_Packet *request, NTP_PacketInfo *request_info, NAU_GenerateResponseAuth(NTP_Packet *request, NTP_PacketInfo *request_info,
NTP_Packet *response, NTP_PacketInfo *response_info, NTP_Packet *response, NTP_PacketInfo *response_info,

View file

@ -51,10 +51,6 @@ extern int NAU_GetSuggestedNtpVersion(NAU_Instance instance);
/* Perform operations necessary for NAU_GenerateRequestAuth() */ /* Perform operations necessary for NAU_GenerateRequestAuth() */
extern int NAU_PrepareRequestAuth(NAU_Instance instance); extern int NAU_PrepareRequestAuth(NAU_Instance instance);
/* Adjust a transmit timestamp for an estimated minimum time it takes to call
NAU_GenerateRequestAuth() */
extern void NAU_AdjustRequestTimestamp(NAU_Instance instance, struct timespec *ts);
/* Extend a request with data required by the authentication mode */ /* Extend a request with data required by the authentication mode */
extern int NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request, extern int NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request,
NTP_PacketInfo *info); NTP_PacketInfo *info);
@ -66,11 +62,6 @@ extern int NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info);
kod code is returned, a KoD response should be sent back. */ kod code is returned, a KoD response should be sent back. */
extern int NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info, uint32_t *kod); extern int NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info, uint32_t *kod);
/* Adjust a transmit timestamp for an estimated minimum time it takes to call
NAU_GenerateResponseAuth() */
extern void NAU_AdjustResponseTimestamp(NTP_Packet *request, NTP_PacketInfo *info,
struct timespec *ts);
/* Extend a response with data required by the authentication mode. This /* Extend a response with data required by the authentication mode. This
function can be called only if the previous call of NAU_CheckRequestAuth() function can be called only if the previous call of NAU_CheckRequestAuth()
was on the same request. */ was on the same request. */

View file

@ -1068,13 +1068,6 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
LCL_ReadCookedTime(&local_transmit, &local_transmit_err); LCL_ReadCookedTime(&local_transmit, &local_transmit_err);
if (smooth_time) if (smooth_time)
UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit); UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit);
/* Pre-compensate the transmit time by approximately how long it will
take to generate the authentication data */
if (auth)
NAU_AdjustRequestTimestamp(auth, &local_transmit);
else
NAU_AdjustResponseTimestamp(request, request_info, &local_transmit);
} }
UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit, UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,

View file

@ -96,14 +96,6 @@ static unsigned int queue_tail;
/* Unix domain socket connected to ntp_signd */ /* Unix domain socket connected to ntp_signd */
static int sock_fd; static int sock_fd;
#define MIN_AUTH_DELAY 1.0e-5
#define MAX_AUTH_DELAY 1.0e-2
/* Average time needed for signing one packet. This is used to adjust the
transmit timestamp in NTP packets. The timestamp won't be very accurate as
the delay is variable, but it should be good enough for MS-SNTP clients. */
static double auth_delay;
/* Flag indicating if the MS-SNTP authentication is enabled */ /* Flag indicating if the MS-SNTP authentication is enabled */
static int enabled; static int enabled;
@ -183,10 +175,6 @@ process_response(SignInstance *inst)
NIO_SendPacket(&inst->response.signed_packet, &inst->remote_addr, &inst->local_addr, NIO_SendPacket(&inst->response.signed_packet, &inst->remote_addr, &inst->local_addr,
ntohl(inst->response.length) + sizeof (inst->response.length) - ntohl(inst->response.length) + sizeof (inst->response.length) -
offsetof(SigndResponse, signed_packet), 0); offsetof(SigndResponse, signed_packet), 0);
/* Update exponential moving average of the authentication delay */
delay = CLAMP(MIN_AUTH_DELAY, delay, MAX_AUTH_DELAY);
auth_delay += 0.1 * (delay - auth_delay);
} }
/* ================================================== */ /* ================================================== */
@ -274,7 +262,6 @@ void
NSD_Initialise() NSD_Initialise()
{ {
sock_fd = INVALID_SOCK_FD; sock_fd = INVALID_SOCK_FD;
auth_delay = MIN_AUTH_DELAY;
enabled = CNF_GetNtpSigndSocket() && CNF_GetNtpSigndSocket()[0]; enabled = CNF_GetNtpSigndSocket() && CNF_GetNtpSigndSocket()[0];
if (!enabled) if (!enabled)
@ -301,13 +288,6 @@ NSD_Finalise()
/* ================================================== */ /* ================================================== */
extern int NSD_GetAuthDelay(uint32_t key_id)
{
return 1.0e9 * auth_delay;
}
/* ================================================== */
int int
NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info, NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info,
NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr) NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr)

View file

@ -35,9 +35,6 @@ extern void NSD_Initialise(void);
/* Finalisation function */ /* Finalisation function */
extern void NSD_Finalise(void); extern void NSD_Finalise(void);
/* Function to get an estimate of delay due to signing */
extern int NSD_GetAuthDelay(uint32_t key_id);
/* Function to sign an NTP packet and send it */ /* Function to sign an NTP packet and send it */
extern int NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info, extern int NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info,
NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr); NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr);

View file

@ -427,12 +427,6 @@ NSD_Finalise(void)
{ {
} }
int
NSD_GetAuthDelay(uint32_t key_id)
{
return 0;
}
int int
NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info, NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info,
NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr) NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr)

View file

@ -125,7 +125,6 @@ test_unit(void)
for (j = 0; j < KEYS; j++) { for (j = 0; j < KEYS; j++) {
TEST_CHECK(KEY_KeyKnown(keys[j])); TEST_CHECK(KEY_KeyKnown(keys[j]));
TEST_CHECK(KEY_GetAuthDelay(keys[j]) >= 0);
TEST_CHECK(KEY_GetAuthLength(keys[j]) >= 16); TEST_CHECK(KEY_GetAuthLength(keys[j]) >= 16);
data_len = random() % (sizeof (data) + 1); data_len = random() % (sizeof (data) + 1);