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