While adding HTTPS capabilities to my STM32 Nucleo board, I needed to solve the problem of current time. This is because TLS needs to check certificate expiration date, so we need a sufficiently accurate estimation of time. So I tried to understand what could I do to ask a network server about the time. I discovered a couple of protocols that are useful for small devices because they need only basic resources.
The RFC 868 describes the “Time Protocol“, which is a very old but deadly simple way to get the time from a server that implements this service. With this protocol a device is able to retrieve a 32-bit unsigned value indicating the number of seconds that have passed since the 1st of January 1900.
There are two ways to connect to the service: TCP or UDP. With TCP the device connects to port 37 and the server immediately sends back to the device the 32-bit value in 4 bytes (in network byte order); the device can now close the connection. With UDP, the device sends a dummy UDP datagram to port 37 of the server, containing 0 or more bytes whose content is ignored by the server; when the server receives a packet, it replies with the 32-bit value as before.
The precision of this time synchronization can’t be less than a second, moreover the time that passes between the sending and the receiving of the packet may vary. Anyway if we simply want the approximate time of the day, it’s good enough.
The implementation that I used in my Nucleo board is here in rfc868_time.c.
Simple Network Time Protocol
Many people are familiar with NTP, which is the protocol that our PCs use to synchronize the time with time servers around the globe. Its specifications are detailed in RFC 5905, and the precision that can be reached is very high.
But a simpler variant exists, aptly named SNTP and described in RFC 4330. An implementation of this protocol is able to retrieve from a server the timestamp containing the number of seconds from 1st of January 1900 and a fraction of second. A whole timestamp occupies 64 bits, and its value is more precise that what can be achieved by the Time Protocol, especially when the device performs some estimation of packet travel time and clock offset, using the timestamps present in the exchanged packets. The interaction also in this case is simple: it’s about sending a 36-byte UDP packet and receiving a similar packet, whose fields contains the timestamps that are used to synchronize the device clock with the server clock.
The implementation that I used in my Nucleo board is here in sntp.c.
There’s a list of NIST servers that implement the common time protocols here: NIST Internet Time Servers. It is advised to resolve time.nist.gov so that the client points to the nearest non-busy server.