Skip to content

Commit dd59fc8

Browse files
author
George Almasi
committedMar 18, 2023
A first commit of the pure python event log enhancement proposal
Signed-off-by: George Almasi <gheorghe@us.ibm.com>
1 parent 6cb52f8 commit dd59fc8

File tree

1 file changed

+176
-166
lines changed

1 file changed

+176
-166
lines changed
 

‎98_pure_python_eventlog_parsing.md

+176-166
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,4 @@
1-
<!--
2-
**Note:** When your enhancement is complete, all of these comment blocks should be removed.
3-
4-
To get started with this template:
5-
6-
- [ ] **Create an issue in keylime/enhancements**
7-
When filing an enhancement tracking issue, please ensure to complete all
8-
fields in that template. One of the fields asks for a link to the enhancement. You
9-
can leave that blank until this enhancement is made a pull request, and then
10-
go back to the enhancement and add the link.
11-
- [ ] **Make a copy of this template.**
12-
name it `NNNN-short-descriptive-title`, where `NNNN` is the issue number (with no
13-
leading-zero padding) assigned to your enhancement above.
14-
- [ ] **Fill out this file as best you can.**
15-
At minimum, you should fill in the "Summary", and "Motivation" sections.
16-
These should be easy if you've preflighted the idea of the enhancement with the
17-
appropriate SIG(s).
18-
- [ ] **Merge early and iterate.**
19-
Avoid getting hung up on specific details and instead aim to get the goals of
20-
the enhancement clarified and merged quickly. The best way to do this is to just
21-
start with the high-level sections and fill out details incrementally in
22-
subsequent PRs.
23-
-->
24-
# enhancement-NNNN: Your short, descriptive title
25-
26-
<!--
27-
This is the title of your enhancement. Keep it short, simple, and descriptive. A good
28-
title can help communicate what the enhancement is and should be considered as part of
29-
any review.
30-
-->
31-
32-
<!--
33-
A table of contents is helpful for quickly jumping to sections of a enhancement and for
34-
highlighting any additional information provided beyond the standard enhancement
35-
template.
36-
-->
1+
# Python Eventlog Parsing for Measured Boot Attestation
372

