Coverage Report

Created: 2026-10-13 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/common/state/backend_format_raw.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2012-2014 Pengutronix, Jan Luebbe <j.luebbe@pengutronix.de>
3
 * Copyright (C) 2013-2014 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
4
 * Copyright (C) 2015 Pengutronix, Marc Kleine-Budde <mkl@pengutronix.de>
5
 * Copyright (C) 2016 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * version 2, as published by the Free Software Foundation.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 */
17
18
#include <common.h>
19
#include <crypto/keystore.h>
20
#include <fuzz.h>
21
#include <digest.h>
22
#include <linux/kernel.h>
23
#include <malloc.h>
24
#include <crc.h>
25
#include <of.h>
26
27
#include "state.h"
28
29
struct state_backend_format_raw {
30
  struct state_backend_format format;
31
32
  struct digest *digest;
33
  unsigned int digest_length;
34
35
  /* For outputs */
36
  struct device *dev;
37
38
  char *secret_name;
39
  int needs_secret;
40
  char *algo;
41
};
42
43
struct __attribute__((__packed__)) backend_raw_header {
44
  uint32_t magic;
45
  uint16_t reserved;
46
  uint16_t data_len;
47
  uint32_t data_crc;
48
  uint32_t header_crc;
49
};
50
51
const int format_raw_min_length = sizeof(struct backend_raw_header);
52
53
static inline struct state_backend_format_raw *get_format_raw(
54
    struct state_backend_format *format)
55
384
{
56
384
  return container_of(format, struct state_backend_format_raw, format);
57
384
}
58
59
static int backend_raw_digest_init(struct state_backend_format_raw *raw)
60
93
{
61
93
  const unsigned char *key;
62
93
  int key_len;
63
93
  int ret;
64
65
93
  if (!raw->digest) {
66
1
    raw->digest = digest_alloc(raw->algo);
67
1
    if (!raw->digest) {
68
0
      dev_err(raw->dev, "algo %s not found\n",
69
0
        raw->algo);
70
0
      return -ENODEV;
71
0
    }
72
1
    raw->digest_length = digest_length(raw->digest);
73
1
  }
74
75
93
  ret = keystore_get_secret(raw->secret_name, &key, &key_len);
76
93
  if (ret) {
77
0
    dev_err(raw->dev, "Could not get secret '%s'\n",
78
0
      raw->secret_name);
79
0
    return ret;
80
0
  }
81
82
93
  ret = digest_set_key(raw->digest, key, key_len);
83
93
  if (ret)
84
0
    return ret;
85
86
93
  ret = digest_init(raw->digest);
87
93
  if (ret) {
88
0
    dev_err(raw->dev, "Failed to initialize digest: %pe\n",
89
0
      ERR_PTR(ret));
90
0
    return ret;
91
0
  }
92
93
93
  return 0;
94
93
}
95
96
static int backend_format_raw_verify(struct state_backend_format *format,
97
             uint32_t magic, const void * buf,
98
             ssize_t *lenp, enum state_flags flags)
