xref: /freebsd/lib/libsecureboot/verify_file.c (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
1 /*-
2  * Copyright (c) 2017-2020, Juniper Networks, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25 /*
26  * Routines to verify files loaded.
27  */
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include <sys/param.h>
32 #include <string.h>
33 #include <sys/queue.h>
34 #include <sys/kenv.h>
35 
36 #include "libsecureboot.h"
37 #include <verify_file.h>
38 #include <manifests.h>
39 
40 #ifdef UNIT_TEST
41 # include <err.h>
42 # define panic warn
43 /*
44  * define MANIFEST_SKIP to Skip - in tests/tvo.c so that
45  * tvo can control the value we use in find_manifest()
46  */
47 extern char *Destdir;
48 extern size_t DestdirLen;
49 extern char *Skip;
50 # undef MANIFEST_SKIP
51 # define MANIFEST_SKIP Skip
52 # undef VE_DEBUG_LEVEL
53 #endif
54 
55 /*
56  * We sometimes need to know if input is verified or not.
57  * The extra slot is for tracking most recently opened.
58  */
59 #ifndef SOPEN_MAX
60 #define SOPEN_MAX       64
61 #endif
62 static int ve_status[SOPEN_MAX+1];
63 static int ve_status_state;
64 struct verify_status;
65 static struct verify_status *verified_files = NULL;
66 static int loaded_manifests = 0;	/* have we loaded anything? */
67 
68 enum {
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 */
74 };
75 
76 #ifndef VE_VERBOSE_DEFAULT
77 # define VE_VERBOSE_DEFAULT VE_VERBOSE_MUST
78 #endif
79 static int Verbose = VE_VERBOSE_DEFAULT;
80 
81 #define VE_STATUS_NONE	1
82 #define VE_STATUS_VALID	2
83 
84 /**
85  * @brief set ve status for fd
86  */
87 static void
88 ve_status_set(int fd, int ves)
89 {
90 	if (fd >= 0 && fd < SOPEN_MAX) {
91 		ve_status[fd] = ves;
92 		ve_status_state = VE_STATUS_VALID;
93 	}
94 	ve_status[SOPEN_MAX] = ves;
95 }
96 
97 /**
98  * @brief get ve status of fd
99  *
100  * What we return depends on ve_status_state.
101  *
102  * @return
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
106  */
107 int
108 ve_status_get(int fd)
109 {
110 	if (!ve_status_state) {
111 		return (VE_NOT_CHECKED);
112 	}
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 */
117 }
118 
119 /**
120  * @brief track verify status
121  *
122  * occasionally loader will make multiple calls
123  * for the same file, we need only check it once.
124  */
125 struct verify_status {
126 	dev_t	vs_dev;
127 	ino_t	vs_ino;
128 	int	vs_status;
129 	struct verify_status *vs_next;
130 };
131 
132 int
133 is_verified(struct stat *stp)
134 {
135 	struct verify_status *vsp;
136 
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);
142 		}
143 	}
144 	return (VE_NOT_CHECKED);
145 }
146 
147 /* most recent first, since most likely to see repeated calls. */
148 void
149 add_verify_status(struct stat *stp, int status)
150 {
151 	struct verify_status *vsp;
152 
153 	vsp = malloc(sizeof(struct verify_status));
154 	if (vsp) {
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;
160 	}
161 }
162 
163 
164 /**
165  * @brief
166  * load specified manifest if verified
167  */
168 int
169 load_manifest(const char *name, const char *prefix,
170     const char *skip, struct stat *stp)
171 {
172 	struct stat st;
173 	size_t n;
174 	int rc;
175 	char *content;
176 
177 	rc = VE_FINGERPRINT_NONE;
178 	n = strlen(name);
179 	if (n > 4) {
180 		if (!stp) {
181 			stp = &st;
182 			if (stat(name, &st) < 0 || !S_ISREG(st.st_mode))
183 				return (rc);
184 		}
185 		rc = is_verified(stp);
186 		if (rc != VE_NOT_CHECKED) {
187 			return (rc);
188 		}
189 		/* loader has no sense of time */
190 		ve_utc_set(stp->st_mtime);
191 		content = (char *)verify_signed(name, VerifyFlags);
192 		if (content) {
193 #ifdef UNIT_TEST
194 			if (DestdirLen > 0 &&
195 			    strncmp(name, Destdir, DestdirLen) == 0) {
196 				name += DestdirLen;
197 				if (prefix &&
198 				    strncmp(prefix, Destdir, DestdirLen) == 0)
199 					prefix += DestdirLen;
200 			}
201 #endif
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));
207 			rc = VE_VERIFIED;
208 		} else {
209 			rc = VE_FINGERPRINT_WRONG;
210 			add_verify_status(stp, rc);	/* remember */
211 		}
212 	}
213 	return (rc);
214 }
215 
216 static int
217 find_manifest(const char *name)
218 {
219 	struct stat st;
220 	char buf[MAXPATHLEN];
221 	char *prefix;
222 	char *skip;
223 	const char **tp;
224 	int rc;
225 
226 	strncpy(buf, name, MAXPATHLEN - 1);
227 	if (!(prefix = strrchr(buf, '/')))
228 		return (-1);
229 	*prefix = '\0';
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);
234 		if (*tp[0] == '.') {
235 			/* skip /../ */
236 			if (prefix[0] == '\0' || prefix[1] == '\0')
237 				continue;
238 		}
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;
243 #else
244 #ifdef MANIFEST_SKIP			/* rare */
245 			if (*tp[0] == '.') {
246 				skip = MANIFEST_SKIP;
247 			} else
248 #endif
249 				skip = NULL;
250 #endif
251 			rc = load_manifest(buf, skip ? prefix : NULL,
252 			    skip, &st);
253 			break;
254 		}
255 	}
256 	free(prefix);
257 	return (rc);
258 }
259 
260 
261 #ifdef LOADER_VERIEXEC_TESTING
262 # define ACCEPT_NO_FP_DEFAULT	VE_MUST + 1
263 #else
264 # define ACCEPT_NO_FP_DEFAULT	VE_MUST
265 #endif
266 
267 static int
268 severity_guess(const char *filename)
269 {
270 	const char *cp;
271 
272 	/*
273 	 * Some files like *.conf and *.hints may be unsigned,
274 	 * a *.tgz is expected to have its own signed manifest.
275 	 */
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)
281 			return (VE_TRY);
282 		if (strcmp(cp, ".4th") == 0 ||
283 		    strcmp(cp, ".lua") == 0 ||
284 		    strcmp(cp, ".rc") == 0)
285 			return (VE_MUST);
286 	}
287 	return (VE_WANT);
288 }
289 
290 static int Verifying = -1;		/* 0 if not verifying */
291 
292 static void
293 verify_tweak(int fd, off_t off, struct stat *stp,
294     char *tweak, int *accept_no_fp)
295 {
296 	if (strcmp(tweak, "off") == 0) {
297 		Verifying = 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");
305 		}
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;
316 		VerifyFlags = 0;
317 	} else if (strcmp(tweak, "silent") == 0) {
318 		Verbose = VE_VERBOSE_SILENT;
319 		VerifyFlags = 0;
320 	} else if (strncmp(tweak, "trust", 5) == 0) {
321 		/* content is trust anchor to add or revoke */
322 		unsigned char *ucp;
323 		size_t num;
324 
325 		if (off > 0)
326 			lseek(fd, 0, SEEK_SET);
327 		ucp = read_fd(fd, stp->st_size);
328 		if (ucp == NULL)
329 			return;
330 		if (strstr(tweak, "revoke")) {
331 			num = ve_trust_anchors_revoke(ucp, stp->st_size);
332 			DEBUG_PRINTF(3, ("revoked %d trust anchors\n",
333 				(int) num));
334 		} else {
335 			num = ve_trust_anchors_add_buf(ucp, stp->st_size);
336 			DEBUG_PRINTF(3, ("added %d trust anchors\n",
337 				(int) num));
338 		}
339 	}
340 }
341 
342 #ifndef VE_DEBUG_LEVEL
343 # define VE_DEBUG_LEVEL 0
344 #endif
345 
346 static int
347 getenv_int(const char *var, int def)
348 {
349 	const char *cp;
350 	char *ep;
351 	long val;
352 
353 	val = def;
354 	cp = getenv(var);
355 	if (cp && *cp) {
356 		val = strtol(cp, &ep, 0);
357 		if ((ep && *ep) || val != (int)val) {
358 			val = def;
359 		}
360 	}
361 	return (int)val;
362 }
363 
364 
365 /**
366  * @brief report verification status
367  *
368  * @param[in] path
369  *	path we attempted to verify
370  *
371  * @param[in] severity
372  * 	indicator of how to handle case of missing fingerprint
373  *
374  * @param[in] status
375  *	result of verification
376  *	0 not a file to be verified, > 0 success, < 0 error
377  *
378  * @param[in] stp
379  *	pointer to struct stat, used in extra info to be output
380  *
381  * The output is dictated by combinations of the above and the setting
382  * of Verbose:
383  *
384  * VE_VERBOSE_SILENT
385  * 	report only failure to verify if severity is VE_WANT or higher.
386  *
387  * VE_VERBOSE_UNVERIFIED
388  * 	report any unverified file.
389  *
390  * VE_VERBOSE_MUST
391  * 	report verified only if severity is VE_MUST or higher.
392  *
393  * VE_VERBOSE_ALL
394  * 	report all verified files.
395  *
396  * VE_VERBOSE_DEBUG
397  * 	if stp is not NULL report dev,inode for path
398  */
399 void
400 verify_report(const char *path, int severity, int status, struct stat *stp)
401 {
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",
407 				    ve_error_get(),
408 				    (long long)stp->st_dev,
409 				    (long long)stp->st_ino);
410 			else
411 				printf("Unverified %s\n", ve_error_get());
412 		}
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",
417 				    path,
418 				    (long long)stp->st_dev,
419 				    (long long)stp->st_ino);
420 			else
421 				printf("Verified %s\n", path);
422 		}
423 	}
424 }
425 
426 
427 /**
428  * @brief prepare to verify an open file
429  *
430  * @param[in] fd
431  * 	open descriptor
432  *
433  * @param[in] filename
434  * 	path we opened and will use to lookup fingerprint
435  *
436  * @param[in] stp
437  *	stat pointer so we can check file type
438  */
439 int
440 verify_prep(int fd, const char *filename, off_t off, struct stat *stp,
441     const char *caller)
442 {
443 	int rc;
444 
445 	if (Verifying < 0) {
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;
451 		if (Verifying) {
452 			ve_self_tests();
453 			ve_anchor_verbose_set(1);
454 		}
455 	}
456 	if (!Verifying || fd < 0)
457 		return (0);
458 	if (stp) {
459 		if (fstat(fd, stp) < 0 || !S_ISREG(stp->st_mode))
460 			return (0);
461 	}
462 	DEBUG_PRINTF(2,
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);
470 	} else {
471 		ve_status_set(fd, rc);
472 	}
473 	return (rc);
474 }
475 
476 /**
477  * @brief verify an open file
478  *
479  * @param[in] fd
480  * 	open descriptor
481  *
482  * @param[in] filename
483  * 	path we opened and will use to lookup fingerprint
484  *
485  * @param[in] off
486  * 	current offset in fd, must be restored on return
487  *
488  * @param[in] severity
489  * 	indicator of how to handle case of missing fingerprint
490  *
491  * We look for a signed manifest relative to the filename
492  * just opened and verify/load it if needed.
493  *
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.
497  *
498  * If verify_fd() returns VE_FINGERPRINT_NONE we accept it if severity
499  * is < accept_no_fp.
500  *
501  * @return >= 0 on success < 0 on failure
502  */
503 int
504 verify_file(int fd, const char *filename, off_t off, int severity,
505     const char *caller)
506 {
507 	static int check_verbose = 1;
508 	static int accept_no_fp = ACCEPT_NO_FP_DEFAULT;
509 	struct stat st;
510 	char *cp;
511 	int rc;
512 
513 	if (check_verbose) {
514 		check_verbose = 0;
515 		Verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT);
516 		VerifyFlags = getenv_int("VE_VERIFY_FLAGS", VEF_VERBOSE);
517 #ifndef UNIT_TEST
518 		ve_debug_set(getenv_int("VE_DEBUG_LEVEL", VE_DEBUG_LEVEL));
519 #endif
520 	}
521 
522 	rc = verify_prep(fd, filename, off, &st, caller);
523 
524 	if (!rc)
525 		return (0);
526 
527 	if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
528 		if (severity <= VE_GUESS)
529 			severity = severity_guess(filename);
530 #ifdef VE_PCR_SUPPORT
531 		/*
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.
535 		 */
536 		ve_pcr_updating_set((severity == VE_MUST));
537 #endif
538 #ifdef UNIT_TEST
539 		if (DestdirLen > 0 &&
540 		    strncmp(filename, Destdir, DestdirLen) == 0) {
541 			filename += DestdirLen;
542 		}
543 #endif
544 		rc = verify_fd(fd, filename, off, &st);
545 		verify_report(filename, severity, rc, &st);
546 		if (rc >= 0) {
547 			if (severity < VE_MUST) { /* not a kernel or module */
548 				if ((cp = strrchr(filename, '/'))) {
549 					cp++;
550 					if (strncmp(cp, "loader.ve.", 10) == 0) {
551 						cp += 10;
552 						verify_tweak(fd, off, &st, cp,
553 						    &accept_no_fp);
554 					}
555 				}
556 			}
557 			add_verify_status(&st, rc);
558 			ve_status_set(fd, rc);
559 			return (rc);
560 		}
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;
565 
566 		add_verify_status(&st, rc);
567 
568 		/* recheck debug/verbose level next time we are called */
569 		if (rc == VE_UNVERIFIED_OK) {
570 			check_verbose = 1;
571 		}
572 	}
573 #ifdef LOADER_VERIEXEC_TESTING
574 	else if (rc != VE_FINGERPRINT_WRONG) {
575 		/*
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.
580 		 */
581 		return (VE_UNVERIFIED_OK);
582 	}
583 #endif
584 	if (rc == VE_FINGERPRINT_WRONG && severity > accept_no_fp)
585 		panic("cannot continue");
586 	ve_status_set(fd, rc);
587 	return (rc);
588 }
589 
590 /**
591  * @brief get hex string for pcr value and export
592  *
593  * In case we are doing measured boot, provide
594  * value of the "pcr" data we have accumulated.
595  */
596 void
597 verify_pcr_export(void)
598 {
599 #ifdef VE_PCR_SUPPORT
600 	char hexbuf[br_sha256_SIZE * 2 + 2];
601 	unsigned char hbuf[br_sha256_SIZE];
602 	char *hinfo;
603 	char *hex;
604 	ssize_t hlen;
605 
606 	hlen = ve_pcr_get(hbuf, sizeof(hbuf));
607 	if (hlen > 0) {
608 		hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
609 		if (hex) {
610 			hex[hlen*2] = '\0'; /* clobber newline */
611 			setenv("loader.ve.pcr", hex, 1);
612 			DEBUG_PRINTF(1,
613 			    ("%s: setenv(loader.ve.pcr, %s\n", __func__,
614 				hex));
615 			hinfo = ve_pcr_hashed_get(1);
616 			if (hinfo) {
617 				setenv("loader.ve.hashed", hinfo, 1);
618 				DEBUG_PRINTF(1,
619 				    ("%s: setenv(loader.ve.hashed, %s\n",
620 					__func__, hinfo));
621 				if ((hlen = strlen(hinfo)) > KENV_MVALLEN) {
622 					/*
623 					 * bump kenv_mvallen
624 					 * roundup to multiple of KENV_MVALLEN
625 					 */
626 					char mvallen[16];
627 
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);
633 				}
634 				free(hinfo);
635 			}
636 		}
637 	}
638 #endif
639 }
640 
641 /*
642  * For tftp and http we need to hash pathname
643  * to be able to fake stat(2) data.
644  */
645 int
646 hash_string(char *s, size_t n, char *buf, size_t bufsz)
647 {
648 	br_hash_compat_context mctx;
649 	const br_hash_class *md;
650 
651 	switch (bufsz) {
652 	case br_sha1_SIZE:
653 		md = &br_sha1_vtable;
654 		break;
655 	case br_sha256_SIZE:
656 		md = &br_sha256_vtable;
657 		break;
658 	default:
659 		if (bufsz < br_sha1_SIZE)
660 			return -1;
661 		md = &br_sha1_vtable;
662 		bufsz = br_sha1_SIZE;
663 		break;
664 	}
665 	if (n == 0)
666 		n = strlen(s);
667 	md->init(&mctx.vtable);
668 	md->update(&mctx.vtable, s, n);
669 	md->out(&mctx.vtable, buf);
670 	return bufsz;
671 }
672 
673 
674