xref: /freebsd/lib/libsecureboot/verify_file.c (revision c1d255d3)
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 struct verify_status *verified_files = NULL;
66 static int loaded_manifests = 0;	/* have we loaded anything? */
67 
68 #define VE_STATUS_NONE	1
69 #define VE_STATUS_VALID	2
70 
71 /**
72  * @brief set ve status for fd
73  */
74 static void
75 ve_status_set(int fd, int ves)
76 {
77 	if (fd >= 0 && fd < SOPEN_MAX) {
78 		ve_status[fd] = ves;
79 		ve_status_state = VE_STATUS_VALID;
80 	}
81 	ve_status[SOPEN_MAX] = ves;
82 }
83 
84 /**
85  * @brief get ve status of fd
86  *
87  * What we return depends on ve_status_state.
88  *
89  * @return
90  *	@li ve_status[fd] if ve_status_state is valid
91  *	@li ve_status[SOPEN_MAX] if ve_status_state is none
92  *	@li VE_NOT_CHECKED if ve_status_state uninitialized
93  */
94 int
95 ve_status_get(int fd)
96 {
97 	if (!ve_status_state) {
98 		return (VE_NOT_CHECKED);
99 	}
100 	if (ve_status_state == VE_STATUS_VALID &&
101 		fd >= 0 && fd < SOPEN_MAX)
102 		return (ve_status[fd]);
103 	return (ve_status[SOPEN_MAX]);	/* most recent */
104 }
105 
106 /**
107  * @brief track verify status
108  *
109  * occasionally loader will make multiple calls
110  * for the same file, we need only check it once.
111  */
112 struct verify_status {
113 	dev_t	vs_dev;
114 	ino_t	vs_ino;
115 	int	vs_status;
116 	struct verify_status *vs_next;
117 };
118 
119 int
120 is_verified(struct stat *stp)
121 {
122 	struct verify_status *vsp;
123 
124 	if (stp->st_ino > 0) {
125 		for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) {
126 			if (stp->st_dev == vsp->vs_dev &&
127 			    stp->st_ino == vsp->vs_ino)
128 				return (vsp->vs_status);
129 		}
130 	}
131 	return (VE_NOT_CHECKED);
132 }
133 
134 /* most recent first, since most likely to see repeated calls. */
135 void
136 add_verify_status(struct stat *stp, int status)
137 {
138 	struct verify_status *vsp;
139 
140 	vsp = malloc(sizeof(struct verify_status));
141 	vsp->vs_next = verified_files;
142 	vsp->vs_dev = stp->st_dev;
143 	vsp->vs_ino = stp->st_ino;
144 	vsp->vs_status = status;
145 	verified_files = vsp;
146 }
147 
148 
149 /**
150  * @brief
151  * load specified manifest if verified
152  */
153 int
154 load_manifest(const char *name, const char *prefix,
155     const char *skip, struct stat *stp)
156 {
157 	struct stat st;
158 	size_t n;
159 	int rc;
160 	char *content;
161 
162 	rc = VE_FINGERPRINT_NONE;
163 	n = strlen(name);
164 	if (n > 4) {
165 		if (!stp) {
166 			stp = &st;
167 			if (stat(name, &st) < 0 || !S_ISREG(st.st_mode))
168 				return (rc);
169 		}
170 		rc = is_verified(stp);
171 		if (rc != VE_NOT_CHECKED) {
172 			return (rc);
173 		}
174 		/* loader has no sense of time */
175 		ve_utc_set(stp->st_mtime);
176 		content = (char *)verify_signed(name, VEF_VERBOSE);
177 		if (content) {
178 #ifdef UNIT_TEST
179 			if (DestdirLen > 0 &&
180 			    strncmp(name, Destdir, DestdirLen) == 0) {
181 				name += DestdirLen;
182 				if (prefix &&
183 				    strncmp(prefix, Destdir, DestdirLen) == 0)
184 					prefix += DestdirLen;
185 			}
186 #endif
187 			fingerprint_info_add(name, prefix, skip, content, stp);
188 			add_verify_status(stp, VE_VERIFIED);
189 			loaded_manifests = 1; /* we are verifying! */
190 			DEBUG_PRINTF(3, ("loaded: %s %s %s\n",
191 				name, prefix, skip));
192 			rc = VE_VERIFIED;
193 		} else {
194 			rc = VE_FINGERPRINT_WRONG;
195 			add_verify_status(stp, rc);	/* remember */
196 		}
197 	}
198 	return (rc);
199 }
200 
201 static int
202 find_manifest(const char *name)
203 {
204 	struct stat st;
205 	char buf[MAXPATHLEN];
206 	char *prefix;
207 	char *skip;
208 	const char **tp;
209 	int rc;
210 
211 	strncpy(buf, name, MAXPATHLEN - 1);
212 	if (!(prefix = strrchr(buf, '/')))
213 		return (-1);
214 	*prefix = '\0';
215 	prefix = strdup(buf);
216 	rc = VE_FINGERPRINT_NONE;
217 	for (tp = manifest_names; *tp; tp++) {
218 		snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp);
219 		DEBUG_PRINTF(5, ("looking for %s\n", buf));
220 		if (stat(buf, &st) == 0 && st.st_size > 0) {
221 #ifdef MANIFEST_SKIP_ALWAYS		/* very unlikely */
222 			skip = MANIFEST_SKIP_ALWAYS;
223 #else
224 #ifdef MANIFEST_SKIP			/* rare */
225 			if (*tp[0] == '.') {
226 				skip = MANIFEST_SKIP;
227 			} else
228 #endif
229 				skip = NULL;
230 #endif
231 			rc = load_manifest(buf, skip ? prefix : NULL,
232 			    skip, &st);
233 			break;
234 		}
235 	}
236 	free(prefix);
237 	return (rc);
238 }
239 
240 
241 #ifdef LOADER_VERIEXEC_TESTING
242 # define ACCEPT_NO_FP_DEFAULT	VE_MUST + 1
243 #else
244 # define ACCEPT_NO_FP_DEFAULT	VE_MUST
245 #endif
246 #ifndef VE_VERBOSE_DEFAULT
247 # define VE_VERBOSE_DEFAULT	0
248 #endif
249 
250 static int
251 severity_guess(const char *filename)
252 {
253 	const char *cp;
254 
255 	/* Some files like *.conf and *.hints may be unsigned */
256 	if ((cp = strrchr(filename, '.'))) {
257 		if (strcmp(cp, ".conf") == 0 ||
258 		    strcmp(cp, ".cookie") == 0 ||
259 			strcmp(cp, ".hints") == 0)
260 			return (VE_TRY);
261 		if (strcmp(cp, ".4th") == 0 ||
262 		    strcmp(cp, ".lua") == 0 ||
263 		    strcmp(cp, ".rc") == 0)
264 			return (VE_MUST);
265 	}
266 	return (VE_WANT);
267 }
268 
269 static int Verifying = -1;		/* 0 if not verifying */
270 
271 static void
272 verify_tweak(int fd, off_t off, struct stat *stp,
273     char *tweak, int *accept_no_fp,
274     int *verbose)
275 {
276 	if (strcmp(tweak, "off") == 0) {
277 		Verifying = 0;
278 	} else if (strcmp(tweak, "strict") == 0) {
279 		/* anything caller wants verified must be */
280 		*accept_no_fp = VE_WANT;
281 		*verbose = 1; /* warn of anything unverified */
282 		/* treat self test failure as fatal */
283 		if (!ve_self_tests()) {
284 			panic("verify self tests failed");
285 		}
286 	} else if (strcmp(tweak, "modules") == 0) {
287 		/* modules/kernel must be verified */
288 		*accept_no_fp = VE_MUST;
289 	} else if (strcmp(tweak, "try") == 0) {
290 		/* best effort: always accept no fp */
291 		*accept_no_fp = VE_MUST + 1;
292 	} else if (strcmp(tweak, "verbose") == 0) {
293 		*verbose = 1;
294 	} else if (strcmp(tweak, "quiet") == 0) {
295 		*verbose = 0;
296 	} else if (strncmp(tweak, "trust", 5) == 0) {
297 		/* content is trust anchor to add or revoke */
298 		unsigned char *ucp;
299 		size_t num;
300 
301 		if (off > 0)
302 			lseek(fd, 0, SEEK_SET);
303 		ucp = read_fd(fd, stp->st_size);
304 		if (ucp == NULL)
305 			return;
306 		if (strstr(tweak, "revoke")) {
307 			num = ve_trust_anchors_revoke(ucp, stp->st_size);
308 			DEBUG_PRINTF(3, ("revoked %d trust anchors\n",
309 				(int) num));
310 		} else {
311 			num = ve_trust_anchors_add_buf(ucp, stp->st_size);
312 			DEBUG_PRINTF(3, ("added %d trust anchors\n",
313 				(int) num));
314 		}
315 	}
316 }
317 
318 #ifndef VE_DEBUG_LEVEL
319 # define VE_DEBUG_LEVEL 0
320 #endif
321 
322 static int
323 getenv_int(const char *var, int def)
324 {
325 	const char *cp;
326 	char *ep;
327 	long val;
328 
329 	val = def;
330 	cp = getenv(var);
331 	if (cp && *cp) {
332 		val = strtol(cp, &ep, 0);
333 		if ((ep && *ep) || val != (int)val) {
334 			val = def;
335 		}
336 	}
337 	return (int)val;
338 }
339 
340 
341 /**
342  * @brief prepare to verify an open file
343  *
344  * @param[in] fd
345  * 	open descriptor
346  *
347  * @param[in] filename
348  * 	path we opened and will use to lookup fingerprint
349  *
350  * @param[in] stp
351  *	stat pointer so we can check file type
352  */
353 int
354 verify_prep(int fd, const char *filename, off_t off, struct stat *stp,
355     const char *caller)
356 {
357 	int rc;
358 
359 	if (Verifying < 0) {
360 		Verifying = ve_trust_init();
361 #ifndef UNIT_TEST
362 		ve_debug_set(getenv_int("VE_DEBUG_LEVEL", VE_DEBUG_LEVEL));
363 #endif
364 		/* initialize ve_status with default result */
365 		rc = Verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING;
366 		ve_status_set(0, rc);
367 		ve_status_state = VE_STATUS_NONE;
368 		if (Verifying) {
369 			ve_self_tests();
370 			ve_anchor_verbose_set(1);
371 		}
372 	}
373 	if (!Verifying || fd < 0)
374 		return (0);
375 	if (stp) {
376 		if (fstat(fd, stp) < 0 || !S_ISREG(stp->st_mode))
377 			return (0);
378 	}
379 	DEBUG_PRINTF(2,
380 	    ("verify_prep: caller=%s,fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n",
381 		caller, fd, filename, (long long)off, (long long)stp->st_dev,
382 		(long long)stp->st_ino));
383 	rc = is_verified(stp);
384 	DEBUG_PRINTF(4,("verify_prep: is_verified()->%d\n", rc));
385 	if (rc == VE_NOT_CHECKED) {
386 		rc = find_manifest(filename);
387 	} else {
388 		ve_status_set(fd, rc);
389 	}
390 	return (rc);
391 }
392 
393 /**
394  * @brief verify an open file
395  *
396  * @param[in] fd
397  * 	open descriptor
398  *
399  * @param[in] filename
400  * 	path we opened and will use to lookup fingerprint
401  *
402  * @param[in] off
403  * 	current offset in fd, must be restored on return
404  *
405  * @param[in] severity
406  * 	indicator of how to handle case of missing fingerprint
407  *
408  * We look for a signed manifest relative to the filename
409  * just opened and verify/load it if needed.
410  *
411  * We then use verify_fd() in libve to actually verify that hash for
412  * open file.  If it returns < 0 we look at the severity arg to decide
413  * what to do about it.
414  *
415  * If verify_fd() returns VE_FINGERPRINT_NONE we accept it if severity
416  * is < accept_no_fp.
417  *
418  * @return >= 0 on success < 0 on failure
419  */
420 int
421 verify_file(int fd, const char *filename, off_t off, int severity,
422     const char *caller)
423 {
424 	static int once;
425 	static int accept_no_fp = ACCEPT_NO_FP_DEFAULT;
426 	static int verbose = VE_VERBOSE_DEFAULT;
427 	struct stat st;
428 	char *cp;
429 	int rc;
430 
431 	rc = verify_prep(fd, filename, off, &st, caller);
432 
433 	if (!rc)
434 		return (0);
435 
436 	if (!once) {
437 		once++;
438 		verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT);
439 	}
440 
441 	if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
442 		if (severity <= VE_GUESS)
443 			severity = severity_guess(filename);
444 #ifdef VE_PCR_SUPPORT
445 		/*
446 		 * Only update pcr with things that must verify
447 		 * these tend to be processed in a more deterministic
448 		 * order, which makes our pseudo pcr more useful.
449 		 */
450 		ve_pcr_updating_set((severity == VE_MUST));
451 #endif
452 #ifdef UNIT_TEST
453 		if (DestdirLen > 0 &&
454 		    strncmp(filename, Destdir, DestdirLen) == 0) {
455 			filename += DestdirLen;
456 		}
457 #endif
458 		if ((rc = verify_fd(fd, filename, off, &st)) >= 0) {
459 			if (verbose || severity > VE_WANT) {
460 #if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0
461 				printf("%serified %s %llu,%llu\n",
462 				    (rc == VE_FINGERPRINT_IGNORE) ? "Unv" : "V",
463 				    filename,
464 				    (long long)st.st_dev, (long long)st.st_ino);
465 #else
466 				printf("%serified %s\n",
467 				    (rc == VE_FINGERPRINT_IGNORE) ? "Unv" : "V",
468 				    filename);
469 #endif
470 			}
471 			if (severity < VE_MUST) { /* not a kernel or module */
472 				if ((cp = strrchr(filename, '/'))) {
473 					cp++;
474 					if (strncmp(cp, "loader.ve.", 10) == 0) {
475 						cp += 10;
476 						verify_tweak(fd, off, &st, cp,
477 						    &accept_no_fp, &verbose);
478 					}
479 				}
480 			}
481 			add_verify_status(&st, rc);
482 			ve_status_set(fd, rc);
483 			return (rc);
484 		}
485 
486 		if (severity || verbose || rc == VE_FINGERPRINT_WRONG)
487 			printf("Unverified: %s\n", ve_error_get());
488 		if (rc == VE_FINGERPRINT_UNKNOWN && severity < VE_MUST)
489 			rc = VE_UNVERIFIED_OK;
490 		else if (rc == VE_FINGERPRINT_NONE && severity < accept_no_fp)
491 			rc = VE_UNVERIFIED_OK;
492 
493 		add_verify_status(&st, rc);
494 	}
495 #ifdef LOADER_VERIEXEC_TESTING
496 	else if (rc != VE_FINGERPRINT_WRONG) {
497 		/*
498 		 * We have not loaded any manifest and
499 		 * not because of verication failure.
500 		 * Most likely reason is we have none.
501 		 * Allow boot to proceed if we are just testing.
502 		 */
503 		return (VE_UNVERIFIED_OK);
504 	}
505 #endif
506 	if (rc == VE_FINGERPRINT_WRONG && severity > accept_no_fp)
507 		panic("cannot continue");
508 	ve_status_set(fd, rc);
509 	return (rc);
510 }
511 
512 /**
513  * @brief get hex string for pcr value and export
514  *
515  * In case we are doing measured boot, provide
516  * value of the "pcr" data we have accumulated.
517  */
518 void
519 verify_pcr_export(void)
520 {
521 #ifdef VE_PCR_SUPPORT
522 	char hexbuf[br_sha256_SIZE * 2 + 2];
523 	unsigned char hbuf[br_sha256_SIZE];
524 	char *hinfo;
525 	char *hex;
526 	ssize_t hlen;
527 
528 	hlen = ve_pcr_get(hbuf, sizeof(hbuf));
529 	if (hlen > 0) {
530 		hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
531 		if (hex) {
532 			hex[hlen*2] = '\0'; /* clobber newline */
533 			setenv("loader.ve.pcr", hex, 1);
534 			DEBUG_PRINTF(1,
535 			    ("%s: setenv(loader.ve.pcr, %s\n", __func__,
536 				hex));
537 			hinfo = ve_pcr_hashed_get(1);
538 			if (hinfo) {
539 				setenv("loader.ve.hashed", hinfo, 1);
540 				DEBUG_PRINTF(1,
541 				    ("%s: setenv(loader.ve.hashed, %s\n",
542 					__func__, hinfo));
543 				if ((hlen = strlen(hinfo)) > KENV_MVALLEN) {
544 					/*
545 					 * bump kenv_mvallen
546 					 * roundup to multiple of KENV_MVALLEN
547 					 */
548 					char mvallen[16];
549 
550 					hlen += KENV_MVALLEN -
551 					    (hlen % KENV_MVALLEN);
552 					if (snprintf(mvallen, sizeof(mvallen),
553 						"%d", (int) hlen) < sizeof(mvallen))
554 						setenv("kenv_mvallen", mvallen, 1);
555 				}
556 				free(hinfo);
557 			}
558 		}
559 	}
560 #endif
561 }
562