1 /*
2 * nts_cookie.c - Network Time Security (NTS) cookie processing
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/draft-ietf-ntp-using-nts-for-ntp-15
8 *
9 * This follows section 6, Suggested Format for NTS Cookies
10 * It uses AEAD_AES_SIV_CMAC_256/384/512 from RFC 5297
11 * The selection is done by the key length.
12 *
13 * We use the implementation in libaes_siv by Daniel Franke (Akamai)
14 * There is a similar implementation in OpenSSL (or soon will be)
15 * It has a slightly different API. See libaes_siv/README.md
16 *
17 */
18
19 #include "config.h"
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <pthread.h>
29 #include <unistd.h>
30
31 #include <aes_siv.h>
32
33 #include "ntpd.h"
34 #include "ntp_stdlib.h"
35 #include "nts.h"
36 #include "nts2.h"
37
38 /* Cookie format:
39 * cookie is I,N,CMAC,C
40 * I Key index, see below
41 * N nonce
42 * C is encrypt(K, N, P)
43 * P is AEAD, C2S, S2C
44 * length of C2S and S2C depends upon AEAD
45 * CMAC is 16 bytes
46 */
47
48 /* K and I should be preserved across boots, and rotated every day or so.
49 * We need to support the old K/I for another day.
50 *
51 * If the file gets corrupted, blow it away and reboot. It will get
52 * recreated, we will start using new cookies, packets from clients
53 * with old cookies will get dropped, and eventually clients will
54 * run out of cookies and use NTS-KE to get new ones.
55 *
56 * It would be possible to run without a cookie file. Nobody would
57 * notice until the server was restarted. Then there would be a flurry
58 * of NTS-KE requests until all clients obtained new/working cookies.
59 */
60
61 /* Encryption within cookies uses AEAD_AES_SIV_CMAC_nnn. That's the
62 * same family of algorithms as NTS uses on the wire.
63 * The nnn is selected by the key length.
64 * 32 => 256
65 * 48 => 384
66 * 64 => 512
67 */
68
69 /* NTS_MAX_COOKIELEN:
70 * 4 I
71 * 16 N
72 * 16 CMAC
73 * 4 AEAD
74 * 64 C2S NTS_MAX_KEYLEN
75 * 64 S2C NTS_MAX_KEYLEN
76 * ------
77 * 168
78 *
79 * That's the max length for our cookies.
80 * Round up a bit in case another implementation uses more.
81 * #define is in include/nts.h
82 */
83
84 /* cookies use same AEAD algorithms as wire */
85 /* This determines which algorithm we use.
86 * Valid choices are 32, 48, and 64
87 * making this a variable rather than #define
88 * opens up the opportunity to pick one at run time.
89 * The default (below) is 32/AEAD_AES_SIV_CMAC_256
90 * You can change that by editing the keys file.
91 */
92 int K_length = AEAD_AES_SIV_CMAC_256_KEYLEN;
93 uint8_t K[NTS_MAX_KEYLEN], K2[NTS_MAX_KEYLEN];
94 uint32_t I, I2;
95 time_t K_time = 0; /* time K was created, 0 for none */
96
97 /* The mutex protects cookie_ctx
98 * The NTS-KE servers can make cookies
99 * while the main NTP server thread is unpacking and making cookies.
100 * If this becomes a bottleneck, we could use a cookie_ctx per thread. */
101 pthread_mutex_t cookie_lock = PTHREAD_MUTEX_INITIALIZER;
102 AES_SIV_CTX* cookie_ctx;
103
104 /* Statistics for ntpq */
105 uint64_t nts_cookie_make = 0;
106 uint64_t nts_cookie_decode = 0;
107 uint64_t nts_cookie_decode_old = 0;
108 uint64_t nts_cookie_decode_too_old = 0;
109 uint64_t nts_cookie_decode_error = 0;
110
111 void nts_lock_cookielock(void);
112 void nts_unlock_cookielock(void);
113
114 // FIXME AEAD_LENGTH
115 /* Associated data: aead (rounded up to 4) plus NONCE */
116 #define AD_LENGTH 20
117 #define AEAD_LENGTH 4
118
119 /* cookie_ctx needed for client side */
nts_cookie_init(void)120 bool nts_cookie_init(void) {
121 cookie_ctx = AES_SIV_CTX_new();
122 if (NULL == cookie_ctx) {
123 msyslog(LOG_ERR, "NTS: Can't init cookie_ctx");
124 exit(1);
125 }
126 return true;
127 }
128
129 /* cookie key needed for server side */
nts_cookie_init2(void)130 bool nts_cookie_init2(void) {
131 bool OK = true;
132 if (!nts_read_cookie_keys()) {
133 nts_make_cookie_key(); /* make new cookie key */
134 nts_make_cookie_key(); /* push new to old, make new */
135 K_time = time(NULL);
136 nts_write_cookie_keys();
137 }
138 return OK;
139 }
140
141 /* Rotate key -- 24 hours after last rotate
142 * That allows a cluster NTS-KE server to keep in sync
143 * if we use ratchet rather than random.
144 */
145 #define SecondsPerDay (24*60*60)
146 // Set this shorter for debugging
147 // keys will timeout, packets will get dropped
148 // after 8 lost packets, it should go through the NTS-KE dance again
149 // #define SecondsPerDay 3600
nts_cookie_timer(void)150 void nts_cookie_timer(void) {
151 time_t now;
152 if (0 == K_time) {
153 return;
154 }
155 now = time(NULL);
156 if (SecondsPerDay > (now-K_time)) {
157 return;
158 }
159 nts_make_cookie_key();
160 /* In case we were off for many days. */
161 while (SecondsPerDay < (now-K_time)) {
162 K_time += SecondsPerDay;
163 }
164 if (nts_write_cookie_keys() )
165 msyslog(LOG_INFO, "NTS: Wrote new cookie key.");
166 else
167 msyslog(LOG_INFO, "NTS: Trouble writing new cookie key.");
168 return;
169 }
170
171
nts_read_cookie_keys(void)172 bool nts_read_cookie_keys(void) {
173 const char *cookie_filename = NTS_COOKIE_KEY_FILE;
174 FILE *in;
175 unsigned long templ;
176 if (NULL != ntsconfig.KI)
177 cookie_filename = ntsconfig.KI;
178 in = fopen(cookie_filename, "r");
179 if (NULL == in) {
180 char errbuf[100];
181 if (ENOENT == errno)
182 return false; /* File doesn't exist */
183 ntp_strerror_r(errno, errbuf, sizeof(errbuf));
184 msyslog(LOG_ERR, "NTSs: can't read old cookie file: %s=>%s",
185 cookie_filename, errbuf);
186 exit(1);
187 }
188 if (1 != fscanf(in, "T: %lu\n", &templ)) {
189 goto bail;
190 }
191 K_time = templ;
192 if (1 != fscanf(in, "L: %d\n", &K_length)) {
193 goto bail;
194 }
195 if ( !((32 == K_length) || (48 == K_length) || (64 == K_length))) {
196 goto bail;
197 }
198 if (1 != fscanf(in, "I: %u\n", &I)) {
199 goto bail;
200 }
201 if (0 != fscanf(in, "K: ")) {
202 goto bail;
203 }
204 for (int i=0; i< K_length; i++) {
205 unsigned int temp;
206 if (1 != fscanf(in, "%02x", &temp)) {
207 goto bail;
208 }
209 K[i] = temp;
210 }
211 if (0 != fscanf(in, "\n")) {
212 goto bail;
213 }
214 if (1 != fscanf(in, "I: %u\n", &I2)) {
215 goto bail;
216 }
217 if (0 != fscanf(in, "K: ")) {
218 goto bail;
219 }
220 for (int i=0; i< K_length; i++) {
221 unsigned int temp;
222 if (1 != fscanf(in, "%02x", &temp)) {
223 goto bail;
224 }
225 K2[i] = temp;
226 }
227 if (0 != fscanf(in, "\n")) {
228 goto bail;
229 }
230 fclose(in);
231 return true;
232
233 bail:
234 msyslog(LOG_ERR, "ERR: Error parsing cookie keys file");
235 fclose(in);
236 return false;
237 }
238
239 /* The draft describes a ratchet mode to make new keys
240 * That's one way to implement a KE server for a cluster of NTP servers.
241 * The KE server and the NTP servers stay in sync without communication
242 * after a one-time copy of the cookie file from NTP server to KE server.
243 */
nts_make_cookie_key(void)244 void nts_make_cookie_key(void) {
245 memcpy(&K2, &K, sizeof(K2)); /* Push current cookie to old */
246 I2 = I;
247 ntp_RAND_priv_bytes(K, sizeof(K));
248 ntp_RAND_bytes((uint8_t *)&I, sizeof(I));
249 return;
250 }
251
nts_write_cookie_keys(void)252 bool nts_write_cookie_keys(void) {
253 const char *cookie_filename = NTS_COOKIE_KEY_FILE;
254 int fd;
255 FILE *out;
256 char errbuf[100];
257 if (NULL != ntsconfig.KI)
258 cookie_filename = ntsconfig.KI;
259 fd = open(cookie_filename, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
260 if (-1 == fd) {
261 ntp_strerror_r(errno, errbuf, sizeof(errbuf));
262 msyslog(LOG_ERR, "ERR: can't open %s: %s", cookie_filename, errbuf);
263 return false;
264 }
265 out = fdopen(fd, "w");
266 if (NULL == out) {
267 ntp_strerror_r(errno, errbuf, sizeof(errbuf));
268 msyslog(LOG_ERR, "ERR: can't fdopen %s: %s", cookie_filename, errbuf);
269 close(fd);
270 return false;
271 }
272 fprintf(out, "T: %lu\n", (unsigned long)K_time);
273 fprintf(out, "L: %d\n", K_length);
274 fprintf(out, "I: %u\n", I);
275 fprintf(out, "K: ");
276 for (int i=0; i< K_length; i++) fprintf(out, "%02x", K[i]);
277 fprintf(out, "\n");
278 fprintf(out, "I: %u\n", I2);
279 fprintf(out, "K: ");
280 for (int i=0; i< K_length; i++) fprintf(out, "%02x", K2[i]);
281 fprintf(out, "\n");
282 fclose(out);
283 return true;
284 }
285
286 /* returns actual length */
nts_make_cookie(uint8_t * cookie,uint16_t aead,uint8_t * c2s,uint8_t * s2c,int keylen)287 int nts_make_cookie(uint8_t *cookie,
288 uint16_t aead,
289 uint8_t *c2s, uint8_t *s2c, int keylen) {
290 uint8_t plaintext[NTS_MAX_COOKIELEN];
291 uint8_t *nonce;
292 int used, plainlength;
293 bool ok;
294 uint8_t * finger;
295 uint32_t temp; /* keep 4 byte alignment */
296 size_t left;
297
298 if (NULL == cookie_ctx)
299 return 0; /* We aren't initialized yet. */
300
301 nts_cookie_make++;
302
303 INSIST(keylen <= NTS_MAX_KEYLEN);
304
305 /* collect plaintext
306 * separate buffer avoids encrypt in place
307 * but costs cache space
308 */
309 finger = plaintext;
310 temp = aead;
311 memcpy(finger, &temp, AEAD_LENGTH);
312 finger += AEAD_LENGTH;
313 memcpy(finger, c2s, keylen);
314 finger += keylen;
315 memcpy(finger, s2c, keylen);
316 finger += keylen;
317 plainlength = finger-plaintext;
318
319 /* collect associated data */
320 finger = cookie;
321
322 memcpy(finger, &I, sizeof(I));
323 finger += sizeof(I);
324
325 nonce = finger;
326 ntp_RAND_bytes(finger, NONCE_LENGTH);
327 finger += NONCE_LENGTH;
328
329 used = finger-cookie;
330 left = NTS_MAX_COOKIELEN-used;
331
332 nts_lock_cookielock();
333
334 ok = AES_SIV_Encrypt(cookie_ctx,
335 finger, &left, /* left: in: max out length, out: length used */
336 K, K_length,
337 nonce, NONCE_LENGTH,
338 plaintext, plainlength,
339 cookie, AD_LENGTH);
340
341 nts_unlock_cookielock();
342
343 if (!ok) {
344 msyslog(LOG_ERR, "NTS: nts_make_cookie - Error from AES_SIV_Encrypt");
345 /* I don't think this should happen,
346 * so crash rather than work incorrectly.
347 * Hal, 2019-Feb-17
348 * Similar code in ntp_extens
349 */
350 exit(1);
351 }
352
353 used += left;
354 INSIST(used <= NTS_MAX_COOKIELEN);
355
356 return used;
357 }
358
359 /* can't decrypt in place - that would trash the unauthenticated packet */
nts_unpack_cookie(uint8_t * cookie,int cookielen,uint16_t * aead,uint8_t * c2s,uint8_t * s2c,int * keylen)360 bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
361 uint16_t *aead,
362 uint8_t *c2s, uint8_t *s2c, int *keylen) {
363 uint8_t *finger;
364 uint8_t plaintext[NTS_MAX_COOKIELEN];
365 uint8_t *key;
366 uint8_t *nonce;
367 uint32_t temp;
368 size_t plainlength;
369 int cipherlength;
370 bool ok;
371
372 if (NULL == cookie_ctx)
373 return false; /* We aren't initialized yet. */
374
375 /* We may get garbage from the net */
376 if (cookielen > NTS_MAX_COOKIELEN)
377 return false;
378
379 finger = cookie;
380 if (0 == memcmp(finger, &I, sizeof(I))) {
381 key = K;
382 nts_cookie_decode++;
383 } else if (0 == memcmp(finger, &I2, sizeof(I2))) {
384 key = K2;
385 nts_cookie_decode_old++;
386 } else {
387 nts_cookie_decode_too_old++;
388 return false;
389 }
390 finger += sizeof(I);
391 nonce = finger;
392 finger += NONCE_LENGTH;
393
394 // require(AD_LENGTH==finger-cookie);
395
396 cipherlength = cookielen - AD_LENGTH;
397 plainlength = NTS_MAX_COOKIELEN;
398
399 nts_lock_cookielock();
400
401 ok = AES_SIV_Decrypt(cookie_ctx,
402 plaintext, &plainlength,
403 key, K_length,
404 nonce, NONCE_LENGTH,
405 finger, cipherlength,
406 cookie, AD_LENGTH);
407
408 nts_unlock_cookielock();
409
410 if (!ok) {
411 nts_cookie_decode_error++;
412 return false;
413 }
414
415 *keylen = (plainlength-AEAD_LENGTH)/2;
416 finger = plaintext;
417 memcpy(&temp, finger, AEAD_LENGTH);
418 *aead = temp;
419 finger += AEAD_LENGTH;
420 memcpy(c2s, finger, *keylen);
421 finger += *keylen;
422 memcpy(s2c, finger, *keylen);
423 finger += *keylen;
424
425 return true;
426 }
427
nts_lock_cookielock(void)428 void nts_lock_cookielock(void) {
429 int err = pthread_mutex_lock(&cookie_lock);
430 if (0 != err) {
431 msyslog(LOG_ERR, "ERR: Can't lock cookie_lock: %d", err);
432 exit(2);
433 }
434 }
435
nts_unlock_cookielock(void)436 void nts_unlock_cookielock(void) {
437 int err = pthread_mutex_unlock(&cookie_lock);
438 if (0 != err) {
439 msyslog(LOG_ERR, "ERR: Can't unlock cookie_lock: %d", err);
440 exit(2);
441 }
442 }
443
444 /* end */
445