|
|
c8bd4f |
From cef0317b83e06fdca25ef52a8bfd59b74d318e5a Mon Sep 17 00:00:00 2001
|
|
|
c8bd4f |
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
|
|
c8bd4f |
Date: Thu, 29 Sep 2022 10:48:36 -0400
|
|
|
c8bd4f |
Subject: [PATCH 5/9] tpm2_eventlog_yaml: fix malformed YAML for EV_IPL data
|
|
|
c8bd4f |
MIME-Version: 1.0
|
|
|
c8bd4f |
Content-Type: text/plain; charset=UTF-8
|
|
|
c8bd4f |
Content-Transfer-Encoding: 8bit
|
|
|
c8bd4f |
|
|
|
c8bd4f |
The code for printing EV_IPL data was fairly crude and often
|
|
|
c8bd4f |
did not generate valid YAML syntax. Some problems
|
|
|
c8bd4f |
|
|
|
c8bd4f |
* Data starting with a space would result in invalid
|
|
|
c8bd4f |
indentation, a leading space requires a quoted string
|
|
|
c8bd4f |
* Non-printable cahracters must generally be escaped,
|
|
|
c8bd4f |
using a quoted string
|
|
|
c8bd4f |
* Embedded NUL bytes were turned into newlines, which
|
|
|
c8bd4f |
mangled any UTF16 encoded data.
|
|
|
c8bd4f |
|
|
|
c8bd4f |
This change attempts to make the YAML output much safer. It
|
|
|
c8bd4f |
is not pefect as it just processes the data bytewise and
|
|
|
c8bd4f |
thus could potentially emit invalid UTF-8 bytes. In practice
|
|
|
c8bd4f |
this won't be a problem for known bootloader emitting EV_IPL
|
|
|
c8bd4f |
events.
|
|
|
c8bd4f |
|
|
|
c8bd4f |
This changes the formatting slightly
|
|
|
c8bd4f |
|
|
|
c8bd4f |
- All strings are now surrounded with double quotes
|
|
|
c8bd4f |
|
|
|
c8bd4f |
- All NUL bytes, including the final trailing NUL
|
|
|
c8bd4f |
are displayed in escaped format.
|
|
|
c8bd4f |
|
|
|
c8bd4f |
- Non-printable ASCII chars are escaped, including
|
|
|
c8bd4f |
the tab character, per YAML recommendations
|
|
|
c8bd4f |
|
|
|
c8bd4f |
A much better long term solution would be to switch to
|
|
|
c8bd4f |
using libyaml for generating the output which would give
|
|
|
c8bd4f |
a strong guarantee of correct formatting.
|
|
|
c8bd4f |
|
|
|
c8bd4f |
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
|
c8bd4f |
---
|
|
|
c8bd4f |
lib/tpm2_eventlog_yaml.c | 141 ++++++++++++++++++++++++++++++++++++---
|
|
|
c8bd4f |
1 file changed, 130 insertions(+), 11 deletions(-)
|
|
|
c8bd4f |
|
|
|
c8bd4f |
diff --git a/lib/tpm2_eventlog_yaml.c b/lib/tpm2_eventlog_yaml.c
|
|
|
c8bd4f |
index fee78027..66a20701 100644
|
|
|
c8bd4f |
--- a/lib/tpm2_eventlog_yaml.c
|
|
|
c8bd4f |
+++ b/lib/tpm2_eventlog_yaml.c
|
|
|
c8bd4f |
@@ -571,6 +571,125 @@ bool yaml_uefi_action(UINT8 const *action, size_t size) {
|
|
|
c8bd4f |
|
|
|
c8bd4f |
return true;
|
|
|
c8bd4f |
}
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+/*
|
|
|
c8bd4f |
+ * The yaml_ipl description is received as raw bytes, but the
|
|
|
c8bd4f |
+ * data will represent a printable string. Unfortunately we
|
|
|
c8bd4f |
+ * are not told its encoding, and this can vary. For example,
|
|
|
c8bd4f |
+ * grub will use UTF8, while sd-boot will UTF16LE.
|
|
|
c8bd4f |
+ *
|
|
|
c8bd4f |
+ * We need to emit YAML with some rules:
|
|
|
c8bd4f |
+ *
|
|
|
c8bd4f |
+ * - No leading ' ' without quoting it
|
|
|
c8bd4f |
+ * - Escape non-printable ascii chars
|
|
|
c8bd4f |
+ * - Double quotes if using escape sequences
|
|
|
c8bd4f |
+ * - Valid UTF8 string
|
|
|
c8bd4f |
+ *
|
|
|
c8bd4f |
+ * This method will ignore the question of original data
|
|
|
c8bd4f |
+ * encoding and apply a few simple rules to make the data
|
|
|
c8bd4f |
+ * mostly YAML compliant. Where it falls down is not
|
|
|
c8bd4f |
+ * guaranteeing valid UTF8, if the input was not already
|
|
|
c8bd4f |
+ * valid UTF8. In practice this limitation shouldn't be
|
|
|
c8bd4f |
+ * a problem given expected measured data.
|
|
|
c8bd4f |
+ *
|
|
|
c8bd4f |
+ * Note: one consequence of this approach is that most
|
|
|
c8bd4f |
+ * UTF16LE data will be rendered with lots of \0 bytes
|
|
|
c8bd4f |
+ * escaped.
|
|
|
c8bd4f |
+ *
|
|
|
c8bd4f |
+ * For ease of output reading, the data is also split on newlines
|
|
|
c8bd4f |
+ */
|
|
|
c8bd4f |
+char **yaml_split_escape_string(UINT8 const *description, size_t size)
|
|
|
c8bd4f |
+{
|
|
|
c8bd4f |
+ char **lines = NULL, **tmp;
|
|
|
c8bd4f |
+ size_t nlines = 0;
|
|
|
c8bd4f |
+ size_t i, j, k;
|
|
|
c8bd4f |
+ size_t len;
|
|
|
c8bd4f |
+ UINT8 *nl;
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ i = 0;
|
|
|
c8bd4f |
+ do {
|
|
|
c8bd4f |
+ nl = memchr(description + i, '\n', size - i);
|
|
|
c8bd4f |
+ len = nl ? (size_t)(nl - (description + i)) : size - i;
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ tmp = realloc(lines, sizeof(char *) * (nlines + 2));
|
|
|
c8bd4f |
+ if (!tmp) {
|
|
|
c8bd4f |
+ LOG_ERR("failed to allocate memory for description lines: %s\n",
|
|
|
c8bd4f |
+ strerror(errno));
|
|
|
c8bd4f |
+ goto error;
|
|
|
c8bd4f |
+ }
|
|
|
c8bd4f |
+ lines = tmp;
|
|
|
c8bd4f |
+ lines[nlines + 1] = NULL;
|
|
|
c8bd4f |
+ k = 0;
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ /* Worst case: every byte needs escaping, plus start/end quotes, plus nul */
|
|
|
c8bd4f |
+ lines[nlines] = calloc(1, (len * 2) + 2 + 1);
|
|
|
c8bd4f |
+ if (!lines[nlines]) {
|
|
|
c8bd4f |
+ LOG_ERR("failed to allocate memory for escaped string: %s\n",
|
|
|
c8bd4f |
+ strerror(errno));
|
|
|
c8bd4f |
+ goto error;
|
|
|
c8bd4f |
+ }
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ lines[nlines][k++] = '"';
|
|
|
c8bd4f |
+ for (j = i; j < (i + len); j++) {
|
|
|
c8bd4f |
+ char escape = '\0';
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ switch (description[j]) {
|
|
|
c8bd4f |
+ case '\0':
|
|
|
c8bd4f |
+ escape = '0';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\a':
|
|
|
c8bd4f |
+ escape = 'a';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\b':
|
|
|
c8bd4f |
+ escape = 'b';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\t':
|
|
|
c8bd4f |
+ escape = 't';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\v':
|
|
|
c8bd4f |
+ escape = 'v';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\f':
|
|
|
c8bd4f |
+ escape = 'f';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\r':
|
|
|
c8bd4f |
+ escape = 'r';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\e':
|
|
|
c8bd4f |
+ escape = 'e';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\'':
|
|
|
c8bd4f |
+ escape = '\'';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ case '\\':
|
|
|
c8bd4f |
+ escape = '\\';
|
|
|
c8bd4f |
+ break;
|
|
|
c8bd4f |
+ }
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ if (escape == '\0') {
|
|
|
c8bd4f |
+ lines[nlines][k++] = description[j];
|
|
|
c8bd4f |
+ } else {
|
|
|
c8bd4f |
+ lines[nlines][k++] = '\\';
|
|
|
c8bd4f |
+ lines[nlines][k++] = escape;
|
|
|
c8bd4f |
+ }
|
|
|
c8bd4f |
+ }
|
|
|
c8bd4f |
+ lines[nlines][k++] = '"';
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ nlines++;
|
|
|
c8bd4f |
+ i += len + 1;
|
|
|
c8bd4f |
+ } while (i < size);
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ return lines;
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ error:
|
|
|
c8bd4f |
+ for (i = 0; lines != NULL && lines[i] != NULL; i++) {
|
|
|
c8bd4f |
+ free(lines[i]);
|
|
|
c8bd4f |
+ }
|
|
|
c8bd4f |
+ free(lines);
|
|
|
c8bd4f |
+ return NULL;
|
|
|
c8bd4f |
+}
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
/*
|
|
|
c8bd4f |
* TCG PC Client PFP section 9.4.1
|
|
|
c8bd4f |
* This event type is extensively used by the Shim and Grub on a wide varities
|
|
|
c8bd4f |
@@ -578,21 +697,21 @@ bool yaml_uefi_action(UINT8 const *action, size_t size) {
|
|
|
c8bd4f |
* the loading of grub, kernel, and initrd images.
|
|
|
c8bd4f |
*/
|
|
|
c8bd4f |
bool yaml_ipl(UINT8 const *description, size_t size) {
|
|
|
c8bd4f |
-
|
|
|
c8bd4f |
+ char **lines = NULL;
|
|
|
c8bd4f |
+ size_t i;
|
|
|
c8bd4f |
tpm2_tool_output(" Event:\n"
|
|
|
c8bd4f |
" String: |-\n");
|
|
|
c8bd4f |
|
|
|
c8bd4f |
- /* We need to handle when description contains multiple lines. */
|
|
|
c8bd4f |
- size_t i, j;
|
|
|
c8bd4f |
- for (i = 0; i < size; i++) {
|
|
|
c8bd4f |
- for (j = i; j < size; j++) {
|
|
|
c8bd4f |
- if (description[j] == '\n' || description[j] == '\0') {
|
|
|
c8bd4f |
- break;
|
|
|
c8bd4f |
- }
|
|
|
c8bd4f |
- }
|
|
|
c8bd4f |
- tpm2_tool_output(" %.*s\n", (int)(j - i), description+i);
|
|
|
c8bd4f |
- i = j;
|
|
|
c8bd4f |
+ lines = yaml_split_escape_string(description, size);
|
|
|
c8bd4f |
+ if (!lines) {
|
|
|
c8bd4f |
+ return false;
|
|
|
c8bd4f |
+ }
|
|
|
c8bd4f |
+
|
|
|
c8bd4f |
+ for (i = 0; lines[i] != NULL; i++) {
|
|
|
c8bd4f |
+ tpm2_tool_output(" %s\n", lines[i]);
|
|
|
c8bd4f |
+ free(lines[i]);
|
|
|
c8bd4f |
}
|
|
|
c8bd4f |
+ free(lines);
|
|
|
c8bd4f |
|
|
|
c8bd4f |
return true;
|
|
|
c8bd4f |
}
|
|
|
c8bd4f |
--
|
|
|
c8bd4f |
2.37.3
|
|
|
c8bd4f |
|