Coverage Report

Created: 2025-01-20 06:04

/src/ntpsec/ntpd/nts.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * nts.c - Network Time Security (NTS) support
3
 * Copyright the NTPsec project contributors
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 *
6
 * Section references are to
7
 * https://tools.ietf.org/html/rfc8915
8
 *
9
 * This module exposes mostly functions and structure pointers (not
10
 * structures) so that the NTS implementation can be sealed off from
11
 * the rest of the code. It supports both the client and server sides.
12
 *
13
 * The exception is client configuration, for which various bits have
14
 * to be set by the config parser.
15
 */
16
17
#include "config.h"
18
19
#include <sys/types.h>
20
#include <sys/stat.h>
21
#include <unistd.h>
22
23
#include <arpa/inet.h>
24
#include <openssl/err.h>
25
26
#include "ntp_types.h"
27
#include "ntp_stdlib.h"
28
#include "ntpd.h"
29
#include "nts.h"
30
#include "nts2.h"
31
32
struct nts_counters nts_cnt, old_nts_cnt;
33
struct ntske_counters ntske_cnt, old_ntske_cnt;
34
35
struct ntsconfig_t ntsconfig = {
36
  .ntsenable = false,
37
  .mintls = NULL,
38
  .maxtls = NULL,
39
  .tlsciphersuites = NULL,
40
  .tlsecdhcurves = NULL,
41
  .cert = NULL,
42
  .key = NULL,
43
  .KI = NULL,
44
  .ca = NULL,
45
  .aead = NULL,
46
  .tlscipherserverpreference = false,
47
};
48
49
void nts_log_version(void);
50
51
/*****************************************************/
52
53
/* More SSL initialization in ssl_init() from libntp/ssl_init.c */
54
55
0
void nts_init(void) {
56
0
  bool ok = true;
57
0
  nts_log_version();
58
0
  if (ntsconfig.ntsenable) {
59
0
    ok &= nts_server_init();
60
0
  }
61
0
  ok &= nts_client_init();
62
0
  ok &= nts_cookie_init();
63
0
  ok &= extens_init();
64
0
  if (!ok) {
65
0
    msyslog(LOG_ERR, "NTS: troubles during init.  Bailing.");
66
0
    exit(1);
67
0
  }
68
0
}
69
70
0
void nts_init2(void) {
71
0
  bool ok = true;
72
0
  if (ntsconfig.ntsenable) {
73
0
    ok &= nts_server_init2();
74
0
    ok &= nts_cookie_init2();
75
0
  }
76
0
  if (!ok) {
77
0
    msyslog(LOG_ERR, "NTS: troubles during init2.  Bailing.");
78
0
    exit(1);
79
0
  }
80
0
}
81
82
/* There are 2 cases:
83
 *  1: match, log version
84
 *  2: mismatch, log both build and run
85
 */
