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 } 527