2 * Copyright (c) 2017-2018, 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>
35 #include "libsecureboot.h"
36 #include <verify_file.h>
37 #include <manifests.h>
39 #define VE_NOT_CHECKED -42
45 * define MANIFEST_SKIP to Skip - in tests/tvo.c so that
46 * tvo can control the value we use in find_manifest()
50 # define MANIFEST_SKIP Skip
51 # undef VE_DEBUG_LEVEL
55 * We sometimes need to know if input is verified or not.
56 * The extra slot is for tracking most recently opened.
58 static int ve_status[SOPEN_MAX+1];
59 static int ve_status_state;
61 struct verify_status *verified_files = NULL;
62 static int loaded_manifests = 0; /* have we loaded anything? */
64 #define VE_STATUS_NONE 1
65 #define VE_STATUS_VALID 2
68 * @brief set ve status for fd
71 ve_status_set(int fd, int ves)
73 if (fd >= 0 && fd < SOPEN_MAX) {
75 ve_status_state = VE_STATUS_VALID;
77 ve_status[SOPEN_MAX] = ves;
81 * @brief get ve status of fd
83 * What we return depends on ve_status_state.
86 * @li ve_status[fd] if ve_status_state is valid
87 * @li ve_status[SOPEN_MAX] if ve_status_state is none
88 * @li VE_NOT_CHECKED if ve_status_state uninitialized
93 if (!ve_status_state) {
94 return (VE_NOT_CHECKED);
96 if (ve_status_state == VE_STATUS_VALID &&
97 fd >= 0 && fd < SOPEN_MAX)
98 return (ve_status[fd]);
99 return (ve_status[SOPEN_MAX]); /* most recent */
103 * @brief track verify status
105 * occasionally loader will make multiple calls
106 * for the same file, we need only check it once.
108 struct verify_status {
112 struct verify_status *vs_next;
116 is_verified(struct stat *stp)
118 struct verify_status *vsp;
120 for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) {
121 if (stp->st_dev == vsp->vs_dev &&
122 stp->st_ino == vsp->vs_ino)
123 return (vsp->vs_status);
125 return (VE_NOT_CHECKED);
128 /* most recent first, since most likely to see repeated calls. */
130 add_verify_status(struct stat *stp, int status)
132 struct verify_status *vsp;
134 vsp = malloc(sizeof(struct verify_status));
135 vsp->vs_next = verified_files;
136 vsp->vs_dev = stp->st_dev;
137 vsp->vs_ino = stp->st_ino;
138 vsp->vs_status = status;
139 verified_files = vsp;
145 * load specified manifest if verified
148 load_manifest(const char *name, const char *prefix,
149 const char *skip, struct stat *stp)
156 rc = VE_FINGERPRINT_NONE;
161 if (stat(name, &st) < 0 || !S_ISREG(st.st_mode))
164 rc = is_verified(stp);
165 if (rc != VE_NOT_CHECKED) {
168 /* loader has no sense of time */
169 ve_utc_set(stp->st_mtime);
170 content = (char *)verify_signed(name, VEF_VERBOSE);
172 fingerprint_info_add(name, prefix, skip, content, stp);
173 add_verify_status(stp, VE_VERIFIED);
174 loaded_manifests = 1; /* we are verifying! */
175 DEBUG_PRINTF(3, ("loaded: %s %s %s\n",
176 name, prefix, skip));
179 rc = VE_FINGERPRINT_WRONG;
180 add_verify_status(stp, rc); /* remember */
187 find_manifest(const char *name)
190 char buf[MAXPATHLEN];
196 strncpy(buf, name, MAXPATHLEN - 1);
197 if (!(prefix = strrchr(buf, '/')))
200 prefix = strdup(buf);
201 rc = VE_FINGERPRINT_NONE;
202 for (tp = manifest_names; *tp; tp++) {
203 snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp);
204 DEBUG_PRINTF(5, ("looking for %s\n", buf));
205 if (stat(buf, &st) == 0 && st.st_size > 0) {
206 #ifdef MANIFEST_SKIP_ALWAYS /* very unlikely */
207 skip = MANIFEST_SKIP_ALWAYS;
209 #ifdef MANIFEST_SKIP /* rare */
211 skip = MANIFEST_SKIP;
216 rc = load_manifest(buf, skip ? prefix : NULL,
226 #ifdef LOADER_VERIEXEC_TESTING
227 # define ACCEPT_NO_FP_DEFAULT VE_MUST + 1
229 # define ACCEPT_NO_FP_DEFAULT VE_MUST
231 #ifndef VE_VERBOSE_DEFAULT
232 # define VE_VERBOSE_DEFAULT 0
236 severity_guess(const char *filename)
240 /* Some files like *.conf and *.hints may be unsigned */
241 if ((cp = strrchr(filename, '.'))) {
242 if (strcmp(cp, ".conf") == 0 ||
243 strcmp(cp, ".cookie") == 0 ||
244 strcmp(cp, ".hints") == 0)
251 verify_tweak(char *tweak, int *accept_no_fp, int *verbose, int *verifying)
253 if (strcmp(tweak, "off") == 0) {
255 } else if (strcmp(tweak, "strict") == 0) {
256 /* anything caller wants verified must be */
257 *accept_no_fp = VE_WANT;
258 *verbose = 1; /* warn of anything unverified */
259 /* treat self test failure as fatal */
260 if (!ve_self_tests()) {
261 panic("verify self tests failed");
263 } else if (strcmp(tweak, "modules") == 0) {
264 /* modules/kernel must be verified */
265 *accept_no_fp = VE_MUST;
266 } else if (strcmp(tweak, "try") == 0) {
267 /* best effort: always accept no fp */
268 *accept_no_fp = VE_MUST + 1;
269 } else if (strcmp(tweak, "verbose") == 0) {
271 } else if (strcmp(tweak, "quiet") == 0) {
277 * @brief verify an open file
282 * @param[in] filename
283 * path we opened and will use to lookup fingerprint
286 * current offset in fd, must be restored on return
288 * @param[in] severity
289 * indicator of how to handle case of missing fingerprint
291 * We look for a signed manifest relative to the filename
292 * just opened and verify/load it if needed.
294 * We then use verify_fd() in libve to actually verify that hash for
295 * open file. If it returns < 0 we look at the severity arg to decide
296 * what to do about it.
298 * If verify_fd() returns VE_FINGERPRINT_NONE we accept it if severity
301 * @return >= 0 on success < 0 on failure
304 verify_file(int fd, const char *filename, off_t off, int severity)
306 static int verifying = -1;
307 static int accept_no_fp = ACCEPT_NO_FP_DEFAULT;
308 static int verbose = VE_VERBOSE_DEFAULT;
314 verifying = ve_trust_init();
315 #ifdef VE_DEBUG_LEVEL
316 ve_debug_set(VE_DEBUG_LEVEL);
318 /* initialize ve_status with default result */
319 rc = verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING;
320 ve_status_set(0, rc);
321 ve_status_state = VE_STATUS_NONE;
328 if (fd < 0 || fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
331 DEBUG_PRINTF(3, ("fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n",
332 fd, filename, (long long)off, (long long)st.st_dev,
333 (long long)st.st_ino));
336 rc = is_verified(&st);
337 if (rc != VE_NOT_CHECKED) {
338 ve_status_set(fd, rc);
341 rc = find_manifest(filename);
342 if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
343 if (severity <= VE_GUESS)
344 severity = severity_guess(filename);
345 if ((rc = verify_fd(fd, filename, off, &st)) >= 0) {
346 if (verbose || severity > VE_WANT) {
347 #if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0
348 printf("Verified %s %llu,%llu\n", filename,
349 (long long)st.st_dev, (long long)st.st_ino);
351 printf("Verified %s\n", filename);
354 if (severity < VE_MUST) { /* not a kernel or module */
356 if ((cp = strrchr(filename, '/'))) {
358 if (strncmp(cp, "loader.ve.", 10) == 0) {
361 &accept_no_fp, &verbose,
366 add_verify_status(&st, rc);
367 ve_status_set(fd, rc);
371 if (severity || verbose)
372 printf("Unverified: %s\n", ve_error_get());
373 if (rc == VE_FINGERPRINT_UNKNOWN && severity < VE_MUST)
374 rc = VE_UNVERIFIED_OK;
375 else if (rc == VE_FINGERPRINT_NONE && severity < accept_no_fp)
376 rc = VE_UNVERIFIED_OK;
378 add_verify_status(&st, rc);
380 #ifdef LOADER_VERIEXEC_TESTING
381 else if (rc != VE_FINGERPRINT_WRONG) {
383 * We have not loaded any manifest and
384 * not because of verication failure.
385 * Most likely reason is we have none.
386 * Allow boot to proceed if we are just testing.
388 return (VE_UNVERIFIED_OK);
391 if (rc == VE_FINGERPRINT_WRONG && severity > accept_no_fp)
392 panic("cannot continue");
393 ve_status_set(fd, rc);
398 * @brief get hex string for pcr value and export
400 * In case we are doing measured boot, provide
401 * value of the "pcr" data we have accumulated.
404 verify_pcr_export(void)
406 #ifdef VE_PCR_SUPPORT
407 char hexbuf[br_sha256_SIZE * 2 + 2];
408 unsigned char hbuf[br_sha256_SIZE];
412 hlen = ve_pcr_get(hbuf, sizeof(hbuf));
414 hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
416 hex[hlen*2] = '\0'; /* clobber newline */
417 setenv("loader.ve.pcr", hex, 1);