Check out the different parts:

Here we will talk about the roughtime time server, and touch a bit on the architecture and security properties. The time reference itself (the time server) is this beauty mess of wires, currently living behind a couch. It has a small cryptographic processor, a GPS and a raspberry pi. This reference propagates the House Standard Time via WiFi.

Server architecture #

Time to build! We partition the time server into two clearly distinct blocks:

  • trusted domain: comprised of a GPS module plus a small RTOS-based microcontroller. Here we implement the following functionality: parsing GPS module NMEA data, key storage, generate cryptographic signatures
  • untrusted domain: a raspberry pi running a golang binary implementing the following functionality: talk to network peers over UDP, construct requests to the trusted domain for signing bundling multiple requests (Merkle tree construction)

Why? The whole point of partitioning this way is to minimize attack surface and compact all the security-critical functionality in a small block. This partition is in a sense optimal: the trusted domain does the minimum amount of work needed, minimizing the trusted codebase. All networking code is offloaded to the raspberry (none of which is security critical), all security-sensitive is in the trusted domain. No secrets live in the raspberry. The worst possible impact of a compromised untrusted domain is availability.

The interface between those two blocks looks essentially like this (less important fields omitted):

typedef struct signing_request_t {
  uint8_t merkle_root[32]; // (merkle-)hash of all client nonces
};

typedef struct signing_response_t {
  uint64_t midpoint; // time at the moment of signing
  uint8_t signature[64]; // essentially, signature over merkle_root + midpoint
};

Note that data in signing_request can be 100% attacker controlled — this is fine and actually a scenario we accept. This means the raspi can be 100% popped (the “only” consequence being reduced availability). Time is not chosen by the untrusted domain, the time reference (the GNSS) is directly fed into the trusted domain. The communication between those two domains is a simple serial line, with no framer (yolo), and fixed size packets (difficult, but not impossible, to screw up). The raspi cannot reflash the microcontroller; a human has to plug a programmer to the microcontroller.