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
35 #include "libsecureboot.h"
36 #include <verify_file.h>
37 #include <manifests.h>
38
39 #ifdef UNIT_TEST
40 # include <err.h>
41 # define panic warn
42 /*
43 * define MANIFEST_SKIP to Skip - in tests/tvo.c so that
44 * tvo can control the value we use in find_manifest()
45 */
46 extern char *Skip;
47 # undef MANIFEST_SKIP
48 # define MANIFEST_SKIP Skip
49 # undef VE_DEBUG_LEVEL
50 #endif
51
52 /*
53 * We sometimes need to know if input is verified or not.
54 * The extra slot is for tracking most recently opened.
55 */
56 static int ve_status[SOPEN_MAX+1];
57 static int ve_status_state;
58 struct verify_status;
59 struct verify_status *verified_files = NULL;
60 static int loaded_manifests = 0; /* have we loaded anything? */
61
62 #define VE_STATUS_NONE 1
63 #define VE_STATUS_VALID 2
64
65 /**
66 * @brief set ve status for fd
67 */
68 static void
ve_status_set(int fd,int ves)69 ve_status_set(int fd, int ves)
70 {
71 if (fd >= 0 && fd < SOPEN_MAX) {
72 ve_status[fd] = ves;
73 ve_status_state = VE_STATUS_VALID;
74 }
75 ve_status[SOPEN_MAX] = ves;
76 }
77
78 /**
79 * @brief get ve status of fd
80 *
81 * What we return depends on ve_status_state.
82 *
83 * @return
84 * @li ve_status[fd] if ve_status_state is valid
85 * @li ve_status[SOPEN_MAX] if ve_status_state is none
86 * @li VE_NOT_CHECKED if ve_status_state uninitialized
87 */
88 int
ve_status_get(int fd)89 ve_status_get(int fd)
90 {
91 if (!ve_status_state) {
92 return (VE_NOT_CHECKED);
93 }
94 if (ve_status_state == VE_STATUS_VALID &&
95 fd >= 0 && fd < SOPEN_MAX)
96 return (ve_status[fd]);
97 return (ve_status[SOPEN_MAX]); /* most recent */
98 }
99
100 /**
101 * @brief track verify status
102 *
103 * occasionally loader will make multiple calls
104 * for the same file, we need only check it once.
105 */
106 struct verify_status {
107 dev_t vs_dev;
108 ino_t vs_ino;
109 int vs_status;
110 struct verify_status *vs_next;
111 };
112
113 int
is_verified(struct stat * stp)114 is_verified(struct stat *stp)
115 {
116 struct verify_status *vsp;
117
118 for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) {
119 if (stp->st_dev == vsp->vs_dev &&
120 stp->st_ino == vsp->vs_ino)
121 return (vsp->vs_status);
122 }
123 return (VE_NOT_CHECKED);
124 }
125
126 /* most recent first, since most likely to see repeated calls. */
127 void
add_verify_status(struct stat * stp,int status)128 add_verify_status(struct stat *stp, int status)
129 {
130 struct verify_status *vsp;
131
132 vsp = malloc(sizeof(struct verify_status));
133 vsp->vs_next = verified_files;
134 vsp->vs_dev = stp->st_dev;
135 vsp->vs_ino = stp->st_ino;
136 vsp->vs_status = status;
137 verified_files = vsp;
138 }
139
140
141 /**
142 * @brief
143 * load specified manifest if verified
144 */
145 int
load_manifest(const char * name,const char * prefix,const char * skip,struct stat * stp)146 load_manifest(const char *name, const char *prefix,
147 const char *skip, struct stat *stp)
148 {
149 struct stat st;
150 size_t n;
151 int rc;
152 char *content;
153
154 rc = VE_FINGERPRINT_NONE;
155 n = strlen(name);
156 if (n > 4) {
157 if (!stp) {
158 stp = &st;
159 if (stat(name, &st) < 0 || !S_ISREG(st.st_mode))
160 return (rc);
161 }
162 rc = is_verified(stp);
163 if (rc != VE_NOT_CHECKED) {
164 return (rc);
165 }
166 /* loader has no sense of time */
167 ve_utc_set(stp->st_mtime);
168 content = (char *)verify_signed(name, VEF_VERBOSE);
169 if (content) {
170 fingerprint_info_add(name, prefix, skip, content, stp);
171 add_verify_status(stp, VE_VERIFIED);
172 loaded_manifests = 1; /* we are verifying! */
173 DEBUG_PRINTF(3, ("loaded: %s %s %s\n",
174 name, prefix, skip));
175 rc = 0;
176 } else {
177 rc = VE_FINGERPRINT_WRONG;
178 add_verify_status(stp, rc); /* remember */
179 }
180 }
181 return (rc);
182 }
183
184 static int
find_manifest(const char * name)185 find_manifest(const char *name)
186 {
187 struct stat st;
188 char buf[MAXPATHLEN];
189 char *prefix;
190 char *skip;
191 const char **tp;
192 int rc;
193
194 strncpy(buf, name, MAXPATHLEN - 1);
195 if (!(prefix = strrchr(buf, '/')))
196 return (-1);
197 *prefix = '\0';
198 prefix = strdup(buf);
199 rc = VE_FINGERPRINT_NONE;
200 for (tp = manifest_names; *tp; tp++) {
201 snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp);
202 DEBUG_PRINTF(5, ("looking for %s\n", buf));
203 if (stat(buf, &st) == 0 && st.st_size > 0) {
204 #ifdef MANIFEST_SKIP_ALWAYS /* very unlikely */
205 skip = MANIFEST_SKIP_ALWAYS;
206 #else
207 #ifdef MANIFEST_SKIP /* rare */
208 if (*tp[0] == '.') {
209 skip = MANIFEST_SKIP;
210 } else
211 #endif
212 skip = NULL;
213 #endif
214 rc = load_manifest(buf, skip ? prefix : NULL,
215 skip, &st);
216 break;
217 }
218 }
219 free(prefix);
220 return (rc);
221 }
222
223
224 #ifdef LOADER_VERIEXEC_TESTING
225 # define ACCEPT_NO_FP_DEFAULT VE_MUST + 1
226 #else
227 # define ACCEPT_NO_FP_DEFAULT VE_MUST
228 #endif
229 #ifndef VE_VERBOSE_DEFAULT
230 # define VE_VERBOSE_DEFAULT 0
231 #endif
232
233 static int
severity_guess(const char * filename)234 severity_guess(const char *filename)
235 {
236 const char *cp;
237
238 /* Some files like *.conf and *.hints may be unsigned */
239 if ((cp = strrchr(filename, '.'))) {
240 if (strcmp(cp, ".conf") == 0 ||
241 strcmp(cp, ".cookie") == 0 ||
242 strcmp(cp, ".hints") == 0)
243 return (VE_TRY);
244 }
245 return (VE_WANT);
246 }
247
248 static void
verify_tweak(int fd,off_t off,struct stat * stp,char * tweak,int * accept_no_fp,int * verbose,int * verifying)249 verify_tweak(int fd, off_t off, struct stat *stp,
250 char *tweak, int *accept_no_fp,
251 int *verbose, int *verifying)
252 {
253 if (strcmp(tweak, "off") == 0) {
254 *verifying = 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");
262 }
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) {
270 *verbose = 1;
271 } else if (strcmp(tweak, "quiet") == 0) {
272 *verbose = 0;
273 } else if (strncmp(tweak, "trust", 5) == 0) {
274 /* content is trust anchor to add or revoke */
275 unsigned char *ucp;
276 size_t num;
277
278 if (off > 0)
279 lseek(fd, 0, SEEK_SET);
280 ucp = read_fd(fd, stp->st_size);
281 if (ucp == NULL)
282 return;
283 if (strstr(tweak, "revoke")) {
284 num = ve_trust_anchors_revoke(ucp, stp->st_size);
285 DEBUG_PRINTF(3, ("revoked %d trust anchors\n",
286 (int) num));
287 } else {
288 num = ve_trust_anchors_add_buf(ucp, stp->st_size);
289 DEBUG_PRINTF(3, ("added %d trust anchors\n",
290 (int) num));
291 }
292 }
293 }
294
295 /**
296 * @brief verify an open file
297 *
298 * @param[in] fd
299 * open descriptor
300 *
301 * @param[in] filename
302 * path we opened and will use to lookup fingerprint
303 *
304 * @param[in] off
305 * current offset in fd, must be restored on return
306 *
307 * @param[in] severity
308 * indicator of how to handle case of missing fingerprint
309 *
310 * We look for a signed manifest relative to the filename
311 * just opened and verify/load it if needed.
312 *
313 * We then use verify_fd() in libve to actually verify that hash for
314 * open file. If it returns < 0 we look at the severity arg to decide
315 * what to do about it.
316 *
317 * If verify_fd() returns VE_FINGERPRINT_NONE we accept it if severity
318 * is < accept_no_fp.
319 *
320 * @return >= 0 on success < 0 on failure
321 */
322 int
verify_file(int fd,const char * filename,off_t off,int severity)323 verify_file(int fd, const char *filename, off_t off, int severity)
324 {
325 static int verifying = -1;
326 static int accept_no_fp = ACCEPT_NO_FP_DEFAULT;
327 static int verbose = VE_VERBOSE_DEFAULT;
328 struct stat st;
329 char *cp;
330 int rc;
331
332 if (verifying < 0) {
333 verifying = ve_trust_init();
334 #ifdef VE_DEBUG_LEVEL
335 ve_debug_set(VE_DEBUG_LEVEL);
336 #endif
337 /* initialize ve_status with default result */
338 rc = verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING;
339 ve_status_set(0, rc);
340 ve_status_state = VE_STATUS_NONE;
341 if (verifying) {
342 ve_self_tests();
343 ve_anchor_verbose_set(1);
344 }
345 }
346 if (!verifying)
347 return (0);
348
349 if (fd < 0 || fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
350 return (0);
351
352 DEBUG_PRINTF(3, ("fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n",
353 fd, filename, (long long)off, (long long)st.st_dev,
354 (long long)st.st_ino));
355
356
357 rc = is_verified(&st);
358 if (rc != VE_NOT_CHECKED) {
359 ve_status_set(fd, rc);
360 return (rc);
361 }
362 rc = find_manifest(filename);
363 if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
364 if (severity <= VE_GUESS)
365 severity = severity_guess(filename);
366 #ifdef VE_PCR_SUPPORT
367 /*
368 * Only update pcr with things that must verify
369 * these tend to be processed in a more deterministic
370 * order, which makes our pseudo pcr more useful.
371 */
372 ve_pcr_updating_set((severity == VE_MUST));
373 #endif
374 if ((rc = verify_fd(fd, filename, off, &st)) >= 0) {
375 if (verbose || severity > VE_WANT) {
376 #if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0
377 printf("%serified %s %llu,%llu\n",
378 (rc == VE_FINGERPRINT_IGNORE) ? "Unv" : "V",
379 filename,
380 (long long)st.st_dev, (long long)st.st_ino);
381 #else
382 printf("%serified %s\n",
383 (rc == VE_FINGERPRINT_IGNORE) ? "Unv" : "V",
384 filename);
385 #endif
386 }
387 if (severity < VE_MUST) { /* not a kernel or module */
388
389 if ((cp = strrchr(filename, '/'))) {
390 cp++;
391 if (strncmp(cp, "loader.ve.", 10) == 0) {
392 cp += 10;
393 verify_tweak(fd, off, &st, cp,
394 &accept_no_fp, &verbose,
395 &verifying);
396 }
397 }
398 }
399 add_verify_status(&st, rc);
400 ve_status_set(fd, rc);
401 return (rc);
402 }
403
404 if (severity || verbose || rc == VE_FINGERPRINT_WRONG)
405 printf("Unverified: %s\n", ve_error_get());
406 if (rc == VE_FINGERPRINT_UNKNOWN && severity < VE_MUST)
407 rc = VE_UNVERIFIED_OK;
408 else if (rc == VE_FINGERPRINT_NONE && severity < accept_no_fp)
409 rc = VE_UNVERIFIED_OK;
410
411 add_verify_status(&st, rc);
412 }
413 #ifdef LOADER_VERIEXEC_TESTING
414 else if (rc != VE_FINGERPRINT_WRONG) {
415 /*
416 * We have not loaded any manifest and
417 * not because of verication failure.
418 * Most likely reason is we have none.
419 * Allow boot to proceed if we are just testing.
420 */
421 return (VE_UNVERIFIED_OK);
422 }
423 #endif
424 if (rc == VE_FINGERPRINT_WRONG && severity > accept_no_fp)
425 panic("cannot continue");
426 ve_status_set(fd, rc);
427 return (rc);
428 }
429
430 /**
431 * @brief get hex string for pcr value and export
432 *
433 * In case we are doing measured boot, provide
434 * value of the "pcr" data we have accumulated.
435 */
436 void
verify_pcr_export(void)437 verify_pcr_export(void)
438 {
439 #ifdef VE_PCR_SUPPORT
440 char hexbuf[br_sha256_SIZE * 2 + 2];
441 unsigned char hbuf[br_sha256_SIZE];
442 char *hex;
443 ssize_t hlen;
444
445 hlen = ve_pcr_get(hbuf, sizeof(hbuf));
446 if (hlen > 0) {
447 hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
448 if (hex) {
449 hex[hlen*2] = '\0'; /* clobber newline */
450 setenv("loader.ve.pcr", hex, 1);
451 }
452 }
453 #endif
454 }
455