Coverage Report

Created: 2026-04-09 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-tpm-eventlog-item.c
Line
Count
Source
1
/*
2
 * Copyright 2026 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
0
#define G_LOG_DOMAIN "FuTpmEventlog"
8
9
#include "config.h"
10
11
#include "fu-bytes.h"
12
#include "fu-common.h"
13
#include "fu-tpm-eventlog-item.h"
14
15
const FuTpmAlg algs[] = {
16
    FU_TPM_ALG_SHA1,
17
    FU_TPM_ALG_SHA256,
18
    FU_TPM_ALG_SHA384,
19
};
20
21
struct _FuTpmEventlogItem {
22
  FuFirmware parent_instance;
23
  FuTpmEventlogItemKind kind;
24
  guint8 pcr;
25
  GBytes *checksums[G_N_ELEMENTS(algs)];
26
};
27
28
0
G_DEFINE_TYPE(FuTpmEventlogItem, fu_tpm_eventlog_item, FU_TYPE_FIRMWARE)
29
0
30
0
static guint
31
0
fu_tpm_eventlog_item_alg_to_idx(FuTpmAlg alg)
32
0
{
33
0
  for (guint i = 0; i < G_N_ELEMENTS(algs); i++) {
34
0
    if (algs[i] == alg)
35
0
      return i;
36
0
  }
37
0
  return G_MAXUINT;
38
0
}
39
40
/**
41
 * fu_tpm_eventlog_item_add_checksum:
42
 * @self: a #FuTpmEventlogItem
43
 * @alg: a #FuTpmAlg, e.g. %FU_TPM_ALG_SHA1
44
 * @checksum: a #GBytes of the raw checksum
45
 *
46
 * Adds the checksum of a specific type.
47
 *
48
 * Since: 2.1.1
49
 **/
50
void
51
fu_tpm_eventlog_item_add_checksum(FuTpmEventlogItem *self, FuTpmAlg alg, GBytes *checksum)
52
0
{
53
0
  guint csum_idx = fu_tpm_eventlog_item_alg_to_idx(alg);
54
0
  g_return_if_fail(FU_IS_TPM_EVENTLOG_ITEM(self));
55
0
  g_return_if_fail(csum_idx != G_MAXUINT);
56
0
  g_return_if_fail(checksum != NULL);
57
58
0
  if (self->checksums[csum_idx] != NULL)
59
0
    g_bytes_unref(self->checksums[csum_idx]);
60
0
  self->checksums[csum_idx] = g_bytes_ref(checksum);
61
0
}
62
63
/**
64
 * fu_tpm_eventlog_item_get_checksum:
65
 * @self: a #FuTpmEventlogItem
66
 * @alg: a #FuTpmAlg, e.g. %FU_TPM_ALG_SHA1
67
 * @error: (nullable): optional return location for an error
68
 *
69
 * Gets the raw checksum of a specific type.
70
 *
71
 * Returns: a #GBytes, or %NULL on error
72
 *
73
 * Since: 2.1.1
74
 **/
75
GBytes *
76
fu_tpm_eventlog_item_get_checksum(FuTpmEventlogItem *self, FuTpmAlg alg, GError **error)
77
0
{
78
0
  guint csum_idx = fu_tpm_eventlog_item_alg_to_idx(alg);
79
0
  g_return_val_if_fail(FU_IS_TPM_EVENTLOG_ITEM(self), NULL);
80
0
  g_return_val_if_fail(csum_idx != G_MAXUINT, NULL);
81
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
82
83
0
  if (self->checksums[csum_idx] == NULL) {
84
0
    g_set_error(error,
85
0
          FWUPD_ERROR,
86
0
          FWUPD_ERROR_NOT_SUPPORTED,
87
0
          "checksum %s not set",
88
0
          fu_tpm_alg_to_string(alg));
89
0
    return NULL;
90
0
  }
91
0
  return g_bytes_ref(self->checksums[csum_idx]);
92
0
}
93
94
/**
95
 * fu_tpm_eventlog_item_get_kind:
96
 * @self: a #FuTpmEventlogItem
97
 *
98
 * Gets the item kind.
99
 *
100
 * Returns: a #FuTpmEventlogItemKind, e.g. %FU_TPM_EVENTLOG_ITEM_KIND_EFI_PLATFORM_FIRMWARE_BLOB
101
 *
102
 * Since: 2.1.1
103
 **/
