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 29 #include <sys/param.h> 30 #include <string.h> 31 #include <sys/queue.h> 32 #include <sys/kenv.h> 33 34 #include "libsecureboot.h" 35 #include <verify_file.h> 36 #include <manifests.h> 37 38 #ifdef UNIT_TEST 39 # include <err.h> 40 # define panic warn 41 /* 42 * define MANIFEST_SKIP to Skip - in tests/tvo.c so that 43 * tvo can control the value we use in find_manifest() 44 */ 45 extern char *Destdir; 46 extern size_t DestdirLen; 47 extern char *Skip; 48 # undef MANIFEST_SKIP 49 # define MANIFEST_SKIP Skip 50 # undef VE_DEBUG_LEVEL 51 #endif 52 53 /* 54 * We sometimes need to know if input is verified or not. 55 * The extra slot is for tracking most recently opened. 56 */ 57 #ifndef SOPEN_MAX 58 #define SOPEN_MAX 64 59 #endif 60 static int ve_status[SOPEN_MAX+1]; 61 static int ve_status_state; 62 struct verify_status; 63 static struct verify_status *verified_files = NULL; 64 static int loaded_manifests = 0; /* have we loaded anything? */ 65 66 enum { 67 VE_VERBOSE_SILENT, /* only report errors */ 68 VE_VERBOSE_UNVERIFIED, /* all unverified files */ 69 VE_VERBOSE_MUST, /* report VE_MUST */ 70 VE_VERBOSE_ALL, /* report all */ 71 VE_VERBOSE_DEBUG, /* extra noise */ 72 }; 73 74 #ifndef VE_VERBOSE_DEFAULT 75 # define VE_VERBOSE_DEFAULT VE_VERBOSE_MUST 76 #endif 77 static int Verbose = VE_VERBOSE_DEFAULT; 78 79 #define VE_STATUS_NONE 1 80 #define VE_STATUS_VALID 2 81 82 /** 83 * @brief set ve status for fd 84 */ 85 static void 86 ve_status_set(int fd, int ves) 87 { 88 if (fd >= 0 && fd < SOPEN_MAX) { 89 ve_status[fd] = ves; 90 ve_status_state = VE_STATUS_VALID; 91 } 92 ve_status[SOPEN_MAX] = ves; 93 } 94 95 /** 96 * @brief get ve status of fd 97 * 98 * What we return depends on ve_status_state. 99 * 100 * @return 101 * @li ve_status[fd] if ve_status_state is valid 102 * @li ve_status[SOPEN_MAX] if ve_status_state is none 103 * @li VE_NOT_CHECKED if ve_status_state uninitialized 104 */ 105 int 106 ve_status_get(int fd) 107 { 108 if (!ve_status_state) { 109 return (VE_NOT_CHECKED); 110 } 111 if (ve_status_state == VE_STATUS_VALID && 112 fd >= 0 && fd < SOPEN_MAX) 113 return (ve_status[fd]); 114 return (ve_status[SOPEN_MAX]); /* most recent */ 115 } 116 117 /** 118 * @brief track verify status 119 * 120 * occasionally loader will make multiple calls 121 * for the same file, we need only check it once. 122 */ 123 struct verify_status { 124 dev_t vs_dev; 125 ino_t vs_ino; 126 int vs_status; 127 struct verify_status *vs_next; 128 }; 129 130 int 131 is_verified(struct stat *stp) 132 { 133 struct verify_status *vsp; 134 135 if (stp->st_ino > 0) { 136 for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) { 137 if (stp->st_dev == vsp->vs_dev && 138 stp->st_ino == vsp->vs_ino) 139 return (vsp->vs_status); 140 } 141 } 142 return (VE_NOT_CHECKED); 143 } 144 145 /* most recent first, since most likely to see repeated calls. */ 146 void 147 add_verify_status(struct stat *stp, int status) 148 { 149 struct verify_status *vsp; 150 151 vsp = malloc(sizeof(struct verify_status)); 152 if (vsp) { 153 vsp->vs_next = verified_files; 154 vsp->vs_dev = stp->st_dev; 155 vsp->vs_ino = stp->st_ino; 156 vsp->vs_status = status; 157 verified_files = vsp; 158 } 159 } 160 161 162 /** 163 * @brief 164 * load specified manifest if verified 165 */ 166 int 167 load_manifest(const char *name, const char *prefix, 168 const char *skip, struct stat *stp) 169 { 170 struct stat st; 171 size_t n; 172 int rc; 173 char *content; 174 175 rc = VE_FINGERPRINT_NONE; 176 n = strlen(name); 177 if (n > 4) { 178 if (!stp) { 179 stp = &st; 180 if (stat(name, &st) < 0 || !S_ISREG(st.st_mode)) 181 return (rc); 182 } 183 rc = is_verified(stp); 184 if (rc != VE_NOT_CHECKED) { 185 return (rc); 186 } 187 /* loader has no sense of time */ 188 ve_utc_set(stp->st_mtime); 189 content = (char *)verify_signed(name, VerifyFlags); 190 if (content) { 191 #ifdef UNIT_TEST 192 if (DestdirLen > 0 && 193 strncmp(name, Destdir, DestdirLen) == 0) { 194 name += DestdirLen; 195 if (prefix && 196 strncmp(prefix, Destdir, DestdirLen) == 0) 197 prefix += DestdirLen; 198 } 199 #endif 200 fingerprint_info_add(name, prefix, skip, content, stp); 201 add_verify_status(stp, VE_VERIFIED); 202 loaded_manifests = 1; /* we are verifying! */ 203 DEBUG_PRINTF(3, ("loaded: %s %s %s\n", 204 name, prefix, skip)); 205 rc = VE_VERIFIED; 206 } else { 207 rc = VE_FINGERPRINT_WRONG; 208 add_verify_status(stp, rc); /* remember */ 209 } 210 } 211 return (rc); 212 } 213 214 static int 215 find_manifest(const char *name) 216 { 217 struct stat st; 218 char buf[MAXPATHLEN]; 219 char *prefix; 220 char *skip; 221 const char **tp; 222 int rc; 223 224 strncpy(buf, name, MAXPATHLEN - 1); 225 if (!(prefix = strrchr(buf, '/'))) 226 return (-1); 227 *prefix = '\0'; 228 prefix = strdup(buf); 229 rc = VE_FINGERPRINT_NONE; 230 for (tp = manifest_names; *tp; tp++) { 231 snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp); 232 if (*tp[0] == '.') { 233 /* skip /../ */ 234 if (prefix[0] == '\0' || prefix[1] == '\0') 235 continue; 236 } 237 DEBUG_PRINTF(5, ("looking for %s\n", buf)); 238 if (stat(buf, &st) == 0 && st.st_size > 0) { 239 #ifdef MANIFEST_SKIP_ALWAYS /* very unlikely */ 240 skip = MANIFEST_SKIP_ALWAYS; 241 #else 242 #ifdef MANIFEST_SKIP /* rare */ 243 if (*tp[0] == '.') { 244 skip = MANIFEST_SKIP; 245 } else 246 #endif 247 skip = NULL; 248 #endif 249 rc = load_manifest(buf, skip ? prefix : NULL, 250 skip, &st); 251 break; 252 } 253 } 254 free(prefix); 255 return (rc); 256 } 257 258 259 #ifdef LOADER_VERIEXEC_TESTING 260 # define ACCEPT_NO_FP_DEFAULT VE_MUST + 1 261 #else 262 # define ACCEPT_NO_FP_DEFAULT VE_MUST 263 #endif 264 265 static int 266 severity_guess(const char *filename) 267 { 268 const char *cp; 269 270 /* 271 * Some files like *.conf and *.hints may be unsigned, 272 * a *.tgz is expected to have its own signed manifest. 273 */ 274 if ((cp = strrchr(filename, '.'))) { 275 if (strcmp(cp, ".conf") == 0 || 276 strcmp(cp, ".cookie") == 0 || 277 strcmp(cp, ".hints") == 0 || 278 strcmp(cp, ".tgz") == 0) 279 return (VE_TRY); 280 if (strcmp(cp, ".4th") == 0 || 281 strcmp(cp, ".lua") == 0 || 282 strcmp(cp, ".rc") == 0) 283 return (VE_MUST); 284 } 285 return (VE_WANT); 286 } 287 288 static int Verifying = -1; /* 0 if not verifying */ 289 290 static void 291 verify_tweak(int fd, off_t off, struct stat *stp, 292 char *tweak, int *accept_no_fp) 293 { 294 if (strcmp(tweak, "off") == 0) { 295 Verifying = 0; 296 } else if (strcmp(tweak, "strict") == 0) { 297 /* anything caller wants verified must be */ 298 *accept_no_fp = VE_WANT; 299 Verbose = VE_VERBOSE_ALL; 300 /* treat self test failure as fatal */ 301 if (!ve_self_tests()) { 302 panic("verify self tests failed"); 303 } 304 } else if (strcmp(tweak, "modules") == 0) { 305 /* modules/kernel must be verified */ 306 *accept_no_fp = VE_MUST; 307 } else if (strcmp(tweak, "try") == 0) { 308 /* best effort: always accept no fp */ 309 *accept_no_fp = VE_MUST + 1; 310 } else if (strcmp(tweak, "verbose") == 0) { 311 Verbose = VE_VERBOSE_ALL; 312 } else if (strcmp(tweak, "quiet") == 0) { 313 Verbose = VE_VERBOSE_UNVERIFIED; 314 VerifyFlags = 0; 315 } else if (strcmp(tweak, "silent") == 0) { 316 Verbose = VE_VERBOSE_SILENT; 317 VerifyFlags = 0; 318 } else if (strncmp(tweak, "trust", 5) == 0) { 319 /* content is trust anchor to add or revoke */ 320 unsigned char *ucp; 321 size_t num; 322 323 if (off > 0) 324 lseek(fd, 0, SEEK_SET); 325 ucp = read_fd(fd, stp->st_size); 326 if (ucp == NULL) 327 return; 328 if (strstr(tweak, "revoke")) { 329 num = ve_trust_anchors_revoke(ucp, stp->st_size); 330 DEBUG_PRINTF(3, ("revoked %d trust anchors\n", 331 (int) num)); 332 } else { 333 num = ve_trust_anchors_add_buf(ucp, stp->st_size); 334 DEBUG_PRINTF(3, ("added %d trust anchors\n", 335 (int) num)); 336 } 337 } 338 } 339 340 #ifndef VE_DEBUG_LEVEL 341 # define VE_DEBUG_LEVEL 0 342 #endif 343 344 static int 345 getenv_int(const char *var, int def) 346 { 347 const char *cp; 348 char *ep; 349 long val; 350 351 val = def; 352 cp = getenv(var); 353 if (cp && *cp) { 354 val = strtol(cp, &ep, 0); 355 if ((ep && *ep) || val != (int)val) { 356 val = def; 357 } 358 } 359 return (int)val; 360 } 361 362 363 /** 364 * @brief report verification status 365 * 366 * @param[in] path 367 * path we attempted to verify 368 * 369 * @param[in] severity 370 * indicator of how to handle case of missing fingerprint 371 * 372 * @param[in] status 373 * result of verification 374 * 0 not a file to be verified, > 0 success, < 0 error 375 * 376 * @param[in] stp 377 * pointer to struct stat, used in extra info to be output 378 * 379 * The output is dictated by combinations of the above and the setting 380 * of Verbose: 381 * 382 * VE_VERBOSE_SILENT 383 * report only failure to verify if severity is VE_WANT or higher. 384 * 385 * VE_VERBOSE_UNVERIFIED 386 * report any unverified file. 387 * 388 * VE_VERBOSE_MUST 389 * report verified only if severity is VE_MUST or higher. 390 * 391 * VE_VERBOSE_ALL 392 * report all verified files. 393 * 394 * VE_VERBOSE_DEBUG 395 * if stp is not NULL report dev,inode for path 396 */ 397 void 398 verify_report(const char *path, int severity, int status, struct stat *stp) 399 { 400 if (status < 0 || status == VE_FINGERPRINT_IGNORE) { 401 if (Verbose >= VE_VERBOSE_UNVERIFIED || severity > VE_TRY || 402 status <= VE_FINGERPRINT_WRONG) { 403 if (Verbose == VE_VERBOSE_DEBUG && stp != NULL) 404 printf("Unverified %s %llu,%llu\n", 405 ve_error_get(), 406 (long long)stp->st_dev, 407 (long long)stp->st_ino); 408 else 409 printf("Unverified %s\n", ve_error_get()); 410 } 411 } else if (status > 0 && Verbose >= VE_VERBOSE_MUST) { 412 if (severity >= VE_MUST || Verbose >= VE_VERBOSE_ALL) { 413 if (Verbose == VE_VERBOSE_DEBUG && stp != NULL) 414 printf("Unverified %s %llu,%llu\n", 415 path, 416 (long long)stp->st_dev, 417 (long long)stp->st_ino); 418 else 419 printf("Verified %s\n", path); 420 } 421 } 422 } 423 424 425 /** 426 * @brief prepare to verify an open file 427 * 428 * @param[in] fd 429 * open descriptor 430 * 431 * @param[in] filename 432 * path we opened and will use to lookup fingerprint 433 * 434 * @param[in] stp 435 * stat pointer so we can check file type 436 */ 437 int 438 verify_prep(int fd, const char *filename, off_t off, struct stat *stp, 439 const char *caller) 440 { 441 int rc; 442 443 if (Verifying < 0) { 444 Verifying = ve_trust_init(); 445 /* initialize ve_status with default result */ 446 rc = Verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING; 447 ve_status_set(0, rc); 448 ve_status_state = VE_STATUS_NONE; 449 if (Verifying) { 450 ve_self_tests(); 451 ve_anchor_verbose_set(1); 452 } 453 } 454 if (!Verifying || fd < 0) 455 return (0); 456 if (stp) { 457 if (fstat(fd, stp) < 0 || !S_ISREG(stp->st_mode)) 458 return (0); 459 } 460 DEBUG_PRINTF(2, 461 ("verify_prep: caller=%s,fd=%d,name='%s',off=%lld,dev=%lld,ino=%llu\n", 462 caller, fd, filename, (long long)off, (long long)stp->st_dev, 463 (unsigned long long)stp->st_ino)); 464 rc = is_verified(stp); 465 DEBUG_PRINTF(4,("verify_prep: is_verified()->%d\n", rc)); 466 if (rc == VE_NOT_CHECKED) { 467 rc = find_manifest(filename); 468 } else { 469 ve_status_set(fd, rc); 470 } 471 return (rc); 472 } 473 474 /** 475 * @brief verify an open file 476 * 477 * @param[in] fd 478 * open descriptor 479 * 480 * @param[in] filename 481 * path we opened and will use to lookup fingerprint 482 * 483 * @param[in] off 484 * current offset in fd, must be restored on return 485 * 486 * @param[in] severity 487 * indicator of how to handle case of missing fingerprint 488 * 489 * We look for a signed manifest relative to the filename 490 * just opened and verify/load it if needed. 491 * 492 * We then use verify_fd() in libve to actually verify that hash for 493 * open file. If it returns < 0 we look at the severity arg to decide 494 * what to do about it. 495 * 496 * If verify_fd() returns VE_FINGERPRINT_NONE we accept it if severity 497 * is < accept_no_fp. 498 * 499 * @return >= 0 on success < 0 on failure 500 */ 501 int 502 verify_file(int fd, const char *filename, off_t off, int severity, 503 const char *caller) 504 { 505 static int check_verbose = 1; 506 static int accept_no_fp = ACCEPT_NO_FP_DEFAULT; 507 struct stat st; 508 char *cp; 509 int rc; 510 511 if (check_verbose) { 512 check_verbose = 0; 513 Verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT); 514 VerifyFlags = getenv_int("VE_VERIFY_FLAGS", VEF_VERBOSE); 515 #ifndef UNIT_TEST 516 ve_debug_set(getenv_int("VE_DEBUG_LEVEL", VE_DEBUG_LEVEL)); 517 #endif 518 } 519 520 rc = verify_prep(fd, filename, off, &st, caller); 521 522 if (!rc) 523 return (0); 524 525 if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) { 526 if (severity <= VE_GUESS) 527 severity = severity_guess(filename); 528 #ifdef VE_PCR_SUPPORT 529 /* 530 * Only update pcr with things that must verify 531 * these tend to be processed in a more deterministic 532 * order, which makes our pseudo pcr more useful. 533 */ 534 ve_pcr_updating_set((severity == VE_MUST)); 535 #endif 536 #ifdef UNIT_TEST 537 if (DestdirLen > 0 && 538 strncmp(filename, Destdir, DestdirLen) == 0) { 539 filename += DestdirLen; 540 } 541 #endif 542 rc = verify_fd(fd, filename, off, &st); 543 verify_report(filename, severity, rc, &st); 544 if (rc >= 0) { 545 if (severity < VE_MUST) { /* not a kernel or module */ 546 if ((cp = strrchr(filename, '/'))) { 547 cp++; 548 if (strncmp(cp, "loader.ve.", 10) == 0) { 549 cp += 10; 550 verify_tweak(fd, off, &st, cp, 551 &accept_no_fp); 552 } 553 } 554 } 555 add_verify_status(&st, rc); 556 ve_status_set(fd, rc); 557 return (rc); 558 } 559 if (rc == VE_FINGERPRINT_UNKNOWN && severity < VE_MUST) 560 rc = VE_UNVERIFIED_OK; 561 else if (rc == VE_FINGERPRINT_NONE && severity < accept_no_fp) 562 rc = VE_UNVERIFIED_OK; 563 564 add_verify_status(&st, rc); 565 566 /* recheck debug/verbose level next time we are called */ 567 if (rc == VE_UNVERIFIED_OK) { 568 check_verbose = 1; 569 } 570 } 571 #ifdef LOADER_VERIEXEC_TESTING 572 else if (rc != VE_FINGERPRINT_WRONG) { 573 /* 574 * We have not loaded any manifest and 575 * not because of verication failure. 576 * Most likely reason is we have none. 577 * Allow boot to proceed if we are just testing. 578 */ 579 return (VE_UNVERIFIED_OK); 580 } 581 #endif 582 if (rc == VE_FINGERPRINT_WRONG && severity > accept_no_fp) 583 panic("cannot continue"); 584 ve_status_set(fd, rc); 585 return (rc); 586 } 587 588 /** 589 * @brief get hex string for pcr value and export 590 * 591 * In case we are doing measured boot, provide 592 * value of the "pcr" data we have accumulated. 593 */ 594 void 595 verify_pcr_export(void) 596 { 597 #ifdef VE_PCR_SUPPORT 598 char hexbuf[br_sha256_SIZE * 2 + 2]; 599 unsigned char hbuf[br_sha256_SIZE]; 600 char *hinfo; 601 char *hex; 602 ssize_t hlen; 603 604 hlen = ve_pcr_get(hbuf, sizeof(hbuf)); 605 if (hlen > 0) { 606 hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen); 607 if (hex) { 608 hex[hlen*2] = '\0'; /* clobber newline */ 609 setenv("loader.ve.pcr", hex, 1); 610 DEBUG_PRINTF(1, 611 ("%s: setenv(loader.ve.pcr, %s\n", __func__, 612 hex)); 613 hinfo = ve_pcr_hashed_get(1); 614 if (hinfo) { 615 setenv("loader.ve.hashed", hinfo, 1); 616 DEBUG_PRINTF(1, 617 ("%s: setenv(loader.ve.hashed, %s\n", 618 __func__, hinfo)); 619 if ((hlen = strlen(hinfo)) > KENV_MVALLEN) { 620 /* 621 * bump kenv_mvallen 622 * roundup to multiple of KENV_MVALLEN 623 */ 624 char mvallen[16]; 625 626 hlen += KENV_MVALLEN - 627 (hlen % KENV_MVALLEN); 628 if (snprintf(mvallen, sizeof(mvallen), 629 "%d", (int) hlen) < (int)sizeof(mvallen)) 630 setenv("kenv_mvallen", mvallen, 1); 631 } 632 free(hinfo); 633 } 634 } 635 } 636 #endif 637 } 638 639 /* 640 * For tftp and http we need to hash pathname 641 * to be able to fake stat(2) data. 642 */ 643 int 644 hash_string(char *s, size_t n, char *buf, size_t bufsz) 645 { 646 br_hash_compat_context mctx; 647 const br_hash_class *md; 648 649 switch (bufsz) { 650 case br_sha1_SIZE: 651 md = &br_sha1_vtable; 652 break; 653 case br_sha256_SIZE: 654 md = &br_sha256_vtable; 655 break; 656 default: 657 if (bufsz < br_sha1_SIZE) 658 return -1; 659 md = &br_sha1_vtable; 660 bufsz = br_sha1_SIZE; 661 break; 662 } 663 if (n == 0) 664 n = strlen(s); 665 md->init(&mctx.vtable); 666 md->update(&mctx.vtable, s, n); 667 md->out(&mctx.vtable, buf); 668 return bufsz; 669 } 670 671 672