MC's journal

Pungenday, the 67 day of Confusion in the YOLD 3184

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, 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.

During the IETF 102 hackathon (14–15 July) I teamed up with my friends Daniel "quite" Lublin, omni and raccoon to make an attempt at implementing the Dansarie NTS spec $DAYJOB has contributed to.

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:

Still left to do:

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.

Written by MC using Emacs and friends.