99
358
{
100
358
  uint32_t crc;
101
358
  struct backend_raw_header *header;
102
358
  int d_len = 0;
103
358
  int ret;
104
358
  const void *data;
105
358
  ssize_t len = *lenp;
106
358
  struct state_backend_format_raw *backend_raw = get_format_raw(format);
107
358
  ssize_t complete_len;
108
109
358
  if (len < format_raw_min_length) {
110
12
    dev_err(backend_raw->dev, "Error, buffer length (%zd) is shorter than the minimum required header length\n",
111
12
      len);
112
12
    return -EINVAL;
113
12
  }
114
115
346
  header = (struct backend_raw_header *)buf;
116
346
  crc = crc32(0, header, sizeof(*header) - sizeof(uint32_t));
117
346
  if (crc != header->header_crc &&
118
267
      !fuzz_insecure_checksum_accepted(crc, header->header_crc))
119
65
    return dev_err_state_init(backend_raw->dev,
120
346
      header->header_crc ? -EINVAL : -ENOMEDIUM,
121
346
      "header crc in raw format, calculated 0x%08x, found 0x%08x\n",
122
346
      crc, header->header_crc);
123
124
281
  if (magic && magic != header->magic) {
125
0
    dev_err(backend_raw->dev, "Error, invalid magic in raw format 0x%08x, should be 0x%08x\n",
126
0
      header->magic, magic);
127
0
    return -EINVAL;
128
0
  }
129
130
281
  if (backend_raw->algo && !(flags & STATE_FLAG_NO_AUTHENTICATION)) {
131
93
    ret = backend_raw_digest_init(backend_raw);
132
93
    if (ret)
133
0
      return ret;
134
135
93
    d_len = digest_length(backend_raw->digest);
136
93
  }
137
138
281
  complete_len = header->data_len + d_len + format_raw_min_length;
139
281
  if (complete_len > len) {
140
37
    dev_err(backend_raw->dev, "Error, invalid data_len %u in header, have data of len %zu\n",
141
37
      header->data_len, len);
142
37
    return -EINVAL;
143
37
  }
144
145
244
  data = buf + sizeof(*header);
146
147
244
  crc = crc32(0, data, header->data_len);
148
244
  if (crc != header->data_crc &&
149
159
      !fuzz_insecure_checksum_accepted(crc, header->data_crc)) {
150
36
    dev_err(backend_raw->dev, "invalid data crc, calculated 0x%08x, found 0x%08x\n",
151
36
      crc, header->data_crc);
152
36
    return -EINVAL;
153
36
  }
154
155
208
  *lenp = header->data_len + sizeof(*header);
156
157
208
  if (backend_raw->algo && !(flags & STATE_FLAG_NO_AUTHENTICATION)) {
158
61
    const void *hmac = data + header->data_len;
159
160
    /* hmac over header and data */
161
61
    ret = digest_update(backend_raw->digest, buf, sizeof(*header) + header->data_len);
162
61
    if (ret) {
163
0
      dev_err(backend_raw->dev, "Failed to update digest, %d\n",
164
0
        ret);
165
0
      return ret;
166
0
    }
167
168
61
    ret = digest_verify(backend_raw->digest, hmac);
169
61
    if (ret < 0) {
170
31
      dev_err(backend_raw->dev, "Failed to verify data, hmac, %d\n",
171
31
        ret);
172
31
      return ret;
173
31
    }
174
61
  }
175
176
177
  return 0;
177
208
}
178
179
static int backend_format_raw_unpack(struct state_backend_format *format,
180
             struct state *state, const void * buf,
181
             ssize_t len)
182
26
{
183
26
  struct state_variable *sv;
184
26
  const struct backend_raw_header *header;
185
26
  const void *data;
186
26
  struct state_backend_format_raw *backend_raw = get_format_raw(format);
187
26
  int ret = 0;
188
189
26
  header = (const struct backend_raw_header *)buf;
190
26
  data = buf + sizeof(*header);
191
192
52
  list_for_each_entry(sv, &state->variables, list) {
193
52
    if (sv->start + sv->size > header->data_len) {
194
0
      dev_err(backend_raw->dev, "State variable ends behind valid data, %s\n",
195
0
        sv->name);
196
0
      ret = -ENOSPC;
197
0
      continue;
198
0
    }
199
52
    memcpy(sv->raw, data + sv->start, sv->size);
200
52
  }
201
202
26
  return ret;
203
26
}
204
205
static inline size_t state_data_size(struct state *state)
206
0
{
207
0
  const struct state_variable *sv;
208
209
  /* Make use of the fact that the list is sorted in ascending order */
210
0
  sv = list_last_entry_or_null(&state->variables, struct state_variable, list);
211
0
  if (!sv)
212
0
    return 0;
213
214
0
  return sv->start + sv->size;
215
0
}
216
217
static int backend_format_raw_pack(struct state_backend_format *format,
218
           struct state *state, void ** buf_out,
219
           ssize_t * len_out)
