Systems with TXT enabled may issue the TPM2_Startup() command from a
locality other than 0. In this case, the initial value of PCR0 will
represent the locality that the call was made from. This is exposed to
higher layers by an EV_NO_ACTION event that has data containing the
NULL-terminated string "StartupLocality" followed by a single byte
representing the state of the locality. As this event is EV_NO_ACTION,
it does not represent an extension in itself.
So:
1) Ignore events that are EV_NO_ACTION when replaying the log, except:
2) For PCR0, if an event is EV_NO_ACTION and contains the string
"StartupLocality", use the final byte of the event data as the initial
value of PCR0 for the replay.
Handle platform certificates that only provide a single property
The spec states that the PlatformProperties field of the
PlatformConfiguration attribute should be a sequence of key value pairs.
However, it seems that if there's only a single property present, it's
sometimes being stored as a bare key value pair rather than a sequence
with a single entry. Work around that.
A number of the struct definitions had broken tag definitions, which
meant some parsing was working by accident and some parsing was entirely
broken. Fixing this uncovered some additional issues (a mixture of
incorrect definitions and platform certificates that violate the spec),
so this is all cleaned up as well.
Attribute certificates are generally using RSA-SHA1 or RSA-SHA256
signatures, so include those. In addition, the CA signing restrictions
imposed for general purpose certificates don't apply here - drop that
restriction from certificate signature validation.
Using the length of a digest to infer the hash algorithm is somewhat
fragile - if we end up with multiple hash algorithms that share the same
digest length, things will break. Instead, pass more complete digest
information through to relevant functions and figure things out by
mapping the TPM hash algorithm to the appropriate Golang type.
Crypto agile logs may contain digest types that we don't currently
handle. However, we still need to know how long each digest is in order
to read over the appropriate amount of the buffer. This information is
provided to us as part of the spec header - make use of it rather than
hardcoding the set of digests and lengths we know about.
golint current generates complaints:
var oidTpmIdLabel should be oidTpmIDLabel
var oidTcgPlatformManufacturerIdV2 should be oidTcgPlatformManufacturerIDV2
var oidTcgPlatformConfigUri should be oidTcgPlatformConfigURI
Update names to satisfy golint.
The following commands were run to generate this change:
gopls rename -w attributecert.go:44:2 oidTpmIDLabel
gopls rename -w attributecert.go:54:2 oidTcgPlatformManufacturerIDV2
gopls rename -w attributecert.go:55:2 oidTcgPlatformConfigURI
gopls rename -w attributecert.go:163:6 authKeyID
gopls rename -w attributecert.go:164:2 ID
gopls rename -w attributecert.go:171:2 ID
gopls rename -w attributecert.go:178:2 ID
gopls rename -w attributecert.go:210:2 BaseCertificateID
gopls rename -w attributecert.go:232:2 ID
gopls rename -w attributecert.go:304:2 ID
gopls rename -w attributecert.go:309:2 ID
gopls rename -w attributecert.go:390:2 ComponentManufacturerID
sed -i 's/Uri/URI/g' attributecert.go
git clean -f
Updates #131
Platform certificates are defined as RFC5755 attribute certificates with
various additional attributes and extensions defined in the TCG Platform
Certificate Profile. Add support for parsing them, derived from
crypto/x509. Include some test certificates and verify we parse them.
@brandonweeks detected another case of the "make([]T, untrustedValue)"
pattern, which would allow an attacker to cause the parser to allocate
an unbounded amount of memory.
Fix this by reading one algorithm at a time instead of pre-allocating a
slice of algorithms.