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