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