RTC Anti-rollback: Difference between revisions

From OLPC
Jump to navigation Jump to search
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
<noinclude>[[Category:Firmware]][[Category:Security]][[Category:Hardware]]{{TOCright}}</noinclude>
<noinclude>[[Category:Firmware]][[Category:Security]][[Category:Hardware]]{{TOCright}}</noinclude>
== Purpose ==
== Purpose and overview ==


RTC anti-rollback (RTCAR) is a Open Firmware based security feature intended to prevent "RTC rollback attacks" - subversion of timed leases by setting the real-time clock backward in time.
RTC anti-rollback (RTCAR) is a Open Firmware based security feature intended to prevent "RTC rollback attacks" - subversion of timed leases by setting the real-time clock backward in time.


RTCAR works by recording a series of timestamps in SPI FLASH, thus recording the dates and times of recent boots. When starting the OS, Open Firmware compares the current RTC value with the most recent stored value. If the stored value is later than the current value, the RTC is deemed to have been "rolled back" and boots in "activation mode". This limits the effectiveness of rollback attacks.
RTCAR works by recording a series of timestamps in SPI FLASH, thus recording the dates and times of recent boots. When starting the OS, Open Firmware compares the current RTC value with the most recent stored value. If the stored value is later than the current value, the RTC is deemed to have been "rolled back" and boots in "activation mode", effectively preventing the system from booting normally. This limits the effectiveness of rollback attacks.


The series of recorded timestamps is protected from attack by existing lockout mechanisms that prevent the writing of SPI FLASH by any entity other than Open Firmware.
The series of recorded timestamps is protected from attack by existing lockout mechanisms that prevent the writing of SPI FLASH by any entity other than Open Firmware.
Line 10: Line 10:
The timestamp storage format is chosen so that the relatively-dangerous operation of erasing a block of SPI FLASH is done only infrequently, only the order of every 6,500 reboots.
The timestamp storage format is chosen so that the relatively-dangerous operation of erasing a block of SPI FLASH is done only infrequently, only the order of every 6,500 reboots.


The activation mode initramfs attempts to contact a server that can automatically recover the system upon event of corruption of the last recorded timestamp value.
== OFW Behavior ==


