Network Time Security
Update: Code available on Github.
The Network Time Protocol (NTP) was born on an interesting PDP-11 operating system called Fuzzball. Fuzzballs were used as routers in the National Science Foundation part of the early Internet. They were remarkably picky about time synchronization.
NTP has been with us ever since and most of Internet (and more) relies on the venerable NTP to synchronize clocks. It's probably one of the oldest protocols still in use.
$DAYJOB keeps a hardware (Verilog) implementation of NTP with attached
atomic clocks running in several locations in Sweden. Yes, you speak NTP
directly to the FPGA chip! No software involved! The service is
available to the public worldwide on
ntp.se, which resolves to anycast
v4 and v6 addresses.
This is, for most purposes, the Swedish time. More about this on Netnod's project pages.
But can you trust it? How do you know that the packets comes from the right sender? UDP spoofing is simple and NTP runs on top of UDP. Most(?) NTP clients use a random TransmitTime in their requests to mitigate this, but it's still sensitive to a man in the middle attack.
NTPv3 introduced support for symmetric authentication on time data using pre-shared keys. It's unchanged in the current v4 of the protocol. It looks remarkably old-fashioned to modern eyes. It's similar to TSIG in DNS, which is also dated, but a bit more useful than the NTP authentication. I think NTP authentication as it currently stands is very seldom used.
Network Time Security (NTS) is an attempt in the IETF NTP working group to change the NTP authentication to something slightly more useful.
None of us has had much to do with the NTP project before, so we knew next to nothing when we started.
We couldn't attend the IETF meeting in Montreal physically, so we spent two days in Netnod's Malmö office instead. Well, evenings and nights, really, in some effort to match the time zone in Montreal and, of course, because it's a well-known fact that you hack best at night, occassionally boosted by Club-Mate.
We coordinated work mostly on ##nts on FreeNode and the occasional MeetEcho video conference provided by the IETF, to be able to see the kickoff and the presentations at the end of the hackathon.
We started with Brett Vickers' Go NTP package which is a pure-Go SNTP implementation. SNTP is a simpler version of the NTP protocol but wire-compatible with its big brother, so we thought it would probably work for our purposes.
However, Brett's package only supports client-side SNTP, so we cut and pasted from internal structures to quickly whip together a very basic SNTP server.
NTS-KE, the key exchange part of NTS, is based on TLS. Go's own TLS implementation doesn't support TLS 1.3 and no RFC 5705 key extraction. Instead, we found the mint TLS 1.3 library and used that to create basic TLS clients and servers. Unfortunately, mint only supports draft-22 of TLS 1.3, but we found a pull request supposedly bringing it up to draft-28.
It worked fine against Mozilla's TLS 1.3-only (HTTPS) test server,
but not against Martin Langer's OpenSSL-based NTS test server. We got TLS handshake errors. We gave up trying to make it work. It will probably work fine in the end when mint has been brought up to date.
On top of our TLS client and server we used mint's RFC 5705-support to extract keys, then negotiate the "ntske/1" ALPN application protocol on top of TLS. Inside all of that we implemented NTS-KE proper which turned out to be a really simple protocol.
The thing we had the most problem with was the cookies. We had a few false starts. It finally dawned on us after reading about the very similar TLS session tickets in RFC 5077.
What we accomplished:
- NTS-KE client that sends a request and can parse NTS-KE replies.
- NTS-KE server with hardcoded replies.
- A very basic SNTP client.
- A very basic SNTP server.
- Communication between the NTS-KE client and the SNTP client to send initial cookie and key material.
- Learned a lot and had a lot of fun!
- After the hackathon proper: Saw some very nice C64 demos and drank a few beers.
Still left to do:
- Implement NTP Extension fields in Brett's NTP package.
- Implement NTS using the extension fields.
- Generating cookies.
- Management of shared secret between the NTS-KE server and the NTP server for encryption of cookies.
We worked on FreeBSD and Linux machines but the code is very portable and cross-compiled cleanly to Windows, but we haven't yet tested anything on Windows.
I haven't touched this since the hackathon. The code is still in a private repo. It will probably end up on Github.