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