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