86
0
void nts_log_version(void) {
87
0
  unsigned long buildVersion = OPENSSL_VERSION_NUMBER;
88
0
  const char * text = OpenSSL_version(OPENSSL_VERSION);
89
0
  bool match = (buildVersion == OpenSSL_version_num()) &&
90
0
    (0 == strcmp(OPENSSL_VERSION_TEXT, text));
91
0
  if (match) {
92
    /* Case 1 */
93
0
    msyslog(LOG_INFO, "INIT: %s, %lx",
94
0
      OPENSSL_VERSION_TEXT, buildVersion);
95
0
  } else {
96
                /* Case 2 */
97
0
    msyslog(LOG_INFO, "INIT: Built with %s, %lx",
98
0
      OPENSSL_VERSION_TEXT, buildVersion);
99
0
    msyslog(LOG_INFO, "INIT: Running with %s, %lx",
100
0
      OpenSSL_version(OPENSSL_VERSION),
101
0
      OpenSSL_version_num());
102
0
    if (buildVersion > OpenSSL_version_num()) {
103
0
      msyslog(LOG_ERR, "INIT: Old OpenSSL library, bailing");
104
0
      exit(1);
105
0
    }
106
0
  }
107
  /*
108
   * If the runtime OpenSSL is 1.1.1a, then bail, since we'll run into errors with the
109
   * TLSv1.3 maximum label length
110
   */
111
0
  if (OpenSSL_version_num() == 0x1010101fL) {
112
0
    msyslog(LOG_ERR, "INIT: OpenSSL 1.1.1a has a maximum label length bug, bailing");
113
0
    exit(1);
114
0
  }
115
0
}
116
117
/*****************************************************/
118
119
0
void nts_timer(void) {
120
0
  nts_cert_timer();
121
0
  nts_cookie_timer();
122
0
}
123
124
/*****************************************************/
125
126
/* 0 is default, -1 is error */
127
0
int nts_translate_version(const char *arg) {
128
0
  if (NULL == arg) {
129
0
    return 0;
130
0
  }
131
0
  if (0 == strcmp(arg, "TLS1.3")) {
132
0
    return TLS1_3_VERSION;
133
0
  }
134
0
  msyslog(LOG_ERR, "NTS: TLS unrecognized version string: %s.", arg);
135
0
  return -1;
136
0
}
137
138
/* Translate text to AEAD code.  NO_AEAD for none/error */
139
0
uint16_t nts_string_to_aead(const char* text) {
140
0
  if (false) {
141
0
  } else if (0 == strcmp(text, "AES_SIV_CMAC_256")) {
142
0
    return AEAD_AES_SIV_CMAC_256;
143
0
  } else if (0 == strcmp(text, "AES_SIV_CMAC_384")) {
144
0
    return AEAD_AES_SIV_CMAC_384;
145
0
  } else if (0 == strcmp(text, "AES_SIV_CMAC_512")) {
146
0
    return AEAD_AES_SIV_CMAC_512;
147
0
  } else {
148
0
    return NO_AEAD;
149
0
  }
150
0
}
151
152
/* returns key length, 0 if unknown arg */
153
2.92k
int nts_get_key_length(uint16_t aead) {
154
2.92k
  switch (aead) {
155
262
      case AEAD_AES_SIV_CMAC_256:
156
262
    return AEAD_AES_SIV_CMAC_256_KEYLEN;
157
229
      case AEAD_AES_SIV_CMAC_384:
158
229
    return AEAD_AES_SIV_CMAC_384_KEYLEN;
159
174
      case AEAD_AES_SIV_CMAC_512:
160
174
    return AEAD_AES_SIV_CMAC_512_KEYLEN;
161
2.25k
      default:
162
2.25k
    return 0;
163
2.92k
  }
164
2.92k
}
165
166
167
/*****************************************************/
168
169
0
bool nts_load_versions(SSL_CTX *ctx) {
170
0
  int minver, maxver;
171
0
  minver = nts_translate_version(ntsconfig.mintls);
172
0
  maxver = nts_translate_version(ntsconfig.maxtls);
173
0
  if ((-1 == minver) || (-1 == maxver))
174
0
    return false;
175
0
  if(0 == minver) minver = TLS1_3_VERSION;   // 3.
176
0
  SSL_CTX_set_min_proto_version(ctx, minver);
177
0
  SSL_CTX_set_max_proto_version(ctx, maxver);
178
0
  return true;
179
0
}
180
181
0
bool nts_load_ciphers(SSL_CTX *ctx) {
182
  /* SSL set_ciphers(uites) ignores typos or ciphers it doesn't support.
183
   * There is no SSL_CTX_get_cipher_list, so we can't easily read back
184
   * the ciphers to see what it took.
185
   * We could make a dummy SSL, read the list, then free it.
186
   * man SSL_CTX_set_ciphersuites() has info.
187
   */
188
0
  if (NULL == ntsconfig.tlsciphersuites) {
189
0
    return true;
190
0
  }
191
  /*  This used to set server-preference See #797 */
192
0
  if (1 != SSL_CTX_set_ciphersuites(ctx, ntsconfig.tlsciphersuites)) {
193
0
    msyslog(LOG_ERR, "NTS: troubles setting ciphersuites.");
194
0
    return false;
195
0
  } else {
196
0
    msyslog(LOG_INFO, "NTS: set ciphersuites %s.", ntsconfig.tlsciphersuites);
197
0
  }
198
0
  return true;
199
0
}
200
201
0
bool nts_load_ecdhcurves(SSL_CTX *ctx) {
202
  /* SSL_CTX_set1_groups_list ignores typos or curves it doesn't support.
203
   * There is no SSL_CTX_get_groups_list, so we can't easily read back
204
   * the ecdhcurves to see what it took.
205
   * We could make a dummy SSL, read the list, then free it.
206
   */
207
0
  if (NULL != ntsconfig.tlsecdhcurves) {
208
    /* FIXME -- const bug in OpenSSL */
209
0
    char *copy = estrdup(ntsconfig.tlsecdhcurves);
210
0
    if (1 != SSL_CTX_set1_groups_list(ctx, copy)) {
211
0
      msyslog(LOG_ERR, "NTS: troubles setting ecdhcurves.");
212
0
      free(copy);
213
0
      return false;
214
0
    } else {
215
0
      msyslog(LOG_INFO, "NTS: set ecdhcurves %s.", ntsconfig.tlsecdhcurves);
216
0
    }
217
0
    free(copy);
218
0
  }
219
0
  return true;
220
0
}
221
222
0
bool nts_set_cipher_order(SSL_CTX *ctx) {
223
0
  if (ntsconfig.tlscipherserverpreference)
224
0
    SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
225
0
  return true;
226
0
}
227
228
229
static struct stat certfile_stat;
230
231
0
void nts_reload_certificate(SSL_CTX *ctx) {
232
0
  struct stat temp_stat;
233
0
  const char *cert = NTS_CERT_FILE;
234
235
0
  if (NULL != ntsconfig.cert)
236
0
    cert = ntsconfig.cert;
237
238
0
  if (0 != stat(cert, &temp_stat)) {
239
0
    return;
240
0
  }
241
242
0
  if ((certfile_stat.st_mtime == temp_stat.st_mtime)
243
0
            && (certfile_stat.st_ctime == temp_stat.st_ctime)) {
244
0
    return;  /* avoid clutter in log file */
245
0
  }
246
247
0
  nts_load_certificate(ctx);
248
249
0
}
250
251
0
bool nts_load_certificate(SSL_CTX *ctx) {
252
0
  const char *cert = NTS_CERT_FILE;
253
0
  const char *key = NTS_KEY_FILE;
254
0
        char errbuf[100];
255
256
0
  if (NULL != ntsconfig.cert)
257
0
    cert = ntsconfig.cert;
258
0
  if (NULL != ntsconfig.key)
259
0
    key = ntsconfig.key;
260
261
  /* for reload checking */
262
0
  if (0 != stat(cert, &certfile_stat)) {
263
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
264
0
    msyslog(LOG_ERR, "NTSs: can't stat certificate (chain) from %s: %s", cert, errbuf);
265
0
    return false;
266
0
  }
267
268
0
  if (1 != SSL_CTX_use_certificate_chain_file(ctx, cert)) {
269
0
    msyslog(LOG_ERR, "NTSs: can't load certificate (chain) from %s", cert);
270
0
    nts_log_ssl_error();
271
0
    return false;
272
0
  } else {
273
0
    msyslog(LOG_ERR, "NTSs: loaded certificate (chain) from %s", cert);
274
0
  }
275
0
  if (1 != SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
276
0
    msyslog(LOG_ERR, "NTSs: can't load private key from %s", key);
277
0
    nts_log_ssl_error();
278
0
    return false;
279
0
  } else {
280
0
    msyslog(LOG_ERR, "NTSs: loaded private key from %s", key);
281
0
  }
282
283
0
  if (1 != SSL_CTX_check_private_key(ctx)) {
284
0
    msyslog(LOG_ERR, "NTSs: Private Key doesn't work ******");
285
0
    return false;
286
0
  } else {
287
0
    msyslog(LOG_INFO, "NTSs: Private Key OK");
288
0
  }
289
0
  return true;
290
0
}
291
292
293
0
int nts_ssl_read(SSL *ssl, uint8_t *buff, int buff_length) {
294
0
  int bytes_read;
295
0
  char errbuf[100];
296
0
  bytes_read = SSL_read(ssl, buff, buff_length);
297
0
  if (0 >= bytes_read) {
298
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
299
0
    msyslog(LOG_INFO, "NTS: SSL_read error: %s", errbuf);
300
0
    nts_log_ssl_error();
301
0
    return -1;
302
0
  }
303
0
  return bytes_read;
304
0
}
305
306
0
int nts_ssl_write(SSL *ssl, uint8_t *buff, int buff_length) {
307
0
  int bytes_written;
308
0
  char errbuf[100];
309
0
  bytes_written = SSL_write(ssl, buff, buff_length);
310
0
  if (0 >= bytes_written) {
311
0
    ntp_strerror_r(errno, errbuf, sizeof(errbuf));
312
0
    msyslog(LOG_INFO, "NTS: SSL_write error: %s", errbuf);
313
0
    nts_log_ssl_error();
314
0
    return -1;
315
0
  }
316
0
  return bytes_written;
317
0
}
318
319
/* Each thread has it's own queue of errors */
320
0
void nts_log_ssl_error(void) {
321
0
  char buff[256];
322
0
  int err = ERR_get_error();
323
0
  SSL_load_error_strings();        /* Needed on NetBSD */
324
0
  while (0 != err) {
325
0
    ERR_error_string_n(err, buff, sizeof(buff));
326
0
    msyslog(LOG_INFO, "NTS: %s", buff);
327
0
    err = ERR_get_error();
328
0
  }
329
0
}
330
331
/*****************************************************/
332
333
/* NB: KE length is body length, Extension length includes header. */
334
335
/* Troubles with signed/unsigned compares when using sizeof() */
336
337
0
void ke_append_record_null(BufCtl* buf, uint16_t type) {
338
0
  append_header(buf, type, 0);
339
0
}
340
341
0
void ke_append_record_uint16(BufCtl* buf, uint16_t type, uint16_t data) {
342
0
  if (NTS_KE_HDR_LNG+NTS_KE_U16_LNG > buf->left)
343
0
    return;
344
0
  append_header(buf, type, NTS_KE_U16_LNG);
345
0
  append_uint16(buf, data);
346
0
}
347
348
0
void ke_append_record_bytes(BufCtl* buf, uint16_t type, uint8_t *data, int length) {
349
0
  if (NTS_KE_HDR_LNG+length > buf->left)
350
0
    return;
351
0
  append_header(buf, type, length);
352
0
  append_bytes(buf, data, length);
353
0
}
354
355
0
void ex_append_record_null(BufCtl* buf, uint16_t type) {
356
0
  append_header(buf, type, NTS_KE_HDR_LNG);
357
0
}
358
359
0
void ex_append_record_uint16(BufCtl* buf, uint16_t type, uint16_t data) {
360
0
  if (NTS_KE_HDR_LNG+NTS_KE_U16_LNG > buf->left)
361
0
    return;
362
0
  append_header(buf, type, NTS_KE_HDR_LNG+NTS_KE_U16_LNG);
363
0
  append_uint16(buf, data);
364
0
}
365
366
0
void ex_append_record_bytes(BufCtl* buf, uint16_t type, uint8_t *data, int length) {
367
0
  if (NTS_KE_HDR_LNG+length > buf->left)
368
0
    return;
369
0
  append_header(buf, type, NTS_KE_HDR_LNG+length);
370
0
  append_bytes(buf, data, length);
371
0
}
372
373
0
void ex_append_header(BufCtl* buf, uint16_t type, uint16_t length) {
374
0
  append_header(buf, type, NTS_KE_HDR_LNG+length);
375
0
}
376
377
0
void append_header(BufCtl* buf, uint16_t type, uint16_t length) {
378
0
  uint16_t * ptr = (uint16_t *)buf->next;
379
0
  if (NTS_KE_HDR_LNG > buf->left)
380
0
    return;
381
0
  *ptr++ = htons(type);
382
0
  *ptr++ = htons(length);
383
0
  buf->next += NTS_KE_HDR_LNG;
384
0
  buf->left -= NTS_KE_HDR_LNG;
385
  /* leaves buf pointing to where data will go */
386
0
}
387
388
0
void append_uint16(BufCtl* buf, uint16_t data) {
389
0
  uint16_t * ptr = (uint16_t *)buf->next;
390
0
  if (NTS_KE_U16_LNG > buf->left)
391
0
    return;
392
0
  *ptr++ = htons(data);
393
0
  buf->next += NTS_KE_U16_LNG;
394
0
  buf->left -= NTS_KE_U16_LNG;
395
0
}
396
397
0
void append_bytes(BufCtl* buf, uint8_t *data, int length) {
398
0
  if (length > buf->left)
399
0
    return;
400
0
  memcpy(buf->next, data, length);
401
0
  buf->next += length;
402
0
  buf->left -= length;
403
0
}
404
405
/* Reads type and length of the next record, and moves cursor to the data */
406
4.79k
uint16_t ke_next_record(BufCtl* buf, int *length) {
407
4.79k
  uint16_t *ptr = (uint16_t *)buf->next;
408
4.79k
  uint16_t type = ntohs(*ptr++);
409
4.79k
  *length = ntohs(*ptr++);
410
4.79k
  buf->next += NTS_KE_HDR_LNG;
411
4.79k
  buf->left -= NTS_KE_HDR_LNG;
412
4.79k
  return type;
413
4.79k
}
414
415
790
uint16_t ex_next_record(BufCtl* buf, int *length) {
416
790
  uint16_t *ptr = (uint16_t *)buf->next;
417
790
  uint16_t type = ntohs(*ptr++);
418
790
  *length = ntohs(*ptr++)-NTS_KE_HDR_LNG;
419
790
  buf->next += NTS_KE_HDR_LNG;
420
790
  buf->left -= NTS_KE_HDR_LNG;
421
790
  return type;
422
790
}
423
424
/* Reads a uint16 from the record and advances to the next data */
425
3.64k
uint16_t next_uint16(BufCtl* buf) {
426
3.64k
  uint16_t *ptr = (uint16_t *)buf->next;
427
3.64k
  uint16_t data = ntohs(*ptr++);
428
3.64k
  buf->next += NTS_KE_U16_LNG;
429
3.64k
  buf->left -= NTS_KE_U16_LNG;
430
3.64k
  return data;
431
3.64k
}
432
433
/* Reads a string of bytes from the record and advances to the next data */
434
1.21k
uint16_t next_bytes(BufCtl* buf, uint8_t *data, int length) {
435
1.21k
  memcpy(data, buf->next, length);
436
1.21k
  buf->next += length;
437
1.21k
  buf->left -= length;
438
1.21k
  return length;
439
1.21k
}
440
441
442
/* end */