This page details the high-level behaviour of the system, and the items in which deployment technicians may need to interact with. Lower level implementation details can be found on the [[/Implementation]] page.
* RTCAR is performed only in secure mode.
* The RTCAR recovery test (see [[#RTCAR Recovery]]) is performed just after the test for firmware update in [[Firmware_security#Process]].
* The RTCAR boot test is performed only if the "ak" tag is not present in [[Manufacturing data]].
* The RTCAR boot test is performed just prior to the test for a valid lease in [[Firmware_security#Process]]. In the presence of rollback or corruption, OFW will boot from actos/actrd. Otherwise it will boot from either runos/runrd or actos/actrd according to the presence or absence of a valid activation lease. In other words, apparent RTC rollback is treated as a missing or invalid lease.
* OFW records the status of the RTCAR check by creating properties in the device tree ''/chosen'' node as follows:
** Property name: '''rtc-timestamp''' Property value: Null-terminated ASCII string containing the value of the most recent preexisting (prior to the current boot) timestamp. The timestamp format is http://en.wikipedia.org/wiki/ISO_8601 , using the UTC timezone, e.g. "20110324T093447\0". The date and time come directly from the contents of the real time clock registers, with no offsetting or other adjustment beyond conversion from the internal BCD storage format into decimal ASCII. If there is no previously-recorded timestamp, as would be the case if '''rtc-status''' contained "empty", the '''rtc-timestamp''' property will not be present.
** Property name: '''rtc-count''' Property value: Null-terminated ASCII string containing a decimal number indicating the number of timestamps that have been recorded up to and including the most recent preexisting (prior to the current boot) one. It is possible, though unlikely, that '''rtc-timestamp''' could be missing even though '''rtc-count''' is nonzero. It is also possible, and similarly unlikely, that '''rtc-count''' could be zero with '''rtc-timestamp''' present. The real guarantee is that '''rtc-count''' will increment on each boot. In the absence of RTCAR recovery operations, the '''rtc-count''' value should accurately reflect the number of timestamps that have been recorded over the lifetime of the system.
** Property name: '''rtc-status''' Property value: Null-terminated ASCII string containing one of the following values:
*** "ok" - the RTC timestamp area is valid and the RTC value is more recent than the last timestamp. In this case, OFW will create a new timestamp recording the current RTC value, for use on the next boot. The timestamp that is exported via the "rtc-timestamp" property is the previously-recorded one, not the new one.
*** "empty" - the RTC timestamp area was initially empty, i.e. no timestamps were recorded in it. In this case, OFW will automatically initialize the timestamp area and create a new timestamp recording the current RTC value, for use on the next boot. This case is not considered as a "rollback", so OFW will not force the use of actos/actrd. The "rtc-timestamp" property will be absent, as no previously-recorded timestamp information is available.
*** "residue" - the RTC timestamp area contained some data, but there was a problem with it, such as an invalid checksum or junk after the last timestamp. This case is considered as a possible attack, so OFW forces the use of actos/actrd. OFW does not record a new timestamp. The "rtc-timestamp" property may be present or absent, according to whether or not there was at least one valid timestamp.
*** "rollback" - the RTC timestamp area is valid format-wise, but the most recent timestamp is later than the current RTC time. This case is considered a possible rollback attempt, so OFW forces the use of actos/actrd. OFW does not record a new timestamp. The "rtc-timestamp" property contains the most recent timestamp, i.e. the one that was more recent than the current RTC value.


== initramfs behaviour ==
== RTCAR properties ==

The activation initramfs (from [[dracut-modules-olpc]]) implements the user-visible behaviour of this system.

* As described above, OFW automatically boots the activation initramfs (actos/actrd) upon detecting rollback or corruption.
* The initramfs observes the presence of the chosen/rtc-* nodes. If rtc-status is "residue" or "rollback", the following steps are executed. Otherwise, the activation initramfs continues with its "normal" behaviour (where it assumes the laptop lacks activation and looks for an activation lease on USB, SD and wifi).
* Instead of searching for an activation, the initramfs enters an alternative mode where it looks for a RTC timestamp reset signature via the network.
* The initramfs connects one by one to all open wifi networks in range, and on each network, connects to the RTC timestamp reset server on the XS predefined addresses on TCP port 191. The logic used here is identical to that used when looking for an activation server.
* When connected to a server, the initramfs sends the message <tt>rtcreset <SERIAL> <RTC-TIMESTAMP> <RTC-COUNT></tt> (e.g. <tt>rtcreset SHC01601310 20200101T000113Z 19</tt>). This is different from the usual message when an activation is sought, where the message would consist of the laptop serial number alone.
* The server may then respond with a RTC timestamp reset signature sent as plain-text.
* If a response is received, the initramfs will save the contents of the response at /security/rtcreset.sig and cleanly reboot the system.
** Upon reboot, as noted above, the [[#RTCAR Recovery]] procedure is executed, which will cause OFW to reprogram the rtc-timestamp field based on the response received from the server.
* If no response is received, the initramfs prints an error message and powers down the XO after a 60 second delay.


Three properties are defined to diagnose and control the state of this system.
In summary, if OFW detects a rollback or rtc-timestamp problem, the activation initramfs is booted. The initramfs attempts to obtain a RTC reset signature from a local server, but if this fails, the system will refuse to boot and power itself off after a short delay.


# '''rtc-timestamp''': Thie property contains the value of the most recent preexisting (prior to the current boot) timestamp. If there is no previously recorded timestamp, this property is not present.
== Viewing RTCAR property values ==
# '''rtc-count''': This property indicates how many timestamps have been recorded. In other words, this property counts how many times the system has been booted.
# '''rtc-status''': This property indicates the current state of the system, and contains one of the following values:
#* "ok" - the RTC timestamp area is valid and the RTC value is more recent than the last timestamp. The system is running normally.
#* "empty" - the RTC timestamp area was initially empty, i.e. no timestamps were recorded in it. A new timestamp will be recorded and presented on next boot. This case is not considered as a "rollback".
#* "residue" - the RTC timestamp area contained some data, but there was a problem with it (e.g. corruption). This case is considered as a possible attack, so the system will hereon refuse to boot normally.
#* "rollback" - the RTC timestamp is later than the current RTC time. This indicates that the clock was rolled back. This case is considered a possible rollback attempt, so the system will hereon refuse to boot normally.


These RTCAR properties can be viewed from Linux with the following terminal commands:
From Linux:
echo $(</proc/device-tree/chosen/rtc-timestamp>
echo $(</proc/device-tree/chosen/rtc-timestamp)
echo $(</proc/device-tree/chosen/rtc-count>
echo $(</proc/device-tree/chosen/rtc-count)
echo $(</proc/device-tree/chosen/rtc-status>
echo $(</proc/device-tree/chosen/rtc-status)


: If /proc/device-tree/ does not exist (i.e. on old builds), use /ofw/ instead.
: If /proc/device-tree/ does not exist (i.e. on old builds), use /ofw/ instead.
Line 55: Line 38:
ok rtc-rollback? .
ok rtc-rollback? .
ok dev /chosen .properties dend
ok dev /chosen .properties dend

== initramfs behaviour ==

When OFW detects a RTCAR-related problem (e.g. attack or corruption), it will first look for a rtc-timestamp reset signature on all available internal/external media (more details on this are presented below). If no such signature is found, rather than booting the system as normal, the activation initramfs is booted.

Instead of running the normal activation code (which looks for an activation on USB/SD and then looks on the network), the initramfs will enter a "RTC timestamp recovery mode". The assumption here is that the system has failed to boot because of a problem with the rtc-timestamp property (while the RTC correctly contains the current date/time): rtc-timestamp may be corrupt, or may incorrectly contain a future date.

In this mode, the initramfs scans for open wireless networks and connects to them one by one. Once connected, the initramfs attempts to connect to a <em>RTC timestamp reset server</em> on a set of predefined addresses. If a connection is established, the initramfs asks the server for a rtc-timestamp reset signature. This signature includes a new value to be written into the rtc-timestamp property.

If the server provides a response, the RTC reset signature is saved to disk and the system is immediately rebooted. Upon rebooting, the firmware detects the RTC reset signature and reprograms rtc-timestamp based on the server's response.

If the newly programmed rtc-timestamp is less than the current date/time as reported by the RTC, the system now boots normally. However, if the rtc-timestamp value is newer than the RTC's date/time, the system will boot again into the activation initramfs and the above cycle will repeat. Such a situation possibly indicates that the problem preventing boot was not with the rtc-timestamp value (as assumed above), but instead with the RTC value (indicating a possible rollback attack).

If a rollback attack has happened, the above rtc-timestamp recovery procedure will not produce fruitful results (either not finding a server, or not recieving a rtc-timestamp which satisfies the system) and the system will refuse to boot after a short time, reporting the error message "Problem with system clock". The XO will then automatically power off after 60 seconds.

In summary, if a rollback or rtc-timestamp problem is detected, the activation initramfs is booted. The initramfs attempts to obtain a RTC reset signature from a local server which will restore the system to usable state in the face of rtc-timestamp corruption problems, but if this fails (e.g. because a rollback attack was attempted), the system will refuse to boot and power itself off after a short delay.


== Recovery ==
== Recovery ==
Line 77: Line 76:
=== Invalid or corrupted RTC timestamp ===
=== Invalid or corrupted RTC timestamp ===


The other possible failure case is where the RTC has the correct time value, but the rtc-timestamp value recorded is either invalid or corrupt. One simple cause of such a situation is that the RTC held (for whatever reason) a future time/date, and the system was booted in this condition causing rtc-timestamp to similarly record a future time/date. Upon correcting the RTC time to the current date/time, the system will detect a rollback, and the system will fail to boot. The recovery process involves resetting the firmware's rtc-timestamp value to one that is behind the current RTC date/time.
The other possible failure case is where the RTC has the correct time value, but the rtc-timestamp value recorded is either invalid or corrupt. One simple cause of such a situation is that the RTC held (for whatever reason) a future time/date, and the system was booted in this condition causing rtc-timestamp to similarly record a future time/date. Upon (innocently) correcting the RTC time to the current date/time, the system will detect a rollback, and the system will fail to boot.


OFW will repair the timestamp area if a suitable RTC timestamp reset signature is present in /security, as detailed below.
The recovery process involves resetting the firmware's rtc-timestamp value to one that is behind the current RTC date/time. A signed RTC timestamp reset signature must be provided, containing a new value that will be automatically programmed into the rtc-timestamp property.


The RTC timestamp reset signature can be obtained from various sources:
* The name of the RTCAR recovery control file is "/security/rtcreset.sig"
* OFW will search internal and external media for a valid signed file at /security/rtcreset.sig. If found, the rtc-timestamp will be reprogrammed to the value specified by the file.
* The signing key is the same one that is used to sign activation leases - either the OLPC key or a deployment-specific key.
* Otherwise, as detailed elsewhere on this page, the activation initramfs will attempt to obtain this signature from a local server.
* The file contains one or more "rtc01:"-format records as defined in [[Firmware_Key_and_Signature_Formats#RTC_Set]]
* The "sig01:" or "sig02:" field must have a key signature that matches a public key in the laptop's list of activation keys.
* The signed data must verify according to that key.
* The serial number in the rtc01: record must match the laptop's serial number.
* The ''currentrtc'' value in the rtc01: record must match the value that was last reported in the '''rtc-timestamp''' property. If the old timestamp is unknown (as might be the case if '''rtc-status''' were "residue" and no timestamp were found in the corrupted timestamp area), ''currentrtc'' must be set to the value "00000000T000000Z".
* The ''nonce'' value in the rtc01: record must be a 10-digit decimal ASCII number in the range 0000000000..2147483647, indicating the timestamp count value to restore. After insertion of the new timestamp, the new count will be "count+1". In general, ''nonce'' should be the same value that was reported in the '''rtc-count''' property, or 0000000000 if there was no such property. OFW does not check that '''nonce''' matches the value of '''rtc-count''' that is implied by the previous state of the timestamp area.
* If all the checks succeed, the ''newrtc'' value in the rtc01: record will be recorded as a new timestamp after restoring valid contents in the timestamp recording area.
* If any of the security checks fails, the timestamp recording area will remain unchanged. In that case, you could recover the timestamp area with a developer key.


See [[/Implementation]] for technical details on how to generate such a signature.
See [[#Generating a RTC timestamp reset signature]] for instructions on how the rtcreset.sig file can be generated using bios-crypto tools. Once generated, the rtcreset.sig file can be provided on external USB or SD (in the 'security' subdirectory of the root) while booting the system.


== RTC timestamp reset server implementations ==
To perform this operation in a more automated fashion, a RTC timestamp reset server can be installed locally on an open network. When RTCAR prevents boot, the activation initramfs will attempt to connect to a local server and request a RTC reset signature. The server needs to be in possession of the required rtcreset.sig file, or needs to be in the position to be able to create it (with the relevant keys and tools available). See below for a sample implementation of how this can be automated.

== Generating a RTC timestamp reset signature ==

As the RTC timestamp reset signature falls within the regular [[Firmware security]] infrastructure, [[bios-crypto]] provides the necessary tools in order to generate a valid and signed <tt>rtcreset.sig</tt>.

Having followed the build/installation instructions documented at [[bios-crypto]], a RTC reset signature can be generated as follows:

$ ./make-rtcreset.sh <SERIAL> <UUID> <EXISTING-RTC-TIMESTAMP> <EXISTING-RTC-COUNT> <NEW-RTC-TIMESTAMP> <SIGNING-KEY>

e.g.
$ ./make-rtcreset.sh SHC005007B7 1273E0EC-AEF1-9FF6-45B2-FB706DC24B8D 20120511T024746Z 141 20110511T024746Z lease

The <tt>EXISTING-RTC-TIMESTAMP</tt> and <tt>EXISTING-RTC-COUNT</tt> parameters must be extracted from the XO in question - the rtcreset signature is specific to the target laptop with the current recorded count/timestamp values, and will not work with different values.

The final parameter corresponds to the key used to sign the output, in the above example it refers to the keypair of lease.public and lease.private.

The above tool can either be used by hand, or it can form the basis of a more automated system (such as the sample server implementation documented below).

== Sample RTC timestamp reset server implementation ==


The <em>RTC timestamp reset server</em> contacted by the initramfs has the responsibility of providing a RTC reset signature for the laptop. Note that this functionality is only useful for the case where the rtc-timestamp value on the XO has become invalid (e.g. in the future) or corrupt -- this server is not used for recovering from an RTC rollback where the rtc-timestamp value is correct but the RTC itself is in the past.
The <em>RTC timestamp reset server</em> contacted by the initramfs has the responsibility of providing a RTC reset signature for the laptop. Note that this functionality is only useful for the case where the rtc-timestamp value on the XO has become invalid (e.g. in the future) or corrupt -- this server is not used for recovering from an RTC rollback where the rtc-timestamp value is correct but the RTC itself is in the past.


=== xs-activation ===
A sample server is provided <b>[http://dev.laptop.org/~dsd/20111228/rtcresetserver.py here]</b> which will attempt to generate a RTC reset signature for each and every laptop that connects to it. This acts as skeleton code only; a real implementation may want to consider the following items:
* Further input data validation
* UUID database rather than a hardcoded list
* Does the client's rtc-timestamp look bad to begin with? If not, there is no need to generate a reset signature.
* Reset to a timestamp reflective of the current time (but perhaps somewhat in the past) rather than a hardcoded timestamp

== Testing ==
Here are some recipes for verifying the correct operation of this feature, using Open Firmware interactive commands. These recipes assume that you can get to the ok prompt, either with a non-secure system or with a developer key.

=== Testing Rollback Detection ===

First, enable the use of this feature by creating an "rt" tag in manufacturing data:

ok " " " rt" $add-tag

Run the anti-rollback check as follows:

ok rtc-rollback? .
0

The first time that you invoke rtc-rollback?, it should return 1, indicating that the timestamp area was empty and has now been initialized. Subsequent invocations should return 0, indicating normal operation.

You can see the relevant properties in /chosen with:

ok dev /chosen .properties dend

To simulate a rollback attack:

ok clock-node @ iselect get-time 1- set-time iunselect

That sets the clock back 1 year (the "1-" decrements the year field). Subsequently:

ok rtc-rollback? .
ffffffff
ok dev /chosen .properties dend
...
rtc-status rollback
...

You can put the clock back to normal with:

ok clock-node @ iselect get-time 1+ set-time iunselect

=== Testing Timestamp Reset ===

Testing the reset function is complicated because you need to make a signed file, which in turn means that you need access to a private key whose public key is on the test machine. Since I don't have access to the OLPC private keys, I had to inject a test key.

First you need to get a copy of the bios-crypto tools:

$ git clone git://dev.laptop.org/bios-crypto
$ cd bios-crypto/build
$ make

Make a keypair for testing:

$ ./makekey lease

That creates "lease.public" and "lease.private". Put "lease.public" on a USB FLASH drive so it can be transferred to the test machine:

$ cp lease.public PATH_TO_USB_FLASH_DRIVE/lease.pub
$ umount PATH_TO_USB_FLASH_DRIVE

Inject the test key into manufacturing data. The following assumes that there are no deployment-specific keys on the machine, so the "a1" key is available. If "a1" is already in use (use ".mfg-data" to check), you will need to use "a2" instead.

ok load u:\lease.pub
ok loaded " a1" $add-key

Now you will need to put the test machine into a state where it thinks a rollback attack has occurred.

ok clock-node @ iselect get-time 1+ set-time iunselect
ok rtc-rollback? .
0
ok clock-node @ iselect get-time 1+ set-time iunselect
ok rtc-rollback? .
ffffffff
ok dev /chosen .properties dend
rtc-count 141
rtc-timestamp 20120511T024746Z
rtc-status rollback

What that did was to set the clock ahead by a year, then rtc-rollback? recorded a new timestamp that is a year in the future. Then it set the clock back to the current year, and rtc-rollback? detected an attack because the current (correct) clock is earlier than the year-in-the-future timestamp. The '''rtc-count''' and '''rtc-timestamp''' properties give us some of the information that we need to construct a signed file to fix the timestamp. The other information that we need is in manufacturing data:

ok " SN" find-tag drop type
SHC005007B7
ok " U#" find-tag drop type
1273E0EC-AEF1-9FF6-45B2-FB706DC24B8D

Armed with those values (which are machine-specific, so you will have to supply your own values), you can make a signed rtcreset.sig file:

$ ./make-rtcreset.sh SHC005007B7 1273E0EC-AEF1-9FF6-45B2-FB706DC24B8D 20120511T024746Z 141 20110511T024746Z lease

Note that the next-to-last field - 20110511T024746Z - is similar to the first date field ("2012...") except that the year was manually restored to the current year - 2011 instead of 2012. That final date field is the timestamp that will be restored into the test machine; it can be any date/time that is before the current RTC date/time.


Patches have been submitted to extend [[xs-activation]] (which already runs a server on the addresses contacted by the activationinitramfs) to generate rtcreset signatures on-demand.
The make-rtcreset.sh script writes the result into the output file rtcreset.sig. Copy it onto the USB FLASH drive for transfer to the test machine:


When such a request is made, xs-activation uses the lease delegation (which it must already possess) in order to generate a <em>delegated</em> RTC timestamp reset signature. This is then sent to the XO, which will use it to reprogram the rtc-timestamp field.
$ mkdir -p PATH_TO_USB_FLASH_DRIVE/security
$ cp rtcreset.sig PATH_TO_USB_FLASH_DRIVE/security
$ umount PATH_TO_USB_FLASH_DRIVE


The server will generate a signature for every client that requests it (where a delegation is available), and will always specify that the RTC timestamp should be programmed to the server's current date/time (which is assumed to be correct).
Insert the USB FLASH drive into the test machine and:


=== Sample/simple server ===
ok load-crypto . get-my-sn .
0 0
ok " u:" dn-buf place
ok ?rtc-update
Trying u:\security\rtcreset.sig
RTCRESET found - Signature valid
Writing
e0000


A sample server is provided <b>[http://dev.laptop.org/~dsd/20111228/rtcresetserver.py here]</b> which will attempt to generate a RTC reset signature for each and every laptop that connects to it. Instead of using delegations (like xs-activation as above), this server uses the master key directly to produce non-delegated RTC timestamp reset signatures.
Instead of typing the commands above, you could instead boot the test machine in secure mode, for example by holding down the "X" game button while booting. In secure mode, the recovery procedure happens automatically.


This acts as skeleton/example code only; be sure to read the comments in the code for some further considerations/ideas.
The recovery will only work once because the timestamp in the signed file will no longer match the last recorded timestamp. To re-test the recovery procedure, you must repeat the above steps beginning with simulating the rollback attack, and then make a new signed rtcreset.sig file.

Latest revision as of 23:00, 29 December 2011

Purpose and overview

RTC anti-rollback (RTCAR) is a Open Firmware based security feature intended to prevent "RTC rollback attacks" - subversion of timed leases by setting the real-time clock backward in time.

RTCAR works by recording a series of timestamps in SPI FLASH, thus recording the dates and times of recent boots. When starting the OS, Open Firmware compares the current RTC value with the most recent stored value. If the stored value is later than the current value, the RTC is deemed to have been "rolled back" and boots in "activation mode", effectively preventing the system from booting normally. This limits the effectiveness of rollback attacks.

The series of recorded timestamps is protected from attack by existing lockout mechanisms that prevent the writing of SPI FLASH by any entity other than Open Firmware.

The timestamp storage format is chosen so that the relatively-dangerous operation of erasing a block of SPI FLASH is done only infrequently, only the order of every 6,500 reboots.

The activation mode initramfs attempts to contact a server that can automatically recover the system upon event of corruption of the last recorded timestamp value.

This page details the high-level behaviour of the system, and the items in which deployment technicians may need to interact with. Lower level implementation details can be found on the /Implementation page.

RTCAR properties

Three properties are defined to diagnose and control the state of this system.

  1. rtc-timestamp: Thie property contains the value of the most recent preexisting (prior to the current boot) timestamp. If there is no previously recorded timestamp, this property is not present.
  2. rtc-count: This property indicates how many timestamps have been recorded. In other words, this property counts how many times the system has been booted.
  3. rtc-status: This property indicates the current state of the system, and contains one of the following values:
    • "ok" - the RTC timestamp area is valid and the RTC value is more recent than the last timestamp. The system is running normally.
    • "empty" - the RTC timestamp area was initially empty, i.e. no timestamps were recorded in it. A new timestamp will be recorded and presented on next boot. This case is not considered as a "rollback".
    • "residue" - the RTC timestamp area contained some data, but there was a problem with it (e.g. corruption). This case is considered as a possible attack, so the system will hereon refuse to boot normally.
    • "rollback" - the RTC timestamp is later than the current RTC time. This indicates that the clock was rolled back. This case is considered a possible rollback attempt, so the system will hereon refuse to boot normally.

These RTCAR properties can be viewed from Linux with the following terminal commands:

 echo $(</proc/device-tree/chosen/rtc-timestamp)
 echo $(</proc/device-tree/chosen/rtc-count)
 echo $(</proc/device-tree/chosen/rtc-status)
If /proc/device-tree/ does not exist (i.e. on old builds), use /ofw/ instead.

Note that these properties will only be available when the system is booted in secure mode with RTCAR enabled.

For systems with security disabled (perhaps only temporarily, via a developer key), the same properties can be read from OFW's ok prompt after manually enabling the RTCAR system:

 ok rtc-rollback? .
 ok dev /chosen  .properties  dend

initramfs behaviour

When OFW detects a RTCAR-related problem (e.g. attack or corruption), it will first look for a rtc-timestamp reset signature on all available internal/external media (more details on this are presented below). If no such signature is found, rather than booting the system as normal, the activation initramfs is booted.

Instead of running the normal activation code (which looks for an activation on USB/SD and then looks on the network), the initramfs will enter a "RTC timestamp recovery mode". The assumption here is that the system has failed to boot because of a problem with the rtc-timestamp property (while the RTC correctly contains the current date/time): rtc-timestamp may be corrupt, or may incorrectly contain a future date.

In this mode, the initramfs scans for open wireless networks and connects to them one by one. Once connected, the initramfs attempts to connect to a RTC timestamp reset server on a set of predefined addresses. If a connection is established, the initramfs asks the server for a rtc-timestamp reset signature. This signature includes a new value to be written into the rtc-timestamp property.

If the server provides a response, the RTC reset signature is saved to disk and the system is immediately rebooted. Upon rebooting, the firmware detects the RTC reset signature and reprograms rtc-timestamp based on the server's response.

If the newly programmed rtc-timestamp is less than the current date/time as reported by the RTC, the system now boots normally. However, if the rtc-timestamp value is newer than the RTC's date/time, the system will boot again into the activation initramfs and the above cycle will repeat. Such a situation possibly indicates that the problem preventing boot was not with the rtc-timestamp value (as assumed above), but instead with the RTC value (indicating a possible rollback attack).

If a rollback attack has happened, the above rtc-timestamp recovery procedure will not produce fruitful results (either not finding a server, or not recieving a rtc-timestamp which satisfies the system) and the system will refuse to boot after a short time, reporting the error message "Problem with system clock". The XO will then automatically power off after 60 seconds.

In summary, if a rollback or rtc-timestamp problem is detected, the activation initramfs is booted. The initramfs attempts to obtain a RTC reset signature from a local server which will restore the system to usable state in the face of rtc-timestamp corruption problems, but if this fails (e.g. because a rollback attack was attempted), the system will refuse to boot and power itself off after a short delay.

Recovery

Two possible failure cases exist:

  1. The RTC may have been rolled back beyond the last recorded rtc-timestamp value, which the system will interpret as a rollback attack and hence fail to boot. In this case, the RTC time must be corrected to restore operation of the XO.
  2. The RTC may have the correct time but the rtc-timestamp value may have become invalid or corrupt. This is similarly interpreted as a rollback attack, and the system will fail to boot until the rtc-timestamp value is corrected or reset.

RTC rolled back

If the RTC was erroneously or intentionally rolled back, the system described on this page will detect a rollback attack and the XO will fail to boot. The recovery procedure for such a situation is to correct the RTC time.

First, obtain a developer key for the system. Boot the system into Linux, and run from a root terminal:

 date --utc -s "<current UTC date/time>"

e.g.

 date --utc -s "2011/12/28 12:04:59"

Now reboot the system (without the developer key present) and normal functionality should be restored.

Alternatively, the date can be reprogrammed from OFW's ok prompt. See Fix clock for instructions.

Invalid or corrupted RTC timestamp

The other possible failure case is where the RTC has the correct time value, but the rtc-timestamp value recorded is either invalid or corrupt. One simple cause of such a situation is that the RTC held (for whatever reason) a future time/date, and the system was booted in this condition causing rtc-timestamp to similarly record a future time/date. Upon (innocently) correcting the RTC time to the current date/time, the system will detect a rollback, and the system will fail to boot.

The recovery process involves resetting the firmware's rtc-timestamp value to one that is behind the current RTC date/time. A signed RTC timestamp reset signature must be provided, containing a new value that will be automatically programmed into the rtc-timestamp property.

The RTC timestamp reset signature can be obtained from various sources:

  • OFW will search internal and external media for a valid signed file at /security/rtcreset.sig. If found, the rtc-timestamp will be reprogrammed to the value specified by the file.
  • Otherwise, as detailed elsewhere on this page, the activation initramfs will attempt to obtain this signature from a local server.

See /Implementation for technical details on how to generate such a signature.

RTC timestamp reset server implementations

The RTC timestamp reset server contacted by the initramfs has the responsibility of providing a RTC reset signature for the laptop. Note that this functionality is only useful for the case where the rtc-timestamp value on the XO has become invalid (e.g. in the future) or corrupt -- this server is not used for recovering from an RTC rollback where the rtc-timestamp value is correct but the RTC itself is in the past.

xs-activation

Patches have been submitted to extend xs-activation (which already runs a server on the addresses contacted by the activationinitramfs) to generate rtcreset signatures on-demand.

When such a request is made, xs-activation uses the lease delegation (which it must already possess) in order to generate a delegated RTC timestamp reset signature. This is then sent to the XO, which will use it to reprogram the rtc-timestamp field.

The server will generate a signature for every client that requests it (where a delegation is available), and will always specify that the RTC timestamp should be programmed to the server's current date/time (which is assumed to be correct).

Sample/simple server

A sample server is provided here which will attempt to generate a RTC reset signature for each and every laptop that connects to it. Instead of using delegations (like xs-activation as above), this server uses the master key directly to produce non-delegated RTC timestamp reset signatures.

This acts as skeleton/example code only; be sure to read the comments in the code for some further considerations/ideas.