I've been hearing about Network Time Security (NTS) being in development for awhile now. With Cloudflare's release of a public NTS service, I wanted to take a closer look at the protocol and test it out.
The current NTS draft (as of July 2019) goes into the protocol, which has two major pieces.
First piece of NTS is a TLS based service running on TCP. It grants cookies and shared secret keys. I'll save that for another post.
The second piece of NTS is extension headers to NTP that allow the whole packet to be authenticated, and part of it can contain encrypted data.
NTP vs NTS tcpdump comparison
Starting with a simple NTP client for comparison, you can see the UDP packets are 48 bytes long.
Now a pair of NTP packets with NTS extensions, they're much bigger:
Let's break apart that request NTS packet. First, the IPv6+UDP header and the standard NTP packet. I've color-coded the fields. This packet is a NTPv4 client request, and sets most of its fields to 0 as the server does not use them. The server puts the client's transmit timestamp in the originate timestamp field, which can be used to weakly verify the response packet's authenticity.
The new NTS extensions are in the next part of the packet:
This packet is using the NTS extensions for Unique ID, Cookie, and AEAD ("NTS Authenticator and Encrypted Extension Fields").
For the AEAD section, this packet is only using associated data and has no encrypted data. AEAD with only associated data and no plaintext is roughly equivalent to a HMAC, but it uses a symmetric cipher instead of a hashing function. Everything before the 0x404 extension header is authenticated with this header, so no parts of the NTP packet or the NTS extensions can be modified without it being detected. The cookie is encrypted with a separate key not known to the client and it tells the server the session keys to use and which AEAD algorithm was negotiated.
The first part of the response packet are the normal IPv6/UDP/NTP headers:
Not much difference there.
Here, the Unique ID matches the request. But instead of having a cookie, it has a much longer ciphertext. This is because the server included a new cookie (with the 0x204 extension) in the encrypted response. All cookies should be handed to the client in an encrypted form (either through the NTS key exchange, or through the encrypted extensions in the 0x404 header).
I've put together a pair of programs to go through the process of a NTS key exchange, as well as adds the NTS extensions to a NTP request.
Example key exchange:
Example NTP packet:
More posts to come!