383
<!-- toc -->
394
- [Release Signoff Checklist](#release-signoff-checklist)
@@ -57,193 +22,238 @@ template.
5722

5823
## Release Signoff Checklist
5924

60-
<!--
61-
**ACTION REQUIRED:** In order to merge code into a release, there must be an
62-
issue in [keylime/enhancements] referencing this enhancement and targeting a release**.
63-
64-
For enhancements that make changes to code or processes/procedures in core
65-
Keylime i.e., [keylime/keylime], we require the following Release
66-
Signoff checklist to be completed.
67-
68-
Check these off as they are completed for the Release Team to track. These
69-
checklist items _must_ be updated for the enhancement to be released.
70-
-->
71-
7225
- [ ] Enhancement issue in release milestone, which links to pull request in [keylime/enhancements]
7326
- [ ] Core members have approved the issue with the label `implementable`
7427
- [ ] Design details are appropriately documented
7528
- [ ] Test plan is in place
7629
- [ ] User-facing documentation has been created in [keylime/keylime-docs]
7730

78-
## Summary
31+
## Proposal summary
7932

8033
The proposal is to replace the dependency on `tpm2-tools` in the
8134
Keylime measured boot attestation code with native python
82-
code. Motivation in detail just below. At the simplest level the
83-
change is just to change the call to the event log parser from
84-
`os.system` to native Python. However, additional complexity reduction
85-
can be achieved by removing the Python based post-processing of the
86-
event log and merging that code into the parser.
87-
88-
We propose to keep the event log parser as a separate project within
89-
the Keylime code base, and to package it independently. This was
90-
proposed by the project maintainers as a way to keep disruptions in
91-
Keylime to a minimum; once the python based event log parser is
35+
code.
36+
37+
Most of the change in Keylime itself to the nature of the parser's
38+
invocation -- from `os.system` to native Python. Additional complexity
39+
reduction can be achieved by removing the Python based post-processing
40+
of the event log and merging that code into the parser. Current
41+
features of post-processing include correct handling of UUIDs (badly
42+
parsed in earlier versions of `tpm2-tools`) and `libefivar`
43+
enhancements to parse device path entries.
44+
45+
We propose to keep the event log parser itself as a separate project
46+
within the Keylime code base, and to package it independently. This
47+
was proposed by the project maintainers as a way to keep disruptions
48+
in Keylime to a minimum; once the python based event log parser is
9249
packaged, it can be listed as a dependency on Keylime itself. To this
9350
end, the python event log parser will have its own CI and unit tests,
9451
code checks, and its own packaging mechanisms.
9552

96-
9753
## Motivation
9854

99-
The chief motivation for this proposal is that keeping Keylime measured
100-
boot attestation alive and functional over the last two years has
101-
resulted in at least two incidents in which upgrading `tpm2-tools` to
102-
a new version caused measured boot attestation to malfunction, because
103-
the output format (nominally YAML) of the tool was changed.
104-
105-
The changes in `tpm2-tools` are typically benign when viewed in context. Some
106-
examples: trailing zeroes were excluded, now being excluded; multiline
107-
output handled incorrectly; certain input parsed to strings of
108-
incorrect length; UUIDs being interpreted incorrectly as in network
109-
order, then as little endian.
110-
111-
However, the *number* of such changes, and the ongoing frequency of
112-
such changes, makes the maintenance of Keylime challenging.
113-
114-
Basically, we propose to replace the approx. 1000 lines of C code in the
115-
tpm2-tools package with a mostly equivalent length (700 lines at
116-
present) of native Python code, maintained by the Keylime project.
117-
55+
The chief motivation for this proposal is to keep measured boot
56+
attestation safe from bit rot. We have, in the last two years of
57+
operating Keylime (2021 to 2023), experienced at least two incidents
58+
in which upgrading `tpm2-tools` to a new version caused measured boot
59+
attestation to malfunction, because the output format (nominally YAML)
60+
of the tool was changed.
61+
62+
Generally speaking the quality of `tpm2-tools` has been improving.
63+
Some examples of disruptive changes we have encountered:
64+
* Trailing zeroes used to be excluded, now are excluded;
65+
* multiline output handled incorrectly in `tpm2-tools` v. 5.5
66+
* certain input parsed to strings of incorrect length, resulting in utf-16 garbage
67+
* UUIDs being interpreted incorrectly as in network order in v. 5.11
68+
69+
These are generally easy to correct for, but require us to actively
70+
follow changes in the tooling, and each new version of `tpm2-tools`
71+
requires us to adjust.
72+
73+
Therefore we propose to replace the approx. 1000 lines of C code in
74+
the `tpm2-tools` package with a mostly equivalent length (700 lines at
75+
present) of native Python code, maintained by the Keylime project. The
76+
code savings come from the fact that OO features of Python allow for
77+
simpler, more natural code organization; Python `struct` is very
78+
effective at parsing binary structures into Python native objects; and
79+
lastly, Python has JSON support.
11880

11981
### Goals
12082

121-
Goal 1: keylime project
122-
Open questions:
123-
124-
Goal 2: a PR in keylime to deploy python event log parser
125-
83+
* Improve the stability of measured boot attestation over time.
84+
* Improve the quality of the measured boot event log parser.
85+
* Reduce Keylime's dependency on foreign tooling.
12686

12787
### Non-Goals
12888

12989
An explicit non-goal of _this_ proposal is to also enhance the
130-
tpm2-tools package by enumerating the issues found during the
90+
`tpm2-tools` package by enumerating the issues found during the
13191
rewrite. That (entirely reasonable) work item should be handled
13292
somewhere else.
13393

13494
We do not (in this proposal) aim to change anything else about
135-
measured boot attestation in Keylime. To that end, the python event
136-
log parser is slated to produce compatible output with what
137-
`tpm2-tools` is producing right now.
95+
measured boot attestation in Keylime. The python event
96+
log parser is designed to produce output comparible with
97+
`tpm2-tools`.
13898

139-
## Proposal
99+
### Notes/Constraints/Caveats (optional)
140100

141-
<!--
142-
This is where we get down to the specifics of what the proposal actually is.
143-
This should have enough detail that reviewers can understand exactly what
144-
you're proposing, but should not include things like API designs or
145-
implementation. The "Design Details" section below is for the real
146-
nitty-gritty.
147-
-->
101+
The most obvious caveat to address is that this project is basically
102+
duplicating code that already exists in `tpm2-tools`, and therefore
103+
could be seen as a duplication of effort, unwise both because of the
104+
wasted labor and the implied long tail of required maintenance.
148105

149-
### User Stories (optional)
106+
The developers' argument is that (a) the duplication of effort is not
107+
that great, since it was done in 2 weeks of part-time work, minus the
108+
organizational aspects such as writing this document (b) the long tail
109+
of management is not really that long, because the specifications we
110+
are following are changing very slowly.
150111

151-
<!--
152-
Detail the things that people will be able to do if this enhancement is implemented.
153-
Include as much detail as possible so that people can understand the "how" of
154-
the system. The goal here is to make this feel real for users without getting
155-
bogged down.
156-
-->
112+
In any case we think that the implicit advantages of python-based
113+
development (e.g. native JSON support) and the much shorter
114+
development loop (i.e. the event log parser's developers and the end
115+
users of Keylime overlap) mitigate the disadvantage of code
116+
duplication.
157117

158-
#### Story 1
118+
### Risks and Mitigations
159119

160-
#### Story 2
120+
The largest risk is that the Python based event loop stops being
121+
maintained, develops bit rot and contributes to a decline of the
122+
quality of the Keylime code base. Mitigation lays in the decision to
123+
continue to use JSON as the exchange format between the parser and the
124+
Keylime measured boot policy agent, which would make a move *back* to
125+
`tpm2-tools` possible at least in principle.
126+
127+
There are no serious security aspects regarding the event log
128+
parser. To the extent that the measured boot event log is
129+
self-checking (i.e. event digests can be recalculated for certain
130+
types of events), the event log parser is already doing so. NB we are
131+
not aware of the `tpm2-tools` based event log parser doing any
132+
self-checking. And of course the python based event log parser is
133+
capable of generating PCR reference values in the same way
134+
as `tpm2-tools`.
135+
136+
Corrupt or maliciously crafted binary event logs have the capability
137+
to disrupt the parser (insufficient self checks have been implemented
138+
to date). To the best of our knowledge such events merely result in
139+
the parsing being aborted with an python Exception.
161140

162-
### Notes/Constraints/Caveats (optional)
141+
## Design Details
163142

164-
To fill in: an extra project, extra code, possible divergence from `tpm2-tools`, duplicating effort.
143+
The parser is implemented as a single Python file, `eventlog.py`. It
144+
includes an `EventLog` class, which is `list` of `Event` objects.
165145

166-
### Risks and Mitigations
146+
An `EventLog` object can be instantiated with a binary buffer
147+
containing the binary event log, and becomes a list of the individual
148+
events in the log.
167149

168-
<!--
169-
What are the risks of this proposal and how do we mitigate. Think broadly.
170-
For example, consider both security and how this will impact the larger
171-
enhancement ecosystem.
150+
`Event` is actually a class hierarchy organized by the TCG list of
151+
event types. Every Event has an attached list of digests, can be
152+
natively parsed into JSON, and has a self-verification method (which
153+
is a noop for certain event types).
172154

173-
How will security be reviewed and by whom?
174-
-->
155+
Currently only three operations are implemented on the EventLog class
156+
itself: (a) parse into JSON, (b) self-verification and (c) generate a
157+
list of PCRs for authentication against a TPM quote.
175158

176-
## Design Details
159+
Typical use case for the EventLog class:
177160

178-
<!--
179-
This section should contain enough information that the specifics of your
180-
change are understandable. This may include API specs (though not always
181-
required) or even code snippets. If there's any ambiguity about HOW your
182-
proposal will be implemented, this is the place to discuss them.
183-
-->
161+
```
162+
args = parser.parse_args()
163+
assert args.file, "file argument is required"
184164
185-
### Test Plan
165+
with open (args.file, 'rb') as fp:
166+
buffer = fp.read()
167+
evlog = eventlog.EventLog(buffer, len(buffer))
168+
print(json.dumps(evlog, default=lambda o: o.toJson(), indent=4))
169+
```
186170

187-
<!--
188-
**Note:** *Not required until targeted at a release.*
171+
The current implementation is somewhat lacking in buffer overflow
172+
checks (these would only happen if the binary event log is corrupted
173+
or crafted maliciously). Exception handling is also somewhat lacking.
189174

190-
Consider the following in developing a test plan for this enhancement:
191-
- Will there be e2e and integration tests, in addition to unit tests?
192-
- How will it be tested in isolation vs with other components?
193175

194-
No need to outline all of the test cases, just the general strategy. Anything
195-
that would count as tricky in the implementation and anything particularly
196-
challenging to test should be called out.
176+
### Test Plan
197177

198-
All code is expected to have adequate tests (eventually with coverage
199-
expectations).
200-
-->
178+
The event log parser has its own test suite (10 different event logs
179+
collected from real machines). The comparison is performed against
180+
`tpm2_eventlog` from `tpm2-tools` version 5.5.
181+
182+
Attached is example output from the CI system:
183+
184+
```
185+
+------------------------------+-------+-------+-------+----
186+
| log file | #Evts | #Fail | Pct. | msg.
187+
+------------------------------+-------+-------+-------+----
188+
|bootlog-5.0.0-rhel-20210423T13| 34| 0| 0.00%|
189+
|thyme-eventlog.bin | 39| 0| 0.00%|
190+
|p511.bin | 58| 0| 0.00%|
191+
|swtpm_measurements.bin | 104| 0| 0.00%|
192+
|puiterwijk.bin | 101| 0| 0.00%|
193+
|201123-eventlog.bin | 60| 0| 0.00%|
194+
|ideapad1.bin | 39| 0| 0.00%|
195+
|inspur.bin | 101| 0| 0.00%|
196+
|rk049-s26.bin | 47| 0| 0.00%|
197+
|intel_svr.bin | 119| 0| 0.00%|
198+
|css-flex14vm4-bootlog.bin | 106| 1| 0.94%|
199+
+------------------------------+-------+--------+------+
200+
| Totals: | 808| 1| 0.12%|
201+
+------------------------------+-------+--------+------+
202+
```
203+
204+
TODO: integration testing
205+
TODO: antagonistic testing (broken event logs)
206+
TODO: testing of PCR generation
207+
TODO: self-check testing
208+
TODO: coverage testing
201209

202210
### Upgrade / Downgrade Strategy
203211

204-
<!--
205-
If applicable, how will the component be upgraded and downgraded? Make sure
206-
this is in the test plan.
207-
208-
Consider the following in developing an upgrade/downgrade strategy for this enhancement
209-
-->
212+
TODO
210213

211-
### Dependencie requirements
214+
### Dependency requirements
212215

213-
<!--
214-
If your new change requires new dependencies, please outline and demonstrate that your selected dependency
215-
is well maintained and packaged in Keylime's supported Operating Systems (currently Debian Stable
216-
and as of time writing Fedora 32/33).
216+
No major dependencies we are aware of, beyond Python itself. There is
217+
an optional dependency on `libefivar`, which would be used by means of
218+
a `CDLL` call in Python.
217219