220
0
{
221
0
  struct state_backend_format_raw *backend_raw = get_format_raw(format);
222
0
  void *buf, *data, *hmac;
223
0
  struct backend_raw_header *header;
224
0
  struct state_variable *sv;
225
0
  unsigned int size_full;
226
0
  unsigned int size_data;
227
0
  int ret;
228
229
0
  if (backend_raw->algo) {
230
0
    ret = backend_raw_digest_init(backend_raw);
231
0
    if (ret)
232
0
      return ret;
233
0
  }
234
235
0
  size_data = state_data_size(state);
236
237
0
  size_full = size_data + sizeof(*header) + backend_raw->digest_length;
238
239
0
  buf = xzalloc(size_full);
240
241
0
  header = buf;
242
0
  data = buf + sizeof(*header);
243
0
  hmac = data + size_data;
244
245
0
  list_for_each_entry(sv, &state->variables, list)
246
0
    memcpy(data + sv->start, sv->raw, sv->size);
247
248
0
  header->magic = state->magic;
249
0
  header->data_len = size_data;
250
0
  header->data_crc = crc32(0, data, size_data);
251
0
  header->header_crc = crc32(0, header,
252
0
           sizeof(*header) - sizeof(uint32_t));
253
254
0
  if (backend_raw->algo) {
255
    /* hmac over header and data */
256
0
    ret = digest_update(backend_raw->digest, buf, sizeof(*header) + size_data);
257
0
    if (ret) {
258
0
      dev_err(backend_raw->dev, "Failed to update digest for packing, %d\n",
259
0
        ret);
260
0
      goto out_free;
261
0
    }
262
263
0
    ret = digest_final(backend_raw->digest, hmac);
264
0
    if (ret < 0) {
265
0
      dev_err(backend_raw->dev, "Failed to finish digest for packing, %d\n",
266
0
        ret);
267
0
      goto out_free;
268
0
    }
269
0
  }
270
271
0
  *buf_out = buf;
272
0
  *len_out = size_full;
273
274
0
  return 0;
275
276
0
out_free:
277
0
  free(buf);
278
279
0
  return ret;
280
0
}
281
282
static void backend_format_raw_free(struct state_backend_format *format)
283
0
{
284
0
  struct state_backend_format_raw *backend_raw = get_format_raw(format);
285
286
0
  free(backend_raw);
287
0
}
288
289
static int backend_format_raw_init_digest(struct state_backend_format_raw *raw,
290
            struct device_node *root,
291
            const char *secret_name)
292
30
{
293
30
  struct property *p;
294
30
  const char *algo;
295
30
  int ret;
296
297
30
  p = of_find_property(root, "algo", NULL);
298
30
  if (!p)      /* does not exist */
299
28
    return 0;
300
301
2
  ret = of_property_read_string(root, "algo", &algo);
302
2
  if (ret)
303
0
    return ret;
304
305
2
  if (!IS_ENABLED(CONFIG_STATE_CRYPTO) && IS_ENABLED(__BAREBOX__)) {
306
0
    dev_err(raw->dev, "algo %s specified, but crypto support for state framework (CONFIG_STATE_CRYPTO) not enabled.\n",
307
0
      algo);
308
0
    return -EINVAL;
309
0
  }
310
311
2
  raw->algo = xstrdup(algo);
312
313
2
  return 0;
314
2
}
315
316
int backend_format_raw_create(struct state_backend_format **format,
317
            struct device_node *node, const char *secret_name,
318
            struct device *dev)
319
30
{
320
30
  struct state_backend_format_raw *raw;
321
30
  int ret;
322
323
30
  raw = xzalloc(sizeof(*raw));
324
325
30
  raw->dev = dev;
326
30
  ret = backend_format_raw_init_digest(raw, node, secret_name);
327
30
  if (ret) {
328
0
    dev_err(raw->dev, "Failed initializing digest for raw format, %d\n",
329
0
      ret);
330
0
    free(raw);
331
0
    return ret;
332
0
  }
333
334
30
  raw->secret_name = xstrdup(secret_name);
335
30
  raw->format.pack = backend_format_raw_pack;
336
30
  raw->format.unpack = backend_format_raw_unpack;
337
30
  raw->format.verify = backend_format_raw_verify;
338
30
  raw->format.free = backend_format_raw_free;
339
30
  raw->format.name = "raw";
340
30
  *format = &raw->format;
341
342
30
  return 0;
343
30
}
344
345
struct digest *state_backend_format_raw_get_digest(struct state_backend_format
346
               *format)
347
0
{
348
0
  struct state_backend_format_raw *backend_raw = get_format_raw(format);
349
350
0
  return backend_raw->digest;
351
0
}