Bug Summary

File:3rdparty/vboot/host/lib/host_key2.c
Warning:line 136, column 3
Potential leak of memory pointed to by 'key'

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 host_key2.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 -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 1714465709 -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-02-073004-2299942-1 -x c host/lib/host_key2.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 * Host functions for keys.
6 */
7
8#include <openssl/pem.h>
9
10#include <errno(*__errno_location ()).h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14
15#include "2common.h"
16#include "2rsa.h"
17#include "2sha.h"
18#include "2sysincludes.h"
19#include "host_common.h"
20#include "host_common21.h"
21#include "host_key21.h"
22#include "host_key.h"
23#include "host_misc.h"
24#include "host_p11.h"
25
26enum vb2_crypto_algorithm vb2_get_crypto_algorithm(
27 enum vb2_hash_algorithm hash_alg,
28 enum vb2_signature_algorithm sig_alg)
29{
30 /* Make sure algorithms are in the range supported by crypto alg */
31 if (sig_alg < VB2_SIG_RSA1024 || sig_alg >= VB2_SIG_ALG_COUNT)
32 return VB2_ALG_COUNT;
33 if (hash_alg < VB2_HASH_SHA1 || hash_alg > VB2_HASH_SHA512)
34 return VB2_ALG_COUNT;
35
36 return (sig_alg - VB2_SIG_RSA1024)
37 * (VB2_HASH_SHA512 - VB2_HASH_SHA1 + 1)
38 + (hash_alg - VB2_HASH_SHA1);
39};
40
41static vb2_error_t vb2_read_local_private_key(uint8_t *buf, uint32_t bufsize,
42 struct vb2_private_key *key)
43{
44 uint64_t alg = *(uint64_t *)buf;
45 key->key_location = PRIVATE_KEY_LOCAL;
46 key->hash_alg = vb2_crypto_to_hash(alg);
47 key->sig_alg = vb2_crypto_to_signature(alg);
48 const unsigned char *start = buf + sizeof(alg);
49
50 key->rsa_private_key = d2i_RSAPrivateKey(0, &start, bufsize - sizeof(alg));
51
52 if (!key->rsa_private_key) {
53 VB2_DEBUG("Unable to parse RSA private key\n")vb2ex_printf(__func__, "Unable to parse RSA private key\n");
54 return VB2_ERROR_UNKNOWN;
55 }
56 return VB2_SUCCESS;
57}
58
59static vb2_error_t vb2_read_p11_private_key(const char *key_info, struct vb2_private_key *key)
60{
61 /* The format of p11 key info: "remote:{lib_path}:{slot_id}:{key_label}" */
62 char *p11_lib = NULL((void*)0), *p11_label = NULL((void*)0);
63 int p11_slot_id;
64 vb2_error_t ret = VB2_ERROR_UNKNOWN;
65 if (sscanf(key_info, "remote:%m[^:]:%i:%m[^:]", &p11_lib, &p11_slot_id, &p11_label) !=
66 3) {
67 VB2_DEBUG("Failed to parse pkcs11 key info\n")vb2ex_printf(__func__, "Failed to parse pkcs11 key info\n");
68 goto done;
69 }
70
71 if (pkcs11_init(p11_lib) != VB2_SUCCESS) {
72 VB2_DEBUG("Unable to initialize pkcs11 library\n")vb2ex_printf(__func__, "Unable to initialize pkcs11 library\n"
)
;
73 goto done;
74 }
75
76 struct pkcs11_key *p11_key = malloc(sizeof(struct pkcs11_key));
77 if (pkcs11_get_key(p11_slot_id, p11_label, p11_key) != VB2_SUCCESS) {
78 VB2_DEBUG("Unable to get pkcs11 key\n")vb2ex_printf(__func__, "Unable to get pkcs11 key\n");
79 free(p11_key);
80 goto done;
81 }
82
83 key->key_location = PRIVATE_KEY_P11;
84 key->p11_key = p11_key;
85 key->sig_alg = pkcs11_get_sig_alg(p11_key);
86 key->hash_alg = pkcs11_get_hash_alg(p11_key);
87 if (key->sig_alg == VB2_SIG_INVALID || key->hash_alg == VB2_HASH_INVALID) {
88 VB2_DEBUG("Unable to get signature or hash algorithm\n")vb2ex_printf(__func__, "Unable to get signature or hash algorithm\n"
)
;
89 free(p11_key);
90 goto done;
91 }
92 ret = VB2_SUCCESS;
93done:
94 free(p11_lib);
95 free(p11_label);
96 return ret;
97}
98
99static bool_Bool is_vb21_private_key(const uint8_t *buf, uint32_t bufsize)
100{
101 const struct vb21_packed_private_key *pkey =
102 (const struct vb21_packed_private_key *)buf;
103 return bufsize >= sizeof(pkey->c.magic) &&
104 pkey->c.magic == VB21_MAGIC_PACKED_PRIVATE_KEY;
105}
106
107struct vb2_private_key *vb2_read_private_key(const char *key_info)
108{
109 struct vb2_private_key *key = (struct vb2_private_key *)calloc(sizeof(*key), 1);
1
Memory is allocated
110 if (!key) {
2
Assuming 'key' is non-null
3
Taking false branch
111 VB2_DEBUG("Unable to allocate private key\n")vb2ex_printf(__func__, "Unable to allocate private key\n");
112 return NULL((void*)0);
113 }
114
115 static const char p11_prefix[] = "remote";
116 static const char local_prefix[] = "local";
117 char *colon = strchr(key_info, ':');
118 if (colon) {
4
Assuming 'colon' is null
5
Taking false branch
119 int prefix_size = colon - key_info;
120 if (!strncmp(key_info, p11_prefix, prefix_size)) {
121 if (vb2_read_p11_private_key(key_info, key) != VB2_SUCCESS) {
122 VB2_DEBUG("Unable to read pkcs11 private key\n")vb2ex_printf(__func__, "Unable to read pkcs11 private key\n");
123 free(key);
124 return NULL((void*)0);
125 }
126 return key;
127 }
128 if (!strncmp(key_info, local_prefix, prefix_size))
129 key_info = colon + 1;
130 }
131
132 // Read the private key from local file.
133 uint8_t *buf = NULL((void*)0);
134 uint32_t bufsize = 0;
135 if (vb2_read_file(key_info, &buf, &bufsize) != VB2_SUCCESS) {
6
Assuming the condition is true
7
Taking true branch
136 VB2_DEBUG("unable to read from file %s\n", key_info)vb2ex_printf(__func__, "unable to read from file %s\n", key_info
)
;
8
Potential leak of memory pointed to by 'key'
137 return NULL((void*)0);
138 }
139
140 vb2_error_t rv;
141 bool_Bool is_vb21 = is_vb21_private_key(buf, bufsize);
142 if (is_vb21)
143 rv = vb21_private_key_unpack_raw(buf, bufsize, key);
144 else
145 rv = vb2_read_local_private_key(buf, bufsize, key);
146
147 free(buf);
148 if (rv != VB2_SUCCESS) {
149 VB2_DEBUG("Unable to read local %s private key\n", is_vb21 ? "vb21" : "vb2")vb2ex_printf(__func__, "Unable to read local %s private key\n"
, is_vb21 ? "vb21" : "vb2")
;
150 free(key);
151 return NULL((void*)0);
152 }
153 return key;
154}
155
156struct vb2_private_key *vb2_read_private_key_pem(
157 const char* filename,
158 enum vb2_crypto_algorithm algorithm)
159{
160 if (algorithm >= VB2_ALG_COUNT) {
161 VB2_DEBUG("%s() called with invalid algorithm!\n",vb2ex_printf(__func__, "%s() called with invalid algorithm!\n"
, __FUNCTION__)
162 __FUNCTION__)vb2ex_printf(__func__, "%s() called with invalid algorithm!\n"
, __FUNCTION__)
;
163 return NULL((void*)0);
164 }
165
166 /* Read private key */
167 FILE *f = fopen(filename, "r");
168 if (!f) {
169 VB2_DEBUG("%s(): Couldn't open key file: %s\n",vb2ex_printf(__func__, "%s(): Couldn't open key file: %s\n", __FUNCTION__
, filename)
170 __FUNCTION__, filename)vb2ex_printf(__func__, "%s(): Couldn't open key file: %s\n", __FUNCTION__
, filename)
;
171 return NULL((void*)0);
172 }
173 struct rsa_st *rsa_key = PEM_read_RSAPrivateKey(f, NULL((void*)0), NULL((void*)0), NULL((void*)0));
174 fclose(f);
175 if (!rsa_key) {
176 VB2_DEBUG("%s(): Couldn't read private key from file: %s\n",vb2ex_printf(__func__, "%s(): Couldn't read private key from file: %s\n"
, __FUNCTION__, filename)
177 __FUNCTION__, filename)vb2ex_printf(__func__, "%s(): Couldn't read private key from file: %s\n"
, __FUNCTION__, filename)
;
178 return NULL((void*)0);
179 }
180
181 /* Store key and algorithm in our struct */
182 struct vb2_private_key *key =
183 (struct vb2_private_key *)calloc(sizeof(*key), 1);
184 if (!key) {
185 RSA_free(rsa_key);
186 return NULL((void*)0);
187 }
188 key->rsa_private_key = rsa_key;
189 key->hash_alg = vb2_crypto_to_hash(algorithm);
190 key->sig_alg = vb2_crypto_to_signature(algorithm);
191
192 /* Return the key */
193 return key;
194}
195
196void vb2_free_private_key(struct vb2_private_key *key)
197{
198 if (!key)
199 return;
200
201 if (key->key_location == PRIVATE_KEY_LOCAL && key->rsa_private_key)
202 RSA_free(key->rsa_private_key);
203 else if (key->key_location == PRIVATE_KEY_P11 && key->p11_key)
204 pkcs11_free_key(key->p11_key);
205
206 if (key->desc)
207 free(key->desc);
208
209 free(key);
210}
211
212vb2_error_t vb2_write_private_key(const char *filename,
213 const struct vb2_private_key *key)
214{
215 /* Convert back to legacy vb1 algorithm enum */
216 uint64_t alg = vb2_get_crypto_algorithm(key->hash_alg, key->sig_alg);
217 if (alg == VB2_ALG_COUNT) {
218 fprintf(stderrstderr, "Can't find crypto algorithm\n");
219 return VB2_ERROR_VB1_CRYPTO_ALGORITHM;
220 }
221
222 uint8_t *outbuf = NULL((void*)0);
223 int buflen = i2d_RSAPrivateKey(key->rsa_private_key, &outbuf);
224 if (buflen <= 0) {
225 fprintf(stderrstderr, "Unable to write private key buffer\n");
226 return VB2_ERROR_PRIVATE_KEY_WRITE_RSA;
227 }
228
229 FILE *f = fopen(filename, "wb");
230 if (!f) {
231 fprintf(stderrstderr, "Unable to open file %s\n", filename);
232 free(outbuf);
233 return VB2_ERROR_PRIVATE_KEY_WRITE_FILE;
234 }
235
236 if (1 != fwrite(&alg, sizeof(alg), 1, f) ||
237 1 != fwrite(outbuf, buflen, 1, f)) {
238 fprintf(stderrstderr, "Unable to write to file %s\n", filename);
239 fclose(f);
240 unlink(filename); /* Delete any partial file */
241 free(outbuf);
242 return VB2_ERROR_PRIVATE_KEY_WRITE_FILE;
243 }
244
245 fclose(f);
246 free(outbuf);
247 return VB2_SUCCESS;
248}
249
250void vb2_init_packed_key(struct vb2_packed_key *key, uint8_t *key_data,
251 uint32_t key_size)
252{
253 memset(key, 0, sizeof(*key));
254 key->key_offset = vb2_offset_of(key, key_data);
255 key->key_size = key_size;
256 key->algorithm = VB2_ALG_COUNT; /* Key not present yet */
257}
258
259struct vb2_packed_key *vb2_alloc_packed_key(uint32_t key_size,
260 uint32_t algorithm,
261 uint32_t version)
262{
263 struct vb2_packed_key *key =
264 (struct vb2_packed_key *)calloc(sizeof(*key) + key_size, 1);
265 if (!key)
266 return NULL((void*)0);
267
268 key->algorithm = algorithm;
269 key->key_version = version;
270 key->key_size = key_size;
271 key->key_offset = sizeof(*key);
272 return key;
273}
274
275vb2_error_t vb2_copy_packed_key(struct vb2_packed_key *dest,
276 const struct vb2_packed_key *src)
277{
278 if (dest->key_size < src->key_size)
279 return VB2_ERROR_COPY_KEY_SIZE;
280
281 dest->key_size = src->key_size;
282 dest->algorithm = src->algorithm;
283 dest->key_version = src->key_version;
284 memcpy(vb2_packed_key_data_mutable(dest),
285 vb2_packed_key_data(src),
286 src->key_size);
287 return VB2_SUCCESS;
288}
289
290struct vb2_packed_key *vb2_read_packed_key(const char *filename)
291{
292 struct vb2_packed_key *key = NULL((void*)0);
293 uint32_t file_size = 0;
294
295 if (VB2_SUCCESS !=
296 vb2_read_file(filename, (uint8_t **)&key, &file_size)) {
297 return NULL((void*)0);
298 }
299
300 if (vb2_packed_key_looks_ok(key, file_size) == VB2_SUCCESS)
301 return key;
302
303 /* Error */
304 free(key);
305 return NULL((void*)0);
306}
307
308struct vb2_packed_key *vb2_read_packed_keyb(const char *filename,
309 uint32_t algorithm,
310 uint32_t version)
311{
312 if (algorithm >= VB2_ALG_COUNT) {
313 fprintf(stderrstderr, "%s() - invalid algorithm\n", __func__);
314 return NULL((void*)0);
315 }
316 if (version > VB2_MAX_KEY_VERSION0xffff) {
317 /* Currently, TPM only supports 16-bit version */
318 fprintf(stderrstderr, "%s() - invalid version %#x\n", __func__,
319 version);
320 return NULL((void*)0);
321 }
322
323 uint8_t *key_data = NULL((void*)0);
324 uint32_t key_size = 0;
325 if (VB2_SUCCESS != vb2_read_file(filename, &key_data, &key_size))
326 return NULL((void*)0);
327
328 uint32_t expected_key_size =
329 vb2_packed_key_size(vb2_crypto_to_signature(algorithm));
330 if (!expected_key_size || expected_key_size != key_size) {
331 fprintf(stderrstderr, "%s() - wrong key size %u for algorithm %u\n",
332 __func__, key_size, algorithm);
333 free(key_data);
334 return NULL((void*)0);
335 }
336
337 struct vb2_packed_key *key =
338 vb2_alloc_packed_key(key_size, algorithm, version);
339 if (!key) {
340 free(key_data);
341 return NULL((void*)0);
342 }
343 memcpy(vb2_packed_key_data_mutable(key), key_data, key_size);
344
345 free(key_data);
346 return key;
347}
348
349vb2_error_t vb2_write_packed_key(const char *filename,
350 const struct vb2_packed_key *key)
351{
352 /* Copy the key, so its data is contiguous with the header */
353 struct vb2_packed_key *kcopy =
354 vb2_alloc_packed_key(key->key_size, 0, 0);
355 if (!kcopy)
356 return VB2_ERROR_PACKED_KEY_ALLOC;
357 if (VB2_SUCCESS != vb2_copy_packed_key(kcopy, key)) {
358 free(kcopy);
359 return VB2_ERROR_PACKED_KEY_COPY;
360 }
361
362 /* Write the copy, then free it */
363 vb2_error_t rv = vb2_write_file(filename, kcopy,
364 kcopy->key_offset + kcopy->key_size);
365 free(kcopy);
366 return rv;
367}
368
369vb2_error_t vb2_packed_key_looks_ok(const struct vb2_packed_key *key,
370 uint32_t size)
371{
372 struct vb2_public_key pubkey;
373 vb2_error_t rv;
374
375 rv = vb2_unpack_key_buffer(&pubkey, (const uint8_t *)key, size);
376 if (rv)
377 return rv;
378
379 if (key->key_version > VB2_MAX_KEY_VERSION0xffff) {
380 /* Currently, TPM only supports 16-bit version */
381 VB2_DEBUG("packed key invalid version\n")vb2ex_printf(__func__, "packed key invalid version\n");
382 return VB2_ERROR_PACKED_KEY_VERSION;
383 }
384
385 return VB2_SUCCESS;
386}
387
388vb2_error_t vb2_unpack_key_data(struct vb2_public_key *key,
389 const uint8_t *key_data, uint32_t key_size)
390{
391 const uint32_t *buf32 = (const uint32_t *)key_data;
392 uint32_t expected_key_size = vb2_packed_key_size(key->sig_alg);
393
394 /* Make sure buffer is the correct length */
395 if (!expected_key_size || expected_key_size != key_size) {
396 VB2_DEBUG("Wrong key size for algorithm\n")vb2ex_printf(__func__, "Wrong key size for algorithm\n");
397 return VB2_ERROR_UNPACK_KEY_SIZE;
398 }
399
400 /* Check for alignment */
401 if (!vb2_aligned(buf32, sizeof(uint32_t))(!(((uintptr_t)(buf32)) & ((sizeof(uint32_t)) - 1))))
402 return VB2_ERROR_UNPACK_KEY_ALIGN;
403
404 key->arrsize = buf32[0];
405
406 /* Validity check key array size */
407 if (key->arrsize * sizeof(uint32_t) != vb2_rsa_sig_size(key->sig_alg))
408 return VB2_ERROR_UNPACK_KEY_ARRAY_SIZE;
409
410 key->n0inv = buf32[1];
411
412 /* Arrays point inside the key data */
413 key->n = buf32 + 2;
414 key->rr = buf32 + 2 + key->arrsize;
415
416 return VB2_SUCCESS;
417}