218-
During code implementation you will also be expected to add the package to CI , the keylime ansible role and
219-
keylimes main installer (`keylime/installers.sh`).
220+
Of course, for Keylime itself to use this code, it would have to be
221+
packaged first.
220222

221-
If the package is not available in the supported Operated systems, the PR will not be merged into master.
223+
## Drawbacks
222224

223-
Adding the package in `requirements.txt` is not sufficent for master which is where we tag releases from.
225+
"Why should this enhancement _not_ be implemented?" -- the most
226+
serious argument against this code is the duplication of effort
227+
(discussed in detail earlier).
224228

225-
You may however be able to work within an experimental branch until a package is made available. If this is
226-
the case, please outline it in this enhancement.
229+
## Unresolved problems at the time of writing this proposal
227230

228-
-->
231+
* TRANSFER: transferring the current Python-native event log parser into the
232+
Keylime project. The current implementation
233+
(https://github.com/galmasi/python3-uefi-eventlog) has its own CI
234+
tooling based on Github Actions, which includes pylint, python type
235+
checking and extensive functional testing against `tpm2_eventlog` by
236+
comparing JSON outputs for a collection of 10 different event logs.
229237

230-
## Drawbacks
238+
* TESTING: The developer[s] would absolutely welcome contributions of
239+
other binary event logs for even more extensive functional
240+
testing. Including maliciously crafted binary event logs designed to
241+
trip up the parser.
231242

232-
<!--
233-
Why should this enhancement _not_ be implemented?
234-
-->
243+
* PACKAGING: There is no packaging code implemented in the project at
244+
this point. The developer[s] would welcome both help with the `pypy`
245+
packaging code and with Red Hat/Canonical packages.
235246

236-
## Alternatives
247+
* PEER REVIEW: The code was written mostly by a single person. A peer
248+
review of the code would be welcome.
237249

238-
<!--
239-
What other approaches did you consider and why did you rule them out? These do
240-
not need to be as detailed as the proposal, but should include enough
241-
information to express the idea and why it was not acceptable.
242-
-->
250+
* DOCUMENTATION: A lot of the event log parser is based on TCG
251+
documentation. Better documentation (attributing parts of the code to
252+
specific TCG and EFI documentation, by chapter and verse) would be
253+
welcome.
243254

244-
## Infrastructure Needed (optional)
255+
* INTEGRATION: a PR in keylime to replace the `tpm2-tools` call with
256+
the native call. Goal 1 would be a pre-requisitve, since the
257+
implication would be that the python event log parser is a package
258+
dependency of keylime.
245259

246-
<!--
247-
Use this section if you need things infrastructure related specific to your enhancement. Examples include a
248-
new subproject, repos requested, github webhook, changes to CI (travis).
249-
-->

0 commit comments

Comments
 (0)
Please sign in to comment.