104
FuTpmEventlogItemKind
105
fu_tpm_eventlog_item_get_kind(FuTpmEventlogItem *self)
106
0
{
107
0
  g_return_val_if_fail(FU_IS_TPM_EVENTLOG_ITEM(self), G_MAXUINT);
108
0
  return self->kind;
109
0
}
110
111
/**
112
 * fu_tpm_eventlog_item_set_kind:
113
 * @self: a #FuTpmEventlogItem
114
 * @kind: a #FuTpmEventlogItemKind, e.g. %FU_TPM_EVENTLOG_ITEM_KIND_EFI_PLATFORM_FIRMWARE_BLOB
115
 *
116
 * Sets item kind.
117
 *
118
 * Since: 2.1.1
119
 **/
120
void
121
fu_tpm_eventlog_item_set_kind(FuTpmEventlogItem *self, FuTpmEventlogItemKind kind)
122
0
{
123
0
  g_return_if_fail(FU_IS_TPM_EVENTLOG_ITEM(self));
124
0
  self->kind = kind;
125
0
}
126
127
/**
128
 * fu_tpm_eventlog_item_get_pcr:
129
 * @self: a #FuTpmEventlogItem
130
 *
131
 * Gets the PCR register.
132
 *
133
 * Returns: value
134
 *
135
 * Since: 2.1.1
136
 **/
137
guint8
138
fu_tpm_eventlog_item_get_pcr(FuTpmEventlogItem *self)
139
0
{
140
0
  g_return_val_if_fail(FU_IS_TPM_EVENTLOG_ITEM(self), G_MAXUINT8);
141
0
  return self->pcr;
142
0
}
143
144
/**
145
 * fu_tpm_eventlog_item_set_pcr:
146
 * @self: a #FuTpmEventlogItem
147
 * @pcr: a value
148
 *
149
 * Sets the PCR register.
150
 *
151
 * Since: 2.1.1
152
 **/
153
void
154
fu_tpm_eventlog_item_set_pcr(FuTpmEventlogItem *self, guint8 pcr)
155
0
{
156
0
  g_return_if_fail(FU_IS_TPM_EVENTLOG_ITEM(self));
157
0
  self->pcr = pcr;
158
0
}
159
160
static guint
161
fu_tpm_eventlog_item_csum_kind_to_idx(GChecksumType csum_kind)
162
0
{
163
0
  if (csum_kind == G_CHECKSUM_SHA1)
164
0
    return fu_tpm_eventlog_item_alg_to_idx(FU_TPM_ALG_SHA1);
165
0
  if (csum_kind == G_CHECKSUM_SHA256)
166
0
    return fu_tpm_eventlog_item_alg_to_idx(FU_TPM_ALG_SHA256);
167
0
  if (csum_kind == G_CHECKSUM_SHA384)
168
0
    return fu_tpm_eventlog_item_alg_to_idx(FU_TPM_ALG_SHA384);
169
0
  return G_MAXUINT;
170
0
}
171
172
static gchar *
173
fu_tpm_eventlog_item_get_checksum_string(FuFirmware *firmware,
174
           GChecksumType csum_kind,
175
           GError **error)
176
0
{
177
0
  FuTpmEventlogItem *self = FU_TPM_EVENTLOG_ITEM(firmware);
178
0
  guint csum_idx = fu_tpm_eventlog_item_csum_kind_to_idx(csum_kind);
179
180
  /* unset */
181
0
  if (csum_idx == G_MAXUINT) {
182
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "not supported");
183
0
    return NULL;
184
0
  }
185
0
  if (self->checksums[csum_idx] == NULL) {
186
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "not set");
187
0
    return NULL;
188
0
  }
189
0
  return fu_bytes_to_string(self->checksums[csum_idx]);
