...
 
Commits (8)
/* backwards.c - check for time going backwards
* Started from Artturi Alm on port-arm@netbsd.org
* Fri, 25 Jan 2019 09:54:42 +0200
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define UNUSED_ARG(arg) ((void)(arg))
static void ts_print(struct timespec *ts0, struct timespec *ts1);
void ts_print(struct timespec *ts0, struct timespec *ts1)
{
printf("ts0=(%ld,%ld)\nts1=(%ld,%ld)\n",
(long)ts0->tv_sec, ts0->tv_nsec,
(long)ts1->tv_sec, ts1->tv_nsec);
}
int
main(int argc, char *argv[])
{
UNUSED_ARG(argc);
UNUSED_ARG(argv);
struct timespec ts0, ts1;
/* Some systems return equal.
* Print first 5 equal examples. */
for(int equal = 0; equal < 5; ) {
clock_gettime(CLOCK_MONOTONIC, &ts0); /* warm up cache */
clock_gettime(CLOCK_MONOTONIC, &ts1);
clock_gettime(CLOCK_MONOTONIC, &ts0);
clock_gettime(CLOCK_MONOTONIC, &ts1);
if ((ts0.tv_sec < ts1.tv_sec) ||
((ts0.tv_sec == ts1.tv_sec) &&
(ts0.tv_nsec <= ts1.tv_nsec))) {
} else {
ts_print(&ts0, &ts1);
if (ts0.tv_sec == ts1.tv_sec
&& ts0.tv_nsec == ts1.tv_nsec)
equal++;
}
}
for(;;) {
clock_gettime(CLOCK_MONOTONIC, &ts0); /* warm up cache */
clock_gettime(CLOCK_MONOTONIC, &ts1);
clock_gettime(CLOCK_MONOTONIC, &ts0);
clock_gettime(CLOCK_MONOTONIC, &ts1);
if ((ts0.tv_sec < ts1.tv_sec) ||
((ts0.tv_sec == ts1.tv_sec) &&
(ts0.tv_nsec < ts1.tv_nsec))) {
} else {
ts_print(&ts0, &ts1);
}
}
}
......@@ -12,7 +12,9 @@ struct table {
#define BATCHSIZE 1000000
#define BILLION 1000000000
#define HISTSIZE 250
#define HISTSIZE 2500
#define NSPERBUCKET 1
#define MAXHISTLINES 10
struct table clocks [] = {
{CLOCK_REALTIME, "CLOCK_REALTIME"},
......@@ -38,7 +40,7 @@ int dups;
int do_res(int type, const char* name);
int do_average(int type, const char* name);
int do_fastest(int type, const char* name);
void do_hist(int type, int fastest);
int do_hist(int type, int fastest);
int do_res(int type, const char* name) {
int err;
......@@ -101,23 +103,33 @@ int do_fastest(int type, const char* name) {
return fastest;
}
void do_hist(int type, int fastest) {
int nsPerBucket = 5;
int do_hist(int type, int fastest) {
int nsPerBucket = NSPERBUCKET;
int i;
int delta, lines, toobig, hits, miss;
struct timespec start, stop;
uint64_t sec, nanos;
int64_t sec, nanos;
unsigned int hist[HISTSIZE];
int faster = 0;
dups = 0;
toobig = 0;
for (i = 0; i < HISTSIZE; i++) hist[i] = 0;
for (i = 0; i < BATCHSIZE; i++) {
clock_gettime(type, &start); /* warm up cache */
clock_gettime(type, &stop);
clock_gettime(type, &start);
clock_gettime(type, &stop);
sec = (stop.tv_sec-start.tv_sec);
nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
if (0 > nanos) {
printf("## Time went backwards: %ld.%9ld-%ld.%9ld=>%ld\n",
(long)stop.tv_sec, stop.tv_nsec,
(long)start.tv_sec, start.tv_nsec,
(long)nanos);
continue;
}
if (0 == nanos) {
/* I've seen this on Pi 1. */
dups++;
......@@ -125,8 +137,11 @@ void do_hist(int type, int fastest) {
}
delta = (nanos-fastest) / nsPerBucket;
if (0 > delta) {
/* fastest wasn't fast enough. */
printf("Too small: %ld, %d\n", (long)nanos, fastest);
/* fastest wasn't fast enough */
if (0 == faster)
faster = delta;
if (faster > delta)
faster = delta;
continue;
}
if (delta < HISTSIZE) {
......@@ -135,6 +150,7 @@ void do_hist(int type, int fastest) {
toobig++;
}
}
if (faster) return faster;
printf("\n");
printf("Histogram: CLOCK_REALTIME, %d ns per bucket, %d samples.\n",
nsPerBucket, BATCHSIZE);
......@@ -142,20 +158,23 @@ void do_hist(int type, int fastest) {
lines = 0;
hits = 0;
for (i=0; i<HISTSIZE; i++) {
if ((5 <= lines) && (0.98*BATCHSIZE<hits)) break; /* minimal printout */
if ((MAXHISTLINES <= lines) && (0.98*BATCHSIZE < hits))
break; /* Avoid clutter of printing long tail */
if (hist[i]) {
printf("%10d %8u\n", i*nsPerBucket+fastest, hist[i]);
lines++;
hits += hist[i];
}
}
miss = i;
miss = i-1;
for ( ; i<HISTSIZE; i++) {
toobig += hist[i];
}
if (dups) printf("%d samples were duplicated.\n", dups);
if (toobig) printf("%d samples were bigger than %d.\n",
toobig, miss*nsPerBucket+fastest);
return faster;
}
......@@ -166,12 +185,12 @@ int main(int argc, char *argv[])
(void)argc; /* Squash unused warnings */
(void)argv;
printf(" res avg min dups CLOCK\n");
printf(" res avg min dups CLOCK\n");
for (int i=0; (NULL != clocks[i].name); i++) {
res = do_res(clocks[i].type, clocks[i].name);
average = do_average(clocks[i].type, clocks[i].name);
fastest = do_fastest(clocks[i].type, clocks[i].name);
printf("%9d %5d %7d", res, average, fastest);
printf("%9d %5d %8d", res, average, fastest);
if (0.9*BATCHSIZE < dups)
/* Hack: negative to show good if close to all are bad */
printf(" %5d", dups-BATCHSIZE);
......@@ -184,8 +203,14 @@ for (int i=0; (NULL != clocks[i].name); i++) {
}
if (1) {
int faster;
fastest = do_fastest(CLOCK_REALTIME, "CLOCK_REALTIME");
do_hist(CLOCK_REALTIME, fastest);
while (1) {
faster = do_hist(CLOCK_REALTIME, fastest);
if (0 == faster) break;
printf("Found faster: %d => %d\n", fastest, faster);
fastest = faster;
}
}
return 0;
......
def build(ctx):
util = ['sht', 'digest-find', 'digest-timing', 'clocks']
util = ['sht', 'digest-find', 'digest-timing', 'clocks', 'backwards']
for name in util:
ctx(
......
/*
* nts.h - NTS (Network Time Security) declarations
* Copyright 2019 by the NTPsec project contributors
* SPDX-License-Identifier: BSD-4-Clause-UC
*/
#ifndef GUARD_NTS_H
#define GUARD_NTS_H
......@@ -141,9 +144,10 @@ struct ntsconfig_t {
};
/* Only valid for AEAD_AES_SIV_CMAC_nnn
* but that's all we use. */
#define AEAD_CMAC_LNG 16
/* CMAC length is wired into AEAD_AES_SIV_CMAC_nnn. */
#define CMAC_LENGTH 16
/* The NONCE length comes from RFC 5116 and/or 5297. */
#define NONCE_LENGTH 16
/* NTS protocol constants */
......@@ -159,6 +163,11 @@ enum nts_record_type {
nts_port_negotiation = 7
};
enum nts_protocol_type {
nts_protocol_NTP = 0,
};
enum nts_errors_type {
nts_unrecognized_critical_section = 0,
nts_bad_request = 1
......@@ -214,19 +223,19 @@ extern struct ntsconfig_t ntsconfig;
/* NTS-related statistics visible via ntpq -c nts */
extern uint64_t nts_client_send;
extern uint64_t nts_client_recv;
extern uint64_t nts_client_recv_good;
extern uint64_t nts_client_recv_bad;
extern uint64_t nts_server_send;
extern uint64_t nts_server_recv;
extern uint64_t nts_server_recv_good;
extern uint64_t nts_server_recv_bad;
extern uint64_t nts_cookie_make;
extern uint64_t nts_cookie_decode;
extern uint64_t nts_cookie_decode_old;
extern uint64_t nts_cookie_decode_too_old;
extern uint64_t nts_cookie_decode_error;
extern uint64_t nts_ke_serves;
extern uint64_t nts_ke_serves_good;
extern uint64_t nts_ke_serves_bad;
extern uint64_t nts_ke_probes;
extern uint64_t nts_ke_probes_good;
extern uint64_t nts_ke_probes_bad;
#endif /* GUARD_NTS_H */
/*
* nts2.h - NTS (Network Time Security) declarations
* Copyright 2019 by the NTPsec project contributors
* SPDX-License-Identifier: BSD-4-Clause-UC
*
* other half of nts.h which doesn't include openssl/ssh.h
* This split helps test routines.
*/
#ifndef GUARD_NTS2_H
#define GUARD_NTS2_H
......
......@@ -48,6 +48,9 @@ static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
case '\t' : case '\r' : case '\n' : case ' ' :
case ',' : case ']' : case '}' :
goto found;
default:
/* not found, keep going */
break;
}
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
parser->pos = start;
......
This diff is collapsed.
......@@ -344,16 +344,17 @@ static const struct ctl_var sys_var[] = {
{ CS_AUTHCMACFAIL, RO, "authcmacfails" },
#define CS_K_LOCKCLOCK 105
{ CS_K_LOCKCLOCK, RO, "lockclock" },
#define CS_nts_client_send 106
{ CS_nts_client_send, RO, "nts_client_send" },
#define CS_nts_client_recv 107
{ CS_nts_client_recv, RO, "nts_client_recv" },
{ CS_nts_client_send, RO, "nts_client_send" },
#define CS_nts_client_recv_good 107
{ CS_nts_client_recv_good, RO, "nts_client_recv_good" },
#define CS_nts_client_recv_bad 108
{ CS_nts_client_recv_bad, RO, "nts_client_recv_bad" },
#define CS_nts_server_send 109
{ CS_nts_server_send, RO, "nts_server_send" },
#define CS_nts_server_recv 110
{ CS_nts_server_recv, RO, "nts_server_recv" },
{ CS_nts_server_send, RO, "nts_server_send" },
#define CS_nts_server_recv_good 110
{ CS_nts_server_recv_good, RO, "nts_server_recv_good" },
#define CS_nts_server_recv_bad 111
{ CS_nts_server_recv_bad, RO, "nts_server_recv_bad" },
......@@ -368,14 +369,14 @@ static const struct ctl_var sys_var[] = {
#define CS_nts_cookie_decode_error 116
{ CS_nts_cookie_decode_error, RO, "nts_cookie_decode_error" },
#define CS_nts_ke_serves 117
{ CS_nts_ke_serves, RO, "nts_ke_serves" },
#define CS_nts_ke_serves_good 117
{ CS_nts_ke_serves_good, RO, "nts_ke_serves_good" },
#define CS_nts_ke_serves_bad 118
{ CS_nts_ke_serves_bad, RO, "nts_ke_serves_bad" },
#define CS_nts_ke_probes 119
{ CS_nts_ke_probes, RO, "nts_ke_probes" },
{ CS_nts_ke_serves_bad, RO, "nts_ke_serves_bad" },
#define CS_nts_ke_probes_good 119
{ CS_nts_ke_probes_good, RO, "nts_ke_probes_good" },
#define CS_nts_ke_probes_bad 120
{ CS_nts_ke_probes_bad, RO, "nts_ke_probes_bad" },
{ CS_nts_ke_probes_bad, RO, "nts_ke_probes_bad" },
#define CS_MAXCODE ((sizeof(sys_var)/sizeof(sys_var[0])) - 1)
{ 0, EOV, "" }
};
......@@ -1963,8 +1964,8 @@ ctl_putsys(
ctl_putuint(sys_var[varid].text, nts_client_send);
break;
case CS_nts_client_recv:
ctl_putuint(sys_var[varid].text, nts_client_recv);
case CS_nts_client_recv_good:
ctl_putuint(sys_var[varid].text, nts_client_recv_good);
break;
case CS_nts_client_recv_bad:
......@@ -1975,8 +1976,8 @@ ctl_putsys(
ctl_putuint(sys_var[varid].text, nts_server_send);
break;
case CS_nts_server_recv:
ctl_putuint(sys_var[varid].text, nts_server_recv);
case CS_nts_server_recv_good:
ctl_putuint(sys_var[varid].text, nts_server_recv_good);
break;
case CS_nts_server_recv_bad:
......@@ -2003,16 +2004,16 @@ ctl_putsys(
ctl_putuint(sys_var[varid].text, nts_cookie_decode_error);
break;
case CS_nts_ke_serves:
ctl_putuint(sys_var[varid].text, nts_ke_serves);
case CS_nts_ke_serves_good:
ctl_putuint(sys_var[varid].text, nts_ke_serves_good);
break;
case CS_nts_ke_serves_bad:
ctl_putuint(sys_var[varid].text, nts_ke_serves_bad);
break;
case CS_nts_ke_probes:
ctl_putuint(sys_var[varid].text, nts_ke_probes);
case CS_nts_ke_probes_good:
ctl_putuint(sys_var[varid].text, nts_ke_probes_good);
break;
case CS_nts_ke_probes_bad:
......
/*
* nts.c - Network Time Security (NTS) support
* Copyright 2019 by the NTPsec project contributors
* SPDX-License-Identifier: BSD-4-Clause-UC
*
* Section references are to
* https://tools.ietf.org/html/draft-ietf-ntp-using-nts-for-ntp-15
......
/*
* nts_client.c - Network Time Security (NTS) client side support
* Copyright 2019 by the NTPsec project contributors
* SPDX-License-Identifier: BSD-4-Clause-UC
*
* Section references are to
* https://tools.ietf.org/html/draft-ietf-ntp-using-nts-for-ntp-15
......@@ -71,7 +73,6 @@ bool nts_probe(struct peer * peer) {
if (NULL == client_ctx)
return false;
nts_ke_probes++;
addrOK = false;
get_systime(&start);
......@@ -106,10 +107,6 @@ bool nts_probe(struct peer * peer) {
return false;
}
// FIXME
// Not much error checking yet.
// Ugly since most SSL routines return 1 on success.
if (NULL == peer->cfg.nts_cfg.ca)
ssl = SSL_new(client_ctx);
else {
......@@ -161,6 +158,7 @@ bool nts_probe(struct peer * peer) {
goto bail;
addrOK = true;
nts_ke_probes_good++;
bail:
if (!addrOK) {
......@@ -201,7 +199,7 @@ SSL_CTX* make_ssl_client_ctx(const char * filename) {
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
ctx = SSL_CTX_new(TLS_client_method());
#else
OpenSSL_add_all_ciphers(); // FIXME needed on NetBSD
// OpenSSL_add_all_ciphers(); // Maybe was needed on NetBSD ??
ctx = SSL_CTX_new(TLSv1_2_client_method());
#endif
if (NULL == ctx) {
......@@ -234,6 +232,7 @@ SSL_CTX* make_ssl_client_ctx(const char * filename) {
return ctx;
}
/* return -1 on error */
int open_TCP_socket(struct peer *peer, const char *hostname) {
char host[256], port[32];
char errbuf[100];
......@@ -382,10 +381,12 @@ bool nts_make_keys(SSL *ssl, uint16_t aead, uint8_t *c2s, uint8_t *s2c, int keyl
// Date: Tue, 15 Jan 2019 11:40:13 +0100
// https://mailarchive.ietf.org/arch/msg/ntp/nkc-9n6XOPt5Glgi_ueLvuD9EfY
const char *label = "EXPORTER-network-time-security/1";
// FIXME, first 2 bytes, next protocol ID (0)
unsigned char context[5] = {0x00, 0x00, 0x00, 0x0f, 0x00};
unsigned char context[5];
context[0] = (nts_protocol_NTP >> 8) & 0xFF;
context[1] = nts_protocol_NTP & 0xFF;
context[2] = (aead >> 8) & 0xFF;
context[3] = aead & 0xFF;
context[4] = 0x00;
if (1 != SSL_export_keying_material(ssl, c2s, keylen,
label, strlen(label),
context, 5, 1)) {
......@@ -415,7 +416,8 @@ bool nts_client_send_request(SSL *ssl, struct peer* peer) {
buf.left = sizeof(buff);
/* 4.1.2 Next Protocol, 0 for NTP */
ke_append_record_uint16(&buf, NTS_CRITICAL+nts_next_protocol_negotiation, 0);
ke_append_record_uint16(&buf,
NTS_CRITICAL+nts_next_protocol_negotiation, nts_protocol_NTP);
/* 4.1.5 AEAD Algorithm List */
// FIXME should be : separated list
......@@ -488,7 +490,7 @@ bool nts_client_process_response(SSL *ssl, struct peer* peer) {
return false;
case nts_next_protocol_negotiation:
data = next_uint16(&buf);
if ((sizeof(data) != length) || (data != 0)) {
if ((sizeof(data) != length) || (data != nts_protocol_NTP)) {
msyslog(LOG_ERR, "NTSc: NPN-Wrong length or bad data: %d, %d",
length, data);
return false;
......@@ -544,7 +546,11 @@ bool nts_client_process_response(SSL *ssl, struct peer* peer) {
msyslog(LOG_ERR, "NTSc: Using server %s=>%s", server, errbuf);
break;
case nts_port_negotiation:
// FIXME check length
if (sizeof(port) != length) {
msyslog(LOG_ERR, "NTSc: PN-Wrong length: %d, %d",
length, critical);
return false;
}
port = next_uint16(&buf);
SET_PORT(&sockaddr, port);
msyslog(LOG_ERR, "NTSc: Using port %d", port);
......@@ -570,7 +576,6 @@ bool nts_client_process_response(SSL *ssl, struct peer* peer) {
} /* case */
} /* while */
// FIXME lots of other checks
if (NO_AEAD == peer->nts_state.aead) {
msyslog(LOG_ERR, "NTSc: No AEAD algorithim.");
return false;
......
/*
* nts_cookie.c - Network Time Security (NTS) cookie processing
* Copyright 2019 by the NTPsec project contributors
* SPDX-License-Identifier: BSD-4-Clause-UC
*
* Section references are to
* https://tools.ietf.org/html/draft-ietf-ntp-using-nts-for-ntp-15
......@@ -77,8 +79,12 @@ uint8_t K[NTS_MAX_KEYLEN], K2[NTS_MAX_KEYLEN];
uint32_t I, I2;
time_t K_time = 0; /* time K was created, 0 for none */
AES_SIV_CTX* cookie_ctx; /* one per thread ?? */
/* The mutex protects cookie_ctx
* The NTS-KE servers can make cookies
* while the main NTP server thread is unpacking and making cookies.
* If this becomes a bottleneck, we could use a cookie_ctx per thread. */
pthread_mutex_t cookie_lock = PTHREAD_MUTEX_INITIALIZER;
AES_SIV_CTX* cookie_ctx;
/* Statistics for ntpq */
uint64_t nts_cookie_make = 0;
......@@ -88,9 +94,7 @@ uint64_t nts_cookie_decode_too_old = 0;
uint64_t nts_cookie_decode_error = 0;
// FIXME duplicated in ntp_extens
#define NONCE_LENGTH 16
// FIXME AEAD_LENGTH
/* Associated data: aead (rounded up to 4) plus NONCE */
#define AD_LENGTH 20
#define AEAD_LENGTH 4
......@@ -150,9 +154,15 @@ bool nts_read_cookie_keys(void) {
if (NULL != ntsconfig.KI)
cookie_filename = ntsconfig.KI;
in = fopen(cookie_filename, "r");
if (NULL == in)
// FIXME check errno - crash if exists but can't read
return false;
if (NULL == in) {
char errbuf[100];
if (ENOENT == errno)
return false; /* File doesn't exist */
IGNORE(strerror_r(errno, errbuf, sizeof(errbuf)));
msyslog(LOG_ERR, "NTSs: can't read old cookie file: %s=>%s",
cookie_filename, errbuf);
exit(1);
}
if (1 != fscanf(in, "T: %lu\n", &templ)) goto bail;
K_time = templ;
if (1 != fscanf(in, "L: %d\n", &K_length)) goto bail;
......@@ -182,7 +192,11 @@ bail:
return false;
}
// FIXME need ratchet mode to make new keys
/* The draft describes a ratchet mode to make new keys
* That's one way to implement a KE server for a cluster of NTP servers.
* The KE server and the NTP servers stay in sync without communication
* after a one-time copy of the cookie file from NTP server to KE server.
*/
bool nts_make_cookie_key(void) {
bool OK = true;
memcpy(&K2, &K, sizeof(K2)); /* Push current cookie to old */
......@@ -216,7 +230,6 @@ bool nts_write_cookie_keys(void) {
close(fd);
return false;
}
// FIXME check return values
fprintf(out, "T: %lu\n", (unsigned long)K_time);
fprintf(out, "L: %d\n", K_length);
fprintf(out, "I: %u\n", I);
......@@ -249,13 +262,7 @@ int nts_make_cookie(uint8_t *cookie,
nts_cookie_make++;
// ASSERT(keylen<NTS_MAX_KEYLEN);
err = pthread_mutex_lock(&cookie_lock);
if (0 != err) {
msyslog(LOG_ERR, "ERR: Can't lock cookie_lock: %d", err);
exit(2);
}
INSIST(keylen < NTS_MAX_KEYLEN);
/* collect plaintext
* separate buffer avoids encrypt in place
......@@ -284,12 +291,25 @@ int nts_make_cookie(uint8_t *cookie,
used = finger-cookie;
left = NTS_MAX_COOKIELEN-used;
err = pthread_mutex_lock(&cookie_lock);
if (0 != err) {
msyslog(LOG_ERR, "ERR: Can't lock cookie_lock: %d", err);
exit(2);
}
ok = AES_SIV_Encrypt(cookie_ctx,
finger, &left, /* left: in: max out length, out: length used */
K, K_length,
nonce, NONCE_LENGTH,
plaintext, plainlength,
cookie, AD_LENGTH);
err = pthread_mutex_unlock(&cookie_lock);
if (0 != err) {
msyslog(LOG_ERR, "ERR: Can't unlock cookie_lock: %d", err);
exit(2);
}
if (!ok) {
msyslog(LOG_ERR, "NTS: nts_make_cookie - Error from AES_SIV_Encrypt");
/* I don't think this should happen,
......@@ -301,13 +321,8 @@ int nts_make_cookie(uint8_t *cookie,
}
used += left;
// ASSERT(length < NTS_MAX_COOKIELEN);
INSIST(used < NTS_MAX_COOKIELEN);
err = pthread_mutex_unlock(&cookie_lock);
if (0 != err) {
msyslog(LOG_ERR, "ERR: Can't unlock cookie_lock: %d", err);
exit(2);
}
return used;
}
......@@ -323,6 +338,7 @@ bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
uint32_t temp;
size_t plainlength;
int cipherlength;
int err;
bool ok;
if (NULL == cookie_ctx)
......@@ -352,13 +368,25 @@ bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
cipherlength = cookielen - AD_LENGTH;
plainlength = NTS_MAX_COOKIELEN;
// FIXME - needs lock
err = pthread_mutex_lock(&cookie_lock);
if (0 != err) {
msyslog(LOG_ERR, "ERR: Can't lock cookie_lock: %d", err);
exit(2);
}
ok = AES_SIV_Decrypt(cookie_ctx,
plaintext, &plainlength,
key, K_length,
nonce, NONCE_LENGTH,
finger, cipherlength,
cookie, AD_LENGTH);
err = pthread_mutex_unlock(&cookie_lock);
if (0 != err) {
msyslog(LOG_ERR, "ERR: Can't unlock cookie_lock: %d", err);
exit(2);
}
if (!ok) {
nts_cookie_decode_error++;
return false;
......
/*
* ntp_extens.c - Network Time Protocol (NTP) extension processing
* Copyright 2019 by the NTPsec project contributors
* SPDX-License-Identifier: BSD-4-Clause-UC
*
* NB: This module is working with the wire format packet.
* It must do byte swapping.
*
* We carefully arrange things so that no padding is necessary.
*
* This is only called by the main ntpd thread, so we don't need
* a lock to protect wire_ctx.
*/
#include "config.h"
......@@ -23,7 +27,6 @@
#include "nts.h"
#include "nts2.h"
// FIXME duplicated in nts_cookie
#define NONCE_LENGTH 16
#define CMAC_LENGTH 16
......@@ -32,10 +35,10 @@
/* Statistics for ntpq */
uint64_t nts_client_send = 0;
uint64_t nts_client_recv = 0;
uint64_t nts_client_recv_good = 0;
uint64_t nts_client_recv_bad = 0;
uint64_t nts_server_send = 0;
uint64_t nts_server_recv = 0;
uint64_t nts_server_recv_good = 0;
uint64_t nts_server_recv_bad = 0;
enum NtpExtFieldType {
......@@ -45,7 +48,8 @@ enum NtpExtFieldType {
NTS_AEEF = 0x404 /* Authenticated and Encrypted Extension Fields */
};
AES_SIV_CTX* wire_ctx = NULL; /* need one per thread */
/* This is only called by the main thread so we don't need a lock. */
AES_SIV_CTX* wire_ctx = NULL;
bool extens_init(void) {
......@@ -127,7 +131,6 @@ bool extens_server_recv(struct ntspacket_t *ntspacket, uint8_t *pkt, int lng) {
int noncelen, cmaclen;
bool sawcookie, sawAEEF;
nts_server_recv++;
nts_server_recv_bad++; /* assume bad, undo if OK */
buf.next = pkt+LEN_PKT_NOMAC;
......@@ -145,7 +148,7 @@ bool extens_server_recv(struct ntspacket_t *ntspacket, uint8_t *pkt, int lng) {
uint8_t *nonce, *cmac;
bool ok;
type = ex_next_record(&buf, &length);
type = ex_next_record(&buf, &length); /* length excludes header */
if (length&3 || length > buf.left || length < 0)
return false;
if (NTS_CRITICAL & type) {
......@@ -216,12 +219,13 @@ bool extens_server_recv(struct ntspacket_t *ntspacket, uint8_t *pkt, int lng) {
break;
default:
/* Non NTS extensions on requests at server.
* Call out when we get some that we want. */
* Call out when we get some that we want.
* Until then, it's probably a bug. */
if (critical)
return false;
buf.next += length;
buf.left -= length;
return false; // FIXME - for now, it's probably a bug
return false;
}
}
......@@ -230,6 +234,7 @@ bool extens_server_recv(struct ntspacket_t *ntspacket, uint8_t *pkt, int lng) {
// printf("ESRx: %d, %d, %d\n",
// lng-LEN_PKT_NOMAC, ntspacket->needed, ntspacket->keylen);
ntspacket->valid = true;
nts_server_recv_good++;
nts_server_recv_bad--;
return true;
}
......@@ -320,7 +325,6 @@ bool extens_client_recv(struct peer *peer, uint8_t *pkt, int lng) {
int idx;
bool sawAEEF = false;
nts_client_recv++;
nts_client_recv_bad++; /* assume bad, undo if OK */
buf.next = pkt+LEN_PKT_NOMAC;
......@@ -334,7 +338,7 @@ bool extens_client_recv(struct peer *peer, uint8_t *pkt, int lng) {
size_t outlen;
bool ok;
type = ex_next_record(&buf, &length);
type = ex_next_record(&buf, &length); /* length excludes header */
if (length&3 || length > buf.left || length < 0)
return false;
if (NTS_CRITICAL & type) {
......@@ -392,12 +396,13 @@ bool extens_client_recv(struct peer *peer, uint8_t *pkt, int lng) {
break;
default:
/* Non NTS extensions on reply from server.
* Call out when we get some that we want. */
* Call out when we get some that we want.
* For now, it's probably a bug. */
if (critical)
return false;
buf.next += length;
buf.left -= length;
return false; // FIXME - for now, it's probably a bug
return false;
}
}
......@@ -405,6 +410,7 @@ bool extens_client_recv(struct peer *peer, uint8_t *pkt, int lng) {
// peer->nts_state.writeIdx, peer->nts_state.readIdx);
if (!sawAEEF)
return false;
nts_client_recv_good++;
nts_client_recv_bad--;
return true;
}
......
/*
* nts_server.c - Network Time Security (NTS) server side support
* Copyright 2019 by the NTPsec project contributors
* SPDX-License-Identifier: BSD-4-Clause-UC
*
* Section references are to
* https://tools.ietf.org/html/draft-ietf-ntp-using-nts-for-ntp-15
......@@ -35,9 +37,9 @@ static int listner4_sock = -1;
static int listner6_sock = -1;
/* Statistics for ntpq */
uint64_t nts_ke_serves = 0;
uint64_t nts_ke_serves_good = 0;
uint64_t nts_ke_serves_bad = 0;
uint64_t nts_ke_probes = 0;
uint64_t nts_ke_probes_good = 0;
uint64_t nts_ke_probes_bad = 0;
......@@ -50,7 +52,7 @@ bool nts_server_init(void) {
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
server_ctx = SSL_CTX_new(TLS_server_method());
#else
OpenSSL_add_all_ciphers(); // FIXME needed on NetBSD
// OpenSSL_add_all_ciphers(); // maybe was needed on NetBSD ??
server_ctx = SSL_CTX_new(TLSv1_2_server_method());
#endif
if (NULL == server_ctx) {
......@@ -130,7 +132,6 @@ void* nts_ke_listener(void* arg) {
sleep(1); /* avoid log clutter on bug */
continue;
}
nts_ke_serves++;
get_systime(&start);
sockporttoa_r(&addr, errbuf, sizeof(errbuf));
......@@ -175,6 +176,7 @@ void* nts_ke_listener(void* arg) {
get_systime(&finish);
finish -= start;
nts_ke_serves_good++;
msyslog(LOG_INFO, "NTSs: NTS-KE server took %.3Lf sec", lfptod(finish));
}
......@@ -337,7 +339,7 @@ bool nts_ke_process_receive(struct BufCtl_t *buf, int *aead) {
return false;
case nts_next_protocol_negotiation:
data = next_uint16(buf);
if ((sizeof(data) != length) || (data != 0)) {
if ((sizeof(data) != length) || (data != nts_protocol_NTP)) {
msyslog(LOG_ERR, "NTSs: NPN-Wrong length or bad data: %d, %d",
length, data);
return false;
......@@ -383,16 +385,16 @@ bool nts_ke_process_receive(struct BufCtl_t *buf, int *aead) {
bool nts_ke_setup_send(struct BufCtl_t *buf, int aead,
uint8_t *c2s, uint8_t *s2c, int keylen) {
uint8_t cookie[NTS_MAX_COOKIELEN];
int cookielen;
/* 4.1.2 Next Protocol, 0 for NTP */
ke_append_record_uint16(buf, NTS_CRITICAL+nts_next_protocol_negotiation, 0);
/* 4.1.2 Next Protocol */
ke_append_record_uint16(buf,
NTS_CRITICAL+nts_next_protocol_negotiation, nts_protocol_NTP);
/* 4.1.5 AEAD Algorithm List */
ke_append_record_uint16(buf, nts_algorithm_negotiation, aead);
for (int i=0; i<NTS_MAX_COOKIES; i++) {
cookielen = nts_make_cookie(cookie, aead, c2s, s2c, keylen);
uint8_t cookie[NTS_MAX_COOKIELEN];
int cookielen = nts_make_cookie(cookie, aead, c2s, s2c, keylen);
ke_append_record_bytes(buf, nts_new_cookie, cookie, cookielen);
}
......