[Openembedded-architecture] Trusted/secure/etc layers
Trevor Woerner
twoerner at gmail.com
Tue May 1 18:57:48 UTC 2018
I AM NOT AN EXPERT!! I'm still learning this stuff, it's very possible my
understanding is incorrect. Please feel copiously free to reply and point out
where my understanding deviates from reality :-)
My interests in security currently revolve around TPM (TPM2, to be specific).
The TPM project began with the realization that a hardware solution was
required to solve some common security issues. A TPM is often used as part
of a secure boot process, therefore any talk of secure boot requires some
understanding of TPM. But TPMs are used for much more than just secure boot,
so having TPM functionality available allows other things as well. Therefore
having a layer for secure boot that includes TPM, opens the door for lots of
non-secure-boot things... you have been warned! :-)
A group of companies and groups got together to form the Trusted
Computing Group (TCG) https://trustedcomputinggroup.org/about/
https://trustedcomputinggroup.org/membership/member-companies/
which then defined the Trusted Platform Module (TPM) as well as a bunch of
other things.
One of the things that plagues the TPM (in my opinion) is that some of the
first TPM specs were developed at a time when silicon was expensive and not so
powerful (i.e. the 90s). As a result, even modern TPMs lack abundant on-board
storage and crypto-acceleration. Today, if one were developing a TPM from
scratch, I'm quite sure it would include a lot more internal storage, and most
likely the ability to do cryptographic acceleration. A TPM is not a crypto
accelerator, it is much more concerned with keys (generation, attestation,
non-repudiation, etc). A TPM can, of course, perform cryptographic operations,
it's just not all that fast.
Technically, a TPM is just a spec. Companies then design chips which purport
to comply to the spec.
The original TPM design culminated in the TPM 1.2 specification. But, over
time, changes and additions were needed, hence the development of TPM2
(currently at 2.0). TPM1.x assumed only one user (the platform) and one set of
algorithms. TPM2.x introduces multiple "hierarchies" (platform, storage, and
endorsement which are persistent, null which is not) and "algorithm agility".
There are a lot of other differences between TPM1 and TPM2. As a result TPM1
and TPM2 systems are not compatible.
At its lowest levels, in operation, a TPM chip reminds me of a block device.
For the most part you send it commands and point it at data, it speaks a
"language" of TPM commands (similar to how a block device would implement,
say, the ATA command set). Although it's possible to write code at
this level, most people wouldn't. On top of the raw TPM commands is
the TSS (TSG Software Stack) which provides utility functions on top
of TPM. For Linux/UNIX systems the TSS for TPM1x was called "trouSerS"
http://trousers.sourceforge.net/faq.html. For TPM2, there are a number of
TSS implementations (Intel: https://github.com/tpm2-software/tpm2-tss,
IBM: https://sourceforge.net/projects/ibmtpm20tss/, Microsoft Research:
https://github.com/Microsoft/TSS.MSR, ...). The TCG defines the TSS, it's not
hap-hazard. As far as I know, none of these (free) TSS implementations
implement the full TSS spec.
The TSS is actually broken down into a set of abstractions/libraries
consisting of (from highest to lowest): Feature API (FAPI), Enhanced System
API (ESAPI), System API (SAPI), TPM Command Transmission Interface (TCTI), TPM
Access Broker (TAB), Resource Manager (RM), and device driver. In a Linux/UNIX
system, the device driver level is handled by the kernel, leaving everything
above that in the TSS stack to user-space software. My understanding is that
none of the free TSS implementations I listed above support all of the TSS. In
fact I don't know that any implementation implements all of any layer (i.e.
just because a given TSS implementation might, for example, implement some of,
say SAPI, does not imply that it has implemented all of the functionality in
all of the layers below SAPI). However, there is enough that is implemented
throughout the stack to do meaningful work. For example most implementations
implement most of the RM and TAB layers, a lot of the TCTI and part of the
SAPI levels. I don't think any of them support ESAPI nor FAPI.
Since TPM2 introduced the idea of multiple users, it is best to interact with
a TPM via an access broker, TAB/RM (TPM Access Broker / Resource Manager),
which is also a TCG spec. On a Linux/UNIX system, the TAB/RM runs as a daemon
and listens to a socket over which applications who want to communicate with a
TPM communicate.
If the device you're using has a TPM, the first thing you need to do is to
figure out if it is a TPM1 or TPM2 device. Once you know which one you have,
you can then work with it. The Linux kernel has good support in terms of
drivers for TPM hardware. The most common TPM hardware of which I'm aware are
the chips from Infineon https://www.ehitex.de/en/evaluation-boards/infineon/?p=1
from whom you can buy daughter boards for the RPi (for example). Just note
whether you're buying a TPM1 or TPM2 device since both are still available.
Now that you have a device, and insmod'ed the linux driver for it, you need a
TSS library and a TAB/RM. With all that in place you can now talk to your TPM
chip; except you can't really talk directly to the chip. All communication
with a TPM must be done via a "session" and any data you want to pass to/from
a TPM must be done via a TPM "entity". Entities can be strung together in
chains, they can sometimes be passed between hierarchies, and whole entity
chains can be invalidated, or just certain entries in the chain.
A TPM will never simply pass you information in the clear. If you asked a TPM
to generate a key for you, for example, it will generate the key but then pass
it to you as a blob. The blob contains the key, but that key is then HMACed
(i.e. fingerprinted) in a way that is unique to the TPM, but also unique to
the session. You can, in the future, point a TPM to a blob and say "did you
make this?" and the TPM can confirm or deny whether it created the blob even
though the question is asked from a different session, but the question must
be asked with a session of the same hierarchy as the hierarchy that was used
to create the blob. (Do you see the path down which this is going?!)
For secure boot, the part of the TPM that is used are the PCRs (Platform
Configuration Register). You point the TPM to the next blob to boot (i.e. the
bootloader), it hashes it along with the current value of the PCR, updates the
PCR, then verifies the result matches an expected. If so, the platform can
unpack the bootloader (in this case) and run it. When the bootloader is ready
to run the kernel (for example) it points the TPM at the kernel blob, the TPM
hashes it, plus the current value of the PCR, updates the PCR, then compares
the result to an expected. If it succeeds the kernel can then be unpacked and
run. The point of incorporating the existing value of the PCR into each of the
subsequent hashes ensures an unbroken chain, but it also means that any change
in earlier firmware requires recalculations to all downstream expected PCR
values.
There's lots of resources for TPMs, I won't bother listing many here. James
Bottomly and Matthew Garret have been doing lots of Linux TSS stuff. Philip
Tricca (for Intel) has been leading a lot of TSS work as well, he also
maintains meta-measured https://github.com/flihp/meta-measured for OE recipes.
I have started a set of blogs describing how to get TPM working on a RPi via
OE. It's a 3-part series, part 1 is published, parts 2 and 3 are done, but not
polished and published yet. It's tricky because it involves RPi stuff, TPM
stuff, and device tree stuff:
http://twoerner.blogspot.ca/2018/01/rpi-and-tpm-and-dt-part-1-background.html
More information about the Openembedded-architecture
mailing list