190
0
}
191
192
static gboolean
193
fu_tpm_eventlog_item_build(FuFirmware *firmware, XbNode *n, GError **error)
194
0
{
195
0
  FuTpmEventlogItem *self = FU_TPM_EVENTLOG_ITEM(firmware);
196
0
  const gchar *tmp;
197
0
  guint64 tmp64;
198
199
  /* simple properties */
200
0
  tmp = xb_node_query_text(n, "kind", NULL);
201
0
  if (tmp != NULL)
202
0
    fu_tpm_eventlog_item_set_kind(self, fu_tpm_eventlog_item_kind_from_string(tmp));
203
0
  tmp64 = xb_node_query_text_as_uint(n, "pcr", NULL);
204
0
  if (tmp64 != G_MAXUINT64)
205
0
    fu_tpm_eventlog_item_set_pcr(self, tmp64);
206
207
  /* checksums */
208
0
  for (guint i = 0; i < G_N_ELEMENTS(algs); i++) {
209
0
    tmp = xb_node_query_text(n, fu_tpm_alg_to_string(algs[i]), NULL);
210
0
    if (tmp != NULL) {
211
0
      g_autoptr(GBytes) blob = fu_bytes_from_string(tmp, error);
212
0
      if (blob == NULL)
213
0
        return FALSE;
214
0
      fu_tpm_eventlog_item_add_checksum(self, algs[i], blob);
215
0
    }
216
0
  }
217
218
  /* success */
219
0
  return TRUE;
220
0
}
221
222
static void
223
fu_tpm_eventlog_item_export(FuFirmware *firmware, FuFirmwareExportFlags flags, XbBuilderNode *bn)
224
0
{
225
0
  FuTpmEventlogItem *self = FU_TPM_EVENTLOG_ITEM(firmware);
226
0
  fu_xmlb_builder_insert_kv(bn, "kind", fu_tpm_eventlog_item_kind_to_string(self->kind));
227
0
  fu_xmlb_builder_insert_kx(bn, "pcr", self->pcr);
228
0
  for (guint i = 0; i < G_N_ELEMENTS(algs); i++) {
229
0
    if (self->checksums[i] != NULL) {
230
0
      g_autofree gchar *value = fu_bytes_to_string(self->checksums[i]);
231
0
      fu_xmlb_builder_insert_kv(bn, fu_tpm_alg_to_string(algs[i]), value);
232
0
    }
233
0
  }
234
0
}
235
236
static void
237
fu_tpm_eventlog_item_finalize(GObject *object)
238
0
{
239
0
  FuTpmEventlogItem *self = FU_TPM_EVENTLOG_ITEM(object);
240
241
0
  for (guint i = 0; i < G_N_ELEMENTS(self->checksums); i++) {
242
0
    if (self->checksums[i] != NULL)
243
0
      g_bytes_unref(self->checksums[i]);
244
0
  }
245
246
0
  G_OBJECT_CLASS(fu_tpm_eventlog_item_parent_class)->finalize(object);
247
0
}
248
249
static void
250
fu_tpm_eventlog_item_class_init(FuTpmEventlogItemClass *klass)
251
0
{
252
0
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
253
0
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
254
0
  object_class->finalize = fu_tpm_eventlog_item_finalize;
255
0
  firmware_class->get_checksum = fu_tpm_eventlog_item_get_checksum_string;
256
0
  firmware_class->build = fu_tpm_eventlog_item_build;
257
0
  firmware_class->export = fu_tpm_eventlog_item_export;
258
0
}
259
260
static void
261
fu_tpm_eventlog_item_init(FuTpmEventlogItem *self)
262
0
{
263
0
}
264
265
/**
266
 * fu_tpm_eventlog_item_new:
267
 *
268
 * Returns: (transfer full): a #FuTpmEventlogItem
269
 *
270
 * Since: 2.1.1
271
 **/
272
FuTpmEventlogItem *
273
fu_tpm_eventlog_item_new(void)
274
0
{
275
0
  return g_object_new(FU_TYPE_TPM_EVENTLOG_ITEM, NULL);
276
0
}