summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorTom Hughes <tomhughes@chromium.org>2021-04-28 12:05:07 -0700
committerCommit Bot <commit-bot@chromium.org>2021-04-28 23:00:06 +0000
commit820adaf9da8b73cdb81bfe09b1132bc354afc85e (patch)
tree600b6c7c6283607c185e87aa498f312cca124753 /docs
parent0670bff29d2bc71b0d8ec97b689ed1580778dc5f (diff)
downloadchrome-ec-820adaf9da8b73cdb81bfe09b1132bc354afc85e.tar.gz
docs/fingerprint: Add TPM Seed design doc
BRANCH=none BUG=b:139532396 TEST=view in gitiles Signed-off-by: Tom Hughes <tomhughes@chromium.org> Change-Id: Iab4df1b7d6876006326c15093cecb333f00d551b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2857474 Commit-Queue: Craig Hesling <hesling@chromium.org> Reviewed-by: Craig Hesling <hesling@chromium.org>
Diffstat (limited to 'docs')
-rw-r--r--docs/fingerprint/fingerprint-authentication-design-doc.md4
-rw-r--r--docs/fingerprint/fingerprint-tpm-seed.md324
-rw-r--r--docs/images/cros_fingerprint_tpm_seed.pngbin0 -> 85879 bytes
3 files changed, 326 insertions, 2 deletions
diff --git a/docs/fingerprint/fingerprint-authentication-design-doc.md b/docs/fingerprint/fingerprint-authentication-design-doc.md
index 6bcbbe9bf4..ef94f402f3 100644
--- a/docs/fingerprint/fingerprint-authentication-design-doc.md
+++ b/docs/fingerprint/fingerprint-authentication-design-doc.md
@@ -208,7 +208,7 @@ every time the TPM is cleared, for example if someone attempts to do a
"[ccd open]" to disable the hardware WP.
The following is a summary of the mechanism, see the specific design doc
-[“TPM-seed for Fingerprint MCU”] for details.
+[TPM Seed for Fingerprint MCU] for details.
The TPM already holds a "[system key]" `Cros_Sys_Key` in NVRAM space that is
used to derive the encryption key of the stateful partition. That "system key"
@@ -752,7 +752,7 @@ The log file is `/var/log/cros_fp.log`.
[UMA]: http://go/uma
[Windows]: https://www.microsoft.com/en-us/windows/windows-hello
[wrappers functions]: https://chrome-internal.googlesource.com/chromeos/platform/ec-private/+/9ebb3f10c611afff695f679aaeed1a35551a116b/fpc_sensor_pal.c#52
-[“TPM-seed for Fingerprint MCU”]: http://go/bio_tpm_seed
+[TPM Seed for Fingerprint MCU]: ../fingerprint/fingerprint-tpm-seed.md
<!-- Images -->
diff --git a/docs/fingerprint/fingerprint-tpm-seed.md b/docs/fingerprint/fingerprint-tpm-seed.md
new file mode 100644
index 0000000000..904fb7243a
--- /dev/null
+++ b/docs/fingerprint/fingerprint-tpm-seed.md
@@ -0,0 +1,324 @@
+# TPM Seed for Fingerprint MCU
+
+Authors: pmalani@google.com, norvez@google.com
+
+Reviewers: semenzato@google.com, apronin@google.com, mnissler@google.com and
+others
+
+Last Updated: 2018-11-01
+
+[TOC]
+
+## Objective
+
+Increase security for Fingerprint (FP) templates by using a TPM-sourced seed in
+addition to internal FPMCU entropy while encrypting FP templates. The
+TPM-sourced seed will be derived from the system key which is loaded from the
+TPM during boot in mount-encrypted.
+
+## Background
+
+Fingerprint authorization in Chrome OS, relies on encrypted FP templates which
+are stored in each user’s mount directory. These templates are created and
+encrypted by the FPMCU during FP enrollment, before being sent back to the AP
+(Application Processor). When the user logs in, these templates are sent to the
+FPMCU where they get decrypted and loaded.
+
+The encryption is performed in the FPMCU using entropy which is internal to the
+MCU and never leaves the MCU. That way, even if the templates are somehow
+obtained by and attacker from the user mount directory, they cannot be
+decrypted, since the attacker will not have access to the MCU entropy. This
+entropy gets reset on every powerwash/recovery.
+
+The complete design doc is [Fingerprint Authentication on Chrome OS].
+
+## Requirements and Scale
+
+The solution proposed should exhibit the following attributes:
+
+* Strengthens security of FP templates.
+* Does not compromise the security of other sub-systems.
+* Works fast and doesn’t affect time to boot, or reduce boot-time stability.
+
+## Design Ideas
+
+In addition to FPMCU entropy, we include a TPM-sourced seed (derived from the
+system key) while performing template encryption. The TPM system key gets
+regenerated during powerwash/recovery, so in the event that the FP templates are
+accessed due to a runtime exploit, a power-wash / recovery from the user will
+ensure:
+
+* The raw templates cannot be decrypted, since the TPM-seed would have been
+ lost irrevocably.
+* Since a new TPM-seed is generated (since a new system key is created), old
+ templates can’t be re-used, even if the attacker could somehow gain access
+ to the FP MCU entropy.
+
+The overall design consists of two components:
+
+* Generating a TPM-seed and sending it to the Biometric sensor managers.
+* The Bio sensor managers sending the seed to the FPMCU and programming it
+ into the encryption / decryption operations of FP templates.
+
+### TPM seed generation {#seed-generation}
+
+![TPM Seed Diagram]
+
+The TPM seed generation would proceed as follows:
+
+1. During mount-encrypted execution, after the `System_key` is loaded, the
+ TPM-backed system key will be HMAC-ed with a simple salt (the string
+ `biod`):
+
+ ```
+ TPM_Seed = HMAC_SHA256(System_key, "biod")
+ ```
+
+2. The resulting 256-bit seed (called `TPM_Seed`) will be maintained in a
+ `brillo::SecureBlob`.
+
+3. The `TPM_seed` will be saved into a tmpfs file
+ (`/run/biod_crypto_init/seed`) for consumption by `bio_crypto_init`. This
+ file's ownership will be set up such that only user/group `biod` can access
+ it.
+
+4. `bio_crypto_init` (the binary which sends the seed to the FPMCU) will be
+ spawned after mount-encrypted completes. This is ensured by setting the
+ `bio_crypto_init` upstart rules to depend on `starting boot-services`
+
+5. On the `bio_crypto_init` side, the `TPM_seed` will be retrieved from the
+ tmpfs file and forwarded to the FP MCU via the various BiometricManagers.
+ Immediately after reading from the tmpfs file, `bio_crypto_init` will nuke
+ (write all 0’s and then delete) the tmpfs file.
+
+6. The upstart rules of biod will be modified such that it will start after
+ `bio_crypto_init` stops (this modification can be made in the `.conf` file
+ of biod)
+
+#### IPC Mechanism {#ipc}
+
+(For a discussion of various alternatives, please see the
+[Alternatives Considered] section)
+
+The IPC mechanism selected should have the following features:
+
+* Allow to quickly pass the `TPM_seed` between mount-encrypted and
+ `bio_crypto_init`.
+* Minimize the presence of extra/asynchronously deleted copies of the
+ `TPM_seed` buffer in kernel and memory. This is crucial to minimize the risk
+ of access to this seed.
+
+The currently proposed method of passing the `TPM_seed` is to use a **file in
+tmpfs**. The sequence would be as follows:
+
+* mount-encrypted will write the `TPM_Seed` to a file in `/run`
+ (`/run/bio_crypto_init/seed`). `/run` is a tmpfs created by the OS for use
+ by various system services.
+* `bio_crypto_init` will read the `TPM_Seed` from the known tmpfs file.
+* As soon as `bio_crypto_init` reads the `TPM_Seed`, it will first overwrite
+ (`/run/biod_crypto_init/seed`) with all 0s, and immediately after will
+ delete `/run/biod_crypto_init/seed`.
+* `bio_crypto_init` can then instantiate its BiometricManager classes and send
+ the data to the FP MCU. This way, even if the sending of data fails, there
+ will not be any stray copy of the `TPM_seed` in a process’s memory, or in
+ tmpfs.
+
+##### Advantages
+
+* No/minimal buffering of copies of `TPM_Seed` in kernel.
+* No need to create and pass FDs between mount-encrypted and
+ `bio_crypto_init`.
+
+##### Disadvantages
+
+* If `bio_crypto_init` crashes / fails to start, the tmpfs file remains in the
+ system, i.e cleanup of tmpfs is reliant on `bio_crypto_init`.
+
+### Programming TPM_Seed into MCU
+
+#### Entropy addition v/s programming TPM Seed
+
+When a device boots up for the first time after going through
+recovery/powerwash, biod will force an "Add Entropy" step. This involves:
+
+* rebooting the FP MCU to RO
+* Performing an entropy addition step
+* Rebooting the FP MCU to RW
+* Verifying that the entropy addition has taken place (by checking the block
+ ID of the rollback info on the MCU).
+
+Unfortunately, since the `TPM_Seed` will be stored in MCU RAM, the reboot of the
+FPMCU will lead to the `TPM_Seed` being lost until the next boot. In the absence
+of a `TPM_Seed`, all FPMCU operations will fail (until the next boot). There is
+no opportunity to reprogram the `TPM_Seed`, because that must take place during
+mount-encrypted, which must necessarily run before `biod` starts.
+
+There are two proposals to work around this issue. The one eventually selected
+has been included here, and the other alternative has been placed in the
+[Alternatives Considered] section.
+
+##### Make bio_crypto_init solely set the TPM_Seed (don't perform entropy_add)
+
+In this method, `bio_crypto_init` will not perform any reboot on the MCU, and
+solely program the `TPM_Seed`. This would mean that if a device was to boot for
+a first time without having done any previous powerwash/recovery, the first boot
+would not have FP functionality. FP functionality would be regained on all
+subsequent boot (since the entropy would have been added/initialized by then).
+
+The downside of this approach is a poor user experience.
+
+The benefit is a simple implementation of the `bio_crypto_init` tool, which will
+consequently also take less time to execute (booting to RO/RW are time consuming
+operations).
+
+In practice all devices leaving the factory floor would have `bio_wash
+--factory_init` done on them during finalisation to initialise the entropy, and
+so this shouldn't affect a large majority of end users.
+
+### Signaling biod to start
+
+In order to avoid races which might occur because both `bio_crypto_init` and
+`biod` will try to access the `BiometricManagers`' hardware. We need to ensure
+that `biod` only starts after `bio_crypto_init` ends.
+
+To accomplish this, `biod.conf` will be modified to include a dependency on
+`bio_crypto_init` to start the daemon. So, the relevant portion of `biod.conf`
+will now be:
+
+```
+start on started system-services and started uinput and stopped bio_crypto_init
+```
+
+### Formula to calculate IKM used for encryption in MCU
+
+In the FPMCU we will use the concatenation of `TPM_Seed` and [`SBP_Src_Key`] as
+Input Key Material (IKM) to derive an encryption key. Combined with a random
+salt, the pseudo random key (PRK) would be derived as:
+
+```
+PRK = HMAC_SHA256(Random_Salt, SBP_Src_Key || TPM_Seed)
+```
+
+## Alternatives Considered {#alt-considered}
+
+A few alternatives are being considered for the IPC Mechanism
+
+#### pipe/socketpair
+
+##### Disadvantages
+
+* The data written to pipes is buffered in internal kernel buffers till it is
+ read out from the other end of the pipe/socketpair. In the case of a
+ `bio_crypto_init` crashing, this will leave a copy in the internal kernel
+ buffers. Question: How long before those internal buffers get cleared in the
+ case of the pipe not being read from?
+
+#### Anonymous file (memfd_create) / Anonymous mmap
+
+##### Disadvantages
+
+* Question: When all references to the anonymous file are dropped, are the
+ contents of the anonymous file re-allocated, overwritten, or is the
+ corresponding inode simply destroyed (and the data blocks still stick around
+ and are reallocated lazily ?)
+
+There was also another alternative considered for the sequence of programming
+the TPM seed and initializing the FPMCU: make `bio_crypto_init` add entropy and
+then set TPM.
+
+## Security Considerations
+
+### Security boundaries
+
+* A new minijailed process (`bio_crypto_init`) is run when `starting
+ boot-services` is signaled.
+* An IPC takes place between mount-encrypted and `bio_crypto_init` via a tmpfs
+ file. The reading and deletion of the tmpfs file is detailed in the
+ [IPC Mechanism] section.
+
+### Privileges
+
+* `bio_crypto_init` runs minijail-ed and runs with user/group `biod`. Only the
+ files required for its functioning (i.e., the tmpfs file `/run/`, the
+ devnode to access the FPMCU, log directory inside
+ `/var/log/bio_crypto_init`) are mounted and visible inside the sandbox. See
+ the [minijail0 arguments] for a full explanation.
+
+### Untrusted input
+
+* The only input is the `System_key` which is retrieved from the TPM anyway
+ during mount-encrypted execution. Thus, no additional or new input is being
+ fed to the feature.
+* Additionally, the derived TPM-seed is saved in a tmpfs file which has a
+ user/group ownership as `biod` so only users `root` or `biod` can access the
+ file. Since `bio_crypto_init` runs only during `starting boot-services` and
+ the process along with the conf file ensures that the file is deleted after
+ execution, there is no additional threat of the `/tmp` file being corrupted.
+
+### Sensitive data
+
+* The feature involves the storage of a `TPM_Seed` derived from the
+ `System_key` from TPM, in a file on tmpfs (the file is zeroed and deleted
+ once read by `bio_crypto_init`).
+
+### Attack surface
+
+* In the event of the contents of the tmp file being read, the `TPM_Seed`
+ would not be of much use to the attacker, since the use of `HMAC_SHA256`
+ means the attacker would still not have access to the system key (brute
+ force trial of HMAC 256 would be required to guess the system salt required
+ to produce the TPM-seed).
+* In the unlikely event of the contents of the tmp file being modified before
+ they are programmed into the FPMCU, FP unlock would fail (since the
+ encrypted templates would not longer be decrypted correctly, since the FPMCU
+ encryption key would have changed). The FP templates encryption key is a
+ combination of both the `TPM_seed` as well as the internal `SBP_Src_Key`
+ combined with a random salt, and since only the encrypted templates are
+ stored on the rootfs, the templates would simply be rendered useless. A
+ powerwash/recovery can help restore functionality of FP unlock, but new
+ templates would have to be registered.
+* This code should not be accessible to remote attackers.
+
+### Implementation robustness
+
+* `bio_crypto_init` uses two processes. A child process is spawned by
+ `bio_crypto_init` and the FPMCU programming is done on the child process.
+ The parent process waits for the child process to complete, or kills the
+ process if it exceeds a timeout limit. This ensures that the process doesn't
+ hang indefinitely.
+* The feature uses tmpfs (`/run/bio_crypto_init/seed`) as an IPC mechanism to
+ transfer the `TPM_Seed` between mount-encrypted and `bio_crypto_init`.
+ Please see the [Alternatives Considered] and [Design Ideas] section
+ regarding rationale behind choosing tmpfs vis a vis socketpair/pipe.
+
+### Cryptography
+
+* `HMAC_SHA256` is used to derived `TPM_Seed` from the `System_key` as
+ described in section [TPM seed generation].
+
+* `HMAC_SHA256` is also used to derive the FPMCU’s encryption key. This is the
+ same as it was earlier; the only change is that source key has been updated
+ to also include the `TPM_Seed`.
+
+## Privacy Considerations
+
+This implementation should not have any adverse implications on Privacy (over
+and above existing functionality on Chrome OS). This provides security hardening
+for the fingerprint templates to prevent their retrieval and mis-use.
+
+[Fingerprint Authentication on Chrome OS]: ../fingerprint/fingerprint-authentication-design-doc.md
+[`SBP_Src_Key`]: ../fingerprint/fingerprint-authentication-design-doc.md#sbp-secret-generation
+[IPC Mechanism]: #ipc
+[minijail0 arguments]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform2/biod/init/bio_crypto_init.conf;l=36;drc=1fcefaa166e868069ad1b81091333ff75e0657f6
+[Design Ideas]: #design-ideas
+[TPM seed generation]: #seed-generation
+[Alternatives Considered]: #alt-considered
+
+<!-- Images -->
+
+<!-- If you make changes to the docs below make sure to regenerate the PNGs by
+ appending "export/png" to the Google Drive link. -->
+
+<!-- https://docs.google.com/drawings/d/1d0ocdnEjsO26c3usP1FwgTZ7VwEr-4ydnC0WMhOnbLY -->
+
+[TPM Seed Diagram]: ../images/cros_fingerprint_tpm_seed.png
diff --git a/docs/images/cros_fingerprint_tpm_seed.png b/docs/images/cros_fingerprint_tpm_seed.png
new file mode 100644
index 0000000000..8213e6f775
--- /dev/null
+++ b/docs/images/cros_fingerprint_tpm_seed.png
Binary files differ