15fff9558SSimon J. Gerraty /*- 25fff9558SSimon J. Gerraty * Copyright (c) 2017-2018, Juniper Networks, Inc. 35fff9558SSimon J. Gerraty * 45fff9558SSimon J. Gerraty * Redistribution and use in source and binary forms, with or without 55fff9558SSimon J. Gerraty * modification, are permitted provided that the following conditions 65fff9558SSimon J. Gerraty * are met: 75fff9558SSimon J. Gerraty * 1. Redistributions of source code must retain the above copyright 85fff9558SSimon J. Gerraty * notice, this list of conditions and the following disclaimer. 95fff9558SSimon J. Gerraty * 2. Redistributions in binary form must reproduce the above copyright 105fff9558SSimon J. Gerraty * notice, this list of conditions and the following disclaimer in the 115fff9558SSimon J. Gerraty * documentation and/or other materials provided with the distribution. 125fff9558SSimon J. Gerraty * 135fff9558SSimon J. Gerraty * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 145fff9558SSimon J. Gerraty * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 155fff9558SSimon J. Gerraty * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 165fff9558SSimon J. Gerraty * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 175fff9558SSimon J. Gerraty * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 185fff9558SSimon J. Gerraty * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 195fff9558SSimon J. Gerraty * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 205fff9558SSimon J. Gerraty * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 215fff9558SSimon J. Gerraty * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 225fff9558SSimon J. Gerraty * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 235fff9558SSimon J. Gerraty * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 245fff9558SSimon J. Gerraty */ 255fff9558SSimon J. Gerraty #include <sys/cdefs.h> 265fff9558SSimon J. Gerraty __FBSDID("$FreeBSD$"); 275fff9558SSimon J. Gerraty #include <sys/queue.h> 285fff9558SSimon J. Gerraty 295fff9558SSimon J. Gerraty #include "libsecureboot-priv.h" 305fff9558SSimon J. Gerraty 315fff9558SSimon J. Gerraty 325fff9558SSimon J. Gerraty struct fingerprint_info { 335fff9558SSimon J. Gerraty char *fi_prefix; /**< manifest entries relative to */ 345fff9558SSimon J. Gerraty char *fi_skip; /**< manifest entries prefixed with */ 355fff9558SSimon J. Gerraty const char *fi_data; /**< manifest data */ 365fff9558SSimon J. Gerraty size_t fi_prefix_len; /**< length of prefix */ 375fff9558SSimon J. Gerraty size_t fi_skip_len; /**< length of skip */ 385fff9558SSimon J. Gerraty dev_t fi_dev; /**< device id */ 395fff9558SSimon J. Gerraty LIST_ENTRY(fingerprint_info) entries; 405fff9558SSimon J. Gerraty }; 415fff9558SSimon J. Gerraty 425fff9558SSimon J. Gerraty static LIST_HEAD(, fingerprint_info) fi_list; 435fff9558SSimon J. Gerraty 445fff9558SSimon J. Gerraty static void 455fff9558SSimon J. Gerraty fingerprint_info_init(void) 465fff9558SSimon J. Gerraty { 475fff9558SSimon J. Gerraty static int once; 485fff9558SSimon J. Gerraty 495fff9558SSimon J. Gerraty if (once) 505fff9558SSimon J. Gerraty return; 515fff9558SSimon J. Gerraty LIST_INIT(&fi_list); 525fff9558SSimon J. Gerraty once = 1; 535fff9558SSimon J. Gerraty } 545fff9558SSimon J. Gerraty 555fff9558SSimon J. Gerraty /** 565fff9558SSimon J. Gerraty * @brief 575fff9558SSimon J. Gerraty * add manifest data to list 585fff9558SSimon J. Gerraty * 595fff9558SSimon J. Gerraty * list is kept sorted by longest prefix. 605fff9558SSimon J. Gerraty * 615fff9558SSimon J. Gerraty * @param[in] prefix 625fff9558SSimon J. Gerraty * path that all manifest entries are resolved via 635fff9558SSimon J. Gerraty * 645fff9558SSimon J. Gerraty * @param[in] skip 655fff9558SSimon J. Gerraty * optional prefix within manifest entries which should be skipped 665fff9558SSimon J. Gerraty * 675fff9558SSimon J. Gerraty * @param[in] data 685fff9558SSimon J. Gerraty * manifest data 695fff9558SSimon J. Gerraty */ 705fff9558SSimon J. Gerraty void 715fff9558SSimon J. Gerraty fingerprint_info_add(const char *filename, const char *prefix, 725fff9558SSimon J. Gerraty const char *skip, const char *data, struct stat *stp) 735fff9558SSimon J. Gerraty { 745fff9558SSimon J. Gerraty struct fingerprint_info *fip, *nfip, *lfip; 755fff9558SSimon J. Gerraty char *cp; 765fff9558SSimon J. Gerraty int n; 775fff9558SSimon J. Gerraty 785fff9558SSimon J. Gerraty fingerprint_info_init(); 795fff9558SSimon J. Gerraty nfip = malloc(sizeof(struct fingerprint_info)); 805fff9558SSimon J. Gerraty if (prefix) { 815fff9558SSimon J. Gerraty nfip->fi_prefix = strdup(prefix); 825fff9558SSimon J. Gerraty } else { 835fff9558SSimon J. Gerraty if (!filename) { 845fff9558SSimon J. Gerraty free(nfip); 855fff9558SSimon J. Gerraty return; 865fff9558SSimon J. Gerraty } 875fff9558SSimon J. Gerraty nfip->fi_prefix = strdup(filename); 885fff9558SSimon J. Gerraty cp = strrchr(nfip->fi_prefix, '/'); 89*53f151f9SSimon J. Gerraty if (cp == nfip->fi_prefix) { 90*53f151f9SSimon J. Gerraty cp[1] = '\0'; 91*53f151f9SSimon J. Gerraty } else if (cp) { 925fff9558SSimon J. Gerraty *cp = '\0'; 93*53f151f9SSimon J. Gerraty } else { 945fff9558SSimon J. Gerraty free(nfip->fi_prefix); 955fff9558SSimon J. Gerraty free(nfip); 965fff9558SSimon J. Gerraty return; 975fff9558SSimon J. Gerraty } 985fff9558SSimon J. Gerraty } 995fff9558SSimon J. Gerraty /* collapse any trailing ..[/] */ 1005fff9558SSimon J. Gerraty n = 0; 101*53f151f9SSimon J. Gerraty while ((cp = strrchr(nfip->fi_prefix, '/')) > nfip->fi_prefix) { 1025fff9558SSimon J. Gerraty if (cp[1] == '\0') { /* trailing "/" */ 1035fff9558SSimon J. Gerraty *cp = '\0'; 1045fff9558SSimon J. Gerraty continue; 1055fff9558SSimon J. Gerraty } 1065fff9558SSimon J. Gerraty if (strcmp(&cp[1], "..") == 0) { 1075fff9558SSimon J. Gerraty n++; 1085fff9558SSimon J. Gerraty *cp = '\0'; 1095fff9558SSimon J. Gerraty continue; 1105fff9558SSimon J. Gerraty } 1115fff9558SSimon J. Gerraty if (n > 0) { 1125fff9558SSimon J. Gerraty n--; 1135fff9558SSimon J. Gerraty *cp = '\0'; 1145fff9558SSimon J. Gerraty } 1155fff9558SSimon J. Gerraty if (n == 0) 1165fff9558SSimon J. Gerraty break; 1175fff9558SSimon J. Gerraty } 1185fff9558SSimon J. Gerraty #ifdef UNIT_TEST 1195fff9558SSimon J. Gerraty nfip->fi_dev = 0; 1205fff9558SSimon J. Gerraty #else 1215fff9558SSimon J. Gerraty nfip->fi_dev = stp->st_dev; 1225fff9558SSimon J. Gerraty #endif 1235fff9558SSimon J. Gerraty nfip->fi_data = data; 1245fff9558SSimon J. Gerraty nfip->fi_prefix_len = strlen(nfip->fi_prefix); 1255fff9558SSimon J. Gerraty if (skip) { 1265fff9558SSimon J. Gerraty nfip->fi_skip_len = strlen(skip); 1275fff9558SSimon J. Gerraty if (nfip->fi_skip_len) 1285fff9558SSimon J. Gerraty nfip->fi_skip = strdup(skip); 1295fff9558SSimon J. Gerraty else 1305fff9558SSimon J. Gerraty nfip->fi_skip = NULL; 1315fff9558SSimon J. Gerraty } else { 1325fff9558SSimon J. Gerraty nfip->fi_skip = NULL; 1335fff9558SSimon J. Gerraty nfip->fi_skip_len = 0; 1345fff9558SSimon J. Gerraty } 1355fff9558SSimon J. Gerraty 1365fff9558SSimon J. Gerraty if (LIST_EMPTY(&fi_list)) { 1375fff9558SSimon J. Gerraty LIST_INSERT_HEAD(&fi_list, nfip, entries); 1385fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("inserted %zu %s at head\n", 1395fff9558SSimon J. Gerraty nfip->fi_prefix_len, nfip->fi_prefix)); 1405fff9558SSimon J. Gerraty return; 1415fff9558SSimon J. Gerraty } 1425fff9558SSimon J. Gerraty LIST_FOREACH(fip, &fi_list, entries) { 1435fff9558SSimon J. Gerraty if (nfip->fi_prefix_len >= fip->fi_prefix_len) { 1445fff9558SSimon J. Gerraty LIST_INSERT_BEFORE(fip, nfip, entries); 1455fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("inserted %zu %s before %zu %s\n", 1465fff9558SSimon J. Gerraty nfip->fi_prefix_len, nfip->fi_prefix, 1475fff9558SSimon J. Gerraty fip->fi_prefix_len, fip->fi_prefix)); 1485fff9558SSimon J. Gerraty return; 1495fff9558SSimon J. Gerraty } 1505fff9558SSimon J. Gerraty lfip = fip; 1515fff9558SSimon J. Gerraty } 1525fff9558SSimon J. Gerraty LIST_INSERT_AFTER(lfip, nfip, entries); 1535fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("inserted %zu %s after %zu %s\n", 1545fff9558SSimon J. Gerraty nfip->fi_prefix_len, nfip->fi_prefix, 1555fff9558SSimon J. Gerraty lfip->fi_prefix_len, lfip->fi_prefix)); 1565fff9558SSimon J. Gerraty } 1575fff9558SSimon J. Gerraty 1585fff9558SSimon J. Gerraty #ifdef MANIFEST_SKIP_MAYBE 1595fff9558SSimon J. Gerraty /* 1605fff9558SSimon J. Gerraty * Deal with old incompatible boot/manifest 1615fff9558SSimon J. Gerraty * if fp[-1] is '/' and start of entry matches 1625fff9558SSimon J. Gerraty * MANIFEST_SKIP_MAYBE, we want it. 1635fff9558SSimon J. Gerraty */ 1645fff9558SSimon J. Gerraty static char * 1655fff9558SSimon J. Gerraty maybe_skip(char *fp, struct fingerprint_info *fip, size_t *nplenp) 1665fff9558SSimon J. Gerraty { 1675fff9558SSimon J. Gerraty char *tp; 1685fff9558SSimon J. Gerraty 1695fff9558SSimon J. Gerraty tp = fp - sizeof(MANIFEST_SKIP_MAYBE); 1705fff9558SSimon J. Gerraty 1715fff9558SSimon J. Gerraty if (tp >= fip->fi_data) { 1725fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("maybe: %.48s\n", tp)); 1735fff9558SSimon J. Gerraty if ((tp == fip->fi_data || tp[-1] == '\n') && 1745fff9558SSimon J. Gerraty strncmp(tp, MANIFEST_SKIP_MAYBE, 1755fff9558SSimon J. Gerraty sizeof(MANIFEST_SKIP_MAYBE) - 1) == 0) { 1765fff9558SSimon J. Gerraty fp = tp; 1775fff9558SSimon J. Gerraty *nplenp += sizeof(MANIFEST_SKIP_MAYBE); 1785fff9558SSimon J. Gerraty } 1795fff9558SSimon J. Gerraty } 1805fff9558SSimon J. Gerraty return (fp); 1815fff9558SSimon J. Gerraty } 1825fff9558SSimon J. Gerraty #endif 1835fff9558SSimon J. Gerraty 1845fff9558SSimon J. Gerraty char * 1855fff9558SSimon J. Gerraty fingerprint_info_lookup(int fd, const char *path) 1865fff9558SSimon J. Gerraty { 1875fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN+1]; 1885fff9558SSimon J. Gerraty char nbuf[MAXPATHLEN+1]; 1895fff9558SSimon J. Gerraty struct stat st; 1905fff9558SSimon J. Gerraty struct fingerprint_info *fip; 1915fff9558SSimon J. Gerraty char *cp, *ep, *fp, *np; 1925fff9558SSimon J. Gerraty const char *prefix; 1935fff9558SSimon J. Gerraty size_t n, plen, nlen, nplen; 1945fff9558SSimon J. Gerraty dev_t dev = 0; 1955fff9558SSimon J. Gerraty 1965fff9558SSimon J. Gerraty fingerprint_info_init(); 1975fff9558SSimon J. Gerraty 1985fff9558SSimon J. Gerraty n = strlcpy(pbuf, path, sizeof(pbuf)); 1995fff9558SSimon J. Gerraty if (n >= sizeof(pbuf)) 2005fff9558SSimon J. Gerraty return (NULL); 2015fff9558SSimon J. Gerraty #ifndef UNIT_TEST 2025fff9558SSimon J. Gerraty if (fstat(fd, &st) == 0) 2035fff9558SSimon J. Gerraty dev = st.st_dev; 2045fff9558SSimon J. Gerraty #endif 2055fff9558SSimon J. Gerraty /* 2065fff9558SSimon J. Gerraty * get the first entry - it will have longest prefix 2075fff9558SSimon J. Gerraty * so we can can work out how to initially split path 2085fff9558SSimon J. Gerraty */ 2095fff9558SSimon J. Gerraty fip = LIST_FIRST(&fi_list); 2105fff9558SSimon J. Gerraty if (!fip) 2115fff9558SSimon J. Gerraty return (NULL); 2125fff9558SSimon J. Gerraty prefix = pbuf; 2135fff9558SSimon J. Gerraty ep = NULL; 2145fff9558SSimon J. Gerraty cp = &pbuf[fip->fi_prefix_len]; 2155fff9558SSimon J. Gerraty do { 2165fff9558SSimon J. Gerraty if (ep) { 2175fff9558SSimon J. Gerraty *ep = '/'; 2185fff9558SSimon J. Gerraty cp -= 2; 2195fff9558SSimon J. Gerraty if (cp < pbuf) 2205fff9558SSimon J. Gerraty break; 2215fff9558SSimon J. Gerraty } 2225fff9558SSimon J. Gerraty nlen = plen = 0; /* keep gcc quiet */ 2235fff9558SSimon J. Gerraty if (cp > pbuf) { 2245fff9558SSimon J. Gerraty for ( ; cp >= pbuf && *cp != '/'; cp--) 2255fff9558SSimon J. Gerraty ; /* nothing */ 2265fff9558SSimon J. Gerraty if (cp > pbuf) { 2275fff9558SSimon J. Gerraty ep = cp++; 2285fff9558SSimon J. Gerraty *ep = '\0'; 2295fff9558SSimon J. Gerraty } else { 2305fff9558SSimon J. Gerraty cp = pbuf; 2315fff9558SSimon J. Gerraty } 2325fff9558SSimon J. Gerraty if (ep) { 2335fff9558SSimon J. Gerraty plen = ep - pbuf; 2345fff9558SSimon J. Gerraty nlen = n - plen - 1; 2355fff9558SSimon J. Gerraty } 2365fff9558SSimon J. Gerraty } 2375fff9558SSimon J. Gerraty if (cp == pbuf) { 2385fff9558SSimon J. Gerraty prefix = "/"; 2395fff9558SSimon J. Gerraty plen = 1; 2405fff9558SSimon J. Gerraty if (*cp == '/') { 2415fff9558SSimon J. Gerraty nlen = n - 1; 2425fff9558SSimon J. Gerraty cp++; 2435fff9558SSimon J. Gerraty } else 2445fff9558SSimon J. Gerraty nlen = n; 2455fff9558SSimon J. Gerraty ep = NULL; 2465fff9558SSimon J. Gerraty } 2475fff9558SSimon J. Gerraty 2485fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("looking for %s %zu %s\n", prefix, plen, cp)); 2495fff9558SSimon J. Gerraty 2505fff9558SSimon J. Gerraty LIST_FOREACH(fip, &fi_list, entries) { 2515fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("at %zu %s\n", 2525fff9558SSimon J. Gerraty fip->fi_prefix_len, fip->fi_prefix)); 2535fff9558SSimon J. Gerraty 2545fff9558SSimon J. Gerraty if (fip->fi_prefix_len < plen) { 2555fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("skipping prefix=%s %zu %zu\n", 2565fff9558SSimon J. Gerraty fip->fi_prefix, fip->fi_prefix_len, 2575fff9558SSimon J. Gerraty plen)); 2585fff9558SSimon J. Gerraty break; 2595fff9558SSimon J. Gerraty } 2605fff9558SSimon J. Gerraty if (fip->fi_prefix_len == plen) { 2615fff9558SSimon J. Gerraty if (fip->fi_dev != 0 && fip->fi_dev != dev) { 2625fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ( 2635fff9558SSimon J. Gerraty "skipping dev=%ld != %ld\n", 2645fff9558SSimon J. Gerraty (long)fip->fi_dev, 2655fff9558SSimon J. Gerraty (long)dev)); 2665fff9558SSimon J. Gerraty continue; 2675fff9558SSimon J. Gerraty } 2685fff9558SSimon J. Gerraty if (strcmp(prefix, fip->fi_prefix)) { 2695fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ( 2705fff9558SSimon J. Gerraty "skipping prefix=%s\n", 2715fff9558SSimon J. Gerraty fip->fi_prefix)); 2725fff9558SSimon J. Gerraty continue; 2735fff9558SSimon J. Gerraty } 2745fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("checking prefix=%s\n", 2755fff9558SSimon J. Gerraty fip->fi_prefix)); 2765fff9558SSimon J. Gerraty if (fip->fi_skip_len) { 2775fff9558SSimon J. Gerraty np = nbuf; 2785fff9558SSimon J. Gerraty nplen = snprintf(nbuf, sizeof(nbuf), 2795fff9558SSimon J. Gerraty "%s/%s", 2805fff9558SSimon J. Gerraty fip->fi_skip, cp); 2815fff9558SSimon J. Gerraty nplen = MIN(nplen, sizeof(nbuf) - 1); 2825fff9558SSimon J. Gerraty } else { 2835fff9558SSimon J. Gerraty np = cp; 2845fff9558SSimon J. Gerraty nplen = nlen; 2855fff9558SSimon J. Gerraty } 2865fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("lookup: '%s'\n", np)); 2875fff9558SSimon J. Gerraty if (!(fp = strstr(fip->fi_data, np))) 2885fff9558SSimon J. Gerraty continue; 2895fff9558SSimon J. Gerraty #ifdef MANIFEST_SKIP_MAYBE 2905fff9558SSimon J. Gerraty if (fip->fi_skip_len == 0 && 2915fff9558SSimon J. Gerraty fp > fip->fi_data && fp[-1] == '/') { 2925fff9558SSimon J. Gerraty fp = maybe_skip(fp, fip, &nplen); 2935fff9558SSimon J. Gerraty } 2945fff9558SSimon J. Gerraty #endif 2955fff9558SSimon J. Gerraty /* 2965fff9558SSimon J. Gerraty * when we find a match: 2975fff9558SSimon J. Gerraty * fp[nplen] will be space and 2985fff9558SSimon J. Gerraty * fp will be fip->fi_data or 2995fff9558SSimon J. Gerraty * fp[-1] will be \n 3005fff9558SSimon J. Gerraty */ 3015fff9558SSimon J. Gerraty if (!((fp == fip->fi_data || fp[-1] == '\n') && 3025fff9558SSimon J. Gerraty fp[nplen] == ' ')) { 3035fff9558SSimon J. Gerraty do { 3045fff9558SSimon J. Gerraty fp++; 3055fff9558SSimon J. Gerraty fp = strstr(fp, np); 3065fff9558SSimon J. Gerraty if (fp) { 3075fff9558SSimon J. Gerraty #ifdef MANIFEST_SKIP_MAYBE 3085fff9558SSimon J. Gerraty if (fip->fi_skip_len == 0 && 3095fff9558SSimon J. Gerraty fp > fip->fi_data && 3105fff9558SSimon J. Gerraty fp[-1] == '/') { 3115fff9558SSimon J. Gerraty fp = maybe_skip(fp, fip, &nplen); 3125fff9558SSimon J. Gerraty } 3135fff9558SSimon J. Gerraty #endif 3145fff9558SSimon J. Gerraty DEBUG_PRINTF(3, 3155fff9558SSimon J. Gerraty ("fp[-1]=%#x fp[%zu]=%#x fp=%.78s\n", 3165fff9558SSimon J. Gerraty fp[-1], nplen, 3175fff9558SSimon J. Gerraty fp[nplen], 3185fff9558SSimon J. Gerraty fp)); 3195fff9558SSimon J. Gerraty } 3205fff9558SSimon J. Gerraty } while (fp != NULL && 3215fff9558SSimon J. Gerraty !(fp[-1] == '\n' && 3225fff9558SSimon J. Gerraty fp[nplen] == ' ')); 3235fff9558SSimon J. Gerraty if (!fp) 3245fff9558SSimon J. Gerraty continue; 3255fff9558SSimon J. Gerraty } 3265fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("found %.78s\n", fp)); 3275fff9558SSimon J. Gerraty /* we have a match! */ 3285fff9558SSimon J. Gerraty for (cp = &fp[nplen]; *cp == ' '; cp++) 3295fff9558SSimon J. Gerraty ; /* nothing */ 3305fff9558SSimon J. Gerraty return (cp); 3315fff9558SSimon J. Gerraty } else { 3325fff9558SSimon J. Gerraty DEBUG_PRINTF(3, 3335fff9558SSimon J. Gerraty ("Ignoring prefix=%s\n", fip->fi_prefix)); 3345fff9558SSimon J. Gerraty } 3355fff9558SSimon J. Gerraty } 3365fff9558SSimon J. Gerraty } while (cp > &pbuf[1]); 3375fff9558SSimon J. Gerraty 3385fff9558SSimon J. Gerraty return (NULL); 3395fff9558SSimon J. Gerraty } 3405fff9558SSimon J. Gerraty 3415fff9558SSimon J. Gerraty static int 3425fff9558SSimon J. Gerraty verify_fingerprint(int fd, const char *path, const char *cp, off_t off) 3435fff9558SSimon J. Gerraty { 3445fff9558SSimon J. Gerraty unsigned char buf[PAGE_SIZE]; 3455fff9558SSimon J. Gerraty const br_hash_class *md; 3465fff9558SSimon J. Gerraty br_hash_compat_context mctx; 3475fff9558SSimon J. Gerraty size_t hlen; 3485fff9558SSimon J. Gerraty int n; 3495fff9558SSimon J. Gerraty 35064ca9a7fSSimon J. Gerraty if (strncmp(cp, "no_hash", 7) == 0) { 35164ca9a7fSSimon J. Gerraty return (VE_FINGERPRINT_IGNORE); 35264ca9a7fSSimon J. Gerraty } else if (strncmp(cp, "sha256=", 7) == 0) { 3535fff9558SSimon J. Gerraty md = &br_sha256_vtable; 3545fff9558SSimon J. Gerraty hlen = br_sha256_SIZE; 3555fff9558SSimon J. Gerraty cp += 7; 3565fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 3575fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha1=", 5) == 0) { 3585fff9558SSimon J. Gerraty md = &br_sha1_vtable; 3595fff9558SSimon J. Gerraty hlen = br_sha1_SIZE; 3605fff9558SSimon J. Gerraty cp += 5; 3615fff9558SSimon J. Gerraty #endif 3625fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 3635fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha384=", 7) == 0) { 3645fff9558SSimon J. Gerraty md = &br_sha384_vtable; 3655fff9558SSimon J. Gerraty hlen = br_sha384_SIZE; 3665fff9558SSimon J. Gerraty cp += 7; 3675fff9558SSimon J. Gerraty #endif 3685fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 3695fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha512=", 7) == 0) { 3705fff9558SSimon J. Gerraty md = &br_sha512_vtable; 3715fff9558SSimon J. Gerraty hlen = br_sha512_SIZE; 3725fff9558SSimon J. Gerraty cp += 7; 3735fff9558SSimon J. Gerraty #endif 3745fff9558SSimon J. Gerraty } else { 3755fff9558SSimon J. Gerraty ve_error_set("%s: no supported fingerprint", path); 3765fff9558SSimon J. Gerraty return (VE_FINGERPRINT_UNKNOWN); 3775fff9558SSimon J. Gerraty } 3785fff9558SSimon J. Gerraty 3795fff9558SSimon J. Gerraty md->init(&mctx.vtable); 3805fff9558SSimon J. Gerraty if (off) 3815fff9558SSimon J. Gerraty lseek(fd, 0, SEEK_SET); 3825fff9558SSimon J. Gerraty do { 3835fff9558SSimon J. Gerraty n = read(fd, buf, sizeof(buf)); 3845fff9558SSimon J. Gerraty if (n < 0) 3855fff9558SSimon J. Gerraty return (n); 3865fff9558SSimon J. Gerraty if (n > 0) 3875fff9558SSimon J. Gerraty md->update(&mctx.vtable, buf, n); 3885fff9558SSimon J. Gerraty } while (n > 0); 3895fff9558SSimon J. Gerraty lseek(fd, off, SEEK_SET); 3905fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, path, cp, hlen)); 3915fff9558SSimon J. Gerraty } 3925fff9558SSimon J. Gerraty 3935fff9558SSimon J. Gerraty 3945fff9558SSimon J. Gerraty /** 3955fff9558SSimon J. Gerraty * @brief 3965fff9558SSimon J. Gerraty * verify an open file 3975fff9558SSimon J. Gerraty * 3985fff9558SSimon J. Gerraty * @param[in] fd 3995fff9558SSimon J. Gerraty * open descriptor 4005fff9558SSimon J. Gerraty * 4015fff9558SSimon J. Gerraty * @param[in] path 4025fff9558SSimon J. Gerraty * pathname to open 4035fff9558SSimon J. Gerraty * 4045fff9558SSimon J. Gerraty * @param[in] off 4055fff9558SSimon J. Gerraty * current offset 4065fff9558SSimon J. Gerraty * 4075fff9558SSimon J. Gerraty * @return 0, VE_FINGERPRINT_OK or VE_FINGERPRINT_NONE, VE_FINGERPRINT_WRONG 4085fff9558SSimon J. Gerraty */ 4095fff9558SSimon J. Gerraty int 4105fff9558SSimon J. Gerraty verify_fd(int fd, const char *path, off_t off, struct stat *stp) 4115fff9558SSimon J. Gerraty { 4125fff9558SSimon J. Gerraty struct stat st; 4135fff9558SSimon J. Gerraty char *cp; 4145fff9558SSimon J. Gerraty int rc; 4155fff9558SSimon J. Gerraty 4165fff9558SSimon J. Gerraty if (!stp) { 4175fff9558SSimon J. Gerraty if (fstat(fd, &st) == 0) 4185fff9558SSimon J. Gerraty stp = &st; 4195fff9558SSimon J. Gerraty } 4205fff9558SSimon J. Gerraty if (stp && !S_ISREG(stp->st_mode)) 4215fff9558SSimon J. Gerraty return (0); /* not relevant */ 4225fff9558SSimon J. Gerraty cp = fingerprint_info_lookup(fd, path); 4235fff9558SSimon J. Gerraty if (!cp) { 4245fff9558SSimon J. Gerraty ve_error_set("%s: no entry", path); 4255fff9558SSimon J. Gerraty return (VE_FINGERPRINT_NONE); 4265fff9558SSimon J. Gerraty } 4275fff9558SSimon J. Gerraty rc = verify_fingerprint(fd, path, cp, off); 4285fff9558SSimon J. Gerraty switch (rc) { 4295fff9558SSimon J. Gerraty case VE_FINGERPRINT_OK: 43064ca9a7fSSimon J. Gerraty case VE_FINGERPRINT_IGNORE: 4315fff9558SSimon J. Gerraty case VE_FINGERPRINT_UNKNOWN: 4325fff9558SSimon J. Gerraty return (rc); 4335fff9558SSimon J. Gerraty default: 4345fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG); 4355fff9558SSimon J. Gerraty } 4365fff9558SSimon J. Gerraty } 4375fff9558SSimon J. Gerraty 4385fff9558SSimon J. Gerraty /** 4395fff9558SSimon J. Gerraty * @brief 4405fff9558SSimon J. Gerraty * open a file if it can be verified 4415fff9558SSimon J. Gerraty * 4425fff9558SSimon J. Gerraty * @param[in] path 4435fff9558SSimon J. Gerraty * pathname to open 4445fff9558SSimon J. Gerraty * 4455fff9558SSimon J. Gerraty * @param[in] flags 4465fff9558SSimon J. Gerraty * flags for open 4475fff9558SSimon J. Gerraty * 4485fff9558SSimon J. Gerraty * @return fd or VE_FINGERPRINT_NONE, VE_FINGERPRINT_WRONG 4495fff9558SSimon J. Gerraty */ 4505fff9558SSimon J. Gerraty int 4515fff9558SSimon J. Gerraty verify_open(const char *path, int flags) 4525fff9558SSimon J. Gerraty { 4535fff9558SSimon J. Gerraty int fd; 4545fff9558SSimon J. Gerraty int rc; 4555fff9558SSimon J. Gerraty 4565fff9558SSimon J. Gerraty if ((fd = open(path, flags)) >= 0) { 4575fff9558SSimon J. Gerraty if ((rc = verify_fd(fd, path, 0, NULL)) < 0) { 4585fff9558SSimon J. Gerraty close(fd); 4595fff9558SSimon J. Gerraty fd = rc; 4605fff9558SSimon J. Gerraty } 4615fff9558SSimon J. Gerraty } 4625fff9558SSimon J. Gerraty return (fd); 4635fff9558SSimon J. Gerraty } 464