Coverage Report

Created: 2026-02-26 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupdplugin/fu-tpm-eventlog-v1.c
Line
Count
Source
1
/*
2
 * Copyright 2019 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#define G_LOG_DOMAIN "FuTpmEventlog"
8
9
#include "config.h"
10
11
#include "fu-byte-array.h"
12
#include "fu-input-stream.h"
13
#include "fu-tpm-eventlog-item.h"
14
#include "fu-tpm-eventlog-v1.h"
15
#include "fu-tpm-struct.h"
16
17
struct _FuTpmEventlogV1 {
18
  FuFirmware parent_instance;
19
};
20
21
0
G_DEFINE_TYPE(FuTpmEventlogV1, fu_tpm_eventlog_v1, FU_TYPE_TPM_EVENTLOG)
22
0
23
0
static gboolean
24
0
fu_tpm_eventlog_v1_parse(FuFirmware *firmware,
25
0
       GInputStream *stream,
26
0
       FuFirmwareParseFlags flags,
27
0
       GError **error)
28
0
{
29
0
  gsize streamsz = 0;
30
0
  if (!fu_input_stream_size(stream, &streamsz, error))
31
0
    return FALSE;
32
0
  for (gsize idx = 0; idx < streamsz; idx += FU_STRUCT_TPM_EVENT_LOG1_ITEM_SIZE) {
33
0
    guint32 datasz = 0;
34
0
    guint32 pcr = 0;
35
0
    guint32 event_type = 0;
36
0
    gsize digestsz = 0;
37
0
    const guint8 *digest;
38
0
    g_autoptr(FuStructTpmEventLog1Item) st = NULL;
39
0
    g_autoptr(FuTpmEventlogItem) item = fu_tpm_eventlog_item_new();
40
0
    g_autoptr(GBytes) checksum_sha1 = NULL;
41
42
0
    st = fu_struct_tpm_event_log1_item_parse_stream(stream, idx, error);
43
0
    if (st == NULL)
44
0
      return FALSE;
45
0
    pcr = fu_struct_tpm_event_log1_item_get_pcr(st);
46
0
    event_type = fu_struct_tpm_event_log1_item_get_type(st);
47
0
    datasz = fu_struct_tpm_event_log1_item_get_datasz(st);
48
0
    if (datasz > 1024 * 1024) {
49
0
      g_set_error_literal(error,
50
0
              FWUPD_ERROR,
51
0
              FWUPD_ERROR_NOT_SUPPORTED,
52
0
              "event log item too large");
53
0
      return FALSE;
54
0
    }
55
56
    /* build item */
57
0
    fu_tpm_eventlog_item_set_pcr(item, pcr);
58
0
    fu_tpm_eventlog_item_set_kind(item, event_type);
59
0
    digest = fu_struct_tpm_event_log1_item_get_digest(st, &digestsz);
60
0
    checksum_sha1 = g_bytes_new(digest, digestsz);
61
0
    fu_tpm_eventlog_item_add_checksum(item, FU_TPM_ALG_SHA1, checksum_sha1);
62
0
    if (datasz > 0) {
63
0
      g_autoptr(GBytes) blob = NULL;
64
0
      blob = fu_input_stream_read_bytes(stream,
65
0
                idx + st->buf->len,
66
0
                datasz,
67
0
                NULL,
68
0
                error);
69
0
      if (blob == NULL)
70
0
        return FALSE;
71
0
      fu_firmware_set_bytes(FU_FIRMWARE(item), blob);
72
0
    }
73
0
    if (!fu_firmware_add_image(firmware, FU_FIRMWARE(item), error))
74
0
      return FALSE;
75
0
    idx += datasz;
76
0
  }
77
78
  /* success */
79
0
  return TRUE;
80
0
}
81
82
static GByteArray *
83
fu_tpm_eventlog_v1_write(FuFirmware *firmware, GError **error)
84
0
{
85
0
  g_autoptr(GByteArray) buf = g_byte_array_new();
86
0
  g_autoptr(GPtrArray) items = fu_firmware_get_images(firmware);
87
88
0
  for (guint i = 0; i < items->len; i++) {
89
0
    FuTpmEventlogItem *item = g_ptr_array_index(items, i);
90
0
    g_autoptr(FuStructTpmEventLog1Item) st = fu_struct_tpm_event_log1_item_new();
91
0
    g_autoptr(GBytes) digest = NULL;
92
0
    g_autoptr(GBytes) blob = NULL;
93
94
0
    fu_struct_tpm_event_log1_item_set_pcr(st, fu_tpm_eventlog_item_get_pcr(item));
95
0
    fu_struct_tpm_event_log1_item_set_type(st, fu_tpm_eventlog_item_get_kind(item));
96
97
0
    digest = fu_tpm_eventlog_item_get_checksum(item, FU_TPM_ALG_SHA1, error);
98
0
    if (digest == NULL)
99
0
      return NULL;
100
0
    if (!fu_struct_tpm_event_log1_item_set_digest(st,
101
0
                    g_bytes_get_data(digest, NULL),
102
0
                    g_bytes_get_size(digest),
103
0
                    error))
104
0
      return NULL;
105
0
    blob = fu_firmware_get_bytes(FU_FIRMWARE(item), error);
106
0
    if (blob == NULL)
107
0
      return NULL;
108
0
    fu_struct_tpm_event_log1_item_set_datasz(st, g_bytes_get_size(blob));
109
0
    fu_byte_array_append_bytes(st->buf, blob);
110
111
    /* done, dump */
112
0
    g_byte_array_append(buf, st->buf->data, st->buf->len);
113
0
  }
114
115
  /* success */
116
0
  return g_steal_pointer(&buf);
117
0
}
118
119
static void
120
fu_tpm_eventlog_v1_class_init(FuTpmEventlogV1Class *klass)
121
0
{
122
0
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
123
0
  firmware_class->parse = fu_tpm_eventlog_v1_parse;
124
0
  firmware_class->write = fu_tpm_eventlog_v1_write;
125
0
}
126
127
static void
128
fu_tpm_eventlog_v1_init(FuTpmEventlogV1 *self)
129
0
{
130
0
  fu_firmware_add_image_gtype(FU_FIRMWARE(self), FU_TYPE_TPM_EVENTLOG_ITEM);
131
0
}
132
133
/**
134
 * fu_tpm_eventlog_v1_new:
135
 *
136
 * Creates a new object to parse TPMv1 eventlog data.
137
 *
138
 * Returns: a #FuTpmEventlog
139
 *
140
 * Since: 2.1.1
141
 **/
142
FuTpmEventlog *
143
fu_tpm_eventlog_v1_new(void)
144
0
{
145
0
  FuTpmEventlogV1 *self;
146
0
  self = g_object_new(FU_TYPE_TPM_EVENTLOG_V1, NULL);
147
0
  return FU_TPM_EVENTLOG(self);
148
0
}