Bug Summary

File:3rdparty/vboot/futility/cmd_vbutil_firmware.c
Warning:line 268, column 2
Value stored to 'now' is never read

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 cmd_vbutil_firmware.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/cmd_vbutil_firmware.c
1/* Copyright 2011 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 * Verified boot firmware utility
6 */
7
8#include <getopt.h>
9#include <inttypes.h> /* For PRIu64 */
10#include <stddef.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14
15#include "2api.h"
16#include "2common.h"
17#include "2rsa.h"
18#include "2sysincludes.h"
19#include "futility.h"
20#include "host_common.h"
21#include "host_key21.h"
22#include "kernel_blob.h"
23#include "util_misc.h"
24#include "vb1_helper.h"
25
26/* Command line options */
27enum {
28 OPT_MODE_VBLOCK = 1000,
29 OPT_MODE_VERIFY,
30 OPT_KEYBLOCK,
31 OPT_SIGNPUBKEY,
32 OPT_SIGNPRIVATE,
33 OPT_VERSION,
34 OPT_FV,
35 OPT_KERNELKEY,
36 OPT_FLAGS,
37 OPT_HELP,
38};
39
40static const struct option long_opts[] = {
41 {"vblock", 1, 0, OPT_MODE_VBLOCK},
42 {"verify", 1, 0, OPT_MODE_VERIFY},
43 {"keyblock", 1, 0, OPT_KEYBLOCK},
44 {"signpubkey", 1, 0, OPT_SIGNPUBKEY},
45 {"signprivate", 1, 0, OPT_SIGNPRIVATE},
46 {"version", 1, 0, OPT_VERSION},
47 {"fv", 1, 0, OPT_FV},
48 {"kernelkey", 1, 0, OPT_KERNELKEY},
49 {"flags", 1, 0, OPT_FLAGS},
50 {"help", 0, 0, OPT_HELP},
51 {NULL((void*)0), 0, 0, 0}
52};
53
54/* Print help and return error */
55static void print_help(int argc, char *argv[])
56{
57 printf("\nUsage: " MYNAME"futility" " %s <--vblock|--verify> <file> [OPTIONS]\n"
58 "\n"
59 "For '--vblock <file>', required OPTIONS are:\n"
60 "\n"
61 " --keyblock <file> Keyblock in .keyblock format\n"
62 " --signprivate <file>"
63 " Signing private key in .vbprivk format\n"
64 " --version <number> Firmware version\n"
65 " --fv <file> Firmware volume to sign\n"
66 " --kernelkey <file> Kernel subkey in .vbpubk format\n"
67 "\n"
68 "optional OPTIONS are:\n"
69 " --flags <number> Preamble flags (defaults to 0)\n"
70 "\n"
71 "For '--verify <file>', required OPTIONS are:\n"
72 "\n"
73 " --signpubkey <file>"
74 " Signing public key in .vbpubk format\n"
75 " --fv <file> Firmware volume to verify\n"
76 "\n"
77 "For '--verify <file>', optional OPTIONS are:\n"
78 " --kernelkey <file>"
79 " Write the kernel subkey to this file\n\n",
80 argv[0]);
81}
82
83/* Create a firmware .vblock */
84static int do_vblock(const char *outfile, const char *keyblock_file,
85 const char *signprivate, uint32_t version,
86 const char *fv_file, const char *kernelkey_file,
87 uint32_t preamble_flags)
88{
89 struct vb2_keyblock *keyblock = NULL((void*)0);
90 struct vb2_private_key *signing_key = NULL((void*)0);
91 struct vb2_packed_key *kernel_subkey = NULL((void*)0);
92 struct vb2_signature *body_sig = NULL((void*)0);
93 struct vb2_fw_preamble *preamble = NULL((void*)0);
94 uint8_t *fv_data = NULL((void*)0);
95 int retval = 1;
96
97 if (!outfile) {
98 FATAL("Must specify output filename\n")do { fprintf(stderr, "FATAL: %s: " "Must specify output filename\n"
, __func__ ); exit(1); } while (0)
;
99 goto vblock_cleanup;
100 }
101 if (!keyblock_file || !signprivate || !kernelkey_file) {
102 FATAL("Must specify all keys\n")do { fprintf(stderr, "FATAL: %s: " "Must specify all keys\n",
__func__ ); exit(1); } while (0)
;
103 goto vblock_cleanup;
104 }
105 if (!fv_file) {
106 FATAL("Must specify firmware volume\n")do { fprintf(stderr, "FATAL: %s: " "Must specify firmware volume\n"
, __func__ ); exit(1); } while (0)
;
107 goto vblock_cleanup;
108 }
109
110 /* Read the keyblock and keys */
111 keyblock = vb2_read_keyblock(keyblock_file);
112 if (!keyblock) {
113 FATAL("Error reading keyblock.\n")do { fprintf(stderr, "FATAL: %s: " "Error reading keyblock.\n"
, __func__ ); exit(1); } while (0)
;
114 goto vblock_cleanup;
115 }
116
117 signing_key = vb2_read_private_key(signprivate);
118 if (!signing_key) {
119 FATAL("Error reading signing key.\n")do { fprintf(stderr, "FATAL: %s: " "Error reading signing key.\n"
, __func__ ); exit(1); } while (0)
;
120 goto vblock_cleanup;
121 }
122
123 kernel_subkey = vb2_read_packed_key(kernelkey_file);
124 if (!kernel_subkey) {
125 FATAL("Error reading kernel subkey.\n")do { fprintf(stderr, "FATAL: %s: " "Error reading kernel subkey.\n"
, __func__ ); exit(1); } while (0)
;
126 goto vblock_cleanup;
127 }
128
129 /* Read and sign the firmware volume */
130 uint32_t fv_size;
131 if (VB2_SUCCESS != vb2_read_file(fv_file, &fv_data, &fv_size))
132 goto vblock_cleanup;
133 if (!fv_size) {
134 FATAL("Empty firmware volume file\n")do { fprintf(stderr, "FATAL: %s: " "Empty firmware volume file\n"
, __func__ ); exit(1); } while (0)
;
135 goto vblock_cleanup;
136 }
137 body_sig = vb2_calculate_signature(fv_data, fv_size, signing_key);
138 if (!body_sig) {
139 FATAL("Error calculating body signature\n")do { fprintf(stderr, "FATAL: %s: " "Error calculating body signature\n"
, __func__ ); exit(1); } while (0)
;
140 goto vblock_cleanup;
141 }
142
143 /* Create preamble */
144 preamble = vb2_create_fw_preamble(version, kernel_subkey, body_sig,
145 signing_key, preamble_flags);
146 if (!preamble) {
147 FATAL("Error creating preamble.\n")do { fprintf(stderr, "FATAL: %s: " "Error creating preamble.\n"
, __func__ ); exit(1); } while (0)
;
148 goto vblock_cleanup;
149 }
150
151 /* Write the output file */
152 FILE *f = fopen(outfile, "wb");
153 if (!f) {
154 FATAL("Can't open output file %s\n", outfile)do { fprintf(stderr, "FATAL: %s: " "Can't open output file %s\n"
, __func__, outfile ); exit(1); } while (0)
;
155 goto vblock_cleanup;
156 }
157 int i = ((1 != fwrite(keyblock, keyblock->keyblock_size, 1, f)) ||
158 (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
159 fclose(f);
160 if (i) {
161 FATAL("Can't write output file %s\n", outfile)do { fprintf(stderr, "FATAL: %s: " "Can't write output file %s\n"
, __func__, outfile ); exit(1); } while (0)
;
162 unlink(outfile);
163 goto vblock_cleanup;
164 }
165
166 /* Success */
167 retval = 0;
168
169vblock_cleanup:
170 if (keyblock)
171 free(keyblock);
172 if (signing_key)
173 free(signing_key);
174 if (kernel_subkey)
175 free(kernel_subkey);
176 if (fv_data)
177 free(fv_data);
178 if (body_sig)
179 free(body_sig);
180 if (preamble)
181 free(preamble);
182
183 return retval;
184}
185
186static int do_verify(const char *infile, const char *signpubkey,
187 const char *fv_file, const char *kernelkey_file)
188{
189 uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE(12 * 1024)]
190 __attribute__((aligned(VB2_WORKBUF_ALIGN8)));
191 struct vb2_workbuf wb;
192 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
193
194 uint32_t now = 0;
195
196 uint8_t *pubkbuf = NULL((void*)0);
197 uint8_t *blob = NULL((void*)0);
198 uint8_t *fv_data = NULL((void*)0);
199 int retval = 1;
200
201 if (!infile || !signpubkey || !fv_file) {
202 FATAL("Must specify filename, signpubkey, and fv\n")do { fprintf(stderr, "FATAL: %s: " "Must specify filename, signpubkey, and fv\n"
, __func__ ); exit(1); } while (0)
;
203 goto verify_cleanup;
204 }
205
206 /* Read public signing key */
207 uint32_t pubklen;
208 struct vb2_public_key sign_key;
209 if (VB2_SUCCESS != vb2_read_file(signpubkey, &pubkbuf, &pubklen)) {
210 ERROR("Reading signpubkey.\n")fprintf(stderr, "ERROR: %s: " "Reading signpubkey.\n", __func__
)
;
211 goto verify_cleanup;
212 }
213 if (VB2_SUCCESS != vb2_unpack_key_buffer(&sign_key, pubkbuf, pubklen)) {
214 ERROR("Unpacking signpubkey.\n")fprintf(stderr, "ERROR: %s: " "Unpacking signpubkey.\n", __func__
)
;
215 goto verify_cleanup;
216 }
217
218 /* Read blob */
219 uint32_t blob_size;
220 if (VB2_SUCCESS != vb2_read_file(infile, &blob, &blob_size)) {
221 FATAL("Error reading input file\n")do { fprintf(stderr, "FATAL: %s: " "Error reading input file\n"
, __func__ ); exit(1); } while (0)
;
222 goto verify_cleanup;
223 }
224
225 /* Read firmware volume */
226 uint32_t fv_size;
227 if (VB2_SUCCESS != vb2_read_file(fv_file, &fv_data, &fv_size)) {
228 FATAL("Error reading firmware volume\n")do { fprintf(stderr, "FATAL: %s: " "Error reading firmware volume\n"
, __func__ ); exit(1); } while (0)
;
229 goto verify_cleanup;
230 }
231
232 /* Verify keyblock */
233 struct vb2_keyblock *keyblock = (struct vb2_keyblock *)blob;
234 if (VB2_SUCCESS !=
235 vb2_verify_keyblock(keyblock, blob_size, &sign_key, &wb)) {
236 FATAL("Error verifying keyblock.\n")do { fprintf(stderr, "FATAL: %s: " "Error verifying keyblock.\n"
, __func__ ); exit(1); } while (0)
;
237 goto verify_cleanup;
238 }
239
240 now += keyblock->keyblock_size;
241
242 printf("Keyblock:\n");
243 printf(" Size: %d\n", keyblock->keyblock_size);
244 printf(" Flags: %d (ignored)\n",
245 keyblock->keyblock_flags);
246
247 struct vb2_packed_key *packed_key = &keyblock->data_key;
248 printf(" Data key algorithm: %d %s\n", packed_key->algorithm,
249 vb2_get_crypto_algorithm_name(packed_key->algorithm));
250 printf(" Data key version: %d\n", packed_key->key_version);
251 printf(" Data key sha1sum: %s\n",
252 packed_key_sha1_string(packed_key));
253
254 struct vb2_public_key data_key;
255 if (VB2_SUCCESS !=
256 vb2_unpack_key(&data_key, &keyblock->data_key)) {
257 ERROR("Parsing data key.\n")fprintf(stderr, "ERROR: %s: " "Parsing data key.\n", __func__
)
;
258 goto verify_cleanup;
259 }
260
261 /* Verify preamble */
262 struct vb2_fw_preamble *pre2 = (struct vb2_fw_preamble *)(blob + now);
263 if (VB2_SUCCESS !=
264 vb2_verify_fw_preamble(pre2, blob_size - now, &data_key, &wb)) {
265 FATAL("Error2 verifying preamble.\n")do { fprintf(stderr, "FATAL: %s: " "Error2 verifying preamble.\n"
, __func__ ); exit(1); } while (0)
;
266 goto verify_cleanup;
267 }
268 now += pre2->preamble_size;
Value stored to 'now' is never read
269
270 uint32_t flags = pre2->flags;
271 if (pre2->header_version_minor < 1)
272 flags = 0; /* Old 2.0 structure didn't have flags */
273
274 printf("Preamble:\n");
275 printf(" Size: %d\n", pre2->preamble_size);
276 printf(" Header version: %d.%d\n",
277 pre2->header_version_major, pre2->header_version_minor);
278 printf(" Firmware version: %d\n", pre2->firmware_version);
279
280 struct vb2_packed_key *kernel_subkey = &pre2->kernel_subkey;
281 printf(" Kernel key algorithm: %d %s\n", kernel_subkey->algorithm,
282 vb2_get_crypto_algorithm_name(kernel_subkey->algorithm));
283 printf(" Kernel key version: %d\n", kernel_subkey->key_version);
284 printf(" Kernel key sha1sum: %s\n",
285 packed_key_sha1_string(kernel_subkey));
286 printf(" Firmware body size: %d\n", pre2->body_signature.data_size);
287 printf(" Preamble flags: %d\n", flags);
288
289 /* TODO: verify body size same as signature size */
290
291 /* Verify body */
292 if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL0x00000001) {
293 printf("Preamble requests USE_RO_NORMAL;"
294 " skipping body verification.\n");
295 } else if (!pre2->body_signature.data_size) {
296 /* cbfstool needs the whole firmware image to get the
297 metadata hash */
298 FATAL("Metadata hash verification not supported.\n"do { fprintf(stderr, "FATAL: %s: " "Metadata hash verification not supported.\n"
"Please use `futility verify BIOS_IMAGE`.\n", __func__ ); exit
(1); } while (0)
299 "Please use `futility verify BIOS_IMAGE`.\n")do { fprintf(stderr, "FATAL: %s: " "Metadata hash verification not supported.\n"
"Please use `futility verify BIOS_IMAGE`.\n", __func__ ); exit
(1); } while (0)
;
300 goto verify_cleanup;
301 } else if (VB2_SUCCESS ==
302 vb2_verify_data(fv_data, fv_size, &pre2->body_signature,
303 &data_key, &wb)) {
304 printf("Body verification succeeded.\n");
305 } else {
306 FATAL("Error verifying firmware body.\n")do { fprintf(stderr, "FATAL: %s: " "Error verifying firmware body.\n"
, __func__ ); exit(1); } while (0)
;
307 goto verify_cleanup;
308 }
309
310 if (kernelkey_file &&
311 VB2_SUCCESS != vb2_write_packed_key(kernelkey_file,
312 kernel_subkey)) {
313 FATAL("Unable to write kernel subkey\n")do { fprintf(stderr, "FATAL: %s: " "Unable to write kernel subkey\n"
, __func__ ); exit(1); } while (0)
;
314 goto verify_cleanup;
315 }
316
317 /* Success */
318 retval = 0;
319
320verify_cleanup:
321 if (pubkbuf)
322 free(pubkbuf);
323 if (blob)
324 free(blob);
325 if (fv_data)
326 free(fv_data);
327
328 return retval;
329}
330
331static int do_vbutil_firmware(int argc, char *argv[])
332{
333
334 char *filename = NULL((void*)0);
335 char *keyblock_file = NULL((void*)0);
336 char *signpubkey = NULL((void*)0);
337 char *signprivate = NULL((void*)0);
338 uint32_t version = 0;
339 char *fv_file = NULL((void*)0);
340 char *kernelkey_file = NULL((void*)0);
341 uint32_t preamble_flags = 0;
342 int mode = 0;
343 int parse_error = 0;
344 char *e;
345 int i;
346
347 while ((i = getopt_long(argc, argv, "", long_opts, NULL((void*)0))) != -1) {
348 switch (i) {
349 case '?':
350 /* Unhandled option */
351 printf("Unknown option\n");
352 parse_error = 1;
353 break;
354 case OPT_HELP:
355 print_help(argc, argv);
356 return !!parse_error;
357
358 case OPT_MODE_VBLOCK:
359 case OPT_MODE_VERIFY:
360 mode = i;
361 filename = optarg;
362 break;
363
364 case OPT_KEYBLOCK:
365 keyblock_file = optarg;
366 break;
367
368 case OPT_SIGNPUBKEY:
369 signpubkey = optarg;
370 break;
371
372 case OPT_SIGNPRIVATE:
373 signprivate = optarg;
374 break;
375
376 case OPT_FV:
377 fv_file = optarg;
378 break;
379
380 case OPT_KERNELKEY:
381 kernelkey_file = optarg;
382 break;
383
384 case OPT_VERSION:
385 version = strtoul(optarg, &e, 0);
386 if (!*optarg || (e && *e)) {
387 printf("Invalid --version\n");
388 parse_error = 1;
389 }
390 break;
391
392 case OPT_FLAGS:
393 preamble_flags = strtoul(optarg, &e, 0);
394 if (!*optarg || (e && *e)) {
395 printf("Invalid --flags\n");
396 parse_error = 1;
397 }
398 break;
399 }
400 }
401
402 if (parse_error) {
403 print_help(argc, argv);
404 return 1;
405 }
406
407 switch (mode) {
408 case OPT_MODE_VBLOCK:
409 return do_vblock(filename, keyblock_file, signprivate, version,
410 fv_file, kernelkey_file, preamble_flags);
411 case OPT_MODE_VERIFY:
412 return do_verify(filename, signpubkey, fv_file, kernelkey_file);
413 default:
414 ERROR("Must specify a mode.\n")fprintf(stderr, "ERROR: %s: " "Must specify a mode.\n", __func__
)
;
415 print_help(argc, argv);
416 return 1;
417 }
418}
419
420DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware, VBOOT_VERSION_1_0,const struct futil_cmd_t __cmd_vbutil_firmware = { .name = "vbutil_firmware"
, .handler = do_vbutil_firmware, .version = VBOOT_VERSION_1_0
, .shorthelp = "Verified boot firmware utility", }
421 "Verified boot firmware utility")const struct futil_cmd_t __cmd_vbutil_firmware = { .name = "vbutil_firmware"
, .handler = do_vbutil_firmware, .version = VBOOT_VERSION_1_0
, .shorthelp = "Verified boot firmware utility", }
;