Bug Summary

File:3rdparty/vboot/futility/file_type_rwsig.c
Warning:line 322, column 3
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name file_type_rwsig.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -resource-dir /opt/xgcc/lib/clang/17 -D CHROMEOS_ENVIRONMENT -D EC_EFS=0 -D EXTERNAL_TPM_CLEAR_REQUEST=0 -D _GNU_SOURCE -D _FILE_OFFSET_BITS=64 -D HAVE_EXECINFO_H -D HAVE_NSS -I /usr/include/nss -I /usr/include/nspr -I firmware/include -I firmware/lib/include -I firmware/lib/cgptlib/include -I firmware/lib/tpm_lite/include -I firmware/2lib/include -I host/include -I host/lib/include -I host/lib21/include -I host/lib21/include -internal-isystem /opt/xgcc/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -source-date-epoch 1715206807 -Os -Wno-deprecated-declarations -Wno-trigraphs -Wwrite-strings -Wno-format-security -Wno-address-of-packed-member -Wno-unknown-warning -Wno-error=deprecated-declarations -std=gnu11 -fconst-strings -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /cb-build/coreboot_scanbuild.0/sharedutils-scanbuildtmp/2024-05-09-073003-3820391-1 -x c futility/file_type_rwsig.c
1/* Copyright 2015 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Some instances of the Chrome OS embedded controller firmware can't do a
6 * normal software sync handshake at boot, but will verify their own RW images
7 * instead. This is typically done by putting a struct vb2_packed_key in the RO
8 * image and a corresponding struct vb21_signature in the RW image.
9 *
10 * This file provides the basic implementation for that approach.
11 */
12
13#include <stdint.h>
14#include <stdio.h>
15#include <unistd.h>
16
17#include "2common.h"
18#include "2rsa.h"
19#include "2sha.h"
20#include "2sysincludes.h"
21#include "file_type.h"
22#include "fmap.h"
23#include "futility.h"
24#include "futility_options.h"
25#include "host_common.h"
26#include "host_common21.h"
27#include "host_key21.h"
28#include "host_misc.h"
29#include "host_signature21.h"
30#include "util_misc.h"
31
32#define SIGNATURE_RSVD_SIZE1024 1024
33
34static void show_sig(const char *fname, const struct vb21_signature *sig)
35{
36 printf("Signature: %s\n", fname);
37 printf(" Vboot API: 2.1\n");
38 printf(" Desc: \"%s\"\n", vb21_common_desc(sig));
39 printf(" Signature Algorithm: %d %s\n", sig->sig_alg,
40 vb2_get_sig_algorithm_name(sig->sig_alg));
41 printf(" Hash Algorithm: %d %s\n", sig->hash_alg,
42 vb2_get_hash_algorithm_name(sig->hash_alg));
43 printf(" Total size: %#x (%d)\n", sig->c.total_size,
44 sig->c.total_size);
45 printf(" ID: ");
46 print_bytes(&sig->id, sizeof(sig->id));
47 printf("\n");
48 printf(" Data size: %#x (%d)\n", sig->data_size,
49 sig->data_size);
50}
51
52int ft_show_rwsig(const char *fname)
53{
54 const struct vb21_packed_key *pkey = show_option.pkey;
55 struct vb2_public_key key;
56 uint8_t workbuf[VB2_VERIFY_DATA_WORKBUF_BYTES(64 + ({ typeof((3 * 1024)) __vb2_max_a = ((3 * 1024)); typeof
(sizeof(struct vb2_digest_context)) __vb2_max_b = (sizeof(struct
vb2_digest_context)); __vb2_max_a > __vb2_max_b ? __vb2_max_a
: __vb2_max_b; }))
]
57 __attribute__((aligned(VB2_WORKBUF_ALIGN8)));
58 uint32_t data_size, sig_size = SIGNATURE_RSVD_SIZE1024;
59 uint32_t total_data_size = 0;
60 uint8_t *data;
61 FmapHeader *fmap;
62 int i;
63 int fd = -1;
64 uint8_t *buf;
65 uint32_t len;
66 int rv = 1;
67
68 if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
69 return 1;
70
71 VB2_DEBUG("name %s len 0x%08x (%d)\n", fname, len, len)vb2ex_printf(__func__, "name %s len 0x%08x (%d)\n", fname, len
, len)
;
72
73 /* Am I just looking at a signature file? */
74 VB2_DEBUG("Looking for signature at 0x0\n")vb2ex_printf(__func__, "Looking for signature at 0x0\n");
75 const struct vb21_signature *sig = (const struct vb21_signature *)buf;
76 if (VB2_SUCCESS == vb21_verify_signature(sig, len)) {
77 show_sig(fname, sig);
78 if (!show_option.fv) {
79 printf("No data available to verify\n");
80 rv = show_option.strict;
81 goto done;
82 }
83 data = show_option.fv;
84 data_size = show_option.fv_size;
85 total_data_size = show_option.fv_size;
86 } else if ((fmap = fmap_find(buf, len))) {
87 /* This looks like a full image. */
88 FmapAreaHeader *fmaparea;
89
90 VB2_DEBUG("Found an FMAP!\n")vb2ex_printf(__func__, "Found an FMAP!\n");
91
92 /* If no public key is provided, use the one packed in RO
93 * image, and print that. */
94 if (!pkey) {
95 pkey = (const struct vb21_packed_key *)
96 fmap_find_by_name(buf, len, fmap, "KEY_RO", 0);
97
98 if (pkey)
99 show_vb21_pubkey_buf(fname, (uint8_t *)pkey,
100 pkey->c.total_size);
101 }
102
103 sig = (const struct vb21_signature *)
104 fmap_find_by_name(buf, len, fmap, "SIG_RW", &fmaparea);
105 if (!sig) {
106 VB2_DEBUG("No SIG_RW in FMAP.\n")vb2ex_printf(__func__, "No SIG_RW in FMAP.\n");
107 goto done;
108 }
109
110 sig_size = fmaparea->area_size;
111
112 VB2_DEBUG("Looking for signature at %#tx (%#x)\n",vb2ex_printf(__func__, "Looking for signature at %#tx (%#x)\n"
, (uint8_t *)sig - buf, sig_size)
113 (uint8_t *)sig - buf, sig_size)vb2ex_printf(__func__, "Looking for signature at %#tx (%#x)\n"
, (uint8_t *)sig - buf, sig_size)
;
114
115 if (VB2_SUCCESS != vb21_verify_signature(sig, sig_size))
116 goto done;
117
118 show_sig(fname, sig);
119 data = fmap_find_by_name(buf, len, fmap, "EC_RW", &fmaparea);
120 data_size = sig->data_size;
121 /*
122 * TODO(crosbug.com/p/62231): EC_RW region should not include
123 * the signature.
124 */
125 total_data_size = fmaparea->area_size - sig_size;
126
127 if (!data) {
128 VB2_DEBUG("No EC_RW in FMAP.\n")vb2ex_printf(__func__, "No EC_RW in FMAP.\n");
129 goto done;
130 }
131 } else {
132 /* Or maybe this is just the RW portion, that does not
133 * contain a FMAP. */
134 if (show_option.sig_size)
135 sig_size = show_option.sig_size;
136
137 VB2_DEBUG("Looking for signature at %#x\n", len - sig_size)vb2ex_printf(__func__, "Looking for signature at %#x\n", len -
sig_size)
;
138
139 if (len < sig_size) {
140 VB2_DEBUG("File is too small\n")vb2ex_printf(__func__, "File is too small\n");
141 goto done;
142 }
143
144 sig = (const struct vb21_signature *)(buf + len - sig_size);
145 if (VB2_SUCCESS == vb21_verify_signature(sig, sig_size)) {
146 show_sig(fname, sig);
147 data = buf;
148 data_size = sig->data_size;
149 total_data_size = len - sig_size;
150 } else {
151 goto done;
152 }
153 }
154
155 if (!pkey) {
156 printf("No public key available to verify with\n");
157 rv = show_option.strict;
158 goto done;
159 }
160
161 /* We already did this once, so it should work again */
162 if (vb21_unpack_key(&key, (const uint8_t *)pkey, pkey->c.total_size)) {
163 VB2_DEBUG("Can't unpack pubkey\n")vb2ex_printf(__func__, "Can't unpack pubkey\n");
164 goto done;
165 }
166
167 if (data_size > total_data_size) {
168 VB2_DEBUG("Invalid signature data_size: bigger than total area size.\n")vb2ex_printf(__func__, "Invalid signature data_size: bigger than total area size.\n"
)
;
169 goto done;
170 }
171
172 /* The sig is destroyed by the verify operation, so make a copy */
173 {
174 uint8_t sigbuf[sig->c.total_size];
175 memcpy(sigbuf, sig, sizeof(sigbuf));
176 struct vb2_workbuf wb;
177
178 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
179
180 if (vb21_verify_data(data, data_size,
181 (struct vb21_signature *)sigbuf,
182 (const struct vb2_public_key *)&key,
183 &wb)) {
184 ERROR("Signature verification failed\n")fprintf(stderr, "ERROR: %s: " "Signature verification failed\n"
, __func__ )
;
185 goto done;
186 }
187 }
188
189 /* Check that the rest of region is padded with 0xff. */
190 for (i = data_size; i < total_data_size; i++) {
191 if (data[i] != 0xff) {
192 ERROR("Padding verification failed\n")fprintf(stderr, "ERROR: %s: " "Padding verification failed\n"
, __func__ )
;
193 goto done;
194 }
195 }
196
197 printf("Signature verification succeeded.\n");
198 rv = 0;
199done:
200 futil_unmap_and_close_file(fd, FILE_RO, buf, len);
201 return rv;
202}
203
204int ft_sign_rwsig(const char *fname)
205{
206 struct vb21_signature *tmp_sig = 0;
207 struct vb2_public_key *pubkey = 0;
208 struct vb21_packed_key *packedkey = 0;
209 uint8_t *keyb_data = 0;
210 uint32_t keyb_size;
211 uint8_t *data; /* data to be signed */
212 uint32_t r, data_size, sig_size = SIGNATURE_RSVD_SIZE1024;
213 int retval = 1;
214 FmapHeader *fmap = NULL((void*)0);
215 FmapAreaHeader *fmaparea;
216 struct vb21_signature *old_sig = 0;
1
'old_sig' initialized to a null pointer value
217 uint8_t *buf = NULL((void*)0);
218 uint32_t len;
219 int fd = -1;
220
221 if (futil_open_and_map_file(fname, &fd, FILE_MODE_SIGN(sign_option)(sign_option.create_new_outfile ? FILE_RO : FILE_RW),
2
Assuming field 'create_new_outfile' is 0
3
'?' condition is false
4
Assuming the condition is false
5
Taking false branch
222 &buf, &len))
223 return 1;
224
225 data = buf;
226 data_size = len;
227
228 VB2_DEBUG("name %s len 0x%08x (%d)\n", fname, len, len)vb2ex_printf(__func__, "name %s len 0x%08x (%d)\n", fname, len
, len)
;
229
230 /* If we don't have a distinct OUTFILE, look for an existing sig */
231 if (sign_option.inout_file_count < 2) {
6
Assuming field 'inout_file_count' is >= 2
7
Taking false branch
232 fmap = fmap_find(data, len);
233
234 if (fmap) {
235 /* This looks like a full image. */
236 VB2_DEBUG("Found an FMAP!\n")vb2ex_printf(__func__, "Found an FMAP!\n");
237
238 old_sig = (struct vb21_signature *)
239 fmap_find_by_name(buf, len, fmap, "SIG_RW",
240 &fmaparea);
241 if (!old_sig) {
242 VB2_DEBUG("No SIG_RW in FMAP.\n")vb2ex_printf(__func__, "No SIG_RW in FMAP.\n");
243 goto done;
244 }
245
246 sig_size = fmaparea->area_size;
247
248 VB2_DEBUG("Looking for signature at %#tx (%#x)\n",vb2ex_printf(__func__, "Looking for signature at %#tx (%#x)\n"
, (uint8_t *)old_sig - buf, sig_size)
249 (uint8_t *)old_sig - buf, sig_size)vb2ex_printf(__func__, "Looking for signature at %#tx (%#x)\n"
, (uint8_t *)old_sig - buf, sig_size)
;
250
251 data = fmap_find_by_name(buf, len, fmap, "EC_RW",
252 &fmaparea);
253 if (!data) {
254 VB2_DEBUG("No EC_RW in FMAP.\n")vb2ex_printf(__func__, "No EC_RW in FMAP.\n");
255 goto done;
256 }
257 } else {
258 /* Or maybe this is just the RW portion, that does not
259 * contain a FMAP. */
260 if (sign_option.sig_size)
261 sig_size = sign_option.sig_size;
262
263 VB2_DEBUG("Looking for old signature at %#x\n",vb2ex_printf(__func__, "Looking for old signature at %#x\n", len
- sig_size)
264 len - sig_size)vb2ex_printf(__func__, "Looking for old signature at %#x\n", len
- sig_size)
;
265
266 if (len < sig_size) {
267 ERROR("File is too small\n")fprintf(stderr, "ERROR: %s: " "File is too small\n", __func__
)
;
268 goto done;
269 }
270
271 /* Take a look */
272 old_sig = (struct vb21_signature *)
273 (buf + len - sig_size);
274 }
275
276 if (vb21_verify_signature(old_sig, sig_size)) {
277 ERROR("Can't find a valid signature\n")fprintf(stderr, "ERROR: %s: " "Can't find a valid signature\n"
, __func__ )
;
278 goto done;
279 }
280
281 /* Use the same extent again */
282 data_size = old_sig->data_size;
283
284 VB2_DEBUG("Found sig: data_size is %#x (%d)\n", data_size,vb2ex_printf(__func__, "Found sig: data_size is %#x (%d)\n", data_size
, data_size)
285 data_size)vb2ex_printf(__func__, "Found sig: data_size is %#x (%d)\n", data_size
, data_size)
;
286 }
287
288 /* Unless overridden */
289 if (sign_option.data_size)
8
Assuming field 'data_size' is 0
9
Taking false branch
290 data_size = sign_option.data_size;
291
292 /* Sign the blob */
293 if (sign_option.prikey) {
10
Assuming field 'prikey' is non-null
11
Taking true branch
294 r = vb21_sign_data(&tmp_sig,
295 data, data_size, sign_option.prikey, 0);
296 if (r) {
12
Assuming 'r' is 0
13
Taking false branch
297 ERROR("Unable to sign data (error 0x%08x)\n", r)fprintf(stderr, "ERROR: %s: " "Unable to sign data (error 0x%08x)\n"
, __func__, r )
;
298 goto done;
299 }
300 } else {
301 VB2_DEBUG("Private key not provided. Copying previous signature\n")vb2ex_printf(__func__, "Private key not provided. Copying previous signature\n"
)
;
302 if (!old_sig) {
303 /* This isn't necessary because no prikey mode runs only
304 * for fmap input or RW input */
305 ERROR("Previous signature not found.\n")fprintf(stderr, "ERROR: %s: " "Previous signature not found.\n"
, __func__ )
;
306 goto done;
307 }
308 tmp_sig = calloc(1, old_sig->c.total_size);
309 if (!tmp_sig)
310 goto done;
311 memcpy(tmp_sig, old_sig, old_sig->c.total_size);
312 }
313
314 if (sign_option.inout_file_count < 2) {
14
Assuming field 'inout_file_count' is < 2
15
Taking true branch
315 /* Overwrite the old signature */
316 if (tmp_sig->c.total_size > sig_size) {
16
Assuming 'sig_size' is >= field 'total_size'
17
Taking false branch
317 ERROR("New sig is too large (%d > %d)\n",fprintf(stderr, "ERROR: %s: " "New sig is too large (%d > %d)\n"
, __func__, tmp_sig->c.total_size, sig_size )
318 tmp_sig->c.total_size, sig_size)fprintf(stderr, "ERROR: %s: " "New sig is too large (%d > %d)\n"
, __func__, tmp_sig->c.total_size, sig_size )
;
319 goto done;
320 }
321 VB2_DEBUG("Replacing old signature with new one\n")vb2ex_printf(__func__, "Replacing old signature with new one\n"
)
;
322 memset(old_sig, 0xff, sig_size);
18
Null pointer passed to 1st parameter expecting 'nonnull'
323 memcpy(old_sig, tmp_sig, tmp_sig->c.total_size);
324 if (fmap && sign_option.ecrw_out) {
325 VB2_DEBUG("Writing %s (size=%d)\n",vb2ex_printf(__func__, "Writing %s (size=%d)\n", sign_option.
ecrw_out, fmaparea->area_size)
326 sign_option.ecrw_out, fmaparea->area_size)vb2ex_printf(__func__, "Writing %s (size=%d)\n", sign_option.
ecrw_out, fmaparea->area_size)
;
327 if (vb2_write_file(sign_option.ecrw_out, data,
328 fmaparea->area_size))
329 goto done;
330 }
331 } else {
332 /* Write the signature to a new file */
333 r = vb21_write_object(sign_option.outfile, tmp_sig);
334 if (r) {
335 ERROR("Unable to write sig (error 0x%08x)\n", r)fprintf(stderr, "ERROR: %s: " "Unable to write sig (error 0x%08x)\n"
, __func__, r )
;
336 goto done;
337 }
338 }
339
340 /* For full images, let's replace the public key in RO. If prikey is
341 * not provided, skip it. */
342 if (fmap && sign_option.prikey) {
343 uint8_t *new_pubkey;
344 uint8_t *pubkey_buf = 0;
345
346 /* Create the public key */
347 if (vb2_public_key_alloc(&pubkey,
348 sign_option.prikey->sig_alg)) {
349 ERROR("Unable to allocate the public key\n")fprintf(stderr, "ERROR: %s: " "Unable to allocate the public key\n"
, __func__ )
;
350 goto done;
351 }
352
353 /* Extract the keyb blob */
354 if (vb_keyb_from_private_key(sign_option.prikey, &keyb_data, &keyb_size)) {
355 ERROR("Couldn't extract the public key\n")fprintf(stderr, "ERROR: %s: " "Couldn't extract the public key\n"
, __func__ )
;
356 goto done;
357 }
358
359 /*
360 * Copy the keyb blob to the public key's buffer, because that's
361 * where vb2_unpack_key_data() and vb2_public_key_pack() expect
362 * to find it.
363 */
364 pubkey_buf = vb2_public_key_packed_data(pubkey);
365 memcpy(pubkey_buf, keyb_data, keyb_size);
366
367 /* Fill in the internal struct pointers */
368 if (vb2_unpack_key_data(pubkey, pubkey_buf, keyb_size)) {
369 ERROR("Unable to unpack the public key blob\n")fprintf(stderr, "ERROR: %s: " "Unable to unpack the public key blob\n"
, __func__ )
;
370 goto done;
371 }
372
373 pubkey->hash_alg = sign_option.prikey->hash_alg;
374 pubkey->version = sign_option.version_specified ?
375 sign_option.version : 1;
376 vb2_public_key_set_desc(pubkey, sign_option.prikey->desc);
377
378 memcpy((struct vb2_id *)pubkey->id, &sign_option.prikey->id,
379 sizeof(*(pubkey->id)));
380
381 if (vb21_public_key_pack(&packedkey, pubkey)) {
382 goto done;
383 }
384
385 new_pubkey = fmap_find_by_name(buf, len, fmap, "KEY_RO",
386 &fmaparea);
387 if (!new_pubkey) {
388 VB2_DEBUG("No KEY_RO in FMAP.\n")vb2ex_printf(__func__, "No KEY_RO in FMAP.\n");
389 goto done;
390 }
391 /* Overwrite the old signature */
392 if (packedkey->c.total_size > fmaparea->area_size) {
393 ERROR("New sig is too large (%d > %d)\n",fprintf(stderr, "ERROR: %s: " "New sig is too large (%d > %d)\n"
, __func__, packedkey->c.total_size, sig_size )
394 packedkey->c.total_size, sig_size)fprintf(stderr, "ERROR: %s: " "New sig is too large (%d > %d)\n"
, __func__, packedkey->c.total_size, sig_size )
;
395 goto done;
396 }
397
398 memset(new_pubkey, 0xff, fmaparea->area_size);
399 memcpy(new_pubkey, packedkey, packedkey->c.total_size);
400 }
401
402 /* Finally */
403 retval = 0;
404done:
405 futil_unmap_and_close_file(fd, FILE_MODE_SIGN(sign_option)(sign_option.create_new_outfile ? FILE_RO : FILE_RW), buf, len);
406 free(tmp_sig);
407 if (pubkey)
408 vb2_public_key_free(pubkey);
409 free(packedkey);
410 free(keyb_data);
411
412 return retval;
413}
414
415enum futil_file_type ft_recognize_rwsig(uint8_t *buf, uint32_t len)
416{
417 const struct vb21_signature *sig = NULL((void*)0);
418 uint32_t sig_size;
419
420 if (!vb21_verify_signature((const struct vb21_signature *)buf, len))
421 return FILE_TYPE_RWSIG;
422
423 FmapHeader *fmap = fmap_find(buf, len);
424 if (fmap) {
425 /* This looks like a full image. */
426 FmapAreaHeader *fmaparea;
427
428 sig = (const struct vb21_signature *)
429 fmap_find_by_name(buf, len, fmap, "SIG_RW", &fmaparea);
430
431 if (!sig)
432 return FILE_TYPE_UNKNOWN;
433
434 sig_size = fmaparea->area_size;
435 } else {
436 /* RW-only image */
437 sig = (const struct vb21_signature *)
438 (buf + len - SIGNATURE_RSVD_SIZE1024);
439 sig_size = SIGNATURE_RSVD_SIZE1024;
440 }
441
442 if (len >= sig_size && !vb21_verify_signature(sig, sig_size))
443 return FILE_TYPE_RWSIG;
444
445 return FILE_TYPE_UNKNOWN;
446}