2 * Copyright (c) 2017-2020, Juniper Networks, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * Routines to verify files loaded.
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
33 #include <sys/queue.h>
36 #include "libsecureboot.h"
37 #include <verify_file.h>
38 #include <manifests.h>
44 * define MANIFEST_SKIP to Skip - in tests/tvo.c so that
45 * tvo can control the value we use in find_manifest()
48 extern size_t DestdirLen;
51 # define MANIFEST_SKIP Skip
52 # undef VE_DEBUG_LEVEL
56 * We sometimes need to know if input is verified or not.
57 * The extra slot is for tracking most recently opened.
62 static int ve_status[SOPEN_MAX+1];
63 static int ve_status_state;
65 static struct verify_status *verified_files = NULL;
66 static int loaded_manifests = 0; /* have we loaded anything? */
69 VE_VERBOSE_SILENT, /* only report errors */
70 VE_VERBOSE_UNVERIFIED, /* all unverified files */
71 VE_VERBOSE_MUST, /* report VE_MUST */
72 VE_VERBOSE_ALL, /* report all */
73 VE_VERBOSE_DEBUG, /* extra noise */
76 #ifndef VE_VERBOSE_DEFAULT
77 # define VE_VERBOSE_DEFAULT VE_VERBOSE_MUST
79 static int Verbose = VE_VERBOSE_DEFAULT;
81 #define VE_STATUS_NONE 1
82 #define VE_STATUS_VALID 2
85 * @brief set ve status for fd
88 ve_status_set(int fd, int ves)
90 if (fd >= 0 && fd < SOPEN_MAX) {
92 ve_status_state = VE_STATUS_VALID;
94 ve_status[SOPEN_MAX] = ves;
98 * @brief get ve status of fd
100 * What we return depends on ve_status_state.
103 * @li ve_status[fd] if ve_status_state is valid
104 * @li ve_status[SOPEN_MAX] if ve_status_state is none
105 * @li VE_NOT_CHECKED if ve_status_state uninitialized
108 ve_status_get(int fd)
110 if (!ve_status_state) {
111 return (VE_NOT_CHECKED);
113 if (ve_status_state == VE_STATUS_VALID &&
114 fd >= 0 && fd < SOPEN_MAX)
115 return (ve_status[fd]);
116 return (ve_status[SOPEN_MAX]); /* most recent */
120 * @brief track verify status
122 * occasionally loader will make multiple calls
123 * for the same file, we need only check it once.
125 struct verify_status {
129 struct verify_status *vs_next;
133 is_verified(struct stat *stp)
135 struct verify_status *vsp;
137 if (stp->st_ino > 0) {
138 for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) {
139 if (stp->st_dev == vsp->vs_dev &&
140 stp->st_ino == vsp->vs_ino)
141 return (vsp->vs_status);
144 return (VE_NOT_CHECKED);
147 /* most recent first, since most likely to see repeated calls. */
149 add_verify_status(struct stat *stp, int status)
151 struct verify_status *vsp;
153 vsp = malloc(sizeof(struct verify_status));
155 vsp->vs_next = verified_files;
156 vsp->vs_dev = stp->st_dev;
157 vsp->vs_ino = stp->st_ino;
158 vsp->vs_status = status;
159 verified_files = vsp;
166 * load specified manifest if verified
169 load_manifest(const char *name, const char *prefix,
170 const char *skip, struct stat *stp)
177 rc = VE_FINGERPRINT_NONE;
182 if (stat(name, &st) < 0 || !S_ISREG(st.st_mode))
185 rc = is_verified(stp);
186 if (rc != VE_NOT_CHECKED) {
189 /* loader has no sense of time */
190 ve_utc_set(stp->st_mtime);
191 content = (char *)verify_signed(name, VerifyFlags);
194 if (DestdirLen > 0 &&
195 strncmp(name, Destdir, DestdirLen) == 0) {
198 strncmp(prefix, Destdir, DestdirLen) == 0)
199 prefix += DestdirLen;
202 fingerprint_info_add(name, prefix, skip, content, stp);
203 add_verify_status(stp, VE_VERIFIED);
204 loaded_manifests = 1; /* we are verifying! */
205 DEBUG_PRINTF(3, ("loaded: %s %s %s\n",
206 name, prefix, skip));
209 rc = VE_FINGERPRINT_WRONG;
210 add_verify_status(stp, rc); /* remember */
217 find_manifest(const char *name)
220 char buf[MAXPATHLEN];
226 strncpy(buf, name, MAXPATHLEN - 1);
227 if (!(prefix = strrchr(buf, '/')))
230 prefix = strdup(buf);
231 rc = VE_FINGERPRINT_NONE;
232 for (tp = manifest_names; *tp; tp++) {
233 snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp);
236 if (prefix[0] == '\0' || prefix[1] == '\0')
239 DEBUG_PRINTF(5, ("looking for %s\n", buf));
240 if (stat(buf, &st) == 0 && st.st_size > 0) {
241 #ifdef MANIFEST_SKIP_ALWAYS /* very unlikely */
242 skip = MANIFEST_SKIP_ALWAYS;
244 #ifdef MANIFEST_SKIP /* rare */
246 skip = MANIFEST_SKIP;
251 rc = load_manifest(buf, skip ? prefix : NULL,
261 #ifdef LOADER_VERIEXEC_TESTING
262 # define ACCEPT_NO_FP_DEFAULT VE_MUST + 1
264 # define ACCEPT_NO_FP_DEFAULT VE_MUST
268 severity_guess(const char *filename)
273 * Some files like *.conf and *.hints may be unsigned,
274 * a *.tgz is expected to have its own signed manifest.
276 if ((cp = strrchr(filename, '.'))) {
277 if (strcmp(cp, ".conf") == 0 ||
278 strcmp(cp, ".cookie") == 0 ||
279 strcmp(cp, ".hints") == 0 ||
280 strcmp(cp, ".tgz") == 0)
282 if (strcmp(cp, ".4th") == 0 ||
283 strcmp(cp, ".lua") == 0 ||
284 strcmp(cp, ".rc") == 0)
290 static int Verifying = -1; /* 0 if not verifying */
293 verify_tweak(int fd, off_t off, struct stat *stp,
294 char *tweak, int *accept_no_fp)
296 if (strcmp(tweak, "off") == 0) {
298 } else if (strcmp(tweak, "strict") == 0) {
299 /* anything caller wants verified must be */
300 *accept_no_fp = VE_WANT;
301 Verbose = VE_VERBOSE_ALL;
302 /* treat self test failure as fatal */
303 if (!ve_self_tests()) {
304 panic("verify self tests failed");
306 } else if (strcmp(tweak, "modules") == 0) {
307 /* modules/kernel must be verified */
308 *accept_no_fp = VE_MUST;
309 } else if (strcmp(tweak, "try") == 0) {
310 /* best effort: always accept no fp */
311 *accept_no_fp = VE_MUST + 1;
312 } else if (strcmp(tweak, "verbose") == 0) {
313 Verbose = VE_VERBOSE_ALL;
314 } else if (strcmp(tweak, "quiet") == 0) {
315 Verbose = VE_VERBOSE_UNVERIFIED;
317 } else if (strcmp(tweak, "silent") == 0) {
318 Verbose = VE_VERBOSE_SILENT;
320 } else if (strncmp(tweak, "trust", 5) == 0) {
321 /* content is trust anchor to add or revoke */
326 lseek(fd, 0, SEEK_SET);
327 ucp = read_fd(fd, stp->st_size);
330 if (strstr(tweak, "revoke")) {
331 num = ve_trust_anchors_revoke(ucp, stp->st_size);
332 DEBUG_PRINTF(3, ("revoked %d trust anchors\n",
335 num = ve_trust_anchors_add_buf(ucp, stp->st_size);
336 DEBUG_PRINTF(3, ("added %d trust anchors\n",
342 #ifndef VE_DEBUG_LEVEL
343 # define VE_DEBUG_LEVEL 0
347 getenv_int(const char *var, int def)
356 val = strtol(cp, &ep, 0);
357 if ((ep && *ep) || val != (int)val) {
366 * @brief report verification status
369 * path we attempted to verify
371 * @param[in] severity
372 * indicator of how to handle case of missing fingerprint
375 * result of verification
376 * 0 not a file to be verified, > 0 success, < 0 error
379 * pointer to struct stat, used in extra info to be output
381 * The output is dictated by combinations of the above and the setting
385 * report only failure to verify if severity is VE_WANT or higher.
387 * VE_VERBOSE_UNVERIFIED
388 * report any unverified file.
391 * report verified only if severity is VE_MUST or higher.
394 * report all verified files.
397 * if stp is not NULL report dev,inode for path
400 verify_report(const char *path, int severity, int status, struct stat *stp)
402 if (status < 0 || status == VE_FINGERPRINT_IGNORE) {
403 if (Verbose >= VE_VERBOSE_UNVERIFIED || severity > VE_TRY ||
404 status <= VE_FINGERPRINT_WRONG) {
405 if (Verbose == VE_VERBOSE_DEBUG && stp != NULL)
406 printf("Unverified %s %llu,%llu\n",
408 (long long)stp->st_dev,
409 (long long)stp->st_ino);
411 printf("Unverified %s\n", ve_error_get());
413 } else if (status > 0 && Verbose >= VE_VERBOSE_MUST) {
414 if (severity >= VE_MUST || Verbose >= VE_VERBOSE_ALL) {
415 if (Verbose == VE_VERBOSE_DEBUG && stp != NULL)
416 printf("Unverified %s %llu,%llu\n",
418 (long long)stp->st_dev,
419 (long long)stp->st_ino);
421 printf("Verified %s\n", path);
428 * @brief prepare to verify an open file
433 * @param[in] filename
434 * path we opened and will use to lookup fingerprint
437 * stat pointer so we can check file type
440 verify_prep(int fd, const char *filename, off_t off, struct stat *stp,
446 Verifying = ve_trust_init();
447 /* initialize ve_status with default result */
448 rc = Verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING;
449 ve_status_set(0, rc);
450 ve_status_state = VE_STATUS_NONE;
453 ve_anchor_verbose_set(1);
456 if (!Verifying || fd < 0)
459 if (fstat(fd, stp) < 0 || !S_ISREG(stp->st_mode))
463 ("verify_prep: caller=%s,fd=%d,name='%s',off=%lld,dev=%lld,ino=%llu\n",
464 caller, fd, filename, (long long)off, (long long)stp->st_dev,
465 (unsigned long long)stp->st_ino));
466 rc = is_verified(stp);
467 DEBUG_PRINTF(4,("verify_prep: is_verified()->%d\n", rc));
468 if (rc == VE_NOT_CHECKED) {
469 rc = find_manifest(filename);
471 ve_status_set(fd, rc);
477 * @brief verify an open file
482 * @param[in] filename
483 * path we opened and will use to lookup fingerprint
486 * current offset in fd, must be restored on return
488 * @param[in] severity
489 * indicator of how to handle case of missing fingerprint
491 * We look for a signed manifest relative to the filename
492 * just opened and verify/load it if needed.
494 * We then use verify_fd() in libve to actually verify that hash for
495 * open file. If it returns < 0 we look at the severity arg to decide
496 * what to do about it.
498 * If verify_fd() returns VE_FINGERPRINT_NONE we accept it if severity
501 * @return >= 0 on success < 0 on failure
504 verify_file(int fd, const char *filename, off_t off, int severity,
507 static int check_verbose = 1;
508 static int accept_no_fp = ACCEPT_NO_FP_DEFAULT;
515 Verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT);
516 VerifyFlags = getenv_int("VE_VERIFY_FLAGS", VEF_VERBOSE);
518 ve_debug_set(getenv_int("VE_DEBUG_LEVEL", VE_DEBUG_LEVEL));
522 rc = verify_prep(fd, filename, off, &st, caller);
527 if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
528 if (severity <= VE_GUESS)
529 severity = severity_guess(filename);
530 #ifdef VE_PCR_SUPPORT
532 * Only update pcr with things that must verify
533 * these tend to be processed in a more deterministic
534 * order, which makes our pseudo pcr more useful.
536 ve_pcr_updating_set((severity == VE_MUST));
539 if (DestdirLen > 0 &&
540 strncmp(filename, Destdir, DestdirLen) == 0) {
541 filename += DestdirLen;
544 rc = verify_fd(fd, filename, off, &st);
545 verify_report(filename, severity, rc, &st);
547 if (severity < VE_MUST) { /* not a kernel or module */
548 if ((cp = strrchr(filename, '/'))) {
550 if (strncmp(cp, "loader.ve.", 10) == 0) {
552 verify_tweak(fd, off, &st, cp,
557 add_verify_status(&st, rc);
558 ve_status_set(fd, rc);
561 if (rc == VE_FINGERPRINT_UNKNOWN && severity < VE_MUST)
562 rc = VE_UNVERIFIED_OK;
563 else if (rc == VE_FINGERPRINT_NONE && severity < accept_no_fp)
564 rc = VE_UNVERIFIED_OK;
566 add_verify_status(&st, rc);
568 /* recheck debug/verbose level next time we are called */
569 if (rc == VE_UNVERIFIED_OK) {
573 #ifdef LOADER_VERIEXEC_TESTING
574 else if (rc != VE_FINGERPRINT_WRONG) {
576 * We have not loaded any manifest and
577 * not because of verication failure.
578 * Most likely reason is we have none.
579 * Allow boot to proceed if we are just testing.
581 return (VE_UNVERIFIED_OK);
584 if (rc == VE_FINGERPRINT_WRONG && severity > accept_no_fp)
585 panic("cannot continue");
586 ve_status_set(fd, rc);
591 * @brief get hex string for pcr value and export
593 * In case we are doing measured boot, provide
594 * value of the "pcr" data we have accumulated.
597 verify_pcr_export(void)
599 #ifdef VE_PCR_SUPPORT
600 char hexbuf[br_sha256_SIZE * 2 + 2];
601 unsigned char hbuf[br_sha256_SIZE];
606 hlen = ve_pcr_get(hbuf, sizeof(hbuf));
608 hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
610 hex[hlen*2] = '\0'; /* clobber newline */
611 setenv("loader.ve.pcr", hex, 1);
613 ("%s: setenv(loader.ve.pcr, %s\n", __func__,
615 hinfo = ve_pcr_hashed_get(1);
617 setenv("loader.ve.hashed", hinfo, 1);
619 ("%s: setenv(loader.ve.hashed, %s\n",
621 if ((hlen = strlen(hinfo)) > KENV_MVALLEN) {
624 * roundup to multiple of KENV_MVALLEN
628 hlen += KENV_MVALLEN -
629 (hlen % KENV_MVALLEN);
630 if (snprintf(mvallen, sizeof(mvallen),
631 "%d", (int) hlen) < (int)sizeof(mvallen))
632 setenv("kenv_mvallen", mvallen, 1);
642 * For tftp and http we need to hash pathname
643 * to be able to fake stat(2) data.
646 hash_string(char *s, size_t n, char *buf, size_t bufsz)
648 br_hash_compat_context mctx;
649 const br_hash_class *md;
653 md = &br_sha1_vtable;
656 md = &br_sha256_vtable;
659 if (bufsz < br_sha1_SIZE)
661 md = &br_sha1_vtable;
662 bufsz = br_sha1_SIZE;
667 md->init(&mctx.vtable);
668 md->update(&mctx.vtable, s, n);
669 md->out(&mctx.vtable, buf);