- rtc_update API does nothing if no RTC. - rtc_get API returns 0 if no RTC. |
||
---|---|---|
.. | ||
crypto | ||
storage | ||
Readme.md | ||
mbed_lib.json | ||
secure_time_client.h | ||
secure_time_client_direct.c | ||
secure_time_client_spe.h | ||
secure_time_client_spe_direct.c | ||
secure_time_impl.c | ||
secure_time_impl.h | ||
secure_time_utils.cpp | ||
secure_time_utils.h |
Readme.md
Secure time
Table of Contents:
Overview
In IoT applications, a trusted source of time is needed to, among other things, ensure the confidentiality and integrity of network connections. This is largely due to the fact that X.509 certificates are used by TLS stack to establish a secure connection between the device and any services. TLS stack enforces X.509 certificate expiration with a required accuracy of up to one hour.
To protect against an attacker who might use an expired certificate to pretend to be a trusted web service, IoT devices need a mechanism for ensuring that they have an internal system time that is accurate to a specified fidelity.
The secure time module supports setting the time from both trusted and regular time sources.
Setting regular time
For regular operations, time source does not require trust requirements.
When setting the time from a regular time source:
- Time data is plain 64-bit value of seconds since UNIX epoch.
- The user can move time forward with no restrictions.
- The user can move time backward only slightly. Up to 3 minutes per day or 1 second per 8 minutes. This is used for natural clock drift adjustment.
See secure_time_set()
in secure_time_client.h.
Setting trusted time
For operations that must trust the current time of the device, time source must be a trusted one.
Setting the time, obtained from a trusted time source (e.g. trusted time server):
- Time data is 64-bit value of seconds since UNIX epoch, which is encapsulated inside a signed blob, which a trusted authority signs.
- The user can move time forward and backward with no restrictions.
- Time is valid only if the blob passes verification for authenticity and freshness.
- Verifying the signature with the aid of a factory-provisioned public key guarantees authenticity.
- Using a nonce guarantees freshness. The device generates the nonce, saves it and sends it to the trusted time source to be encapsulated in the blob and verified when the time blob reaches the device.
See secure_time_set_trusted_init()
and secure_time_set_trusted_commit()
in
secure_time_client.h.
Signed blob content
|---------- signed fields -------------------|
v v
|---------|-----|----------------|-----------|---------|----|
|timestamp|nonce|delegations_size|delegations|sign_size|sign|
|---------|-----|----------------|-----------|---------|----|
^ ^ ^ ^ ^ ^
| | | | | |
| | | | | --- DER-encoded signature
| | | | | over the signed fields.
| | | | |
| | | | --- Size of the following
| | | | signature, 16-bit unsigned
| | | | integer in Little Endian format.
| | | |
| | | --- 0 or more delegation records.
| | |
| | --- Size of the following delegation records,
| | 16-bit unsigned integer in Little Endian format.
| |
| -------- 64-bit nonce generated by Secure Time code.
|
------ 64-bit value of seconds since UNIX epoch in Little Endian format.
Blob content description
- timestamp - 64-bit value of seconds since UNIX epoch in Little Endian format.
- nonce - 64-bit nonce generated by Secure Time code for validating time blob freshness.
- delegations_size - size of following delegation records, 16-bit unsigned integer in Little Endian format. 0 size means no delegations are provided.
- delegations - 0 (delegations_size==0) or more delegation records for supporting trust chains.
- sign_size - 16-bit Little Endian size in bytes of the following DER-encoded signature.
- signature - DER-encoded signature over signed fields using either CA (delegations_size==0) or delegation private key.
Each delegation record consists of:
- key_len - 16-bit Little Endian size in bytes of the following DER-encoded public key.
- DER-encoded public key.
- Signature size - 16-bit Little Endian size in bytes of the following DER-encoded signature.
- DER-encoded signature over key size and key fields.
|------------------ First delegation ---------| |----------------- N-th delegation -------------|
| | | |
|-- Signed fields -----| | |-- Signed fields -----| |
v v v v v v
|-----------|----------|-------------|--------| .. |-----------|----------|------------- |---------|
|Key_size(1)|Pub_key(1)|Sign_size(CA)|Sign(CA)| .. |Key_size(N)|Pub_key(N)|Sign_size(N-1)|Sign(N-1)|
|-----------|----------|-------------|--------| .. |-----------|----------|------------- |---------|
^ ^ ^ ^ ^
| | | | |
| | | | Signature using Nth-1 private key over ---
| | | | Nth public key & size fields
| | | |
| | | --- DER-encoded signature over the signed
| | | fields using CA private key.
| | |
| | --- Signature size - 16-bit value in Little Endian format.
| |
| --- First public key.
|
--- 16-bit value in Little Endian format.
In case no delegation records are present (delegations_size==0) - the time blob is signed by CA using its private key.
CA public key expected to be available on the device using factory provisioning.
A single delegation record is combined from the size of DER-encoded public key, DER-encoded public key, size of DER-encoded signature and DER-encoded signature over that public key and size fields using private key belonging to signing authority located downstream on the trust chain. The signature is represented using signature size and signature data.
Secure Time code performing blob's authenticity verification acts as follows:
- Delegation records are processed from left to right.
- The blob's signature is validated using the CA public key in case no delegations are provided. Alternatively, in case when one or more delegation records are present, the last (rightmost) public key in the delegation chain is used to verify time blob signature.
Getting current time
See secure_time_get()
in secure_time_client.h.